AWS Lambda ベースのサーバーレスオブザーバビリティと OpenTelemetry
このガイドでは、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 レイヤーの紹介
- ADOT Lambda レイヤーを使用した Lambda 関数の自動計装
- ADOT Collector のカスタム設定サポート
- Amazon Managed Service for Prometheus (AMP) との統合
- ADOT Lambda レイヤー使用の長所と短所
- 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 で実行ログとトレースを表示する例を見てみましょう。
-
ドキュメント に従って、
ランタイム
、リージョン
、アーキテクチャタイプ
に基づいて 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 関数にレイヤーを追加します。
- AWS コンソールの場合 、手順 に従って Lambda 関数にレイヤーを追加します。「ARN を指定」で、上記で選択したレイヤー ARN を貼り付けます。
- IaC オプションの場合、Lambda 関数の SAM テンプレートは次のようになります:
Layers:
- !Sub arn:aws:lambda:${AWS::Region}:901920570463:layer:aws-otel-java-agent-arm64-ver-1-28-1:1 -
Lambda 関数に環境変数を追加します。Node.js または Java の場合は
AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler
、Python の場合はAWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument
を追加します。 -
Lambda 関数のアクティブトレースを有効にします。
注意
デフォルトでは、レイヤ ーは 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 がトリガーとして設定されている場合)呼び出します。例えば、API を介して Lambda 関数を呼び出す(
curl
を使用)と、以下のようなログが生成されます:
curl -X GET https://XXXXXX.execute-api.us-east-1.amazonaws.com/Prod/listBuckets
Lambda 関数のログ:
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
...
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 コンソールに移動し、トレースの下でトレース ID を選択します。以下のようなトレースマップとセグメントタイムラインが表示されるはずです:
ADOT Collector のカスタム設定サポート
ADOT Lambda レイヤーは、OpenTelemetry SDK と ADOT Collector コンポーネントの両方を組み合わせています。ADOT Collector の設定は OpenTelemetry 標準に従っています。デフォルトでは、ADOT Lambda レイヤーは config.yaml を使用し、テレメトリデータを AWS X-Ray にエクスポートします。しかし、ADOT Lambda レイヤーは他のエクスポーターもサポートしており、メトリクスとトレースを他の宛先に送信することができます。カスタム設定でサポートされている利用可能なコンポーネントの完全なリストはこちらで確認できます。
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 コレクター設定ファイルのサンプル:
#ルートディレクトリにある collector.yaml
#環境変数 'OPENTELEMETRY_COLLECTOR_CONFIG_FILE' を '/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]
Prometheus Remote Write Exporter は、リトライとタイムアウトの設定も構成できます。詳細については、ドキュメント を参照してください。注意
sigv4auth
拡張機能のサービス値は aps
(amazon prometheus service) である必要があります。また、Lambda 関数の実行ロールに必要な AMP 権限があることを確認してください。AWS Lambda の AMP に必要な権限とポリシーの詳細については、AWS Managed Service for Prometheus の ドキュメント を参照してください。
- 環境変数
OPENTELEMETRY_COLLECTOR_CONFIG_FILE
を追加し、設定ファイルのパスを値として設定します。例:/var/task/<設定ファイルへのパス>
.yaml。これにより、Lambda Layer 拡張機能にコレクター設定の場所を指示します。
Function:
Type: AWS::Serverless::Function
Properties:
...
Environment:
Variables:
OPENTELEMETRY_COLLECTOR_CONFIG_FILE: /var/task/collector.yaml
- OpenTelemetry Metrics API を使用してメトリクスを追加するように Lambda 関数コードを更新します。こちらの例を参照してください。
// メーターを取得
Meter meter = GlobalOpenTelemetry.getMeterProvider()
.meterBuilder("aws-otel")
.setInstrumentationVersion("1.0")
.build();
// カウンターを構築(例:LongCounter)
LongCounter counter = meter
.counterBuilder("processed_jobs")
.setDescription("Processed jobs")
.setUnit("1")
.build();
// API ユーザーが記録する属性への参照を保持することをお勧めします
Attributes attributes = Attributes.of(stringKey("Key"), "SomeWork");
// データを記録
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 を使用する方が適している場合があります。詳細な比較と適切なトレースツールの選択に関するガイダンスについては、AWS ドキュメントの ADOT と X-Ray SDK の選択 を参照してください。
ADOT 使用時のコールドスタートレイテンシーの管理
Java 用の ADOT Lambda レイヤーはエージェントベースです。つまり、自動計装を有効にすると、Java エージェントは OTel のサポートされているすべてのライブラリを計装しようとします。これにより、Lambda 関数のコールドスタートレイテンシーが大幅に増加します。そのため、アプリケーションで使用されているライブラリやフレームワークに対してのみ自動計装を有効にすることをお勧めします。
特定の計装のみを有効にするには、以下の環境変数を使用できます:
OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED
:false に設定すると、レイヤーでの自動計装が無効になり、各計装を個別に有効にする必要があります 。OTEL_INSTRUMENTATION_<NAME>_ENABLED
:特定のライブラリやフレームワークの自動計装を有効にするには true に設定します。「NAME」を有効にしたい計装に置き換えてください。利用可能な計装のリストについては、特定のエージェント計装の抑制を参照してください。
例えば、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 レイヤーについて説明し、AWS Lambda 関数を計測する方法を紹介しました。 簡単な設定で自動計測を有効にし、ADOT コレクターをカスタマイズして複数の宛先にオブザーバビリティシグナルを送信する方法を説明しました。 ADOT の使用に関する長所と短所を強調し、Lambda 関数のコールドスタートレイテンシーにどのような影響を与えるかを説明し、コールドスタート時間を管理するためのベストプラクティスも推奨しました。 これらのベストプラクティスを採用することで、アプリケーションを一度だけ計測し、ベンダーに依存しない方法で複数の監視ソリューションにログ、メトリクス、トレースを送信することができます。
さらに深く掘り下げるために、AWS One Observability Workshop の AWS マネージドオープンソースオブザーバビリティモジュールを実践することを強くおすすめします。