背景
SUZURI事業部WEBアプリケーションエンジニアのkromiiiです。
昨年SUZURIではメインのアプリケーション環境をHerokuからAWSに移行しました。
https://tech.pepabo.com/2024/06/13/heroku-to-eks
移行に伴いCI/CD環境もHerokuからArgo CDを使ったデプロイ方法に移行されました。
現在SUZURIで実装されているCI/CDの流れは以下の通りです。
- masterブランチにPull Requestがマージされる
- GitHub ActionsによってDocker Imageをビルド
- ビルドしたイメージをECRにプッシュ
- Argo CD Image UpdaterによってImageの更新を検知
- Argo CDによってデプロイを行う
発生した問題
このCI/CDの流れはほぼ完璧に動いていたのですが、なぜかRevertしたPull RequestがArgo CD Image Updaterに検知されないという問題が発生していました。
ここでいうRevert Pull Requestというのは、例えばAというPull Requestをマージした後、検証環境で問題があった場合にAというPull Requestを打ち消すような差分を積んだPull Requestのことです。
当初はImageのビルドに問題があるのではないかと考え、GitHub ActionsやECRのダッシュボードを確認してみたのですが、Docker Image自体は正常にビルドされECRにプッシュされていました。
つまり、ECR上で新しいイメージが作成されているにもかかわらず、Argo CD Image Updaterが更新を検知できない状態でした。
手動でSyncボタンを押したり、Argo CD Image Updaterの再起動も試しましたが、一向に新しいImageがロールアウトされることはなく、結局場当たり的にRevertしたPull Requestにさらに別のPull Requestをマージすることで、当座の対応をしていました。
原因
あるときふと思い立ってArgo CD Image Updaterのレポジトリを見ながら関連するイシューがないか探していたところ、たまたま以下のようなイシューを発見しました。
https://github.com/argoproj-labs/argocd-image-updater/issues/681
これはArgo CD Image Updater の update-strategy: latest
の仕様の改善を提案するイシューで、latest
の基準として、イメージのビルド時刻ではなくプッシュ時刻を採用するようにする提案でした。
RevertしたPull Requestの場合、この「最新のビルド時刻」というのが曲者で、イメージのビルド時に全てのレイヤーでキャッシュが使われた場合、イメージのビルド時刻は古いままとなってしまいます。
- イメージ A をビルド・プッシュ
- イメージ B をビルド・プッシュ
- B に問題があり、A の状態に Revert してイメージ C をプッシュ
- C は A のレイヤーを再利用するため、ビルド時刻は A と同じ
SUZURIではGitHub Actionsでのイメージビルド時にできる限りキャッシュを使うようにしているため、このような問題が発生していたようです。
解決方法
当該のイシューに書いてある通り、ビルドの時刻を Dockerfile に埋め込むことで対応できました。
具体的にはアプリケーションの Dockerfile に以下のように ARG で TIMESTAMP を追加しました。
# ArgoCD Image Updaterが更新を正しく検知するためにタイムスタンプを埋め込む
# https://github.com/argoproj-labs/argocd-image-updater/issues/681
ARG TIMESTAMP
RUN echo $TIMESTAMP > /dev/null
これを使ってGitHub Actionsにおけるイメージビルド時に以下のようなタイムスタンプを埋め込みます。
--build-arg TIMESTAMP=$(date +%s) \
これにより、ビルドごとに必ず一つのレイヤーは新規のレイヤーとして作られることになり、リリースによって作成されたDocker Imageのビルド時刻はプッシュ時刻と完全に一致するようになります。
結果としてArgo CD Image UpdaterがRevert Pull Requestの変更を正しく検知できるようになりました。
最後に
ブログにまとめるとさっと解決したように見えますが、実際には問題を発見してから解決までには数ヶ月ほどかかってしまいました。
類似事例を日本語で探していたのですがなかなか見つからず、Argo CD Image Updaterの問題だということを特定するまでにかなり時間がかかりました。
あり得そうなシチュエーションの割に日本語での情報が少なかったので、この記事が誰かの助けになれば幸いです。