Closed31

Ruby で実装した Lambda 関数 を CDK でデプロイして動作させるメモ

snakasnaka

CDK でさくっとデプロイしたは良いが、依存する Gem がインストールされていない

Lambda 関数内で以下の Gem を利用しているが、それがデプロイ対象に入っていないらしい?

https://github.com/mikel/mail

{
    "errorMessage": "cannot load such file -- mail",
    "errorType": "Init<LoadError>",
    "stackTrace": [
        "<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
        "<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
        "/var/task/mail_receiver.rb:3:in `<top (required)>'",
        "<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
        "<internal:/var/lang/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:136:in `require'",
        "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:48:in `run'",
        "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:221:in `bootstrap_handler'",
        "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:203:in `start'",
        "/var/runtime/index.rb:4:in `<main>'"
    ]
}
snakasnaka

解決してくれそうな Construct Library がある

https://github.com/hanazuki/cdk-lambda-ruby

snakasnaka

If a file named "Gemfile" exists directly inside sourceDirectory, the dependency gems are bundled using Bundler. Bundling is performed inside a Docker container using the Lambda builder images privided by AWS. The bundlerConfig prop may have the without field to specify a colon-separated list of gem groups to skip installation.

snakasnaka

Error: GitIgnoreStrategy expects an absolute file path

cdk diff したらなんかエラーが

snakasnaka

スタックトレース(一部改変済み)

Error: Failed to bundle asset SesMailRecieverStack/MailHandler/MailHandler/Code/Stage, bundle output is located at /Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.2a38ebf16e8e97acb132dd55f881188a8e0022a6b0601a8f29315cdbc825511e-error: Error: GitIgnoreStrategy expects an absolute file path
    at AssetStaging.bundle (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:2:619)
    at AssetStaging.stageByBundling (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:5297)
    at stageThisAsset (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:2728)
    at Cache.obtain (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/private/cache.js:1:242)
    at new AssetStaging (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:3125)
    at new Asset (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-s3-assets/lib/asset.js:1:1141)
    at AssetCode.bind (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/code.js:5:3487)
    at new Function (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/function.js:1:9422)
    at new RubyFunction (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/cdk-lambda-ruby/lib/function.ts:32:5)
    at new MailHandler (/Users/hogehoge/cdk-example/hoge-cdk/ses-mail-reciever/lib/mail_handler.ts:23:20)

メッセージは

Error: GitIgnoreStrategy expects an absolute file path
snakasnaka

ここの sourceDirectory が絶対パスでなければならないということかもしれない

    this.handler = new lambdaRuby.RubyFunction(this, 'MailHandler', {
      runtime: lambda.Runtime.RUBY_3_3,
      handler: 'mail_receiver.lambda_handler',
      sourceDirectory: 'lambda',
    });
snakasnaka

以下のような修正でこのエラーは解消した

-    sourceDirectory: 'lambda',
+    sourceDirectory: path.join(__dirname, '../lambda'),
snakasnaka

bundler のワーニング

Your bundle only supports platforms ["arm64-darwin-22"] but your local platform
is aarch64-linux. Add the current platform to the lockfile with
`bundle lock --add-platform aarch64-linux` and try again.
snakasnaka

bundle lock --add-platform aarch64-linux

を実行したら Gemfile.lock が以下のように修正された

 PLATFORMS
+  aarch64-linux
   arm64-darwin-22
snakasnaka

Error: docker exited with status 16

なんか Docker Image のビルドで落ちた?

Error: Failed to bundle asset SesMailRecieverStack/MailHandler/MailHandler/Code/Stage, bundle output is located at /Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.7cd5b91369ef89105a48c551878b2fb6010786cb95f1fa0d7e3f2eb4284e1f11-error: Error: docker exited with status 16
--> Command: docker run --rm -u "501:20" -v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.7cd5b91369ef89105a48c551878b2fb6010786cb95f1fa0d7e3f2eb4284e1f11:/asset-output:delegated" -v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/.cache/lambda-ruby:/asset-cache:delegated" --env "BUNDLING_OUTPUT_DIR=/asset-output" --env "BUNDLING_CACHE_DIR=/asset-cache" --env "BUNDLE_WITHOUT=development:test" -w "/asset-output" "public.ecr.aws/sam/build-ruby3.3" "/bin/sh" -euc "export HOME=$(mktemp -d)\n\nexport MAKEFLAGS=-j$(nproc)\n\nexport BUNDLE_USER_CACHE=$BUNDLING_CACHE_DIR/bundler\nexport BUNDLE_CLEAN=true\nexport BUNDLE_DEPLOYMENT=true\nexport BUNDLE_GLOBAL_GEM_CACHE=true\nexport BUNDLE_PATH=vendor/bundle\nexport BUNDLE_RETRY=3\n\nif test -f Gemfile; then\n  bundle config set --local deployment \"$BUNDLE_DEPLOYMENT\"\n  bundle config set --local path \"$BUNDLE_PATH\"\n  bundle config set --local without \"$BUNDLE_WITHOUT\"\n  exec bundle install\nelse\n  exec rm -rf vendor/bundle\nfi\n"
    at AssetStaging.bundle (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:2:619)
    at AssetStaging.stageByBundling (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:5297)
    at stageThisAsset (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:2728)
    at Cache.obtain (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/private/cache.js:1:242)
    at new AssetStaging (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:3125)
    at new Asset (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-s3-assets/lib/asset.js:1:1141)
    at AssetCode.bind (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/code.js:5:3487)
    at new Function (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/aws-cdk-lib/aws-lambda/lib/function.js:1:9422)
    at new RubyFunction (/Users/cdk-example/hoge-cdk/ses-mail-reciever/node_modules/cdk-lambda-ruby/lib/function.ts:32:5)
    at new MailHandler (/Users/cdk-example/hoge-cdk/ses-mail-reciever/lib/mail_handler.ts:24:20)
snakasnaka

cdk-lambda-ruby 使うと Docker Image もビルドするようになってる?

そのあたりの挙動の違いも気になる

snakasnaka

README.md に書いていた

Bundling is performed inside a Docker container using the Lambda builder images privided by AWS.

snakasnaka

実行された docker コマンド

docker run --rm -u "501:20" \
-v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/asset.7cd5b91369ef89105a48c551878b2fb6010786cb95f1fa0d7e3f2eb4284e1f11:/asset-output:delegated" \
-v "/Users/cdk-example/hoge-cdk/ses-mail-reciever/cdk.out/.cache/lambda-ruby:/asset-cache:delegated" \
--env "BUNDLING_OUTPUT_DIR=/asset-output" \
--env "BUNDLING_CACHE_DIR=/asset-cache" \
--env "BUNDLE_WITHOUT=development:test" \
-w "/asset-output" \
"public.ecr.aws/sam/build-ruby3.3" "/bin/sh" -euc
"export HOME=$(mktemp -d)

export MAKEFLAGS=-j$(nproc)

export BUNDLE_USER_CACHE=$BUNDLING_CACHE_DIR/bundler
export BUNDLE_CLEAN=true
export BUNDLE_DEPLOYMENT=true
export BUNDLE_GLOBAL_GEM_CACHE=true
export BUNDLE_PATH=vendor/bundle
export BUNDLE_RETRY=3

if test -f Gemfile; then
  bundle config set --local deployment \"$BUNDLE_DEPLOYMENT\"
  bundle config set --local path \"$BUNDLE_PATH\"
  bundle config set --local without \"$BUNDLE_WITHOUT\"
  exec bundle install
else
  exec rm -rf vendor/bundle
fi
"
snakasnaka

動作結果の確認

Lambda のコンソールを見て vendor/bundle に gem などが格納されていることを確認した

snakasnaka

Gemfile に gem を追加したらエラーになる

試しに "prawn" を追加してみた

diff --git a/ses-mail-reciever/lambda/Gemfile b/ses-mail-reciever/lambda/Gemfile
index 91579df..bb56f49 100644
--- a/ses-mail-reciever/lambda/Gemfile
+++ b/ses-mail-reciever/lambda/Gemfile
@@ -4,3 +4,4 @@ source "https://rubygems.org"
 
 gem "mail"
 gem 'jwt'
+gem 'prawn'

すると cdk diff でエラーになった

You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.

If this is a development machine, remove the /asset-output/Gemfile freeze 
by running `bundle config unset deployment`.

The dependencies in your gemfile changed

You have added to the Gemfile:
* prawn
snakasnaka

原因

bundle install 実行していないため、GemfileGemfile.lockの整合性が取れていない状態だった。

対応

Gemfile を更新したら ./lambda ディレクトリで以下を実行することで Gamfile.lock を更新する

bundle install
snakasnaka

Error: Cannot retrieve value from context provider key-provider since account/region are not specified at the stack level.

cdk diff を実行すると以下のようなエラー

Error: Cannot retrieve value from context provider key-provider since account/region are not specified at the stack level. Configure "env" with an account and region when you define your stack.See https://docs.aws.amazon.com/cdk/latest/guide/environments.html for more details.
snakasnaka

原因

環境変数 AWS_PROFILE などの設定が抜けていた

対応

環境変数など AWS CLI が動作する状態にする

このスクラップは5ヶ月前にクローズされました