kaniko でコンテナイメージをビルドすると際にキャッシュが聞かない場合がある

kaniko でコンテナイメージをビルドすると際にキャッシュが聞かない場合がある

tl;dr

kaniko の --build-arg にコンテナイメージのビルド毎に異なる値を入れる運用してて、 v0.19.0 より前のバージョンを使用してる場合はキャッシュが聞かないので注意してください。

発生した問題

kaniko の説明については↓を参照してください。 kaniko が解決したいこと

コンテナイメージ用の Dockerfile 内で環境変数を設定するのに ARG を使用してる場合、kaniko でビルドする場合 --build-arg を使用することで外から ARG に値を渡すことが出来ます。

仕事で GKE 用のコンテナイメージを CloudBuild でビルドしており、運用上の関係でソースコード内で Cloud Build の REVISION_ID (毎回のビルドで生成されるハッシュ値) を参照している箇所があるため、それを外から渡してやる必要がありました。

steps:
  - name: 'gcr.io/kaniko-project/executor:v0.13.0'
    args:
      - --destination=gcr.io/$PROJECT_ID/app:latest
      - --cache=true
      - --cache-ttl=6h
      - --build-arg=BUILD_ID=${REVISION_ID}

↑のようにコンテナイメージをビルドしてコンテナ内で正常に変数を取得できることを確認できたのですが、2回目のビルドから変更が無い Dockerfile コマンド (COPY など)にもかかわらず全くキャッシュが効かないという事象が発生しました。

原因を調査してみたところ、v0.18.0 以前のバージョンの kaniko には --build-arg にビルド毎に異なる値を入れるとキャッシュが聞かない問題があることがわかりました。

Is there a way not to include build-args in the cache key? · Issue#1008 · GoogleContainerTools/kaniko https://github.com/GoogleContainerTools/kaniko/issues/637 · Issue#637 · GoogleContainerTools/kaniko

func (s *stageBuilder) build() error {
    ...
    compositeKey := NewCompositeCache(dgst)
    compositeKey.AddKey(s.opts.BuildArgs...)
    ...
}

ただ、現在は https://github.com/GoogleContainerTools/kaniko/pull/1085 にて修正されており、v0.19.0 にて変更が取り込まれているので、kaniko を使用する際は v0.19.0 以降のバージョンを使用するのが良いでしょう。

v0.18.0 以前のバージョンを使ってる場合の回避策 (kubernetes の場合)

kubernetes を使ってる場合↓のようにして env で環境を設定を出来ます。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: busybox
    image: busybox
    env:
    - name: TEST_ENV
      value: "test"

これを利用して ConfigMap をビルド時に動的に作り、↑の Pod の yaml から参照してやることで回避することが可能です。