Lambda Extension による Python 関数性能監視

はじめに

2020年10月にプレビューとなった AWS Lambda Extensions により,コード変更なしに Lambda 関数の AppDynamics での監視が可能となりました。

AWS Lambda Extensions(プレビュー)を構築する

Step-by-Step Guide: Enhancing Lambda Performance Monitoring with AppDynamics | Application Performance Monitoring Blog

 

これまでは,AppDynamics Tracer SDK を用いるため Lambda 関数のコード変更が必要でしたが, AppDynamics Extension Layer を追加することによりコード変更なしでモニタリング可能となりました。

本記事では,AWS SAM CLI を用いて Lambda 関数のテスト/デプロイ, AppDynamics による性能監視を試してみます。

AppDynamics Lambda Extension 利用前提条件

  • Node.js 10+, Python 3.6+ で書かれた Lambda 関数がインストゥルメント可能
  • Serverless APM for AWS Lambda subscription へサブスクライブ済み
  • AppDynamics SaaS Controller : バージョン 4.5.11 以降が利用可能

 

利用可能な AWS リージョン

2020年12月時点では,以下のAWSリージョンで Lambda Extension 経由での性能監視が可能です。

  • ap-northeast-1 (東京)
  • ap-northeast-2 (ソウル)
  • ap-south-1
  • ap-southeast-1
  • ap-southeast-2
  • eu-central-1
  • eu-north-1
  • eu-west-1
  • eu-west-2
  • eu-west-3
  • ca-central-1
  • sa-east-1
  • us-east-1
  • us-east-2
  • us-west-1

 

インストゥルメント手順公式ドキュメント

2020年12月時点で英語版のみとなりますが,Extension を用いた Lambda 関数のインストゥルメント手順の公式ドキュメントはこちらになります。

Use the AppDynamics AWS Lambda Extension to Instrument Serverless APM at Runtime – AppDynamics Documentation

以下にインストゥルメント手順を解説いたします。

Serverless APM for AWS Lambda subscription へサブスクライブ

以下の手順で Serverless APM for AWS Lambda subscription のサブスクライブを行います。

  1. Serverless APM for AWS Lambda subscription から Continue to Subscribe をクリック
  2. Subscribe をクリック
  3. Set Up Your Account をクリック
  4. AppDynamics SaaS コントローラURL/コントローラアクセスキーを入力

サブスクリプションの確認は AWS Marketplace > Manage subscriptions から行うことができます。

AWS SAM CLI による Lambda 関数のデプロイと AppDynamics Extension インストゥルメント

今回は AWS マネジメントコンソールを極力用いず,AWS SAM CLI を用いて監視対象の Lambda 関数のデプロイを行ってみます。AWS SAM CLI のインストールをされていない方は以下のリンクからご自分の利用環境に合わせてインストールを事前に行ってください。

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html

template.yaml の編集

SAM のテンプレートを編集し,Layers に 以下のように ARN,

arn:aws:lambda:ap-northeast-1:716333212585:layer:appdynamics-lambda-extension:9 を設定します(東京リージョンの場合)。利用リージョンが異なる場合は ap-northeast-1 を適宜変更してください。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: AppDynamics Lambda extension
Resources:
  Function:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.8
      CodeUri: code
      Handler: app.lambda_handler
      MemorySize: 128
      Timeout: 3
      Environment:
        Variables:
          APPDYNAMICS_CONTROLLER_HOST: your-account.saas.appdynamics.com
          APPDYNAMICS_SERVERLESS_API_ENDPOINT: 'https://syd-sls-agent-api.saas.appdynamics.com'
          APPDYNAMICS_ACCOUNT_NAME: your-account
          APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY: your-access-key
          APPDYNAMICS_APPLICATION_NAME: your-application
          APPDYNAMICS_TIER_NAME: your-tier
          AWS_LAMBDA_EXEC_WRAPPER: /opt/appdynamics-extension-script
      Layers:
        - >-
          arn:aws:lambda:ap-northeast-1:716333212585:layer:appdynamics-lambda-extension:9

各環境変数はご利用の AppDynamics コントローラへのアクセス情報,アプリケーション名,Tier名に適宜置き換えてください。なお,アクセスキーは SaaS コントローラ の右上の歯車アイコン – License – Account で確認することができます。

サンプル Python コード

今回は以下の非常にシンプルなサンプルコードを用います。ifconfig.io に GET リクエストを送り,グローバル IP アドレスを取得します。

import urllib.request

def lambda_handler(event, context):
    url = 'https://ifconfig.io/'
    req = urllib.request.Request(url)
    req.add_header("User-Agent", 'curl')
    with urllib.request.urlopen(req) as res:
        body = res.read()
        return {
            'statusCode': 200,
            'body': body.decode().strip()
        }

このスクリプトは code/app.py として保存しておきます。

ビルド

今回は Python 3.8 Runtime を用いますが,ローカル環境で 正常に SAM から Python 3.8 を実行できない場合は(Python 2.7 との競合等),sam build -u でDocker コンテナを利用することにより抽象化/仮想化することができます。

$ sam build -u
Starting Build inside a container
Building codeuri: code runtime: python3.8 metadata: {} functions: ['SampleFunction']

Fetching amazon/aws-sam-cli-build-image-python3.8 Docker container image......
Mounting /Users/foo/sample_app/code as /tmp/samcli/source:ro,delegated inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

 

ローカルテスト実行

sam local invoke でローカルテストを実行することができます。

$ sam local invoke
Invoking app.lambda_handler (python3.8)
arn:aws:lambda:ap-northeast-1:716333212585:layer:appdynamics-lambda-extension:9 is already cached. Skipping download
Skip pulling image and use local one: samcli/lambda:python3.8-f00964ae55accef74c51e9ff8.

Mounting /Users/foo/sample_app/.aws-sam/build/SampleFunction as /var/task:ro,delegated inside runtime container
[Appdynamics wrapper script] AWS_Execution_Env is
[Appdynamics wrapper script]  not supported, running lambda with default arguments
START RequestId: db5cd0c4-3cf3-10a1-8fde-bf6711cc3df0 Version: $LATEST
END RequestId: db5cd0c4-3cf3-10a1-8fde-bf6711cc3df0
REPORT RequestId: db5cd0c4-3cf3-10a1-8fde-bf6711cc3df0 Init Duration: 241.18 ms Duration: 371.69 ms Billed Duration: 400 ms Memory Size: 128 MB Max Memory Used: 27 MB

{"statusCode":200,"body":"xx.xxx.xxx.xxx"}

 

Lambda 関数,AppDynamics Extension Layer のデプロイ

正常にグローバル IP アドレスを取得可能なことが確認できましたら,sam deploy –guided で自動デプロイを行うことができます。

$ sam deploy --guided

Configuring SAM deploy
======================

 Looking for config file [samconfig.toml] :  Found
 Reading default arguments  :  Success

 Setting default arguments for 'sam deploy'
 =========================================
 Stack Name [Python]:
 AWS Region [ap-northeast-1]:
 #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
 Confirm changes before deploy [Y/n]: y
 #SAM needs permission to be able to create roles to connect to the resources in your template
 Allow SAM CLI IAM role creation [Y/n]: y
 Save arguments to configuration file [Y/n]: y
 SAM configuration file [samconfig.toml]:
 SAM configuration environment [default]:

 Looking for resources needed for deployment: Found!

  Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxx
  A different default S3 bucket can be set in samconfig.toml

 Saved arguments to config file
 Running 'sam deploy' for future deployments will use the parameters saved above.
 The above parameters can be changed by modifying samconfig.toml
 Learn more about samconfig.toml syntax at
 https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

 Deploying with following values
 ===============================
 Stack name                 : Python
 Region                     : ap-northeast-1
 Confirm changeset          : True
 Deployment s3 bucket       : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxx
 Capabilities               : ["CAPABILITY_IAM"]
 Parameter overrides        : {}
 Signing Profiles           : {}

Initiating deployment
=====================

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------
Operation                         LogicalResourceId                 ResourceType                      Replacement
-------------------------------------------------------------------------------------------------------------------------------------
+ Add                             SampleFunctionRole                AWS::IAM::Role                    N/A
+ Add                             SampleFunction                    AWS::Lambda::Function             N/A
-------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:679382613873:changeSet/samcli-deploy1606793756/cda913e6-946d-4713-b0b2-71c816716825

Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2020-12-01 12:36:12 - Waiting for stack create/update to complete

CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                    ResourceType                      LogicalResourceId                 ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                AWS::IAM::Role                    SampleFunctionRole                -
CREATE_IN_PROGRESS                AWS::IAM::Role                    SampleFunctionRole                Resource creation Initiated
CREATE_COMPLETE                   AWS::IAM::Role                    SampleFunctionRole                -
CREATE_IN_PROGRESS                AWS::Lambda::Function             SampleFunction                    -
CREATE_IN_PROGRESS                AWS::Lambda::Function             SampleFunction                    Resource creation Initiated
CREATE_COMPLETE                   AWS::Lambda::Function             SampleFunction                    -
CREATE_COMPLETE                   AWS::CloudFormation::Stack        Python                               -
-------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - Python in ap-northeast-1

 

AWS CLI によるLambda 関数の実行

aws lambda list-functions –query Functions[].FunctionName を実行することにより,デプロイされている Lambda 関数のリストを取得することができます。

$ aws lambda list-functions --query Functions[].FunctionName
[
    "Python-Function-123456ABCDEF"                
]

次に,以下のように aws lambda invoke により,コマンドラインから Lambda 関数を実行することが可能です。

$ aws lambda invoke --function-name Python-Function-123456ABCDEF /dev/stdout
{"statusCode": 200, "body": "xx.xxx.xxx.xxx"}
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

 

Lambda 関数実行ログの確認

sam logs コマンドで Lambda 関数のログを確認します。

sam logs -n Python-Function-123456ABCDEF

...中略...

2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:41.708000 START RequestId: e0db5107-9048-45b6-a2d6-c9e586417891 Version: $LATEST
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:41.715000 2020-12-01 04:28:41,715 AppDynamics - transaction_service.py [INFO]: Starting the business transaction.
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:42.095000 2020-12-01 04:28:42,094 AppDynamics - transaction_service.py [INFO]: Stopping the business transaction.
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:42.095000 2020-12-01 04:28:42,095 AppDynamics - event_service.py [INFO]: Total number of items in the events queue are 4
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:42.095000 2020-12-01 04:28:42,095 AppDynamics - event_service.py [INFO]: Successfully scheduled the sending of events to downstream
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:42.754000 2020-12-01 04:28:42,754 AppDynamics - http_service.py [INFO]: HTTP post request was successful for url https://syd-sls-agent-api.saas.appdynamics.com/v1/events
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:42.756000 END RequestId: e0db5107-9048-45b6-a2d6-c9e586417891
2020/12/01/[$LATEST]6e06e51410a146fab5b645091d7ce510 2020-12-01T04:28:42.756000 REPORT RequestId: e0db5107-9048-45b6-a2d6-c9e586417891    Duration: 1041.72 ms Billed Duration: 1042 ms Memory Size: 128 MB Max Memory Used: 81 MB

AppDynamics – http_service.py [INFO]: HTTP post request was successful for url https://syd-sls-agent-api.saas.appdynamics.com/v1/events を含む行が確認でき,正常にメトリックが AppDynamics SaaS プラットフォームに送信されていることが確認できます。

 

Application Flow Map の確認

AppDynamics SaaS コントローラ上で,template.yaml の APPDYNAMICS_APPLICATION_NAME で指定したアプリケーションの Application Flow Map を確認すると,以下のように Lambda 関数(Python) Tier からリモートサービスとして,ifconfig.io がコールされていることが確認できました。

 

Lambda 関数/S3 バケット/CloudFormation スタックの削除

SAM により作成した Lambda 関数,S3 バケット, CloudFormation スタックを以下のコマンドで削除することができます(Python: CloudFormation スタック名)。

aws cloudformation delete-stack --stack-name Python

 

まとめ

今回は AWS SAM CLI を用い,2020年10月に導入された AppDynamics Lambda Extension で性能監視を行う,Python で書かれた Lambda 関数のデプロイ,テストを実施しました。

Extension Layer により,従来必要であった Lambda 関数のコード変更が不要となり,より利便性が高くなったと考えます。

後藤 智

セールスエンジニア

Cisco AppDynamics

2020年に Cisco 入社。

ビジネス・オブザーバビリティ(可観測性)・ソリューション AppDynamics の技術適合性検討,導入価値検証(Proof of Value)の技術的支援(プリセールス)を担当。

View Comments

  • 2021/05/26 に Lambda Extension が GA となったようです。