OpenTelemetry を使用した Lambda ベースのサーバーレスアプリケーションのオブザーバビリティ¶
このガイドでは、AWS X-RayやAmazon CloudWatchなどのネイティブな AWS モニタリングサービスとともに、マネージドなオープンソースのツールとテクノロジーを使用して、Lambda ベースのサーバーレスアプリケーションのオブザーバビリティを設定するためのベストプラクティスをカバーします。 AWS Distro for OpenTelemetry(ADOT)、AWS X-Ray、Amazon Managed Service for Prometheus(AMP)などのツールと、これらのツールを使用してサーバーレスアプリケーションについての実行可能なインサイトを取得し、問題をトラブルシューティングし、アプリケーションのパフォーマンスを最適化する方法について説明します。
カバーする主要トピック¶
このオブザーバビリティのベストプラクティスガイドのセクションでは、次のトピックを深掘りします。
- AWS Distro for OpenTelemetry(ADOT) と ADOT Lambda Layer の概要
- ADOT Lambda Layer を使用した Lambda 関数の自動計装
- ADOT Collector のカスタム構成のサポート
- Amazon Managed Service for Prometheus(AMP) との統合
- ADOT Lambda Layer 使用の長所と短所
- ADOT 使用時のコールドスタート待ち時間の管理
AWS Distro for OpenTelemetry(ADOT)の概要¶
AWS Distro for OpenTelemetry(ADOT) は、Cloud Native Computing Foundation(CNCF)のOpenTelemetry(OTel) プロジェクトのセキュアで実稼働準備が整った AWS サポート付きディストリビューションです。ADOT を使用することで、アプリケーションに一度だけインスツルメンテーションを適用し、相関したメトリクスとトレースを複数のモニタリングソリューションに送信できます。
AWS のマネージド OpenTelemetry Lambda Layer は、OpenTelemetry Lambda Layer を利用して、AWS Lambda から非同期的にテレメトリデータをエクスポートします。AWS Lambda 関数をラップし、OpenTelemetry ランタイム固有の SDK、ADOT コレクターのトリムダウンバージョンをパッケージ化することで、プラグアンドプレイなユーザーエクスペリエンスを提供します。この際、AWS Lambda 関数の自動インスツルメンテーションのためのアウトオブザボックスの構成が施されます。ADOT Lambda Layer コレクターコンポーネントである Receivers、Exporters、Extensions は、Amazon CloudWatch、Amazon OpenSearch Service、Amazon Managed Service for Prometheus、AWS X-Ray などとの統合をサポートしています。完全なリストはこちらをご覧ください。ADOT はパートナーソリューションとの統合もサポートしています。
ADOT Lambda Layer は、自動インスツルメンテーション(Python、NodeJS、Java 用)と、特定のライブラリや SDK セットのカスタムインスツルメンテーションの両方をサポートしています。自動インスツルメンテーションの場合、デフォルトで Lambda Layer がトレースを AWS X-Ray にエクスポートするように構成されます。カスタムインスツルメンテーションの場合は、対応するライブラリインスツルメンテーションをそれぞれの OpenTelemetry ランタイムインスツルメンテーションレポジトリ から含め、コード内で関数での初期化を行う必要があります。
AWS Lambda での ADOT Lambda レイヤーを使用した自動計装¶
コード変更なしで、ADOT Lambda レイヤーを使用して Lambda 関数の自動計装を簡単に有効にできます。 既存の Java ベースの Lambda 関数に ADOT Lambda レイヤーを追加し、CloudWatch で実行ログとトレースを表示する例を見ていきましょう。
runtime
、region
、arch type
に基づいて、ドキュメント の Lambda レイヤーの ARN を選択します。 Lambda レイヤーは Lambda 関数と同じリージョンで使用するようにしてください。 たとえば、Java の自動計装用 Lambda レイヤーはarn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-agent-x86_64-ver-1-28-1:1
です。- コンソールまたは IaC を使用して、Lambda 関数にレイヤーを追加します。
- コンソールを使用する場合は、手順に従って Lambda 関数にレイヤーを追加します。 ARN を指定 に上記で選択したレイヤー ARN を貼り付けます。
- IaC オプションの場合、Lambda 関数の SAM テンプレートは次のようになります。
- Node.js または Java の場合は
AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler
、Python の場合はAWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument
という環境変数を Lambda 関数に追加します。 - Lambda 関数でアクティブトレーシングを有効にします。
Note
デフォルトでは、レイヤーはトレースを AWS X-Ray にエクスポートするように構成されています。 Lambda 関数の実行ロールに必要な AWS X-Ray アクセス許可があることを確認してください。 AWS Lambda の AWS X-Ray アクセス許可の詳細については、AWS Lambda ドキュメントを参照してください。Tracing: Active
- Lambda レイヤー構成、環境変数、X-Ray トレースを使用した SAM テンプレートの例は次のようになります。
Resources: ListBucketsFunction: Type: AWS::Serverless::Function Properties: Handler: com.example.App::handleRequest ... ProvisionedConcurrencyConfig: ProvisionedConcurrentExecutions: 1 Policies: - AWSXrayWriteOnlyAccess - AmazonS3ReadOnlyAccess Environment: Variables: AWS_LAMBDA_EXEC_WRAPPER: /opt/otel-handler Tracing: Active Layers: - !Sub arn:aws:lambda:${AWS::Region}:901920570463:layer:aws-otel-java-agent-amd64-ver-1-28-1:1 Events: HelloWorld: Type: Api Properties: Path: /listBuckets Method: get
- AWS X-Ray でのトレースのテストと可視化
Lambda 関数を直接または API (トリガーとして構成されている場合) 経由で呼び出します。 たとえば、API 経由で Lambda 関数を呼び出すと、次のようなログが生成されます (
curl
を使用)。 Lambda 関数のログ:
INIT_START Runtime Version: java:11.v23 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:d8547b2b4b9c3a87d99a42a8197838256f11e0afe5f7ce2d58e4574f4e6cf50d
{level:info,msg:Launching OpenTelemetry Lambda extension,version:v0.32.0}
{level:info,logger:telemetryAPI.Listener,msg:Listening for requests,address:sandbox:53612}
{level:info,logger:telemetryAPI.Client,msg:Subscribing,baseURL:http://127.0.0.1:9001/2022-07-01/telemetry}
{level:info,logger:telemetryAPI.Client,msg:Subscription success,response:\OK\}
{level:info,caller:service/telemetry.go:84,msg:Setting up own telemetry...}
{level:info,caller:service/telemetry.go:201,msg:Serving Prometheus metrics,address:localhost:8888,level:Basic}
{level:info,caller:exporter@v0.82.0/exporter.go:275,msg:Development component. May change in the future.,kind:exporter,data_type:metrics,name:logging}
{level:info,caller:service/service.go:132,msg:Starting aws-otel-lambda...,Version:v0.32.0,NumCPU:2}
{level:info,caller:extensions/extensions.go:30,msg:Starting extensions...}
{level:info,caller:otlpreceiver@v0.82.0/otlp.go:83,msg:Starting GRPC server,kind:receiver,name:otlp,data_type:traces,endpoint:localhost:4317}
{level:info,caller:otlpreceiver@v0.82.0/otlp.go:101,msg:Starting HTTP server,kind:receiver,name:otlp,data_type:traces,endpoint:localhost:4318}
{level:info,caller:service/service.go:149,msg:Everything is ready. Begin running and processing data.}
Picked up JAVA_TOOL_OPTIONS: -javaagent:/opt/opentelemetry-javaagent.jar
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
[otel.javaagent 2023-09-24 15:28:16:862 +0000] [main] INFO io.opentelemetry.javaagent.tooling.VersionLogger - opentelemetry-javaagent - version: 1.28.0-adot-lambda1-aws
EXTENSION Name: collector State: Ready Events: [INVOKE, SHUTDOWN]
START RequestId: ed8f8444-3c29-40fe-a4a1-aca7af8cd940 Version: 3
...
Event### {resource: /listBuckets,path: /listBuckets/,httpMethod: GET,headers: {Accept=*/*, CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, CloudFront-Viewer-ASN=7224, CloudFront-Viewer-Country=US, Host=yf0ukeu0sg.execute-api.us-east-1.amazonaws.com, User-Agent=curl/8.1.2, Via=2.0 31341771a4bfa40d7b1f61883ffb56c6.cloudfront.net (CloudFront), X-Amz-Cf-Id=ooZO2eehCAwGzPW0nq6NKOwKLQGBkmhtuFCzsRhyCISbnex6c45Jcw==, X-Amzn-Trace-Id=Root=1-65105691-384f7da75714148655fa631b, X-Forwarded-For=15.248.0.124, 15.158.50.42, X-Forwarded-Port=443, X-Forwarded-Proto=https},multiValueHeaders: {Accept=[*/*], CloudFront-Forwarded-Proto=[https], CloudFront-Is-Desktop-Viewer=[true], CloudFront-Is-Mobile-Viewer=[false], CloudFront-Is-SmartTV-Viewer=[false], CloudFront-Is-Tablet-Viewer=[false], CloudFront-Viewer-ASN=[7224], CloudFront-Viewer-Country=[US], Host=[yf0ukeu0sg.execute-api.us-east-1.amazonaws.com], User-Agent=[curl/8.1.2], Via=[2.0 31341771a4bfa40d7b1f61883ffb56c6.cloudfront.net (CloudFront)], X-Amz-Cf-Id=[ooZO2eehCAwGzPW0nq6NKOwKLQGBkmhtuFCzsRhyCISbnex6c45Jcw==], X-Amzn-Trace-Id=[Root=1-65105691-384f7da75714148655fa631b], X-Forwarded-For=[15.248.0.124, 15.158.50.42], X-Forwarded-Port=[443], X-Forwarded-Proto=[https]},requestContext: {accountId: 681808143105,resourceId: 7xxz9z,stage: Prod,requestId: 56c8c9ad-3d8d-4f20-aed1-bcef03b5e8e4,identity: {sourceIp: 15.248.0.124,userAgent: curl/8.1.2,},resourcePath: /listBuckets,httpMethod: GET,apiId: yf0ukeu0sg,path: /Prod/listBuckets/,},isBase64Encoded: false}
...
END RequestId: ed8f8444-3c29-40fe-a4a1-aca7af8cd940
REPORT RequestId: ed8f8444-3c29-40fe-a4a1-aca7af8cd940 Duration: 5144.38 ms Billed Duration: 5145 ms Memory Size: 1024 MB Max Memory Used: 345 MB Init Duration: 27769.64 ms
XRAY TraceId: 1-65105691-384f7da75714148655fa631b SegmentId: 2c52a147021ebd20 Sampled: true
ログからわかるように、OpenTelemetry Lambda 拡張機能は opentelemetry-javaagent を使用して Lambda 関数の計装とリスニングを開始し、AWS X-Ray でトレースを生成します。
上記の Lambda 関数呼び出しからのトレースを表示するには、AWS X-Ray コンソールに移動し、[Traces] の下のトレース ID を選択します。 次のようなトレースマップとセグメントタイムラインが表示されるはずです。
ADOT Collector のカスタム設定のサポート¶
ADOT Lambda Layer は、OpenTelemetry SDK と ADOT Collector のコンポーネントを組み合わせています。ADOT Collector の設定は OpenTelemetry 標準に従います。デフォルトでは、ADOT Lambda Layer は config.yaml を使用し、これはテレメトリデータを AWS X-Ray にエクスポートします。ただし、ADOT Lambda Layer は他のエクスポーターもサポートしているため、メトリクスとトレースを他のデスティネーションに送信することもできます。カスタム設定でサポートされている利用可能なコンポーネントの完全なリストはこちら を参照してください。
Amazon Managed Service for Prometheus(AMP) との統合¶
カスタムコレクター設定を使用して、Lambda 関数からメトリクスを Amazon Managed Prometheus(AMP)にエクスポートできます。
- 自動計測のステップに従って、Lambda レイヤーを構成し、環境変数
AWS_LAMBDA_EXEC_WRAPPER
を設定します。 - Lambda 関数がメトリクスを送信する先となる、AWS アカウント内に Amazon Managed Prometheus ワークスペースを作成 します。AMP ワークスペースから
Endpoint - remote write URL
をメモします。これは、ADOT コレクター設定で設定する必要があります。 -
Lambda 関数のルートディレクトリに、前のステップの AMP エンドポイントリモートライト URL の詳細を含むカスタム ADOT コレクター設定ファイル(collector.yaml など)を作成します。設定ファイルは S3 バケットから読み込むこともできます。 ADOT コレクター設定ファイルのサンプル:
Prometheus リモートライトエクスポーターは、再試行とタイムアウトの設定でも構成できます。詳細は、ドキュメント を参照してください。#collector.yaml in the root directory #Set an environemnt variable 'OPENTELEMETRY_COLLECTOR_CONFIG_FILE' to '/var/task/collector.yaml' extensions: sigv4auth: service: "aps" region: "<workspace_region>" receivers: otlp: protocols: grpc: http: exporters: logging: prometheusremotewrite: endpoint: "<workspace_remote_write_url>" namespace: test auth: authenticator: sigv4auth service: extensions: [sigv4auth] pipelines: traces: receivers: [otlp] exporters: [awsxray] metrics: receivers: [otlp] exporters: [logging, prometheusremotewrite]
注
sigv4auth 拡張機能のサービス値は aps (Amazon Prometheus Service) である必要があります。また、Lambda 関数の実行ロールに必要な AMP アクセス許可があることを確認してください。AWS Lambda 用の AMP で必要なアクセス許可とポリシーの詳細は、Amazon Managed Service for Prometheus のドキュメントを参照してください。 -
環境変数
OPENTELEMETRY_COLLECTOR_CONFIG_FILE
を追加し、設定ファイルへのパスを値として設定します。例: /var/task/<config file="" path="">
.yaml。これにより、Lambda レイヤー拡張機能がコレクター設定を見つける場所が指示されます。 - Lambda 関数のコードを更新して、OpenTelemetry メトリクス API を使用してメトリクスを追加します。こちらの例を確認してください。
// get meter Meter meter = GlobalOpenTelemetry.getMeterProvider() .meterBuilder("aws-otel") .setInstrumentationVersion("1.0") .build(); // Build counter e.g. LongCounter LongCounter counter = meter .counterBuilder("processed_jobs") .setDescription("Processed jobs") .setUnit("1") .build(); // It is recommended that the API user keep a reference to Attributes they will record against Attributes attributes = Attributes.of(stringKey("Key"), "SomeWork"); // Record data counter.add(123, attributes);
ADOT Lambdaレイヤーの使用のメリットとデメリット¶
Lambda関数からAWS X-Rayにトレースを送信する場合、X-Ray SDK または AWS Distro for OpenTelemetry(ADOT) Lambdaレイヤー を使用できます。X-Ray SDKは、さまざまなAWSサービスの計装を容易にサポートしていますが、トレースをX-Rayにのみ送信できます。一方、Lambdaレイヤーの一部として含まれているADOTコレクターは、各言語の多数のライブラリの計装をサポートしています。これを使用して、メトリクスとトレースをAWS X-RayやAmazon CloudWatch、Amazon OpenSearch Service、Amazon Managed Service for Prometheusなどの他のモニタリングソリューションに収集および送信できます。
ただし、ADOTが提供する柔軟性のため、Lambda関数で追加のメモリが必要になり、コールドスタートのレイテンシに顕著な影響が生じる可能性があります。したがって、低レイテンシーを最適化しているLambda関数でOpenTelemetryの高度な機能を必要としていない場合は、ADOTよりもAWS X-Ray SDKを使用する方が適している場合があります。詳細な比較と適切なトレースツールの選択のためのガイダンスについては、ADOTとX-Ray SDKの選択に関するAWSドキュメントを参照してください。
ADOT を使用する際のコールドスタート待ち時間の管理¶
Java 用の ADOT Lambda Layer はエージェントベースであるため、自動計測を有効にすると、Java エージェントは OTel でサポートされているすべてのライブラリを計測しようとします。これにより、Lambda 関数のコールドスタート待ち時間が大幅に増加します。したがって、アプリケーションで使用されているライブラリ/フレームワークのみ自動計測を有効にすることをおすすめします。
特定の計測のみを有効にするには、次の環境変数を使用できます:
OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED
: false に設定すると、Layer の自動計測が無効になり、各計測を個別に有効にする必要があります。OTEL_INSTRUMENTATION_<name>_ENABLED
: 特定のライブラリまたはフレームワークの自動計測を有効にするには true に設定します。を有効にする計測で置き換えます。使用可能な計測のリストについては、特定のエージェント計測の抑制を参照してください。
たとえば、Lambda と AWS SDK の自動計測のみを有効にするには、次の環境変数を設定します:
OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=false
OTEL_INSTRUMENTATION_AWS_LAMBDA_ENABLED=true
OTEL_INSTRUMENTATION_AWS_SDK_ENABLED=true
その他のリソース¶
まとめ¶
このオブザーバビリティのベストプラクティスガイドでは、オープンソーステクノロジを使用した AWS Lambda ベースのサーバレスアプリケーションのためのものです。AWS Distro for OpenTelemetry (ADOT) と Lambda Layer の概要と、AWS Lambda 関数にインスツルメンテーションを行う方法をカバーしました。自動インスツルメンテーションを簡単に有効にできることと、シンプルな設定で ADOT コレクタをカスタマイズして、複数のデスティネーションにオブザーバビリティ シグナルを送信できることを説明しました。ADOT の利点と欠点を強調表示し、Lambda 関数のコールドスタート待ち時間にどのような影響があるかを説明するとともに、コールドスタート時間を管理するためのベストプラクティスも推奨しました。これらのベストプラクティスを採用することで、アプリケーションを一度だけインスツルメンテーションして、ログ、メトリクス、トレースを複数のモニタリング ソリューションにベンダーに依存しない方法で送信できます。
より深い分析のために、AWS One Observability ワークショップ の AWS マネージド オープンソース Observability モジュールを実践することを強くおすすめします。