CircleCI で CIRCLE_SHA1 を使う場合の注意
過去に自分がミスった内容と似た事例を他にも見かけたので、今更ながらメモ。
TL; DR
- CircleCI の ECS/ECR へのデプロイに関するドキュメントで、コンテナイメージのタグに
CIRCLE_SHA1
の値が設定されているが、これには要注意 - CircleCI における
CIRCLE_SHA1
の値は、最終コミットを識別するハッシュ値だよ - Git上のブランチやタグに依って変わるわけではないので、ブランチ・タグによって異なるものの識別には使えないよ
- イメージタグのような識別子を作成する場合、それが必要なユニーク性を持っているか確認することが必要だよ
CircleCI で ECR/ECS にデプロイするときのコンテナイメージタグ
CircleCI 公式のドキュメントとして、以下の記事が公開されています。 (2019/12/15現在)
上記記事より引用
version: 2.1 orbs: aws-ecr: circleci/aws-ecr@0.0.2 aws-ecs: circleci/aws-ecs@0.0.3 workflows: build-and-deploy: jobs: - aws-ecr/build_and_push_image: account-url: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com" repo: "${AWS_RESOURCE_NAME_PREFIX}" region: ${AWS_DEFAULT_REGION} tag: "${CIRCLE_SHA1}" - ...
ビルドの結果出来上がる個々の コンテナイメージを識別するものとしてタグを設定します(上記例の tag
)が、ここでは、タグに設定する値は "${CIRCLE_SHA1}"
となっています。
(以前のドキュメントでは、普通に docker
コマンドを使用して docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com:${CIRCLE_SHA1}
という感じになっていたはず…)
CIRCLE_SHA1 って?
さて、この CIRCLE_SHA1
に設定される値はどのようなものでしょうか。こちらも CircleCI の公式ドキュメントで説明されています。
VCS が Git であれば、 Git のコミットハッシュと同一の値になります。CircleCI でビルドを開始する際に Git リポジトリから取得した内容 (バージョン断面) を識別するものと考えていいと思います。
コンテナイメージタグに CIRCLE_SHA1 を設定すると
この CIRCLE_SHA1
をコンテナイメージタグに使うと、どうなるでしょう?
「Git リポジトリの内容が同一ならば、ビルドされるコンテナイメージも同一である」という条件が成り立つのであれば、これで問題ありません。CIRCLE_SHA1
がリポジトリの内容ごとにユニークであるので、そこと 1:1 に対応付けられるコンテナイメージも CIRCLE_SHA1
で識別することができます。
しかし、上記の条件が必ずしも成り立たない場合、つまりGitリポジトリが同一であっても、できあがるコンテナイメージが異なる場合がある(異なるイメージそれぞれを管理する必要がある)場合は注意が必要です。
例えば、よく見かける方式として、本番環境やステージング環境にリリースを行うために、Git 上の master から特定のブランチにマージし、それをトリガーとして CircleCI で各環境向けのビルドおよびデプロイを行う、という方式を考えます。
コンテナイメージ内に環境の情報を含める場合は、当然、リポジトリの内容が同一であっても、本番環境向けとステージング環境向けでできあがるコンテナイメージに差異が発生します。しかし、 CIRCLE_SHA1
の値は、トリガーとなったブランチに依らず。あくまでも最終コミットのハッシュ値によって決定されるため、それぞれのコンテナイメージに同一のタグが設定されることになります。
Docker および ECR の仕様上、すでに存在するタグと同一のタグを付与して Push した場合、古い方のイメージからはタグが剥がされてしまうため、例えば ステージング環境へのデプロイ後に本番環境へのデプロイを行った場合、ステージング環境の ECS クラスタにも本番環境用のコンテナイメージがデリバリされてしまうことになります。また、並行して複数環境のビルド・デプロイを行って、完了する順番が不定となるような場合、見かけ上ランダムにコンテナイメージが切り替わるため、再現検証の難しい障害となることがあります。
回避方法
この問題をするには、以下のやり方が考えられます
インフラ構成や実装の手間、ユニーク性の要件、費用等に合わせた方法を取るとよいでしょう。
まとめ
CIRCLE_SHA1
(に限りませんが) を何かの識別子として使用する場合、そのユニーク性が識別する対象のユニーク性と合致するかどうか、毎回きちんと検証しましょうというお話でした。