AWS Lambda のデバッグ: 一般的な呼び出しエラーとその解決策

AWS Lambda 関数のデバッグの技術を習得しましょう。この包括的なガイドでは、IAM 権限の問題や VPC 接続の問題から、メモリ不足や関数のタイムアウトなどのリソース制約まで、最も一般的な呼び出しエラーを詳しく説明します。CloudWatch ログを効果的に活用し、設定の最適化、依存関係の管理、実行ロールの修正など、実践的で実行可能な修正を適用して、信頼性の高い一貫したサーバーレス関数のパフォーマンスを確保する方法を学びましょう。

AWS Lambdaのデバッグ:一般的な呼び出しエラーとその修正方法

AWS Lambdaの呼び出しエラーは、通常、呼び出し元が関数を呼び出せない、Lambdaがランタイムを起動できない、またはコードが起動してから失敗する、の3つのうちのいずれかに起因します。最速の修正方法は、メモリ、タイムアウト、IAMポリシー、VPC設定を変更する前に、どの段階で失敗したかを特定することです。

CloudWatch Logsから始め、次に権限、ハンドラー設定、依存関係、ネットワークの順に確認します。

デバッグのベースラインの確立:CloudWatch Logs

関数を変更する前に、ロググループ /aws/lambda/YourFunctionName を確認します。通常のLambda実行では、通常、以下のプラットフォームログ行が含まれます。

  1. START: 実行の開始を示します。
  2. END: 実行の完了を示します。
  3. REPORT: 要約メトリクス(Duration、Billed Duration、Memory Used、Max Memory Used、X-Rayトレースの詳細)を提供します。

関数が起動しない場合、アプリケーションログが表示されないことがあります。その場合は、呼び出し元のサービス、Lambdaコンソールのテスト結果、CloudTrailイベント、および関数のリソースベースのポリシーを確認します。

権限とアクセスエラーの解決

権限エラーは、おそらくLambda呼び出し失敗の最も一般的な原因です。これらは通常、関数の実行に必要な権限がないか、呼び出し元のエンティティに関数を呼び出す権限がないかの2つのカテゴリに分類されます。

実行ロール(IAMロール)の失敗

すべてのLambda関数は、IAM実行ロールを引き受ける必要があります。このロールが誤って設定されていると、関数は必要なAWSサービスと対話できません。

よくある不足している権限:

必要なサービスアクセス 必要なIAMポリシーアクション
CloudWatchへのログ記録 logs:CreateLogGrouplogs:CreateLogStreamlogs:PutLogEvents
VPC接続 ec2:CreateNetworkInterfaceec2:DeleteNetworkInterfaceec2:DescribeNetworkInterfaces
S3/DynamoDBの読み取り s3:GetObjectdynamodb:GetItemなど

修正方法:

  1. AWSコンソールでLambda関数の設定に移動します。
  2. 「権限」タブを確認し、アタッチされているIAMロールポリシーを確認します。
  3. ロールに基本的なAWS管理ポリシー AWSLambdaBasicExecutionRole があること、またはカスタムポリシーに必要なCloudWatchアクションが含まれていることを確認します。
  4. 特定のバケットプレフィックスに対する s3:GetObject など、コードに実際に必要なサービス権限のみを追加します。

リソースベースのポリシーエラー(呼び出し権限)

Lambdaが別のサービス(S3、API Gateway、SNS、クロスアカウント呼び出しなど)によって呼び出される場合、そのサービスには関数を呼び出すための明示的な権限が必要です。

症状: サービス(例:S3)がLambdaをトリガーしようとしますが、CloudWatchログに何も表示されず、サービスがエラーを報告します。

修正方法:add-permission CLIコマンドまたは同等のコンソール設定を使用して、呼び出し権限を付与します。たとえば、S3バケットが関数を呼び出せるようにする場合:

aws lambda add-permission \
    --function-name my-processing-function \
    --statement-id S3InvokePermission \
    --action lambda:InvokeFunction \
    --principal s3.amazonaws.com \
    --source-arn arn:aws:s3:::my-trigger-bucket

クロスアカウント呼び出しの場合は、両側を確認します。呼び出し元には lambda:InvokeFunction を呼び出すIAM権限が必要であり、Lambda関数にはその呼び出し元を許可するリソースベースのポリシーが必要です。

設定とリソース制約エラー

これらのエラーは、定義されたランタイム環境設定と関数に課せられたリソース制限に関連しています。

関数タイムアウトエラー

関数タイムアウトは一般的な障害であり、実行が最大許容時間を超えたことを示します。Lambdaは実行を強制終了し、Task timed out エラーをログに記録します。

診断:

  1. CloudWatchログの REPORT 行を確認します。Duration と設定されたタイムアウトを比較します。
  2. 関数が早期にタイムアウトする場合(例:30秒の制限のうち5秒後)、ボトルネックは初期化または接続(例:DNSルックアップの待機)である可能性があります。

修正方法:

  • タイムアウトの増加: タスクが本質的に長時間実行される場合(例:大規模なデータ処理)、タイムアウトを増やします(最大15分)。
  • コード/依存関係の最適化: タスクが遅い場合は、コードをプロファイリングしてボトルネックを特定します。外部呼び出しには、コード内で適切なタイムアウトが定義されていることを確認します。
  • コールドスタートの処理: 大規模な初期化プロセスはタイムアウトの原因となる可能性があります。コールドスタートが重要な場合は、Lambdaのプロビジョニングされた同時実行性を使用します。

メモリ枯渇エラー

関数に割り当てられたRAMよりも多くのRAMが必要な場合、クラッシュし、ランタイムに応じて OutOfMemoryError または同様のメッセージがログに記録されます。

診断: CloudWatchの REPORT 行の Max Memory Used メトリクスを確認します。この値が一貫して設定された Memory Size に近いか等しい場合、メモリリークまたはリソース不足が発生している可能性があります。

修正方法: メモリ割り当てを増やして再テストします。メモリを多く割り当てるとLambdaはより多くのCPUを割り当てるため、メモリを増やすと実行時間が短縮され、コストの一部を相殺できる場合があります。安くなると決めつけずに、実際の関数で測定してください。

AWS Lambda Power Tuningは、特定のワークロードのメモリ設定を比較するのに役立ちます。

ハンドラーの設定ミス(Runtime.HandlerNotFound

これは、Lambdaが関数設定で定義されたエントリポイントを見つけられない場合に発生します。

症状: Error: Runtime.HandlerNotFound または同様の起動失敗。

修正方法: 関数設定のハンドラーフィールドが構造 [ファイル名].[関数名] と一致していることを確認します。たとえば、my_code.py で定義され、エントリ関数が lambda_handler であるPython関数の場合、ハンドラーを my_code.lambda_handler に設定する必要があります。

Node.jsの場合、ハンドラー名はモジュールとエクスポートされた関数に従います。たとえば、index.js でエクスポートされた handler 関数の場合は index.handler です。

ネットワーキングとVPC接続の問題

Lambda関数がVirtual Private Cloud(VPC)内で実行されるように設定されている場合、プライベートリソースにアクセスできますが、デフォルトではパブリックインターネットアクセスが失われます。

インターネットアクセスの欠如

LambdaがVPC内にあり、外部サービスに接続する必要がある場合、NATゲートウェイまたは他の承認された出口経路を介してインターネットへのルートが必要です。関数をパブリックサブネットに配置しても、パブリックIPアドレスは付与されません。

症状: HTTP接続の失敗、パブリックエンドポイントへのアクセス時のタイムアウト。

修正方法:

  1. 関数がLambdaワークロード用のプライベートサブネットにアタッチされていることを確認します。
  2. これらのプライベートサブネットに、NATゲートウェイへのアウトバウンドインターネットトラフィック(0.0.0.0/0)を指示するルートテーブルエントリがあることを確認します。
  3. LambdaがAWSサービスにのみプライベートにアクセスする必要がある場合は、S3およびDynamoDB用のゲートウェイエンドポイントや、サポートされているサービス用のインターフェイスエンドポイントなどのVPCエンドポイントを検討します。

セキュリティグループとACLの制限

関数は正常に起動できますが、そのセキュリティグループ、ターゲットセキュリティグループ、ネットワークACL、またはルートテーブルが接続をブロックするとハングする可能性があります。

修正方法:Lambdaセキュリティグループからターゲットポートへのアウトバウンドトラフィックを許可し、ターゲットセキュリティグループでLambdaセキュリティグループからのインバウンドトラフィックを許可します。たとえば、PostgreSQLに接続するLambda関数には、LambdaからのアウトバウンドTCP 5432 と、データベース側のインバウンドTCP 5432 が必要です。

実行ロールにVPCアクセスに必要なEC2ネットワークインターフェイス権限がない場合、Lambdaは関数の実行に必要なVPCネットワーキングの準備中に失敗する可能性があります。

デプロイとランタイムの設定ミス

これらの問題は、コードバンドルの構造化方法や選択されたランタイム環境に関連しています。

依存関係とパッケージエラー

コードが外部ライブラリに依存しており、それらが特定のランタイム環境用に正しくバンドルまたはインストールされていない場合、関数は初期化中に失敗します。

症状: module not foundcannot import name、または No such file or directory などのランタイム例外(PythonやNode.jsで特に一般的)。

修正方法:

  1. ローカル環境とLambda環境: Lambdaランタイムに一致する環境で依存関係をビルドします(例:Pythonの場合は pip install -t . を使用して依存関係を正しく配置します)。
  2. Lambdaレイヤーの使用: より大きく安定した依存関係をLambdaレイヤーにパッケージ化して、メインのデプロイパッケージのサイズを減らし、デプロイ速度を向上させます。
  3. パスの確認: ランタイム設定がインストールされた依存関係の場所を正しく指していることを確認します。

デプロイパッケージのサイズと形式

Lambdaにはデプロイパッケージのサイズ制限があり、その制限は、.zipファイルを直接アップロードするか、Amazon S3を介してアップロードするか、レイヤーを使用するか、コンテナイメージをデプロイするかによって異なります。大規模な関数を再構築する前に、現在のLambdaクォータをパッケージ化方法に応じて確認します。

症状: サイズエラーでデプロイが失敗するか、大きなパッケージがコールドスタートの遅延の原因になります。

修正方法:

  • 削減: 不要なファイル、ドキュメント、開発依存関係を削除します。
  • レイヤー: 静的アセットや大きな依存関係をLambdaレイヤーに移動します。
  • コンテナイメージ: 非常に大きなアプリケーションの場合は、Amazon ECRからコンテナイメージとして関数をデプロイすることを検討します。

イベントとペイロードの問題

一部の呼び出しエラーは、イベント自体に起因します。

  • 不正な形式のJSON: コンソールテストとCLI呼び出しには、有効なJSONペイロードが必要です。
  • 予期しないイベント形状: S3イベント、API Gatewayイベント、EventBridgeイベントには同じフィールドがありません。
  • 非同期再試行動作: 非同期呼び出しは、失敗後に再試行し、設定されている場合、失敗したイベントを宛先またはデッドレターキューに送信する可能性があります。

直接CLIテストの場合は、応答とログをキャプチャします。

aws lambda invoke \
    --function-name my-function \
    --payload '{"ping": true}' \
    --cli-binary-format raw-in-base64-out \
    response.json

--cli-binary-format raw-in-base64-out オプションは、AWS CLI v2でコマンドラインに生のJSONを直接渡す場合によく必要です。

トラブルシューティング手順のまとめ

呼び出しエラーが発生した場合は、次の体系的なアプローチに従います。

  1. 最初にCloudWatchを確認: START 行の前にLambdaサービスによって記録された即時エラーを探します。
  2. IAMロールを確認: 関数の実行ロールに必要なすべての権限(ログ記録、VPC、サービスアクセス)があることを確認します。
  3. 設定を確認: ハンドラー名、メモリ設定、タイムアウト制限を確認します。
  4. VPC設定を分析: VPCを使用している場合は、セキュリティグループ、サブネットマッピング、ルートテーブル(特にNATゲートウェイアクセス)を確認します。
  5. 依存関係を調査: 必要なすべてのライブラリが正しくパッケージ化され、ランタイムからアクセス可能であることを確認します。

失敗が呼び出し前、ランタイム起動中、コード内のいずれで発生したかがわかれば、修正はより絞り込まれます。最初にログを確認し、アクティブなIAM IDとリソースポリシーを証明してから、表示される特定のエラーに基づいて、ハンドラー、パッケージ、タイムアウト、メモリ、VPC設定を調整します。