「自分のマシンでは動いたのに」という罠
よくあるシナリオです。Dockerイメージはローカルマシンで完璧に動作するのに、Kubernetesにデプロイした途端にPodがクラッシュします。ログを確認すると、次のような苛立たしいメッセージが表示されます。
standard_init_linux.go:211: exec user process caused "exec format error"
Podはおそらく CrashLoopBackOff のループに陥っています。これはアプリケーションコードのバグではなく、根本的なアーキテクチャの不一致です。あるCPUタイプ向けにビルドされたコンテナを、まったく異なる言語を話すサーバー上で実行しようとしているのです。
根本原因:ARM64 vs. x86_64
クラウド環境の状況は変化しました。現在、多くの開発者はApple Silicon (ARM64) を搭載したMacを使用していますが、多くの本番クラスターは依然として従来のIntelやAMD (x86_64/AMD64) ハードウェアで稼働しています。
M1、M2、M3チップを搭載したMacで docker build を実行すると、DockerはデフォルトでARM64イメージを作成します。そのイメージを標準的なAWSの t3.medium インスタンス (x86_64) にデプロイすると、Linuxカーネルは命令を実行できません。これはPlayStationのディスクをXboxで再生しようとするようなもので、物理的なフォーマットが根本的に互換性がないのです。
アーキテクチャの不一致を確認する
ビルドパイプラインを書き換える前に、CPUアーキテクチャが本当に原因であることを確認しましょう。
1. ノードのハードウェアを確認する
以下のコマンドを使用して、Kubernetesノードが実際にどのアーキテクチャで動作しているかを特定します。
kubectl get nodes -o custom-columns=NAME:.metadata.name,ARCH:.status.nodeInfo.architecture
結果に amd64 と表示されているのに、最新のMacBookでビルドしている場合は、不一致が原因であると分かります。
2. イメージを検査する
次のステップとして、レジストリ内のイメージメタデータを直接確認します。
docker pull your-repo/your-image:tag
docker inspect your-repo/your-image:tag | grep Architecture
"Architecture": "arm64" と表示されているのに、ノードが amd64 の場合、コンテナは決して起動しません。
クリーンな解決策:Docker Buildxによるマルチアーキテクチャビルド
最も信頼できる長期的な解決策は「マニフェストリスト」を作成することです。これにより、単一のイメージタグで複数のアーキテクチャをサポートできるようになります。Kubernetesがイメージをプルすると、レジストリはノードのハードウェアに一致するバージョンを自動的に送信します。
ステップ1:ビルダーをセットアップする
Docker Buildxは、異なるプラットフォーム向けのクロスコンパイルという重労働を処理してくれます。まず、新しいビルダーインスタンスを作成します。
# マルチアーキテクチャをサポートする新しいビルダーを作成する
docker buildx create --name global-builder --use
# ビルダーを初期化する
docker buildx inspect --bootstrap
ステップ2:両方の環境向けにビルドする
--platform フラグを使用して、両方のアーキテクチャを一度にターゲットにします。ローカルのDockerストレージは通常、一度に1つのアーキテクチャしか保持できないため、レジストリに直接 --push する必要があることに注意してください。
docker buildx build --platform linux/amd64,linux/arm64 -t your-repo/your-app:v1.0 --push .
この1つのコマンドで、Intel/AMDとARM64(AWS Gravitonなど)の両方のシステム向けにアプリをパッケージ化できます。
近道:単一のアーキテクチャを強制する
単一のアーキテクチャに対して迅速な修正が必要な場合もあります。ARMのサポートが不要な場合は、MacにIntel互換イメージのビルドを強制します。
docker build --platform linux/amd64 -t your-repo/your-app:v1.0 .
警告: これにはQEMUエミュレーションが使用されます。Macがまったく異なるプロセッサをシミュレートするため、通常30秒で終わるビルドに5分かかる場合があります。
混合アーキテクチャクラスターの処理
クラスターでインスタンスが混在している場合(Intelの m5.large とARMベースの m6g.large の組み合わせなど)、Kubernetesを誘導する必要があります。deployment.yaml で nodeSelector を使用して、Podが互換性のあるハードウェアに配置されるようにします。
spec:
template:
spec:
nodeSelector:
kubernetes.io/arch: amd64 # またはターゲットがarm64の場合はarm64
最終確認
新しいイメージをプッシュした後、デプロイを再起動して最新のマニフェストをプルします。
kubectl rollout restart deployment your-app-name
Podのステータスを確認してください。Running と表示されれば、バイナリとハードウェアがようやく同期したことになります。
重要なポイント
- Buildxは不可欠: ハードウェアが混在するチームで作業する場合は、
docker buildxをデフォルトのビルドツールにしましょう。 - ベースイメージを確認する:
python:3.12-slimやnode:20-bookwormなどのほとんどの公式イメージはすでにマルチアーキテクチャ対応ですが、独自の内部イメージは対応していない可能性があります。 - 早めにログを確認する: "Exec format error" が表示されたら、アプリケーションロジックを調べるのをやめましょう。問題はコーディングのバグではなく、物理的な互換性です。

