Skip to content

3-shake/spring_cloud_function_dd_sample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

spring_cloud_function_dd_sample

Spring Cloud Function(Java 21)+ Datadog APM 対応の AWS Lambda サンプルです。 コンテナイメージ運用と ZIP 配布の両方に対応しています。

このリポジトリは社内検証用に実際の動作環境を模倣して作成したサンプルアプリです。 関連する社内プロジェクト情報は以下の Notion ページを参照してください。

プロジェクトページ(社内限)

主なファイル

  • src/main/java/com/example/LambdaHandlerApplication.java : 関数本体(手動スパン付きと自動計測の2種類を提供)
  • src/main/java/com/example/ItemRepository.java : DBアクセスの共通インターフェース
  • src/main/java/com/example/JdbcSecretsManagerRepository.java : jdbc-secretsmanager を使う実装
  • src/main/java/com/example/HandlerManagedSecretRepository.java : ハンドラ内で Secrets Manager を明示実行する実装
  • src/main/java/com/example/JdbcSecretsManagerConfig.java : jdbc モード時だけ DataSource / JdbcTemplate を組み立てる設定
  • build.gradle : Gradle ビルド設定
  • Dockerfile : マルチステージ。builder で Gradle ビルドし、runner に成果物と Datadog を同梱

Secrets Manager 呼び出し方式

Secrets の取得方式は 2 つあり、設定で切り替えできます。

背景として、jdbc-secretsmanager は Spring の DataSource 初期化や接続取得のタイミングで Secrets Manager を呼び出すため、Datadog 上では Secrets Manager のスパンが Lambda ハンドラの子スパンにならないことがあります。これに対して、ハンドラ内で GetSecretValue を明示実行する方式では、Secrets Manager の呼び出しをハンドラ配下の子スパンとして観測しやすくなります。

このサンプルでは、通常の JDBC 運用に近い構成を維持したい場合と、Secrets Manager の呼び出し位置を Datadog 上で明確にしたい場合の両方を比較できるように、2 つのモードを用意しています。

  • jdbc : jdbc-secretsmanager を利用します。Secrets Manager 呼び出しはハンドラ外で発生することがあります。
  • handler : ハンドラ内で GetSecretValue を明示実行します。Datadog 上で Lambda ハンドラの子スパンに載せたい場合はこちらを使います。

設定ファイルはモード別に分けています。

  • src/main/resources/application.properties : 共通設定
  • src/main/resources/application-jdbc.properties : jdbc モード用
  • src/main/resources/application-handler.properties : handler モード用

起動時は SPRING_PROFILES_ACTIVE で切り替えます。

# jdbc-secretsmanager を使う
SPRING_PROFILES_ACTIVE=jdbc

# ハンドラ内で Secrets Manager を明示実行する
SPRING_PROFILES_ACTIVE=handler

profile 未指定時は jdbc がデフォルトです。

jdbchandler はどちらも同じアプリ接続用 Secret を参照します。

  • jdbc : spring.datasource.username=rds/postgres/sample/credentials
  • handler : app.db.secret-id=rds/postgres/sample/credentials

この Secret は RDS が自動管理するマスター認証情報 Secret とは別に運用する前提です。

jdbc モードの流れ

jdbc モードでは、Spring 起動時に jdbc profile の Bean が選ばれ、関数実行時は JdbcSecretsManagerRepository が利用されます。Secrets Manager 呼び出し自体は jdbc-secretsmanager ドライバ内部で発生します。

sequenceDiagram
    participant APIGW as API Gateway
    participant FI as FunctionInvoker
    participant SB as Spring Boot
    participant CFG as JdbcSecretsManagerConfig
    participant REPO as JdbcSecretsManagerRepository
    participant JT as JdbcTemplate
    participant DS as DataSource
    participant DRV as jdbc-secretsmanager driver
    participant SM as Secrets Manager
    participant PG as PostgreSQL

    Note over SB: load application.properties
    Note over SB: load application-jdbc.properties
    Note over SB: activate profile jdbc
    SB->>CFG: create config beans
    CFG->>DS: create HikariDataSource
    CFG->>JT: create JdbcTemplate
    SB->>REPO: create JdbcSecretsManagerRepository
    SB->>FI: inject ItemRepository(jdbc)

    APIGW->>FI: invoke Lambda
    FI->>REPO: findById(id)
    REPO->>JT: queryForList(...)
    JT->>DS: getConnection()
    DS->>DRV: open connection
    DRV->>SM: GetSecretValue
    DRV->>PG: connect
    JT->>PG: execute SQL
    PG-->>JT: rows
    JT-->>REPO: rows
    REPO-->>FI: rows
Loading

handler モードの流れ

handler モードでは、Spring 起動時に handler profile の Bean が選ばれ、関数実行時は HandlerManagedSecretRepository が利用されます。Secrets Manager 呼び出しはアプリケーションコード内で明示実行されます。

sequenceDiagram
    participant APIGW as API Gateway
    participant FI as FunctionInvoker
    participant SB as Spring Boot
    participant REPO as HandlerManagedSecretRepository
    participant SM as Secrets Manager
    participant DS as DriverManagerDataSource
    participant JT as JdbcTemplate
    participant PG as PostgreSQL

    Note over SB: load application.properties
    Note over SB: load application-handler.properties
    Note over SB: activate profile handler
    SB->>REPO: create HandlerManagedSecretRepository
    SB->>FI: inject ItemRepository(handler)

    APIGW->>FI: invoke Lambda
    FI->>REPO: findById(id)
    REPO->>SM: GetSecretValue
    REPO->>DS: create DataSource
    REPO->>JT: create JdbcTemplate
    JT->>PG: connect
    JT->>PG: execute SQL
    PG-->>JT: rows
    JT-->>REPO: rows
    REPO-->>FI: rows
Loading

使い分けの実務上の目安

  • jdbc : 既存の jdbc-secretsmanager 構成を維持したいとき
  • handler : Secrets Manager の呼び出しを Datadog で Lambda ハンドラ配下の子スパンとして確認したいとき
  • 切り分け目的で接続失敗の内訳を見たい場合も handler の方が追いやすいです

ビルド&プッシュ(コンテナイメージ)

※ Lambda を arm64 で使う想定。x86_64 の場合は --platform linux/amd64 を付けてください。

DOCKER_BUILDKIT=0 docker build -t <ECR-URI>:latest .
docker push <ECR-URI>:latest

(Dockerfile 内で gradle clean jar copyRuntimeLibs を実行するため、事前にローカルでビルドする必要はありません)

ZIP 配布で Lambda にアップする場合

  1. ラッパーがない場合は作成(Gradleがインストール済みなら wrapper を省略して gradle でも可)
    gradle wrapper --gradle-version 8.10.2 --distribution-type=bin
    chmod +x gradlew
  2. ZIP を生成
    gradle clean lambdaZip
    生成物: build/distributions/spring_cloud_function_dd_sample-0.1.0-lambda.zip
  3. Lambda にコード更新(ZIP)
    aws lambda update-function-code \
      --function-name <FUNCTION_NAME> \
      --region <REGION> \
      --zip-file fileb://build/distributions/spring_cloud_function_dd_sample-0.1.0-lambda.zip
  4. Lambda 設定
    • ランタイム: Java 21
    • ハンドラ: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
    • 環境変数: Datadog (例) AWS_LAMBDA_EXEC_WRAPPER=/opt/datadog_wrapper, DD_API_KEY, DD_SITE など
    • DB接続モードを切り替える場合は SPRING_PROFILES_ACTIVE=jdbc または SPRING_PROFILES_ACTIVE=handler
    • (レイヤー運用する場合は dd-trace-java と Datadog-Extension をアーキテクチャに合わせて追加)

関数の実行方法(手動確認)

AWS CLI で直接 invoke します。--cli-binary-format raw-in-base64-out を付けて JSON を渡してください。

aws lambda invoke \
  --function-name <FUNCTION_NAME> \
  --region <REGION> \
  --cli-binary-format raw-in-base64-out \
  --payload '{"queryStringParameters":{"id":"1"}}' \
  /tmp/out.json

cat /tmp/out.json

レスポンス例: {"id":1,"found":true,"item":{"id":1,"name":"alpha","status":"active"}}

Lambda コンソールから手動実行する場合も、queryStringParameters.id を含むイベントを渡してください。id が無いと DB 問い合わせや Secrets Manager 呼び出しまで進みません。

Lambda 設定(コンテナイメージ)

  • イメージURI: 上記でプッシュした ECR イメージ
  • ハンドラ: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
  • 環境変数(例)
    • AWS_LAMBDA_EXEC_WRAPPER=/opt/datadog_wrapper
    • SPRING_PROFILES_ACTIVE=jdbc または SPRING_PROFILES_ACTIVE=handler
    • DD_SITE=datadoghq.com
    • DD_API_KEY(本番では Secrets 等で注入)
    • 必要に応じて DD_SERVICE DD_ENV など

Datadog

  • Datadog Java Agent と Extension は Dockerfile で /opt に同梱済み。
  • アーキテクチャは Lambda に合わせて arm64 を使用。

動作確認のヒント

  • タイムアウト/メモリは十分に確保(例: 1024MB / 15s 以上)
  • イメージに依存JARと本体JARが含まれているかは docker run --rm --entrypoint "" <image> sh -c 'ls /var/task/lib' で確認できます。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors