🏗️

EKS移行でamd64ビルドを廃止したら、Argo CD Image Updaterが最新イメージを追従しなくなった

に公開

はじめに、そして結論

プライベートクラウドからEKS(ECR)への移行を進める中で、従来はマルチアーキテクチャ(amd64 + arm64)でビルドしていたコンテナイメージをarm64のみに切り替えた。すると、Argo CD Image Updater がECRにpushされた最新のイメージタグを認識しなくなり、古いタグのまま更新が止まってしまった。

原因は、Argo CD Image Updater がデフォルトで自身が動作するノードのアーキテクチャと同じplatformのマニフェストを参照してイメージのcreation timeを取得すること。今回のケースでは Image Updater が amd64 ノードで動作していたため linux/amd64 のマニフェストを探しに行き、arm64のみのイメージからはメタデータを読み取れず候補から除外されていた。

つまり、これはEKS移行やarm64への切り替えに固有の問題ではなく、Image Updater が動作するノードのアーキテクチャと、監視対象のイメージのアーキテクチャが一致しない場合に普遍的に発生する

修正は、ArgoCD Applicationのアノテーションに platforms: linux/arm64 を追加するだけで完了した。

argocd-image-updater.argoproj.io/<image_alias>.platforms: linux/arm64

背景

移行前の構成

  • コンテナイメージは マルチアーキテクチャ(amd64 + arm64) でビルド
  • プライベートクラウド上のレジストリとECRの両方にpush
  • Argo CD Image Updater がレジストリを監視し、最新タグを自動でArgoCD Applicationに反映

移行後の構成

  • EKS上でワークロードを実行、イメージはECRのみにpush
  • EKSのノードは arm64(Graviton) を採用
  • イメージのビルドも arm64のみ に変更(amd64ビルドを廃止)
  • Argo CD Image Updater の image-list アノテーションをプライベートレジストリからECRに変更済み
# Before
- argocd-image-updater.argoproj.io/image-list: myapp-web=registry.example.com/myorg/myapp/myapp-web
# After
+ argocd-image-updater.argoproj.io/image-list: myapp-web=123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myorg/myapp/myapp-web

この構成変更後、Image Updater によるイメージタグの自動更新が停止した。

症状

staging環境のweb deploymentが、ECRにpushされた最新のイメージタグ(staging-abc1234)を参照せず、古いタグ(staging-def5678)のまま止まっていた。

調査

1. image-updater testコマンドでの検証

Argo CD Image Updater には test サブコマンドがあり、特定のイメージに対してどのタグが最新と判定されるかをドライランでテストできる。

kubectl exec -n argocd <image-updater-pod> -- \
  argocd-image-updater test \
  123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myorg/myapp/myapp-web \
  --update-strategy newest-build \
  --allow-tags 'regexp:^staging-[0-9a-z]+$' \
  --registries-conf-path /app/config/registries.conf \
  --loglevel debug

debugログが以下のように出力された。

Manifest list did not contain any usable reference.
Platforms requested: (linux/amd64), platforms included: (linux/arm64,unknown/unknown)
No metadata found for myorg/myapp/myapp-web:staging-abc1234

Image Updater は linux/amd64 のマニフェストを探しているが、新しいイメージには linux/arm64unknown/unknown(attestation)しか含まれていない。そのためcreation timeを取得できず、候補から除外されていた。

2. なぜ linux/amd64 を探すのか

Image Updater がどのノードで動いているか確認した。

$ kubectl get pod -n argocd <image-updater-pod> -o jsonpath='{.spec.nodeName}'
ip-10-0-1-100.ap-northeast-1.compute.internal

$ kubectl get node ip-10-0-1-100.ap-northeast-1.compute.internal \
    -o jsonpath='{.status.nodeInfo.architecture}'
amd64

Image Updater自体が amd64ノード で動作していた。newest-build 戦略ではイメージのcreation timeを比較するためにマニフェストリストからプラットフォーム固有のマニフェストを取得する必要があるが、デフォルトでは自身が動作しているノードのアーキテクチャ(linux/amd64)のマニフェストを探す

クラスタにはamd64とarm64の両方のノードが存在するが、Image Updater Pod はたまたまamd64ノードにスケジュールされていた。

3. 古いタグが「最新」として選ばれる理由

staging-def5678 は、マルチアーキテクチャビルドがまだ行われていた時期の最後のイメージであり、linux/amd64 マニフェストを含んでいた。そのため Image Updater がcreation timeを正常に取得でき、「amd64マニフェストを持つタグの中で最新」として選ばれ続けていた。

つまり、マルチアーキテクチャビルドを廃止してarm64のみに切り替えた時点から、それ以降の全てのタグが Image Updater から見えなくなっていた

修正

ArgoCD Applicationのアノテーションに platforms を追加し、linux/arm64 のマニフェストを参照するように指定した。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  annotations:
    argocd-image-updater.argoproj.io/image-list: >-
      myapp-web=123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myorg/myapp/myapp-web,
      myapp-worker=123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myorg/myapp/myapp-worker
    argocd-image-updater.argoproj.io/myapp-web.allow-tags: regexp:^staging-[0-9a-z]+$
    argocd-image-updater.argoproj.io/myapp-web.update-strategy: newest-build
    argocd-image-updater.argoproj.io/myapp-web.platforms: linux/arm64  # 追加
    argocd-image-updater.argoproj.io/myapp-worker.allow-tags: regexp:^staging-[0-9a-z]+$
    argocd-image-updater.argoproj.io/myapp-worker.update-strategy: newest-build
    argocd-image-updater.argoproj.io/myapp-worker.platforms: linux/arm64  # 追加

まとめ

Argo CD Image Updater の newest-build 戦略は、マニフェストリストからプラットフォーム固有のマニフェストを取得してcreation timeを比較する。プラットフォームの指定がない場合、Image Updater 自身が動作しているノードのアーキテクチャがデフォルトで使われる

EKS移行に伴いarm64のみのビルドに切り替える場合、以下のいずれかの対応が必要になる。

  1. platforms アノテーションで明示的にarm64を指定する(今回の対応)
  2. Image Updater Pod自体をarm64ノードにスケジュールする
  3. マルチアーキテクチャビルドを維持する

1が最もシンプルで影響範囲が限定的な対応となる。argocd-image-updater test コマンドの --loglevel debug は、このような問題の切り分けに非常に有用だった。

参考

GitHubで編集を提案
GMOペパボ株式会社

Discussion