AWS - Lambda

提供: MochiuWiki : SUSE, EC, PCB

2025年12月8日 (月) 13:25時点におけるWiki (トーク | 投稿記録)による版 (Lambda関数の作成)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

概要

AWS Lambdaは、AWSが提供するサーバーレスコンピューティングサービスである。
サーバの管理やプロビジョニングを行うことなく、コードを実行できる環境を提供する。

主な特徴を以下に示す。

  • サーバーレス
    サーバ管理、OS管理、パッチ適用が不要
  • イベント駆動型
    S3、DynamoDB、API Gateway等のイベントをトリガーに実行
  • 自動スケーリング
    リクエスト数に応じて自動的にスケール
  • 従量課金
    実行時間とメモリ使用量に基づく課金
  • 多言語対応
    Python、Node.js、Java、Go、Ruby、.NET等をサポート


AWS Lambdaの基本概念を以下に示す。

  • 関数
    実行するコードの単位
  • トリガー
    関数を起動するイベントソース
  • ランタイム
    コードを実行する環境 (言語とバージョン)
  • ハンドラ
    関数のエントリーポイント
  • 実行ロール
    関数が他のAWSサービスにアクセスするためのIAMロール


AWS Lambdaは永続的な無料利用枠を提供しており、個人利用や小規模なアプリケーションであれば無料枠内で運用できることが多い。


Lambdaの無料枠について

無料枠の内容

  • リクエスト数 : 月100万リクエストまで無料
  • コンピューティング時間
    月40万GB秒まで無料
    128MBメモリで実行した場合、約320万秒 (約888時間) 相当
  • その他
    Lambda関数のコード保存は無料
    CloudWatch Logsへの書き込みは別途課金対象


※注意

  • この無料枠は12ヶ月限定ではなく、永続的に利用可能である。
  • 無料枠はアカウント全体で共有される。
  • データ転送料金は別途発生する場合がある。
  • 同時実行数には制限があり、デフォルトは1000 (リージョンごと) である。


料金体系

無料枠を超えた場合の料金 (東京リージョンの例)

  • リクエスト料金
    • $0.20 / 100万リクエスト

  • コンピューティング料金
    • $0.0000166667 / GB秒
    • 例 : 128MBメモリで100ミリ秒実行 = 0.0125GB秒
    • 100万回実行の場合 : 約$0.21

  • 追加料金
    • Provisioned Concurrency : $0.000004861 / GB秒
    • Ephemeral Storage (512MB超過分) : $0.0000000309 / GB秒



Lambdaの停止

AWS Lambdaには従来的な意味での停止という概念がない。
EC2のようなインスタンスベースのサービスとは異なり、Lambdaはイベント駆動型のサーバーレスサービスであり、実行されていない時は課金が発生しないためである。

コストを抑える方法

使用していない場合のコストを抑えるには、以下に示す選択肢がある。

1. トリガーの無効化
  • イベントソース (CloudWatch Events、API Gateway等) を無効化する。
  • 関数自体は残しておくことができる。
  • トリガーがなければ実行されないため、コストは発生しない。


2. 関数の削除
  • 完全に使用しない場合は削除する。
  • コードはバージョン管理システム(Git等)で管理しておく。


3. メモリサイズの最適化
  • 必要最小限のメモリサイズに設定する。
  • ただし、メモリサイズはCPU性能にも影響するため、バランスが重要である。
  • パフォーマンステストを行い、最適な値を見つける。


コスト構造について

実行がない場合

  • コード保存料金は発生しない。(無料)
  • CloudWatch Logsのストレージ料金のみ発生する可能性がある。
  • 基本的にコストは0円またはほぼ0円


実行がある場合

  • リクエスト数とコンピューティング時間に基づいて課金される。
  • 例 : 128MBメモリ、100ミリ秒実行、月10万回の場合
    リクエスト料金 : $0.02
    コンピューティング料金 : $0.021
    合計 : 約$0.041/月 (約6円/月)


コストを下げる方法

  • 実行時間の短縮
    コードの最適化により実行時間を短縮する。
    不要な処理を削減する。
  • メモリの最適化
    適切なメモリサイズを選択する。
    大きすぎるメモリは無駄なコストとなる。
  • ログの管理
    CloudWatch Logsの保持期間を適切に設定する。
    不要なログ出力を削減する。


完全に無料にするには、トリガーを無効化して関数を実行させないこと。


Lambda関数の作成

1. マネジメントコンソールでの作成

  1. AWSマネジメントコンソールにログインする。
  2. リージョンを選択する。
    東京リージョン : ap-northeast-1
  3. 検索バーに "Lambda" と入力して選択する。
  4. [関数の作成]を選択する。


2. 作成オプション

  1. 作成方法を選択する。
    • 1から作成 (推奨)
      基本的な関数を自分で作成
    • ブループリントの使用
      テンプレートから作成
    • コンテナイメージ
      Dockerイメージから作成

  2. 関数名を入力する。
    例 : MyFunction
  3. ランタイムを選択する。
    例 : Python 3.12、Node.js 20.x、Java 21 等
    ※注意
    サポートされている最新バージョンを選択することを推奨する。

  4. アーキテクチャ
    x86_64 または arm64 (Graviton2)
    arm64はコスト効率が良い。

  5. アクセス権限
    • デフォルトの実行ロールを使用
      基本的なLambda実行権限のみ
    • 既存のロールを使用
      事前に作成したIAMロールを指定
    • AWS ポリシーテンプレートから新しいロールを作成
      S3、DynamoDB等へのアクセス権限を持つロールを作成
  6. [関数の作成]を選択する。


関数が作成されると、コードエディタが表示される。

Python関数の例

 # lambda_function.py
 
 def lambda_handler(event, context):
    # eventには入力データが含まれる
    # contextには実行環境の情報が含まれる
 
    print("イベント内容:", event)
 
    # 処理の例
    name = event.get('name', 'World')
    message = f'Hello, {name}!'
 
    # レスポンスの返却
    return {
       'statusCode': 200,
       'body': message
    }


関数設定の確認と変更

作成した関数を選択して、以下に示す項目を確認・変更する。

  • コードタブ
    関数コードの編集、テストイベントの作成
  • テストタブ
    テストイベントの作成と実行
  • 設定タブ
    一般設定 : タイムアウト(デフォルト3秒、最大15分)、メモリ (128[MB]〜10240[MB])
    環境変数 : キーと値のペアで設定
    トリガー : イベントソースの追加
    送信先 : 成功・失敗時の送信先設定
    アクセス権限 : 実行ロールの確認と変更
  • モニタータブ
    CloudWatchメトリクス、ログの確認



Linux PCからのアクセス設定

AWS CLIのインストール

方法1 : pip経由 (推奨)

Python3をインストールする。

sudo apt update
sudo apt install python3 python3-pip -y


AWS CLIをインストールする。

pip3 install awscli --user


正常にインストールされているかどうかを確認する。

aws --version


方法2 : 公式インストーラ

AWS CLIをダウンロードおよびインストールする。

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install


正常にインストールされているかどうかを確認する。

aws --version


アクセスキーの作成

  1. AWSマネジメントコンソールで "IAM" を検索する。
  2. [ユーザ] - 作成したIAMユーザを選択する。
  3. [セキュリティ認証情報]タブを選択する。
  4. [アクセスキーを作成]を選択する。
  5. ユースケース : [コマンドラインインターフェイス (CLI)]を選択する。
  6. 確認のチェックボックスにチェックを入力する。
  7. [次へ]を選択する。
  8. 説明タグを入力する。(オプション)
    例 : MyLinuxPC
  9. [アクセスキーを作成]を選択する。
    重要 : アクセスキーIDとシークレットアクセスキーを控えておく。
    • シークレットキーは後で確認できない。
    • .csvファイルをダウンロードして安全に保管する。


AWS CLIの設定

設定コマンドを実行する。

aws configure


以下に示すものを順番に入力する。

  • AWS Access Key ID
    作成したアクセスキーID
  • AWS Secret Access Key
    シークレットアクセスキー
  • Default region name
    例 : ap-northeast-1 (東京リージョン)
  • Default output format
    json (推奨)


設定ファイルの場所は以下の通りである。

  • ~/.aws/credentials
    アクセスキー情報
  • ~/.aws/config
    リージョンや出力形式


接続テスト

Lambda関数一覧を取得する。

aws lambda list-functions


特定の関数の情報を取得する。

aws lambda get-function --function-name MyFunction



Lambdaの基本操作 (CLI)

関数の呼び出し

 # 同期呼び出し(レスポンスを待つ)
 aws lambda invoke \
     --function-name MyFunction \
     --payload '{"name": "太郎"}' \
     response.json
 
 # レスポンスの確認
 cat response.json


関数の呼び出し (非同期)

 # 非同期呼び出し(レスポンスを待たない)
 aws lambda invoke \
     --function-name MyFunction \
     --invocation-type Event \
     --payload '{"name": "花子"}' \
     response.json


関数コードの更新

 # ZIPファイルから更新
 # まずコードをZIP化
 zip function.zip lambda_function.py
 
 # 関数を更新
 aws lambda update-function-code \
     --function-name MyFunction \
     --zip-file fileb://function.zip


環境変数の設定

 # 環境変数の設定
 aws lambda update-function-configuration \
     --function-name MyFunction \
     --environment Variables="{DB_HOST=localhost,DB_PORT=5432}"


タイムアウトとメモリの変更

 # タイムアウトを30秒、メモリを512[MB]に設定
 aws lambda update-function-configuration \
     --function-name MyFunction \
     --timeout 30 \
     --memory-size 512


ログの確認

 # CloudWatch Logsのログストリーム一覧を取得
 aws logs describe-log-streams \
     --log-group-name /aws/lambda/MyFunction \
     --order-by LastEventTime \
     --descending \
     --max-items 1
 
 # ログイベントの取得
 aws logs get-log-events \
     --log-group-name /aws/lambda/MyFunction \
     --log-stream-name 'ログストリーム名'


関数の削除

 # 関数の削除
 aws lambda delete-function \
     --function-name MyFunction



Python SDK (boto3) の使用

以下の例では、Pythonを使用してAWS Lambdaを操作している。

まず、boto3をインストールする。

pip3 install boto3 --user


 # lambda_client_example.py
 
 import boto3
 import json
 
 # Lambdaクライアントの作成
 lambda_client = boto3.client('lambda', region_name='ap-northeast-1')
 
 # 関数の呼び出し(同期)
 def invoke_function():
    response = lambda_client.invoke(
       FunctionName='MyFunction',
       InvocationType='RequestResponse',  # 同期呼び出し
       Payload=json.dumps({
          'name': '山田太郎'
       })
    )
 
    # レスポンスの取得
    response_payload = json.loads(response['Payload'].read())
    print("レスポンス:", response_payload)
    print("ステータスコード:", response['StatusCode'])
 
 # 関数の呼び出し (非同期)
 def invoke_function_async():
    response = lambda_client.invoke(
       FunctionName='MyFunction',
       InvocationType='Event',  # 非同期呼び出し
       Payload=json.dumps({
          'name': '佐藤花子'
       })
    )
 
    print("非同期呼び出し完了:", response['StatusCode'])
 
 # 関数の一覧取得
 def list_functions():
    response = lambda_client.list_functions()
 
    for func in response['Functions']:
       print(f"関数名: {func['FunctionName']}")
       print(f"  ランタイム: {func['Runtime']}")
       print(f"  メモリサイズ: {func['MemorySize']}MB")
       print(f"  タイムアウト: {func['Timeout']}秒")
       print()
 
 # 関数の設定取得
 def get_function_config():
    response = lambda_client.get_function_configuration(
       FunctionName='MyFunction'
    )
 
    print("関数設定:")
    print(f"  メモリサイズ: {response['MemorySize']}MB")
    print(f"  タイムアウト: {response['Timeout']}秒")
    print(f"  ランタイム: {response['Runtime']}")
    print(f"  ハンドラ: {response['Handler']}")
 
 # 環境変数の更新
 def update_environment_variables():
    response = lambda_client.update_function_configuration(
       FunctionName='MyFunction',
       Environment={
          'Variables': {
             'DB_HOST': 'mydb.example.com',
             'DB_PORT': '3306',
             'DEBUG': 'true'
          }
       }
    )
 
    print("環境変数更新完了")
 
 # メイン処理
 if __name__ == '__main__':
    invoke_function()
    # invoke_function_async()
    # list_functions()
    # get_function_config()
    # update_environment_variables()


# 実行方法
python3 lambda_client_example.py


Lambda関数内でのboto3の使用

Lambda関数内で他のAWSサービスにアクセスする場合の例を以下に示す。

 # lambda_function.py (DynamoDBへのアクセス例)
 
 import boto3
 import json
 from datetime import datetime
 
 dynamodb = boto3.resource('dynamodb')
 table = dynamodb.Table('MyTable')
 
 def lambda_handler(event, context):
    try:
       # DynamoDBにデータを保存
       item = {
          'id': event.get('id', '001'),
          'timestamp': datetime.now().isoformat(),
          'data': event.get('data', {})
       }
 
       table.put_item(Item=item)
 
       return {
          'statusCode': 200,
          'body': json.dumps({
             'message': 'データ保存成功',
             'item': item
          })
       }
 
    except Exception as e:
       print(f"エラー: {str(e)}")
       return {
          'statusCode': 500,
          'body': json.dumps({
             'message': 'エラーが発生しました',
             'error': str(e)
          })
       }


※注意
この関数を実行するには、Lambda実行ロールにDynamoDBへのアクセス権限が必要である。

デバッグ方法

 # AWS CLIのデバッグモード
 
 aws lambda invoke --function-name MyFunction --payload '{}' response.json --debug


 # Lambda関数内でのログ出力
 
 import logging
 
 logger = logging.getLogger()
 logger.setLevel(logging.INFO)
 
 def lambda_handler(event, context):
    logger.info(f"受信したイベント: {event}")
    logger.debug(f"コンテキスト情報: {context}")
 
    # 処理...
 
    return {'statusCode': 200}



セキュリティ

実行ロールの設定

Lambda関数が他のAWSサービスにアクセスするには、適切なIAMロールが必要である。

  • 基本的な実行ロールのポリシー例
 {
    "Version": "2012-10-17",
    "Statement": [
       {
          "Effect": "Allow",
          "Action": [
             "logs:CreateLogGroup",
             "logs:CreateLogStream",
             "logs:PutLogEvents"
          ],
          "Resource": "arn:aws:logs:*:*:*"
       }
    ]
 }


  • DynamoDBアクセスを含むポリシー例
 {
    "Version": "2012-10-17",
    "Statement": [
       {
          "Effect": "Allow",
          "Action": [
             "logs:CreateLogGroup",
             "logs:CreateLogStream",
             "logs:PutLogEvents"
          ],
          "Resource": "arn:aws:logs:*:*:*"
       },
       {
          "Effect": "Allow",
          "Action": [
             "dynamodb:PutItem",
             "dynamodb:GetItem",
             "dynamodb:Query",
             "dynamodb:Scan"
          ],
          "Resource": "arn:aws:dynamodb:ap-northeast-1:*:table/MyTable"
       }
    ]
 }


環境変数での機密情報管理

  • 機密情報 (APIキー、パスワード等) はコードに直接記述しない。
  • 環境変数を使用する。
  • より安全性を高めるには AWS Secrets Manager または AWS Systems Manager Parameter Store を使用する。


  • Secrets Managerの使用例
 import boto3
 import json
 
 def get_secret(secret_name):
    client = boto3.client('secretsmanager', region_name='ap-northeast-1')
 
    response = client.get_secret_value(SecretId=secret_name)
    secret = json.loads(response['SecretString'])
 
    return secret
 
 def lambda_handler(event, context):
    # シークレットの取得
    db_credentials = get_secret('myapp/database')
 
    db_host = db_credentials['host']
    db_password = db_credentials['password']
 
    # データベース接続処理
    # ...略


VPCアクセス

Lambda関数をVPC内のリソース (RDS、ElastiCache等) に接続する場合

設定方法

  1. Lambda関数の設定で VPC を選択する。
  2. サブネット(プライベートサブネット推奨)を選択する。
  3. セキュリティグループを選択する。
  4. 実行ロールに以下の権限を追加する。
 {
    "Effect": "Allow",
    "Action": [
       "ec2:CreateNetworkInterface",
       "ec2:DescribeNetworkInterfaces",
       "ec2:DeleteNetworkInterface"
    ],
    "Resource": "*"
 }


※注意

  • VPC接続により、コールドスタート時間が増加する可能性がある。
  • インターネットアクセスが必要な場合は、NATゲートウェイが必要となる。


レイヤーの使用

複数の関数で共通のライブラリや依存関係を共有する場合、Lambdaレイヤーを使用する。

  • レイヤーの作成例
 # ライブラリのインストール
 mkdir python
 pip3 install requests -t python/
 
 # ZIPファイルの作成
 zip -r my-layer.zip python/
 
 # レイヤーの作成
 aws lambda publish-layer-version \
     --layer-name my-dependencies \
     --zip-file fileb://my-layer.zip \
     --compatible-runtimes python3.12


  • 関数へのレイヤー追加
 aws lambda update-function-configuration \
     --function-name MyFunction \
     --layers arn:aws:lambda:ap-northeast-1:123456789012:layer:my-dependencies:1



トラブルシューティング

エラー : "Task timed out after X seconds"

  • 原因
    関数の実行がタイムアウト設定を超えた
  • 解決方法
    タイムアウト設定を延長する(最大15分)
    コードを最適化して実行時間を短縮する
    長時間処理の場合は Step Functions の使用を検討する


エラー : "AccessDeniedException"

  • 原因
    実行ロールに必要な権限がない
  • 解決方法
    Lambda実行ロールに適切なIAMポリシーをアタッチする
    CloudWatch Logsでエラー詳細を確認する


エラー : "Out of memory"

  • 原因
    メモリ設定が不足している
  • 解決方法
    メモリサイズを増やす。(128[MB]〜10240[MB])
    メモリリークがないかコードを確認する。
    大きなファイル処理の場合は、S3 または EFS の使用を検討する。


エラー : "ResourceNotFoundException"

  • 原因
    指定した関数が存在しない、または、リージョンが違う。
  • 解決方法
    関数名とリージョンを確認する。
    関数が削除されていないか確認する。


コールドスタートの遅延

  • 原因
    関数が初回実行時または長時間未使用後に実行環境の初期化が必要。
  • 解決方法
    Provisioned Concurrencyを使用する。(有料)
    メモリサイズを増やす。(CPU性能も向上)
    依存関係を最小化する。
    Lambda SnapStartを使用する。(Java限定)


VPC接続の問題

  • 原因
    VPC設定が正しくない、または、セキュリティグループの設定に問題がある。
  • 解決方法
    サブネットにルートテーブルが正しく設定されているか確認する。
    セキュリティグループのインバウンド・アウトバウンドルールを確認する。
    NATゲートウェイまたはVPCエンドポイントの設定を確認する。


デバッグのヒント

  • CloudWatch Logsの活用
    print文やlogging.info()でログを出力する。
    ログ保持期間を適切に設定する。
  • X-Rayの使用
    関数の実行トレースを可視化する。
    ボトルネックを特定する。
  • ローカルでの試験
    AWS SAM CLIを使用してローカル環境で試験する。
    Dockerを使用して、Lambda実行環境を再現する。