ECS Express Modeの新機能「CPUアーキテクチャ自動検出」で、x86_64からARM64イメージへの切り替えを試してみた

ECS Express Modeの新機能「CPUアーキテクチャ自動検出」で、x86_64からARM64イメージへの切り替えを試してみた

ECS Express Modeで、CPUアーキテクチャの自動検出がサポートされました。既存サービスをARM64イメージへupdateした際に、サービスリビジョンのoverridesでアーキテクチャが自動補正される挙動をAWS CLIで確認しています。
2026.07.09

はじめに

ECS Express Modeで、CPUアーキテクチャの自動検出がサポートされました。AWS CLI v2のChangelogには以下の記載があります。

2.35.18

api-change:ecs: Amazon ECS now automatically detects the correct CPU architecture for Express Mode services.

https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst

Express Modeはサービス作成時にタスク定義を自動生成しますが、runtimePlatform.cpuArchitecture はこれまで常に X86_64 固定でした。ARM64イメージを指定しても、タスクはx86_64として起動するため exec format error(exit code 255)で停止します。

この制約に対して、7月1日にカスタムタスク定義のサポートが追加され、ユーザーが明示的にアーキテクチャを指定できるようになりました。

https://dev.classmethod.jp/articles/ecs-express-mode-custom-task-definition/

さらに7月8日には、既存サービスのupdate時にECSがイメージのアーキテクチャを自動で検出し、タスク定義の宣言とミスマッチがある場合にオーバーライドを適用する機能が追加されました。今回はこの自動検出の挙動を検証します。

これまでのアーキテクチャ対応の流れを整理します。

時期 手法 概要 ユーザー操作
〜2026年6月 ワークアラウンド x86で作成後、タスク定義を手動でARM64に変更 CLI手動編集が必要
2026年7月1日 カスタムタスク定義 ユーザーがruntimePlatformで明示指定 タスク定義に設定が必要
2026年7月8日 アーキテクチャ自動検出 ECSがミスマッチを検出し自動でオーバーライド 既存サービスのupdateでは追加設定不要

検証内容

検証環境

  • リージョン: ap-northeast-1
  • クラスター: default
  • AWS CLI: 2.35.19
  • イメージ: nginx:alpine のx86_64ビルド(タグ :x86)とARM64ビルド(タグ :arm64 / :arm64-v2)をECRにプッシュ
  • ECRリポジトリ: express-mode-arch-detect-test

x86_64イメージでサービスを作成

まず、x86_64イメージでExpress Modeサービスを作成し、正常稼働を確認しました。

aws ecs create-express-gateway-service \
  --cluster default \
  --execution-role-arn arn:aws:iam::123456789012:role/ecsTaskExecutionRole \
  --infrastructure-role-arn arn:aws:iam::123456789012:role/ecsInfrastructureRoleForExpressServices \
  --primary-container '{"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/express-mode-arch-detect-test:x86", "containerPort": 80}' \
  --health-check-path "/" \
  --region ap-northeast-1

タスクがRUNNINGになり、エンドポイントからHTTP 200が返ることを確認しました。

aws ecs describe-tasks \
  --cluster default \
  --tasks "$(aws ecs list-tasks --cluster default --service-name express-mode-arch-detect-test-8cce --query 'taskArns[0]' --output text)" \
  --query 'tasks[0].{lastStatus:lastStatus, arch:attributes[?name==`ecs.cpu-architecture`].value|[0]}' \
  --output json
{
    "lastStatus": "RUNNING",
    "arch": "x86_64"
}

この時点でのタスク定義は runtimePlatform.cpuArchitecture: X86_64 です。Express Modeが自動生成したデフォルトのタスク定義で、カスタムタスク定義は使用していません。

ARM64イメージへのupdate

update-express-gateway-service でARM64ビルドのイメージに変更しました。2回のupdateを実行し、2回目でoverridesの自動適用を確認しています。

aws ecs update-express-gateway-service \
  --service-arn "arn:aws:ecs:ap-northeast-1:123456789012:service/default/express-mode-arch-detect-test-8cce" \
  --primary-container '{"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/express-mode-arch-detect-test:arm64-v2", "containerPort": 80}' \
  --region ap-northeast-1

1回目のupdate(別のARM64イメージタグ)ではロールバックが発生しました。原因は特定できていませんが、再度updateを実行した際にoverridesが正常に適用されました。以降の検証結果は2回目のupdateに基づきます。

overridesの自動適用を確認

update実行から約16分後にoverridesが出現し、約25分後にARM64タスクがRUNNINGになりデプロイが完了しました。

describe-service-revisions で新しいサービスリビジョンに overrides が付与されていることを確認しました。

aws ecs describe-service-revisions \
  --service-revision-arns "arn:aws:ecs:ap-northeast-1:123456789012:service-revision/default/express-mode-arch-detect-test-8cce/4391819737795370172" \
  --query 'serviceRevisions[0].{overrides:overrides, taskDefinition:taskDefinition}' \
  --output json
{
    "overrides": {
        "runtimePlatform": {
            "cpuArchitecture": "ARM64"
        }
    },
    "taskDefinition": "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/default-express-mode-arch-detect-test-8cce:3"
}

タスク定義自体は X86_64 のままですが、サービスリビジョンレベルでアーキテクチャが自動でオーバーライドされています。

この挙動はCLI helpでも以下のように説明されています。

This value might differ from the architecture declared in the task definition—for example, when Amazon ECS detects an architecture mismatch during an Amazon ECS Express deployment and runs tasks on a different architecture. You can't set this value.

ARM64タスクの起動確認

overrides適用後、ARM64タスクがPENDINGからRUNNINGに遷移しました。update実行からデプロイ完了まで約25分でした。

aws ecs describe-tasks \
  --cluster default \
  --tasks "$(aws ecs list-tasks --cluster default --service-name express-mode-arch-detect-test-8cce --query 'taskArns[0]' --output text)" \
  --query 'tasks[0].{lastStatus:lastStatus, arch:attributes[?name==`ecs.cpu-architecture`].value|[0], taskDefinitionArn:taskDefinitionArn}' \
  --output json
{
    "lastStatus": "RUNNING",
    "arch": "arm64",
    "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/default-express-mode-arch-detect-test-8cce:3"
}

タスク定義は :3(X86_64)のまま、実タスクはoverridesにより arm64 で起動しています。

デプロイ完了

カナリアデプロイが完了し、新しいサービスリビジョンへの切り替わりを確認しました。

aws ecs list-service-deployments \
  --service "arn:aws:ecs:ap-northeast-1:123456789012:service/default/express-mode-arch-detect-test-8cce" \
  --query 'serviceDeployments[0].{status:status, targetServiceRevisionArn:targetServiceRevisionArn}' \
  --output json
{
    "status": "SUCCESSFUL",
    "targetServiceRevisionArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-revision/default/express-mode-arch-detect-test-8cce/4391819737795370172"
}

エンドポイントもHTTP 200を返し続けています。

update後の各レイヤーの状態

update完了後の各レイヤーの状態を整理します。

レイヤー 備考
タスク定義 runtimePlatform.cpuArchitecture X86_64 カスタムタスク定義は使用せず、自動生成された値のまま
サービスリビジョン overrides.runtimePlatform.cpuArchitecture ARM64 ECSが自動設定、Read-only
実行中タスク ecs.cpu-architecture arm64 overridesに従って起動

タスク定義を書き換えるのではなく、サービスリビジョンのoverridesとして適用される点が特徴です。

初回create時の挙動(自動検出が効かないケース)

ARM64イメージを直接指定してサービスを新規作成した場合、自動検出は適用されませんでした。

aws ecs create-express-gateway-service \
  --cluster default \
  --execution-role-arn arn:aws:iam::123456789012:role/ecsTaskExecutionRole \
  --infrastructure-role-arn arn:aws:iam::123456789012:role/ecsInfrastructureRoleForExpressServices \
  --primary-container '{"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/express-mode-arch-detect-test:arm64", "containerPort": 80}' \
  --health-check-path "/" \
  --region ap-northeast-1

タスクはx86_64として起動し、ARM64バイナリを実行できずexit code 255で停止しました。

{
    "lastStatus": "STOPPED",
    "stoppedReason": "Essential container in task exited",
    "containers": [
        {
            "lastStatus": "STOPPED",
            "exitCode": 255
        }
    ]
}

サービスリビジョンの overridesnull のままで、デプロイは ROLLBACK_FAILED(初回デプロイのためロールバック先が存在しない)となりました。

{
    "status": "ROLLBACK_FAILED",
    "statusReason": "No rollback candidate was found to run the rollback."
}

自動検出はupdate時のセーフティネットであり、初回createには適用されません。新規サービスでARM64を使う場合は、カスタムタスク定義で runtimePlatform を明示指定してください。

注意事項

  • overridesフィールドはRead-only: ユーザーがAPIで直接設定することはできません。今回確認したCPUアーキテクチャのoverridesは、ECSがアーキテクチャミスマッチを検出した場合に自動で付与されます。
  • 今回の検証ではoverrides出現まで時間がかかりました: update実行から約16分後にoverridesが出現しました。反映まで時間がかかる場合があるため、describe-service-revisions で確認する際は時間を置いてください。
  • AWS CLI 2.35.18以降が必要overrides フィールドの取得にはこのバージョン以降のCLIが必要です(CHANGELOGで当該API変更が反映されたバージョン)。古いバージョンでは describe-service-revisions の出力に overrides が含まれません。
  • 公式APIドキュメントは未反映: 2026年7月9日時点で ServiceRevision の公式リファレンスページにはこの変更が反映されていません。CLI helpおよびbotocoreサービスモデルでは確認できます。

まとめ

ECS Express ModeのCPUアーキテクチャ自動検出により、既存サービスをARM64ビルドのイメージへupdateした際、サービスリビジョンの overrides によってARM64タスクとして起動できることを確認しました。タスク定義自体はX86_64のままで、アーキテクチャ差分はサービスリビジョン側で補正されます。

ARM64実行環境はx86_64より約20%低い料金設定のため、ARM64で動作するアプリケーションであれば、既存のExpress Modeサービスをより低コストなARM64実行環境へ切り替える手段として利用できます。

一方で、今回の検証では初回updateでロールバックしたケースがありました。また、新規create時には自動検出が適用されなかったため、新規サービスでARM64を使う場合はカスタムタスク定義で runtimePlatform.cpuArchitecture を明示する必要があります。

参考リンク

https://dev.classmethod.jp/articles/ecs-express-mode-arm64-fargate-spot-exec/

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事