継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

Amazon ECS Gateway で複数の ECS サービスを 1 つの ALB に載せて公開する手順を試したメモ✍

タダです.

ECS サービスの前段に置く ALB,証明書,セキュリティグループを ECS 側で払い出して管理してくれる Amazon ECS Gateway が発表されました.東京リージョンでゲートウェイの作成からサービスの接続を試したのでメモにまとめます.

aws.amazon.com

ECS Gateway の概要

ECS Gateway は,ECS サービスへのイングレスの設定をゲートウェイに一度書き,それを複数のサービスで共有するアカウントレベルのリソースです.サブネット,セキュリティグループ,WAF の Web ACL などを決めたゲートウェイを作ってクラスターに関連付け,アプリケーションチームはサービスにゲートウェイコネクタというパラメーターを足すだけで HTTPS の URL を得られます.

ECS が作るリソースは,ゲートウェイ単位で共有するものとサービス単位のものに分かれます.1 つの ALB をホストベースルーティングで最大 25 サービスが共有し,いっぱいになると次の ALB が追加されます.

種別 リソース
共有 ALB,リスナー,ALB のセキュリティグループ
サービス単位 ACM 証明書,DNS ホスト名,リスナールール,ターゲットグループ,サービスのセキュリティグループ

docs.aws.amazon.com

事前準備

AWS CLI 2.38.5 にして検証を行いました.

ECS が ALB や証明書を作るときに引き受けるインフラストラクチャロールも必要です.ドキュメントの手順どおり,ecs.amazonaws.com を信頼するロールに AWS 管理ポリシーの AmazonECSInfrastructureRoleForGatewayHostSharedALB を付けました.

aws iam create-role \
  --role-name ecsInfrastructureRoleForGateways \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": { "Service": "ecs.amazonaws.com" },
        "Action": "sts:AssumeRole"
      }
    ]
  }'

aws iam attach-role-policy \
  --role-name ecsInfrastructureRoleForGateways \
  --policy-arn arn:aws:iam::aws:policy/AmazonECSInfrastructureRoleForGatewayHostSharedALB

iam:PassRole が要るのはゲートウェイを作る側だけで,アプリケーションチームには ALB の作成権限も要りません.

docs.aws.amazon.com

ECS Gateway を試す

検証用にクラスター ecs-gateway-demo を作り,デフォルト VPC の 3 つのパブリックサブネット(1a,1c,1d)を使いました.

ゲートウェイの作成

create-gateway で名前,インフラストラクチャロール,ALB の設定を渡してゲートウェイを作り,associate-gateway-with-cluster でクラスターに関連付けます.

aws ecs create-gateway \
  --name demo-public-gateway \
  --infrastructure-role-arn arn:aws:iam::123456789012:role/ecsInfrastructureRoleForGateways \
  --configuration '{
    "hostSharedAlb": {
      "networkConfiguration": {
        "subnets": ["subnet-6e379519", "subnet-309e5969", "subnet-7ad68052"],
        "ipAddressType": "ipv4"
      },
      "scheme": "internet-facing"
    }
  }'

aws ecs associate-gateway-with-cluster \
  --gateway demo-public-gateway \
  --cluster ecs-gateway-demo

describe-gateway を見ると,deletionProtection が既定で true,maxAlbCount が 10,currentAlbCount が 0 でした.クラスターに関連付けても ALB は作られず,サービスが接続するまで何も作られないというドキュメントどおりの動きでした.

サービスの接続

タスク定義は nginx のコンテナのポートに web という名前を付けただけで,Fargate のサービスを --gateway-connectors 付きで作りました.

aws ecs create-service \
  --cluster ecs-gateway-demo \
  --service-name web \
  --task-definition ecs-gateway-demo-web \
  --desired-count 1 --launch-type FARGATE \
  --network-configuration 'awsvpcConfiguration={subnets=[subnet-6e379519,subnet-309e5969,subnet-7ad68052],assignPublicIp=ENABLED}' \
  --gateway-connectors '[{"portName": "web"}]'

接続状態は describe-service-revisions の ecsManagedResources.gatewayConnections で確認します.

[
    {
        "portName": "web",
        "serviceUrl": "https://we-ec25e2c719fb482db56acdf726266ac7.ecs.ap-northeast-1.on.aws",
        "accessType": "PUBLIC",
        "status": "ACTIVE",
        "resources": {
            "hostSharedAlb": [
                {
                    "acmCertificateArn": "...",
                    "loadBalancerArn": "...",
                    "listenerArn": "...",
                    "listenerRuleArn": "...",
                    "targetGroupArn": "..."
                }
            ]
        }
    }
]

ECS が作ったリソース

サービスの接続で ECS が自分のアカウントに作ったリソースを,ALB のルーティング,タスクのセキュリティグループ,タグの順に確認しました.

まず,ALB がどのようにリクエストを振り分けているかです.ALB の DNS 名を取得し,払い出された URL ではなく ALB の DNS 名に直接アクセスしてみました.

ALB_DNS=$(aws elbv2 describe-load-balancers \
  --query 'LoadBalancers[?starts_with(LoadBalancerName,`ecs-gateway`)].DNSName' --output text)
curl -sk -o /dev/null -w '%{http_code}\n' https://$ALB_DNS/

結果は 404 でした.リスナーは HTTPS の 443 番だけで,ホストヘッダーが払い出されたホスト名と一致したリクエストだけをサービスのターゲットグループへ転送し,それ以外は 404 を返すルールになっています.複数のサービスで 1 つの ALB を共有できるのは,このホスト名ごとのルールがあるためです.

次に,タスクにどのセキュリティグループが付いているかです.タスクの ENI を辿って確認しました.

TASK=$(aws ecs list-tasks --cluster ecs-gateway-demo --service-name web --query 'taskArns[0]' --output text)
ENI=$(aws ecs describe-tasks --cluster ecs-gateway-demo --tasks $TASK \
  --query 'tasks[0].attachments[0].details[?name==`networkInterfaceId`].value' --output text)
aws ec2 describe-network-interfaces --network-interface-ids $ENI --query 'NetworkInterfaces[0].Groups'

サービス作成時にセキュリティグループを指定しなかったので VPC の default が付き,そこに ECS が作ったサービス用のグループが追加されていました.

[
    { "GroupId": "sg-42980d27", "GroupName": "default" },
    { "GroupId": "sg-0e745e46104981b95", "GroupName": "ecs-gateway-service-sg-78453db0...-1" }
]

サービス用のグループは ALB からの 80 番だけを許可しますが,自分で指定したグループのルールもそのまま効きます.ALB からしか届かない状態にするには,自前のセキュリティグループ側も絞っておく必要があります.

最後にタグです.ECS が作った ALB,ターゲットグループ,セキュリティグループ,証明書には AmazonECSManaged=true と aws:ecs:gateway-arn(値はゲートウェイの ARN)のタグが付いていて,ELB や EC2 のコンソールでこのタグを使って絞り込めました.

2 つ目のサービスの接続

同じタスク定義で 2 つ目のサービス web2 を作ると,50 秒ほどで ACTIVE になりました.describe-gateway-resources を見ると同じ ALB に 2 つのルートが載っていて,currentAlbCount は 1 のままです.1 つ目との差は ALB を作るかどうかで,2 つ目以降のサービスはすぐに URL を得られるのが良いです.

アクセスタイプのフィルター

ゲートウェイコネクタは接続先のゲートウェイを名前で指定せず,アクセスタイプ,VPC,アベイラビリティーゾーンの条件を満たすゲートウェイすべてに接続します.PUBLIC のゲートウェイしかないクラスターに PRIVATE で絞ったサービスを作ると,API 呼び出しの時点で拒否されました.

aws: [ERROR]: An error occurred (InvalidParameterException) when calling the CreateService operation: gatewayConnector with portName 'web' has filters.accessTypes [PRIVATE] but none of the gateways associated with cluster arn:aws:ecs:ap-northeast-1:123456789012:cluster/ecs-gateway-demo match; associated gateway access types: [PUBLIC]

逆にフィルターを省略すると両方が対象になるので,あとからインターネット向けのゲートウェイがクラスターに関連付けられると,次のデプロイでサービスが公開されます.公開してはいけないサービスは PRIVATE で絞っておくべきです.

docs.aws.amazon.com

料金と対応リージョン

ECS Gateway 自体は追加料金なしで,ALB やデータ転送など作られたリソースの分だけ課金されます.商用リージョンすべてで利用できます.

まとめ

Amazon ECS Gateway でゲートウェイの作成からサービスの接続を東京リージョンで試しました.

Amazon Bedrock AgentCore Runtime の microVM のことを簡単に整理して試したメモ✍

タダです.

Amazon Bedrock AgentCore Runtime は,はセッションごとに microVM を起動してエージェントを動かします.microVM で簡単なプログラムを動かしたメモをまとめます.

docs.aws.amazon.com

microVM によるセッション分離

InvokeAgentRuntime に runtimeSessionId を渡すと,初回の呼び出しでそのセッション専用の microVM が起動し,以降同じセッション ID の呼び出しは同じ microVM に届きます.microVM 同士は CPU,メモリ,ファイルシステムが分離されていて,セッション終了時に microVM ごと破棄され,メモリも消去されます.

セッションの状態は以下の 3 つです.

  • Active:同期リクエストの処理中か,ping で HealthyBusy を返すバックグラウンド処理中
  • Idle:次の呼び出しを待っている
  • Stopped:microVM が終了している

Stopped になるのは,アイドルタイムアウト(既定 15 分),最長稼働時間(既定 8 時間),StopRuntimeSession の呼び出し,ヘルスチェック失敗のいずれかです.Stopped のセッションを同じ ID で呼ぶと新しい microVM が起動します.セッション ID 自体は Runtime を削除するまで有効です.

microVM のメモリとディスクに書いたものは microVM と一緒に消えます.セッションをまたいで状態を残すなら AgentCore Memory などの外部に置くか,ファイルシステム設定のセッションストレージを使います.

docs.aws.amazon.com

タイムアウトは Runtime の lifecycleConfiguration で変更でき,idleRuntimeSessionTimeout の既定が 900 秒,maxLifetime の既定が 28,800 秒です.

検証用のコード

ホスト名,アーキテクチャ,カーネル,CPU 数,メモリ,プロセス起動からの経過秒数と,/tmp に置いたカウンターの値を返すコードです.

import os
import platform
import socket
import time
from pathlib import Path

from bedrock_agentcore import BedrockAgentCoreApp

app = BedrockAgentCoreApp()
BOOT = time.time()


def meminfo():
    info = {}
    with open("/proc/meminfo") as f:
        for line in f:
            k, v = line.split(":", 1)
            if k in ("MemTotal", "MemAvailable"):
                info[k] = v.strip()
    return info


def bump(path):
    p = Path(path)
    try:
        p.parent.mkdir(parents=True, exist_ok=True)
        n = int(p.read_text()) + 1 if p.exists() else 1
        p.write_text(str(n))
        return n
    except Exception as e:
        return f"error: {e}"


@app.entrypoint
def handler(payload, context):
    return {
        "message": payload.get("prompt"),
        "hostname": socket.gethostname(),
        "machine": platform.machine(),
        "kernel": platform.release(),
        "cpu_count": os.cpu_count(),
        "mem": meminfo(),
        "process_uptime_sec": round(time.time() - BOOT, 1),
        "counter_tmp": bump("/tmp/counter"),
        "session_id": getattr(context, "session_id", None),
    }


if __name__ == "__main__":
    app.run()

デプロイは S3 に置いた zip からの直接コードデプロイを使いました.

uv pip install \
  --python-platform aarch64-manylinux2014 \
  --python-version 3.13 \
  --target=deployment_package \
  --only-binary=:all: \
  -r pyproject.toml
cd deployment_package && zip -qr ../deployment_package.zip . && cd ..
zip -q deployment_package.zip main.py
aws s3 cp deployment_package.zip s3://<バケット名>/probe/deployment_package.zip

docs.aws.amazon.com

Runtime の作成

東京リージョン,AWS CLI 2.36.34 で作成しました.実行ロールは既存のものを使っています.

aws bedrock-agentcore-control create-agent-runtime \
  --region ap-northeast-1 \
  --agent-runtime-name probe_microvm \
  --agent-runtime-artifact '{"codeConfiguration":{"code":{"s3":{"bucket":"<バケット名>","prefix":"probe/deployment_package.zip"}},"runtime":"PYTHON_3_13","entryPoint":["main.py"]}}' \
  --network-configuration '{"networkMode":"PUBLIC"}' \
  --role-arn arn:aws:iam::111122223333:role/<実行ロール名>

呼び出して microVM の中を見る

以下のコマンドで呼び出しました.

aws bedrock-agentcore invoke-agent-runtime \
  --region ap-northeast-1 \
  --agent-runtime-arn arn:aws:bedrock-agentcore:ap-northeast-1:111122223333:runtime/probe_microvm-IKCETD2Sv7 \
  --runtime-session-id ca2818dc498e431f9a452d303a7969bf2d23 \
  --payload "$(echo '{"prompt":"hello microvm #1"}' | base64)" /dev/stdout

以下の結果が返ってきました.

{"message": "hello microvm #1", "hostname": "localhost", "machine": "aarch64", "kernel": "6.1.161-18.298.amzn2023.aarch64", "cpu_count": 2, "mem": {"MemTotal": "8209720 kB", "MemAvailable": "7814084 kB"}, "process_uptime_sec": 0.3, "counter_tmp": 1, "session_id": "ca2818dc498e431f9a452d303a7969bf2d23"}

料金

CPU とメモリの消費量に対する秒単位の課金で,I/O 待ちの CPU 時間は課金されません.メモリはアイドル中もセッションが終わるまで課金が続きます.料金ページには Runtime v1 と v2 の単価が載っていて,v2 ではアイドルが 120 秒続くと未使用のメモリが自動回収されます.

項目 v1 v2
CPU 1 vCPU 時間あたり USD 0.0895 1 vCPU 時間あたり USD 0.1276
メモリ 1 GB 時間あたり USD 0.00945 1 GB 時間あたり USD 0.0169

LLM の応答待ちが長いエージェントでは CPU の課金は抑えられますが,アイドルタイムアウトまでメモリの課金は続くので,idleRuntimeSessionTimeout は利用パターンに合わせて見直すのが良さそうです.

aws.amazon.com

まとめ

AgentCore Runtime の microVM によるセッション分離を整理し,検証用のコードで microVM の中の環境を確認しました.microVM は停止すると中身ごと消えるので,残したい状態は microVM の外に置く前提で設計するのが良さそうです.

Amazon Bedrock AgentCore Code Interpreter で sandbox 環境を使う手順を試したメモ✍

タダです.

エージェントが生成したコードを自分の端末や本番のコンテナでそのまま実行するのは避けたく,Amazon Bedrock AgentCore の Code Interpreter が提供する隔離された sandbox 環境でコードを実行する手順を東京リージョンで試したのでメモにまとめます.

docs.aws.amazon.com

Code Interpreter の sandbox 環境とは

Code Interpreter は,エージェントが書いた Python,JavaScript,TypeScript のコードを AgentCore 側の隔離環境で実行して結果を返すビルトインツールです.実行環境はセッション単位で microVM が割り当てられ,セッション内では実行間で変数やファイルの状態が保持されます.1 セッションあたりの上限は 2 vCPU / 8 GB メモリ,ディスク 10 GB で,API 経由のファイル受け渡しは 100 MB までです.セッションのタイムアウトは既定で 15 分,最長 8 時間まで延ばせます.

Code Interpreter のリソースには 2 種類あります.

  • システム ARN:aws.codeinterpreter.v1 という ID で全リージョンに用意済みのもの.最も制限の強い既定設定で,作成作業なしにセッションを開始できます
  • カスタム ARN:ネットワークモードと実行ロールを自分で指定して作成するもの

docs.aws.amazon.com

ネットワークモードは 3 つで,sandbox 環境の外にどこまで出られるかが変わります.

モード 外部アクセス
SANDBOX AWS サービスへの限定的なアクセスのみ.S3 のデータ操作が可能
PUBLIC パブリックインターネットへアクセス可能
VPC 自分の VPC 内のリソースへ接続.サブネットとセキュリティグループの指定が必要

SANDBOX モードはパブリックインターネットに出られないので,外部から追加パッケージを取り込むことはできない前提で,事前インストール済みのライブラリで賄うことになります.pandas,numpy,matplotlib,scikit-learn などの定番は入っているので,データ分析用途なら SANDBOX のままで足りるケースが多そうです.

docs.aws.amazon.com

事前準備

呼び出し側の IAM 権限

Code Interpreter を操作する IAM ユーザーまたはロールには,以下のアクションを許可します.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock-agentcore:CreateCodeInterpreter",
        "bedrock-agentcore:StartCodeInterpreterSession",
        "bedrock-agentcore:InvokeCodeInterpreter",
        "bedrock-agentcore:StopCodeInterpreterSession",
        "bedrock-agentcore:DeleteCodeInterpreter",
        "bedrock-agentcore:ListCodeInterpreters",
        "bedrock-agentcore:GetCodeInterpreter",
        "bedrock-agentcore:GetCodeInterpreterSession",
        "bedrock-agentcore:ListCodeInterpreterSessions"
      ],
      "Resource": "arn:aws:bedrock-agentcore:ap-northeast-1:111122223333:code-interpreter/*"
    }
  ]
}

実行ロール

sandbox の中から AWS CLI や boto3 で S3 などを触らせたい場合は,Code Interpreter に実行ロールを渡します.信頼ポリシーのプリンシパルは bedrock-agentcore.amazonaws.com で,aws:SourceAccount と aws:SourceArn の条件を付けておきます.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BedrockAgentCoreBuiltInTools",
      "Effect": "Allow",
      "Principal": {
        "Service": "bedrock-agentcore.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "111122223333"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:bedrock-agentcore:ap-northeast-1:111122223333:*"
        }
      }
    }
  ]
}

docs.aws.amazon.com

システム ARN をそのまま使うだけなら実行ロールは不要です.今回の検証でも実行ロールは付けずに進めています.

sandbox 環境を使う手順

流れは,Code Interpreter の作成,セッションの開始,コードの実行,セッションの停止の 4 ステップです.作成と削除はコントロールプレーン API,セッション操作とコード実行はデータプレーン API に分かれています.検証は AWS CLI 2.36.34 と boto3 で行いました.

Code Interpreter の作成

SANDBOX モードのカスタム Code Interpreter を AWS CLI で作成したコマンドが以下です.

aws bedrock-agentcore-control create-code-interpreter \
  --region ap-northeast-1 \
  --name "mySandboxInterpreter" \
  --description "Sandbox for agent generated code" \
  --network-configuration '{"networkMode": "SANDBOX"}'

1 秒足らずで READY のレスポンスが返ってきました.

{
    "codeInterpreterId": "mySandboxInterpreter-FpBSeElECh",
    "codeInterpreterArn": "arn:aws:bedrock-agentcore:ap-northeast-1:111122223333:code-interpreter-custom/mySandboxInterpreter-FpBSeElECh",
    "createdAt": "2026-10-11T01:30:22.307124+00:00",
    "status": "READY"
}

ドキュメントの作成手順ページでは aws bedrock-agentcore create-code-interpreter と書かれていますが,実際には bedrock-agentcore 配下にこのコマンドはなく Found invalid choice になるので,bedrock-agentcore-control を指定する必要がありました.--execution-role-arn は省略できるので,S3 を触らせたいときだけ付ければよさそうです.名前はアカウント内で一意である必要があります.

docs.aws.amazon.com

セッションの開始

セッションはデータプレーンの bedrock-agentcore 配下で開始します.以降はシステム ARN の aws.codeinterpreter.v1 を使いました.

aws bedrock-agentcore start-code-interpreter-session \
  --region ap-northeast-1 \
  --code-interpreter-identifier "aws.codeinterpreter.v1" \
  --name "sandbox-session" \
  --session-timeout-seconds 900

こちらも 1.4 秒ほどで sessionId が返ってきました.

{
    "codeInterpreterIdentifier": "aws.codeinterpreter.v1",
    "sessionId": "01M4M9A6XHH2Q185PW6D7VVYHT",
    "createdAt": "2026-10-11T01:30:22.989824+00:00"
}

ドキュメントの例は --code-interpreter-id ですが,CLI の実際のオプション名は --code-interpreter-identifier でした.sessionTimeoutSeconds は 60 秒以上が推奨で,上限は 28,800 秒です.

docs.aws.amazon.com

コードの実行

コード実行の InvokeCodeInterpreter はストリーミングで結果を返す API で,AWS CLI にはコマンドが用意されていません(aws bedrock-agentcore invoke-code-interpreter は Found invalid choice になります).そのため実行は SDK か awscurl で行います.コンソールに表示される Code Interpreter のサンプルコードをもとに,boto3 で実行したものが以下です.

import boto3
import json

client = boto3.client('bedrock-agentcore', region_name='ap-northeast-1')
response = client.invoke_code_interpreter(
    codeInterpreterIdentifier='mySandboxInterpreter-7NWo36cKHa',
    sessionId='01M4MCD2DSW6ZG27DCVK7YKK2B',
    name='executeCode',
    arguments={
        'code':'print("Hello, world!")',
        'language':'python'
    }
)

for event in response['stream']:
    print(json.dumps(event['result'], indent=2))
{
  "content": [
    {
      "type": "text",
      "text": "Hello, world!"
    }
  ],
  "structuredContent": {
    "stdout": "Hello, world!",
    "stderr": "",
    "exitCode": 0,
    "executionTime": 0.01004648208618164
  },
  "isError": false
}

続けて,バージョン表示と変数の定義を実行したのが以下です.

response = client.invoke_code_interpreter(
    codeInterpreterIdentifier="aws.codeinterpreter.v1",
    sessionId="01M4M9A6XHH2Q185PW6D7VVYHT",
    name="executeCode",
    arguments={
        "language": "python",
        "code": "import pandas as pd, numpy as np, sys\nprint(sys.version)\nprint(pd.__version__, np.__version__)\nx = 6 * 7\nprint(x)",
    },
)

structuredContent に標準出力,標準エラー,終了コード,実行時間が分かれて入っているので,エージェント側で成否を判定しやすい形になっています.sandbox 側の Python は 3.12,pandas は 2.3.1 でした.

{
  "content": [
    {
      "type": "text",
      "text": "3.12.13 (main, Jun 18 2026, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-5)]\n2.3.1 1.26.4\n42"
    }
  ],
  "structuredContent": {
    "stdout": "3.12.13 (main, Jun 18 2026, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-5)]\n2.3.1 1.26.4\n42",
    "stderr": "",
    "exitCode": 0,
    "executionTime": 0.9748482704162598
  },
  "isError": false
}

sandbox から外に出られないことの確認

システム ARN は SANDBOX モードなので,executeCommand で外部への通信を試してみました.curl https://pypi.org/simple/ は名前解決の段階で失敗します.

curl: (6) Could not resolve host: pypi.org

エージェントが生成したコードが外部 API や PyPI に手を伸ばしても届かないので,SANDBOX モードで使うなら事前インストール済みライブラリの範囲でプロンプトを組む必要があります.なお ls -la でカレントディレクトリを見ると node_modules や nodejs-ts-execution といった Node.js 実行用のディレクトリが同居しており,実行ユーザーは root ではない一般ユーザーでした.

docs.aws.amazon.com

セッションの停止と削除

使い終わったセッションは明示的に停止します.

aws bedrock-agentcore stop-code-interpreter-session \
  --region ap-northeast-1 \
  --code-interpreter-identifier "aws.codeinterpreter.v1" \
  --session-id "01M4M9A6XHH2Q185PW6D7VVYHT"

停止前後で get-code-interpreter-session を叩くと,status が READY から TERMINATED に変わっていました.ドキュメントのステータス一覧は ACTIVE / STOPPING / STOPPED と書かれているので,実際に返る値とは異なるようです.停止したセッションは再開できず,続けて使いたい場合は新しいセッションを開始します.

{
    "codeInterpreterIdentifier": "aws.codeinterpreter.v1",
    "sessionId": "01M4M9A6XHH2Q185PW6D7VVYHT",
    "name": "sandbox-session",
    "createdAt": "2026-10-11T01:30:22.989824+00:00",
    "sessionTimeoutSeconds": 900,
    "status": "TERMINATED"
}

最初に作ったカスタム Code Interpreter は aws bedrock-agentcore-control delete-code-interpreter --code-interpreter-id mySandboxInterpreter-FpBSeElECh で削除し,status が DELETED で返ってきました.

料金

Code Interpreter は使った CPU とメモリに対する秒単位の従量課金で,最低課金は 1 秒,メモリは 128 MB 分が最低請求単位です.

項目 単価
CPU 1 vCPU 時間あたり USD 0.0895
メモリ 1 GB 時間あたり USD 0.00945

ドキュメントでも不要な課金を避けるために使い終わったセッションは停止するよう案内されているので,タイムアウトを用途に合わせて短めにしておくか,処理が終わったら停止する実装にしておくのが安全だと感じました.

aws.amazon.com

まとめ

Amazon Bedrock AgentCore Code Interpreter で sandbox 環境を作り,セッションを開始してコードを実行し,停止するまでの手順を東京リージョンで試しました.

AWS MCP Server が東京リージョンを含む 6 リージョンで利用可能になったメモ✍

タダです.

AWS MCP Server が東京を含む 6 つのリージョンで新たに利用可能になりました.前回記事で Claude Code から接続したときはバージニア北部のエンドポイントしかなく,東京のリソースを触るのにリクエストは一度米国へ飛んでいたので,その構成がどう変わるかをドキュメントをもとに整理します.

aws.amazon.com

アップデートの概要

2026 年 10 月 2 日付で,シンガポール,シドニー,東京,アイルランド,ロンドン,オレゴンの 6 リージョンが追加されました.既存のバージニア北部とフランクフルトを合わせて 8 リージョンです.エンドポイントはリージョンコードを埋めるだけの規則的な形になっています.

リージョン コード エンドポイント
米国東部(バージニア北部) us-east-1 https://aws-mcp.us-east-1.api.aws/mcp
米国西部(オレゴン) us-west-2 https://aws-mcp.us-west-2.api.aws/mcp
アジアパシフィック(シンガポール) ap-southeast-1 https://aws-mcp.ap-southeast-1.api.aws/mcp
アジアパシフィック(シドニー) ap-southeast-2 https://aws-mcp.ap-southeast-2.api.aws/mcp
アジアパシフィック(東京) ap-northeast-1 https://aws-mcp.ap-northeast-1.api.aws/mcp
欧州(フランクフルト) eu-central-1 https://aws-mcp.eu-central-1.api.aws/mcp
欧州(アイルランド) eu-west-1 https://aws-mcp.eu-west-1.api.aws/mcp
欧州(ロンドン) eu-west-2 https://aws-mcp.eu-west-2.api.aws/mcp

docs.aws.amazon.com

アナウンスで挙げられている利点は,開発者に近い場所で MCP サーバーを動かせることによるレイテンシの低減と,リクエストのデータをリージョン内に留められることの 2 点です.エージェントに渡すプロンプトやツールの入出力がどこを経由するかは選べるようになったのは良いところだと感じました.

東京リージョンを指定する例

エンドポイントのリージョンは接続先の MCP サーバーがどこで動くかを決め,AWS_REGION メタデータはエージェントが AWS API を叩くときのデフォルトリージョンを決めます.今回のアップデートで,次のように東京に揃えられます.

{
  "mcpServers": {
    "aws-mcp": {
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws@latest",
        "https://aws-mcp.ap-northeast-1.api.aws/mcp",
        "--metadata", "AWS_REGION=ap-northeast-1"
      ]
    }
  }
}

変更点はエンドポイントの URL だけで,IAM の aws-mcp:InvokeMcp などの権限や,uv 経由でプロキシを立てる構成は前回のままです.逆に言うと,エンドポイントを東京にしても AWS_REGION を書かなければ操作対象はバージニア北部のままなので,二つを別々に意識する必要があります.

docs.aws.amazon.com

クォータはリージョンごと

AWS MCP Server のクォータは,他のサービスと同じくリージョン単位で管理されます.主なものは以下です.

  • 同時接続数:アカウントあたり 1 リージョンで 100(引き上げ不可)
  • 同時アクティブセッション数:アカウントあたり 180,IAM ユーザー / ロールあたり 90(いずれも引き上げ可)
  • 認証済みリクエストのレート:アカウントあたり 1 リージョンで 10 リクエスト / 秒
  • 未認証リクエストのレート:送信元 IP あたり 1 リージョンで 5 リクエスト / 秒

docs.aws.amazon.com

利用量は CloudWatch の AWS/Usage 名前空間に CallCount などのメトリクスとして出るので,複数リージョンに分ける前に現状の利用量を見ておくのがよさそうです.

まとめ

AWS MCP Server が東京を含む 6 リージョンに拡大したアップデートをまとめました.

Datadog のサービスアカウントと アプリケーションキー で EntraID の SCIM プロビジョニングを構成したメモ✍

タダです.

前回は Datadog の SSO と SAML Group Mappings を Microsoft EntraID(以降 EntraID)で構成する内容をまとめました.今回は続編として,EntraID から Datadog へ SCIM プロビジョニングを設定し,ユーザー同期を自動化する手順をメモにまとめます.

sadayoshi-tada.hatenablog.com

なぜサービスアカウントの アプリケーションキー を使うのか

SCIM を構成する際は Datadog の アプリケーションキー を使用しますが,ここで通常のユーザーアカウントに紐づく アプリケーションキー を使うと運用上の問題が起きます.そのユーザーが退職などで Datadog からデプロビジョニングされると アプリケーションキー も失効し,SCIM 連携が完全に破壊されて組織全体が Datadog へアクセスできなくなるからです.

Datadog のドキュメントでも専用のサービスアカウントを作成して アプリケーションキー を発行することが強く推奨されています.

docs.datadoghq.com

Datadog 側の準備

サービスアカウントの作成

まず Datadog で SCIM 専用のサービスアカウントを作成します.Organization Settings > Service Accounts から New Service Account を選択し,名前とメールアドレスを設定します.サービスアカウントのメールアドレスは組織内でユニークである必要はありません.ロールには少なくとも user_access_invite と user_access_manage の権限を含めたロールを割り当てます.SCIM API が要求する全権限のリストは SCIM API ドキュメントに記載されています.

docs.datadoghq.com

Terraform でサービスアカウントとロールを構成する場合の簡易なコードイメージは以下です.

data "datadog_permissions" "datadog_perms" {}
resource "datadog_role" "scim_role" {
  name = "user_access_invite_and_manage"
  permission {
    id = data.datadog_permissions.datadog_perms.permissions.user_access_invite
  }
  permission {
    id = data.datadog_permissions.datadog_perms.permissions.user_access_manage
  }
}
resource "datadog_service_account" "scim" {
  email = "scim-provisioning@example.com"
  name  = "SCIM Provisioning Service Account"
  roles = [datadog_role.scim_role.id]
}

registry.terraform.io

アプリケーションキー の発行

作成したサービスアカウントの詳細画面から New Key を選択し,アプリケーションキー を発行しコピーしておきます.

EntraID 側の設定

プロビジョニングの構成

前回 SSO で使用した EntraID の Enterprise Application と同じものを開き,Provisioning タブへ移動します.Provisioning Mode で Automatic を選択すると Admin Credentials のセクションが表示されます.

ここに以下を設定します:

  • Tenant URL: Datadog の SCIM エンドポイント https://[設定先の org のカスタムサブドメインがあればそれを設定する]/api/v2/scim?aadOptscim062020
  • Secret Token: 先ほど発行したサービスアカウントの アプリケーションキー

Tenant URL の API host は Datadog サイトごとに異なるので注意が必要です.たとえば US1 サイトなら api.datadoghq.com,US3 サイトなら api.us3.datadoghq.com,EU1 サイトなら api.datadoghq.eu のように,アプリホスト(app.datadoghq.com 等)ではなく API ホストを指定します.サイトごとの SCIM エンドポイントは SCIM API リファレンスに記載されています.

docs.datadoghq.com

?aadOptscim062020 部分は Entra ID 専用のフラグです.これは EntraID の SCIM 動作を修正するように指示するフラグです.

learn.microsoft.com

属性マッピングとプロビジョニング開始

Attribute Mapping セクションで Provision Azure Active Directory Users を選択し,Enabled を Yes に設定します.EntraID から Datadog へ同期される属性は以下のようにマッピングされます.

  • userPrincipalName → userName
  • displayName → name.formatted
  • jobTitle → title
  • mail → emails[type eq "work"].value
  • Not([IsSoftDeleted]) → active

learn.microsoft.com

プロビジョニングを開始したらプロビジョニングログや Datadog 側へのアカウント同期状況を確認します.

まとめ

Datadog の SCIM プロビジョニングを EntraID で構成する手順をまとめました.前回の記事とあわせた設定を行うことで手動でのユーザー招待や権限設定の手間を軽減(もしくは無くして)ユーザー管理を実現できるため,運用負担が軽減できます.