tl;dr

外部モジュールはrequirements.txtにfreezeしてソースファイルと同じディレクトリに配置する。

handlerはeventcontextを受け取るので引数を用意する。

Dynamodb等Lambda関数の実行時にAWSの他のサービスを使用する場合、IAMロールへの権限付与を行う。

FunctionNameはCDKで管理する場合、名前が変動するので環境変数からきちんと渡す。

失敗例

  • CDKを用いてLambda関数をデプロイした時、必要な外部モジュールが見つからずエラーになっていた。 requirements.txtcdk.jsonと同様のルートディレクトリに配置していたが、deploy時にモジュールのインストールが行われなかった。

  • handlerが呼び出されたとき、引数の個数でエラーが送出された。

  • Lambdaから他のLambdaがInvokeできない

対処

CDKを用いてLambda関数をデプロイするときのモジュール

requirements.txtはstackで指定したentryと同じディレクトリを探索するので同じ場所に配置する必要がある。

1
2
3
4
5
6
7
8
9
const getFeedLambdaFunc = new PythonFunction(this, 'getFeedFunc', {
      entry: './src/getFeed/',
      timeout: cdk.Duration.seconds(180),
      runtime: Runtime.PYTHON_3_7,
      index: 'lambda_getFeed.py',
      environment: {'RSSSOURCE_TABLENAME': rssSourceTableName,
                    'UPDATEFUNC_NAME': updateArticleLambdaFunc.functionName
    }
    });

handlerが呼び出されたとき引数の個数でエラーになる

Lambda関数が呼び出されたときhandlerにはeventcontextが渡される。

eventにはLambda関数を呼び出したイベントから渡されたデータが格納され、contextにはAWSの環境情報(ロググループ、実行されている関数のバージョン等)が格納される。

参照するかの有無に関わらず、2つの引数を受ける必要があるので注意する。

LambdaからLambdaのInvokeができない

開発中非常に詰まった点、

stack内では

1
B_LambdaFunc.grantInvoke(A_LambdaFunc)

とすることでAがBを実行する権限を得ることができる。

A_LambdaFuncからの呼び出しは次のように行っていた。

1
2
3
4
5
invoke_response = boto3.client('lambda').invoke(
            FunctionName="B_LambdaFunc", # wrong
            InvocationType='Event',
            Payload=Payload
        )

このように呼び出すと、CloudWatch Logsには以下のようにエラーが残る。

no identity-based policy allows the lambda:InvokeFunction action

エラーを見る限りではidentity-basedでは許可されない→Resource-basedにすればいいのでは?

という考えに陥るのだが、実際にはFunctionNameが間違っていることから起こっているエラーのため権限を見直してもエラーは改善されない。

stack側のA_LambdaFuncを定義する段階で

1
environment: {'FUNC_NAME': B_LambdaFunc.functionName}

のように環境変数としてfunctionNameを渡して利用するのが正解だった。 2時間溶かした

結論

Docsはちゃんと読もう