本ブログでは、AWS Lambdaにコンテナイメージ(Python3.9)を展開し、実行されている環境にAgentを計装して頂く方法を紹介いたします。
前提
- Pythonやコンテナについて基本的な知識がある。
- AWSのCLIを利用する環境がすでに設定されている。
- Serverlessを利用する環境が行われている。
自動計装される内容の確認
まず、コンテナではない通常のRuntimeに計装した場合に、どのような差分が発生するかを確認します。
そのためにserverlessを使って、簡単なLambda関数を使います。
簡単なLambda関数の作成と展開
まず、任意のフォルダで以下のコマンドを実行し、Serverlessを使って簡単なLambda関数を作成します。
npm install --save-dev serverless-newrelic-lambda-layers
すると、実行フォルダにテンプレートからサンプルのプロジェクトが作成されます。基本的には、そのまま展開しても良いですが、awsのリージョンのみ設定します。serverless.ymlを開いて以下のようにリージョンを追加してください。なお、YAMLなのでインデントが正しくつけれられるよう注意してください。
# you can overwrite defaults here
# stage: dev
# region: us-east-1
region: ap-northeast-1 #Tokyoリージョンを設定
続いて、以下のコマンドで展開します。
sls deploy
ServerlessやAWS CLIが利用できるように設定済みであれば、問題なくAWSのアカウントに展開されるかと思います。
続いてSAMファイルをダウンロードします。展開されたLambda関数をAWSのコンソール上で表示し、画面右上のDownloadから「Download AWS SAM file」をクリックしダウンロードします。するとyamlファイルが取得できます。
New Relicを計装して、差分を確認する
続いて、計装するためにNew Relicへログインし、画面左側の「+ Add Data」から「Monitor your Lambda functions」のタイルを選択します。
続いて、最初の設問に回答します。今回は、以下のようにしています。
設問 | 回答 |
---|---|
設問Serverlessの利用 | 回答Yes |
設問Node or Python or Java8.al2 or Java11ランタイムの利用 | 回答Yes |
設問Extension経由かCloudwatchLogs経由のどちらを利用するか | 回答Lambda Extension |
続いて表示されるガイドに従い計装し、再度 sls deploy
コマンドを使って展開し、SAMファイルを再度ダウンロードします。
続いて、計装前のSAMファイルと計装後のSAMファイルを比較してみましょう。
すると、上の画像のようにいくつか差分が確認できます。確認できる点としては、上から順に以下の4つになると思います。
- Handler関数が「newrelic_lambda_wrapper.handler」に変更されている
- 「NEW_RELIC_」で始まる環境変数がいくつか追加されている
- LayersにNew Relicのレイヤーが追加されている
- Policiesにシークレットから値を読み取る権限が追加されている
4つ目のシークレットへの権限に関して、お客様の環境に対象のシークレットが自動的に追加されているはずです。初めて展開される場合は、AWSのCloudFormationを確認していただくと、「NewRelicLicenseKeySecret」というStackがあり、こちらでシークレットが追加されています。こちらからライセンスキーを読み取るための権限になります。なお、すでに展開されている場合は、それが自動的に、再利用されます。
これで、差分の取得が終わったのでサンプルのLambda関数は不要となります。削除は以下のコマンドで実施していただけます。
sls remove
では、取得できた差分を使って対象のLambdaコンテナーへ計装していきましょう。
Lambdaコンテナーに計装する
今回のサンプルで利用するコンテナの内容は非常にシンプルで、以下のDockerfileとapp.pyのみの構成となっています。こちらに計装していきます。
# Dockerfile
FROM public.ecr.aws/lambda/python:3.9
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.handler" ]
# app.py
import sys
def handler(event, context):
return 'Hello from AWS Lambda using Python' + sys.version + '!'
# Dockerfile
FROM public.ecr.aws/x6n7b2o2/newrelic-lambda-layers-python:39 AS layer
FROM public.ecr.aws/lambda/python:3.9
COPY --from=layer /opt/ /opt/
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.handler" ]
内容としては、2行目でLayerを取り込み、5行目でそれを/opt/にコピーしているだけになります。
これでコンテナ側の修正は完了したので、ECRに展開し、対象のLambda関数のImageを更新してください。
続いて、Lambdaの設定の変更です。まず、差分の1つ目にあった、Handlerの書き換えを行います。こちらは、対象のLambda関数のImage configurationにて上書きできます。元のapp.pyを確認していただくと、CMDでapp.handlerを指定しているので、CMD overrideで newrelic_lambda_wrapper.handler
を設定して下さい。
これで、Lambdaの実行環境から呼び出されるハンドラーがNew Relicのハンドラーに上書きされました。元のハンドラーはNew RelicのLayerから呼び出される必要がありますが、こちらはLambdaの環境変数にて設定します。
続いて差分2つ目の環境変数を設定します。各変数名及び値は、以下のように設定してください。基本的には最初に取得した計装後の環境変数と同じで問題ありません(ハンドラー関数を除く)
環境変数名 | 値 |
---|---|
環境変数名NEW_RELIC_ACCOUNT_ID | 値(対象のLambdaの観測データをインジェストするNew RelicのアカウントID) |
環境変数名NEW_RELIC_TRUSTED_ACCOUNT_KEY | 値(親アカウントID(対象の組織のrootアカウントID)) |
環境変数名NEW_RELIC_APP_NAME | 値(New Relic上で表示するアプリ名) |
環境変数名NEW_RELIC_LAMBDA_HANDLER | 値(Layerから呼び返す元のハンドラー関数) |
環境変数名NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS | 値true |
環境変数名NEW_RELIC_NO_CONFIG_FILE | 値true |
環境変数名NEW_RELIC_SERVERLESS_MODE_ENABLED | 値true |
続いて最後の差分です。LambdaのRoleにシークレットへアクセスするためのポリシーを追加します。差分として取得できた内容で、シークレットのARNが確認できると思います。以下のように対象のLambda関数のRoleへ対象シークレットへGetSecretValueのActionを実行する権限を付与してください。
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:<region>:<account>:secret:NEW_RELIC_LICENSE_KEY-<ランダム文字列>"
]
}
以上で設定は完了です。Lambda関数を実行して、問題なく実行できるかなど確認してみてください。問題なければNew RelicのAll EntitiesのLambda functionsにて対象の関数のデータをご確認いただくことができると思います。
なお、今回の設定では、Extensionの利用が有効になっています。Extensionを有効にした場合、対象のLambda関数から直接New Relicへデータを送信します。対象のLambda関数が配置されているVPCがインターネットへアクセスできる必要があることご注意ください。インターネットアクセスを許可することができない場合は、Extensionを利用しない方法にて計装を行ってください。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。