💡

Lambda container images で New Relic の Lambda Layer を使う

2021/08/30に公開

前提

New Relic で Lambda の APM を使うには、以下ドキュメントの通り Lambda Extensions(Layer) を使う必要があります
しかし、Lambda container images では Lambda Layer の機能を使うことができません
https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/enable-lambda-monitoring/instrument-your-own/

解決策として、以下 AWS ブログに記載がある通り、Lambda Layer で動作させるスクリプトファイルを Container image 内に配置する必要があります
https://aws.amazon.com/jp/blogs/news/working-with-lambda-layers-and-extensions-in-container-images/

CDK を使って New Relic の Lambda Layer を有効にした Nodejs runtime の Lambda をデプロイする方法

ディレクトリ構成

CDK のディレクトリ構成はかなり簡略化しますが、以下のような内容になります

.
├── Lambda
│   ├── Dockerfile
│   ├── index.js
│   ├── layer
│   │   └── newrelic.zip
│   ├── node_modules
│   ├── package-lock.json
│   └── package.json
├── bin
│   └── cdk-bot.ts
├── lib
│   └── cdk-stack.ts
└── node_modules

今回は Lambda ディレクトリ配下に、Lambda で利用するスクリプトファイルと Container image 用の Dockerfile を配置します
また、layer ディレクトリを作成し、その中に New Relic の Lambda Layer で利用されるアプリケーションを zip ファイルに固めて配置しました

なお、New Relic の Lambda Layer で利用されるアプリケーションは上述の AWS ブログを参考に以下のコマンドを利用して zip ファイルにしており、New Relic の Lambda Layer の ARN は https://layers.newrelic-external.com/ のサイトにて確認します

curl $(aws lambda get-layer-version-by-arn --arn arn:aws:lambda:ap-northeast-1:451483290750:layer:NewRelicNodeJS14X:21 --query 'Content.Location' --output text) --output newrelic.zip

Lambda

Lambda はシンプルに index.js を利用します

Dockerfile

index.js や package*.json は cp でディレクトリにコピーします
また、New Relic の Lambda Layer として利用する newrelic.zip は、AWS ブログを参考にコピーして /opt ディレクトリ配下に解凍して配置します

FROM amazon/aws-lambda-nodejs:14
RUN yum install -y unzip
COPY index.js package*.json layer/newrelic.zip ./
RUN npm install

RUN mkdir -p /opt
RUN unzip newrelic.zip -d /opt
RUN rm newrelic.zip

CMD [ "newrelic-lambda-wrapper.handler" ]

なお、handler は New Relic のドキュメントに記載がある通り newrelic-lambda-wrapper.handler とします
https://docs.newrelic.com/docs/serverless-function-monitoring/aws-lambda-monitoring/enable-lambda-monitoring/instrument-your-own/

Update your function's handler to point to the newly attached layer in the console for your function:

~ SNIP ~
Node: newrelic-lambda-wrapper.handler (hyphens)

CDK

CDK で Lambda container images のデプロイを行うには、DockerImageFunction クラスが利用できます
fromImageAsset で Lambda 用の Dockerfile があるディレクトリを指定します
https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.DockerImageFunction.html

const nodejsFunction = new lambda.DockerImageFunction(this, "nodejsFunction", {
      code: lambda.DockerImageCode.fromImageAsset("Lambda"),
      memorySize: 128,
      logRetention: logs.RetentionDays.ONE_WEEK,
      environment: {
        NEW_RELIC_LAMBDA_EXTENSION_ENABLED: 'true',
        NEW_RELIC_LAMBDA_HANDLER: 'index.handler',
        NEW_RELIC_ACCOUNT_ID: 'xxxxx'
      },
    });

あとはいつもどおり CDK をデプロイすれば New Relic の Lambda Layer で利用するアプリケーションが内包された Lambda container images がデプロイされます

Discussion