Kaniko キャッシュの使用

概要

Kaniko キャッシュは、Cloud Build の機能の 1 つであり、コンテナビルドのアーティファクトをキャッシュに保存します。キャッシュ保存の際は、コンテナ イメージ レジストリ(Google 独自の Container Registry など)内に中間レイヤが保存され、インデックス付けされます。レジストリ内のレイヤは、以降のビルドに利用できます。Kaniko キャッシュはオープンソースのツール Kaniko をベースとしています。

Kaniko キャッシュの仕組みは次のとおりです。

  • Cloud Build では、コンテナ イメージのレイヤがビルド時にレジストリに直接アップロードされるため、明示的な push ステップはありません。すべてのレイヤが正常にビルドされると、それらレイヤを含むイメージ マニフェストがレジストリに書き込まれます。

  • Kaniko では、各レイヤが、その作成元の Dockerfile ディレクティブと、先行するすべてのディレクティブ(FROM 行のイメージのダイジェストに至るまでのもの)のコンテンツに従ってキャッシュに保存されます。

ビルドでの Kaniko キャッシュの有効化

Docker ビルドで Kaniko キャッシュを有効にするには、次に示すように、cloudbuild.yaml ファイルで cloud-builders/docker ワーカーを kaniko-project/executor ワーカーに置き換えます。

Kaniko ビルド

steps:
- name: 'gcr.io/kaniko-project/executor:latest'
  args:
  - --destination=gcr.io/$PROJECT_ID/image
  - --cache=true
  - --cache-ttl=XXh

Docker ビルド

steps:
- name: gcr.io/cloud-builders/docker
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/image', '.']
images:
- 'gcr.io/$PROJECT_ID/image'

ここで

  • --destination=gcr.io/$PROJECT_ID/image はターゲットのコンテナ イメージです。Cloud Build によって、Dockerfile が含まれるプロジェクトからのプロジェクト ID が自動的に置き換えられます。

  • --cache=true を指定すると、Kaniko キャッシュが有効になります。

  • --cache-ttl=XXh ではキャッシュ保存の有効期限が設定されます。XX はキャッシュ保存の期限が切れるまでの時間数です。キャッシュ保存の有効期限の構成をご覧ください。

注: Kaniko キャッシュでは images: 属性をサポートしていません。

gcloud builds submit --tag [IMAGE] コマンドを使用してビルドを実行する場合、次に示すようにプロパティ builds/use_kanikoTrue に設定することで Kaniko キャッシュを有効化できます。

gcloud config set builds/use_kaniko True

例: Node.js ビルドでの Kaniko キャッシュの使用

次の例では、Dockerfile に関して一般的に推奨されている方法を使用して Node.js アプリの差分ビルドを実行する方法を示しています。ここに示す方法は、サポートされている他のすべての言語のビルドにも適用されます。

ここでは、ビルド間で変更される可能性が低いディレクティブを Dockerfile の先頭に移動し、変更される可能性の高いディレクティブを末尾に移動します。これによってビルドプロセスでの差分処理が効率化され、ビルドを迅速化できます。

ここでは次の Dockerfile について考えてみます。

FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD [ "npm", "start" ]

この Dockerfile では次の処理が行われます。

このビルドを実行する際には、Cloud Build に複数のビルドを対象とするイメージレイヤのキャッシュが存在しないため、ビルドの実行のたびに Cloud Build で各ステップを実行しなければなりません。しかし、Kaniko キャッシュを有効にしてこのビルドを実行した場合は、以下の処理が行われます。

  1. 初回の実行時に Cloud Build によってすべてのステップが実行され、各ディレクティブによってレイヤがコンテナ イメージ レジストリに書き込まれます。

  2. Kaniko では、レイヤの作成元のディレクティブとそのすべての先行ディレクティブのコンテンツから導出されたキャッシュキーによるタグが、各レイヤに付けられます。

  3. それ以降、Cloud Build で同じ Dockerfile からビルドを実行するときは、そのファイルが変更されたかどうかが確認されます。変更されていない場合、Cloud Build ではレジストリに保存されているキャッシュ内のレイヤを使用してビルドが実施されるため、ビルドの完了までの時間が短縮されます。以下をご覧ください。

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # no change -> cached!
CMD [ "npm", "start" ]     # metadata, nothing to do

package.json ファイルを変更した場合、Cloud Build では、COPY ステップより前のディレクティブについてはコンテンツが変更されていないため、実行する必要がありません。ただし、package.json ファイルの変更によって COPY ステップは変更されるため、COPY ステップの後のステップはすべて再実行する必要があります。以下をご覧ください。

FROM node:8                # no change -> cached!
COPY package*.json ./      # changed, must re-run
RUN npm install            # preceding layer changed
COPY . .                   # preceding layer changed
CMD [ "npm", "start" ]     # metadata, nothing to do

アプリのコンテンツだけが変更され、依存関係は変更されていないという最も一般的な状況では、package.json ファイルは変更されないままで保持され、Cloud Build では最後の COPY . . ステップのみの再実行が必要になります。この結果、このステップではソース コンテンツがコンテナ イメージ レジストリ内のレイヤにコピーされるだけなので、ビルドが迅速化されます。

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # changed, must re-run
CMD [ "npm", "start" ]     # metadata, nothing to do

キャッシュ保存の有効期限の構成

--cache-ttl フラグは、キャッシュ内のレイヤのうち特定の有効期限内に push されなかったものを無視するよう Kaniko に指示します。

構文は --cache-ttl=XXh で、XX は時間数です。たとえば、--cache-ttl=6h に設定した場合、キャッシュ保存の有効期限は 6 時間です。

有効期限を長くすると、依存関係が頻繁に変更されない場合は、ビルドが迅速化されます。有効期限を短くすると、更新された依存関係(Maven パッケージや Node.js モジュール)がより迅速に取り込まれるものの、キャッシュ内のレイヤがあまり使用されなくなります。

キャッシュ保存の有効期限をコマンドラインから設定するには、次のコマンドを実行します。

gcloud config set builds/kaniko_cache_ttl XX

XX は、時間数で表したキャッシュ保存の有効期限です。

Node.js の例では、RUN ./install_node.sh ディレクティブの出力は変わらないままであるため、キャッシュ保存されていても、このディレクティブを定期的に再実行する必要があります。--cache-ttl パラメータの 6 時間という設定はバランスのとれた値です。このディレクティブのコンテンツが変更されたかどうかに関係なく、営業日ごとに少なくとも 1 回はディレクティブが実行されるからです。ただし、ビルドの実行時に毎回実行されるわけではないのでシステムの負荷が軽減されます。

フィードバックを送信...