0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Lambda の Metadata API で AZ 情報を取得してみた

0
Posted at

はじめに

今回は 2026/3/19 に発表された以下のアップデートを試してみます。

AWS Lambda に新しく Metadata API が追加されました。

Lambda 関数が実行されている Availability Zone(AZ)の情報を取得できるようになっています。

正直なところ、Lambda に Metadata API があること自体を知りませんでした。
EC2 にはインスタンスメタデータがありますが、Lambda にも似た仕組みがあったんですね。

せっかくなので AZ 情報だけでなくメタデータを丸ごと出力して中身を確認してみました。

取得方法は「直接 API を呼び出す方法」と「Powertools for AWS Lambda を使う方法」の 2 パターンで試しています。

この記事で学べること

  • AWS Lambda Metadata API の概要と仕組み
  • 直接 API を呼び出してメタデータを取得する方法
  • Powertools for AWS Lambda(TypeScript)を使ってメタデータを取得する方法
  • メタデータのレスポンス内容
  • AWS CDK でのデプロイ方法

前提知識・条件

  • 動作確認時の各ライブラリのバージョンは以下のとおり
ライブラリ バージョン
AWS CDK 2.x
Node.js ランタイム 22.x
@aws-lambda-powertools/commons 2.17.0
TypeScript 5.9.3

Lambda Metadata API とは

AWS Lambda のドキュメントを確認してみます。

The Lambda metadata endpoint lets your functions discover which Availability Zone (AZ) they are running in, enabling you to optimize latency by routing to same-AZ resources like Amazon ElastiCache and Amazon RDS endpoints, and to implement AZ-aware resilience patterns.

Lambda 関数がどの AZ で動いているかを検出できるエンドポイントとのことです。
同一 AZ のリソースへルーティングすることでレイテンシを最適化したり、AZ を意識した回復パターンを実装したりできる模様ですね。

仕組みとしては、Lambda の実行環境内に用意されたローカルの HTTP エンドポイントにリクエストを送ることでメタデータを取得します。

以下の 2 つの環境変数が Lambda の実行環境に自動で設定されています。

環境変数 説明
AWS_LAMBDA_METADATA_API メタデータサーバーのアドレス(例: 169.254.100.1:9001
AWS_LAMBDA_METADATA_TOKEN 認証用のトークン。リクエスト時に Bearer トークンとして使用

エンドポイントは以下の形式です。

GET http://${AWS_LAMBDA_METADATA_API}/2026-01-15/metadata/execution-environment

認証は Authorization: Bearer ${AWS_LAMBDA_METADATA_TOKEN} ヘッダーで行います。SSRF 対策としてトークンベースの認証が採用されているとのことです。

AZ ID について

ここで返却される AZ の情報は「AZ ID」(例: use1-az1)です。

普段よく目にする AZ 名(例: us-east-1a)とは異なり、AZ ID はすべての AWS アカウントで同じ物理的なロケーションを指します。

AZ 名はアカウントによって異なる物理インフラにマッピングされることがあるので、クロスアカウントで一貫性のある識別をする際に便利ですね。

詳しくは以下のページに記載があります。

やってみた

では、順を追って作っていきます!

1. Lambda 関数の作成(直接 API 呼び出し)

まずは Metadata API を直接呼び出す方法です。

handler-direct.ts
const METADATA_ENDPOINT_PATH = '/2026-01-15/metadata/execution-environment';

let cachedMetadata: Record<string, unknown> | undefined;

export const handler = async () => {
  if (!cachedMetadata) {
    const metadataApi = process.env.AWS_LAMBDA_METADATA_API;
    const metadataToken = process.env.AWS_LAMBDA_METADATA_TOKEN;

    if (!metadataApi || !metadataToken) {
      throw new Error(
        'AWS_LAMBDA_METADATA_API and AWS_LAMBDA_METADATA_TOKEN environment variables are required',
      );
    }

    const url = `http://${metadataApi}${METADATA_ENDPOINT_PATH}`;
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${metadataToken}` },
    });

    if (!res.ok) {
      throw new Error(`Metadata API returned ${res.status}: ${res.statusText}`);
    }

    cachedMetadata = (await res.json()) as Record<string, unknown>;
  }

  return {
    statusCode: 200,
    body: JSON.stringify({
      method: 'direct',
      metadata: cachedMetadata,
    }),
  };
};

ポイントを簡単に説明します。

  • AWS_LAMBDA_METADATA_APIAWS_LAMBDA_METADATA_TOKEN は Lambda が自動で設定してくれる
  • cachedMetadata でキャッシュしている。ドキュメントにも Cache-Control: private, max-age=43200, immutable と記載あり。実行環境内ではレスポンスが不変なのでキャッシュして問題ない
  • AZ ID だけでなく、レスポンス全体(metadata)をそのまま返すようにしている。中身が気になったので!

2. Lambda 関数の作成(Powertools 版)

次に Powertools for AWS Lambda(TypeScript)を使った方法です。

handler-powertools.ts
import { getMetadata } from '@aws-lambda-powertools/commons/utils/metadata';

export const handler = async () => {
  const metadata = await getMetadata();

  return {
    statusCode: 200,
    body: JSON.stringify({
      method: 'powertools',
      metadata,
    }),
  };
};

こちらはかなりシンプルです。getMetadata() を呼ぶだけで、環境変数の取得やトークンの付与をすべて Powertools が面倒を見てくれます。

さらに getMetadata() は内部でキャッシュも持っているので、複数回呼んでも実際の API リクエストは 1 回だけです。
直接呼び出し版のように自前でキャッシュ変数を用意する必要もありません。

直接呼び出しと比較すると、コード量がかなり少なくなりますね。

また、Lambda SnapStart を利用している場合、スナップショットからの復元時に AZ の変更もあり得ます。
Powertools はこのケースでもキャッシュを自動で無効化し、最新のメタデータを再取得してくれます。

自前で実装する場合は「復元されたらキャッシュを捨てて再取得する」ロジックを書く必要があるので、便利ですね。

最後に簡単な比較表も作っておきました。

観点 直接呼び出し Powertools
コード量 多い(エンドポイント構築、認証ヘッダー設定、エラーハンドリングが必要) 少ない(getMetadata() のみ)
キャッシュ 自分で実装が必要 自動で対応
SnapStart 対応 自分で考慮が必要 自動で対応
依存パッケージ なし @aws-lambda-powertools/commons が必要

3. CDK でデプロイ

次にAWS CDK でデプロイします。2 つの Lambda 関数を作成するスタックです。

cdk-stack.ts
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import * as cdk from 'aws-cdk-lib/core';
import type { Construct } from 'constructs';
import * as path from 'node:path';

const LAMBDA_AZ_METADATA_DIR = path.join(__dirname, '../../lambda-az-metadata');

export class LambdaAvailabilityZoneMetadataStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const powertoolsFn = new NodejsFunction(this, 'AzMetadataPowertools', {
      entry: path.join(LAMBDA_AZ_METADATA_DIR, 'handler-powertools.ts'),
      handler: 'handler',
      runtime: Runtime.NODEJS_22_X,
      timeout: cdk.Duration.seconds(10),
    });

    const directFn = new NodejsFunction(this, 'AzMetadataDirect', {
      entry: path.join(LAMBDA_AZ_METADATA_DIR, 'handler-direct.ts'),
      handler: 'handler',
      runtime: Runtime.NODEJS_22_X,
      timeout: cdk.Duration.seconds(10),
    });

    new cdk.CfnOutput(this, 'AzMetadataPowertoolsFunctionArn', {
      value: powertoolsFn.functionArn,
    });

    new cdk.CfnOutput(this, 'AzMetadataDirectFunctionArn', {
      value: directFn.functionArn,
    });
  }
}

特別な設定は不要で、NodejsFunction で Lambda を作成するだけです。

最初は Metadata API 用の IAM ポリシーが必要かな?とも思ったのですが、実行環境内のローカルエンドポイントなので不要でした。

4. 実行結果を確認してみる

デプロイ後、それぞれの Lambda 関数を実行してみます。

直接呼び出し版のレスポンスです。

{
  "statusCode": 200,
  "body": "{\"method\":\"direct\",\"metadata\":{\"AvailabilityZoneID\":\"apne1-az4\"}}"
}

Powertools 版のレスポンスです。

{
  "statusCode": 200,
  "body": "{\"method\":\"powertools\",\"metadata\":{\"AvailabilityZoneID\":\"apne1-az4\"}}"
}

どちらも同じ AvailabilityZoneID が返ってきました。今回は apne1-az4(東京リージョンの AZ4)で実行されていますね。

メタデータの中身を全部出力してみたところ、現時点では AvailabilityZoneID のみ返却されている模様です。
もっといろいろ入っているかと期待していたのですが、今のところはこれだけみたいですね。
ドキュメントにも以下の記載がありました。

Additional fields may be added to the response in future updates. Clients should ignore unknown fields and not fail if new fields appear.

今後フィールドの追加もあり得るとのことです。
今のうちからレスポンス全体を柔軟に扱えるようにしておくとよさそうですね。

5. 複数回実行してみる

同じ関数を短期間で複数回実行してみると、同じ AZ ID が返ってきます。

これは実行環境(コンテナ)が再利用されている間は同じ AZ で動作するためです。

キャッシュも効いているので、2 回目以降は Metadata API へのリクエストも発生しません。

しばらく時間を空けて実行することで、 AZ IDが変わることも確認しました。

まとめ

AWS Lambda の Metadata API を使って AZ 情報を取得する方法を 2 パターンで試してみました。

  • Lambda Metadata API は 2026/3/19 にリリースされた新機能で、追加コストなしで利用可能
  • 直接 API を呼び出す方法と、Powertools for AWS Lambda を使う方法がある
  • Powertools を使うとコードがかなりシンプルになる(キャッシュや SnapStart 対応も自動)
  • 現時点のレスポンスには AvailabilityZoneID のみ含まれている。今後フィールドの追加予定あり
  • AZ ID はアカウント間で一貫した物理ロケーションを指すので、クロスアカウントでの AZ 指定に便利

AZ 情報を取得できるようになったことで、同一 AZ 内のリソースへのルーティングなど、レイテンシを意識したアーキテクチャも Lambda で実現しやすくなりそうです。

今回のソースコードは以下に格納していますので、もしよかったらどうぞ!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?