Kubernetes マニフェストでのコンテナ イメージ ダイジェストの使用

このチュートリアルでは、Kubernetes にコンテナをデプロイするデベロッパーとオペレーターを対象に、コンテナ イメージ ダイジェストを使用してコンテナ イメージを識別する方法について説明します。コンテナ イメージ ダイジェストはコンテナ イメージを一意かつ不変的に識別します。

イメージ ダイジェストを使用してコンテナ イメージをデプロイすると、イメージタグを使用する場合と比べていくつかのメリットがあります。イメージ ダイジェストの詳細については、このチュートリアルに進む前に、コンテナ イメージ ダイジェストの使用に関する付属ドキュメントをご覧ください。

Kubernetes Pod 仕様のコンテナの image 引数は、ダイジェスト付きのイメージを受け入れます。この引数は、Deployment、StatefulSet、DaemonSet、ReplicaSet、CronJob、Job リソースの template セクションなど、Pod の仕様を使用するすべての場所に適用されます。

ダイジェストを使用してイメージをデプロイするには、イメージ名に続けて @sha256: とダイジェスト値を指定します。次に、ダイジェスト付きのイメージを使用する Deployment リソースの例を示します。Deployment は、クラスタ内のノードに分散された Pod の複数のレプリカを実行できる Kubernetes API オブジェクトです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
spec:
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
        ports:
        - containerPort: 8080

イメージ ダイジェストを使用するデメリットの 1 つは、イメージをレジストリに公開するまでダイジェスト値がわからないことです。新しいイメージをビルドすると、ダイジェスト値が変わるため、デプロイのたびに Kubernetes マニフェストを更新しなければなりません。

このチュートリアルでは、Skaffoldkptdigesterkustomizegke-deployko などのツールを利用して、マニフェストでイメージ ダイジェストを使用する方法について説明します。

推奨事項

このドキュメントでは、Kubernetes Deployment でイメージ ダイジェストを使用する方法をいくつか説明します。このドキュメントで説明するツールは、他のツールと組み合わせて使用します。たとえば、さまざまな環境のバリアントを作成するために kustomize で kpt 関数の出力を使用できます。Skaffold では、ko を使用してイメージをビルドし、kubectl または kpt を使用してイメージを Kubernetes クラスタにデプロイできます。

これらのツールが補完的な関係にあるのは、これらのツールが Kubernetes リソースモデル(KRM)に基づいて構造化された編集を行うためです。このモデルではツールがプラグイン可能なため、これらのツールを活用して、アプリやサービスのデプロイに役立つプロセスとパイプラインを構築できます。

最初の段階では、既存のツールとプロセスに最適なアプローチをおすすめします。

  • Skaffold では、イメージ参照にダイジェストを追加できます。この機能は、構成に小さな変更を加えて有効にします。Skaffold を採用すると、さまざまなツールがコンテナ イメージをビルドしてデプロイする仕組みを抽象化するなど、追加のメリットが提供されます。

  • Kubernetes クラスタで、変更用 Admission Webhook として digester ツールを使用すると、コンテナ イメージの現在のビルドとデプロイのプロセスへの影響を最小限に抑えながら、すべてのデプロイメントにダイジェストを追加できます。また、digester Webhook では、Namespace にラベルを追加することのみが必要とされ、Binary Authorization の導入も簡素化されます。

  • kpt は、Kubernetes マニフェストを操作する柔軟なツールが必要な場合に最適です。digester ツールは、kpt パイプラインのクライアントサイド KRM 関数として使用できます。

  • すでに kustomize を使用して環境間で Kubernetes マニフェストを管理している場合は、イメージ トランスフォーマーを利用して、ダイジェストによってイメージをデプロイすることをおすすめします。

  • Go アプリのイメージをビルドして公開する場合は ko が最適です。これは、KnativeTektonsigstore などのオープンソース プロジェクトで使用されています。

このドキュメントで説明するツールを使用していない場合は、Skaffold と digester Webhook から使い始めることをおすすめします。Skaffold は、デベロッパーとリリースチームの両方でよく使用されているツールで、このチュートリアルで説明する他のツールと連携して機能します。要件の変化に合わせて、これらの統合オプションを利用できます。Kubernetes の digester Webhook は、クラスタ全体に対してダイジェスト ベースのデプロイを有効にすることで、Skaffold を補完します。

Skaffold の使用

Skaffold は、Kubernetes クラスタに対するアプリケーションの継続的な開発とデプロイを行うためのコマンドライン ツールです。

Skaffold を使用してイメージを作成し、そのイメージを Artifact Registry に push します。Kubernetes マニフェスト テンプレートの image プレースホルダ値を、push されたイメージの名前、タグ、ダイジェストで置き換えます。

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/skaffold
    cd ~/container-image-digests-tutorial/skaffold
    
  2. Skaffold Git リポジトリのクローンを作成します。

    git clone https://github.com/GoogleContainerTools/skaffold.git
    
  3. getting-started のサンプルのあるディレクトリに移動します。

    cd skaffold/examples/getting-started
    
  4. Skaffold のバージョンと一致する Git タグをチェックアウトします。

    git checkout $(skaffold version)
    
  5. skaffold.yaml 構成ファイルを表示します。

    cat skaffold.yaml
    

    ファイルは、次のような形式です。

    apiVersion: skaffold/v4beta6
    kind: Config
    build:
      artifacts:
      - image: skaffold-example
    manifests:
      rawYaml:
      - k8s-pod.yaml

    build.artifacts セクションには、プレースホルダのイメージ名が含まれています。Skaffold は、入力のマニフェスト ファイルで、このプレースホルダを検索します。

    manifests セクションでは、現在のディレクトリで k8s-pod.yaml という名前の入力マニフェストを読み取るように Skaffold に指示しています。

    使用可能なすべてのオプションの概要については、skaffold.yaml リファレンス ドキュメントをご覧ください。

  6. Kubernetes マニフェスト テンプレートを表示します。

    cat k8s-pod.yaml
    

    次のようなファイルが表示されます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: getting-started
    spec:
      containers:
      - name: getting-started
        image: skaffold-example

    image フィールドの skaffold-example プレースホルダ値は、skaffold.yaml ファイル内の image フィールドの値と一致します。Skaffold によって、このプレースホルダ値は、レンダリングされた出力の完全なイメージ名とダイジェストで置き換えられます。

  7. イメージをビルドして Artifact Registry に push します。

    skaffold build \
        --default-repo=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY \
        --file-output=artifacts.json \
        --interactive=false \
        --push=true \
        --update-check=false
    

    このコマンドは、次のフラグを使用しています。

    • --file-output フラグは、Skaffold がビルドされたイメージに関する情報(ダイジェスト値など)を保存するファイルを指定します。
    • --push フラグは、--default-repo フラグで指定されたコンテナ イメージ レジストリにビルドイメージを push するように Skaffold に指示します。
    • --interactive フラグと --update-check フラグは、どちらも false に設定されています。ビルド パイプラインなどの非対話形式の環境では、これらのフラグを false に設定しますが、ローカル開発ではデフォルト値(両方のフラグで true)のままにしておきます。

    Cloud Deploy を使用して GKE にデプロイする場合は、リリースを作成する際に --file-output フラグのファイルを --build-artifacts フラグの数値として使用してください。

  8. 前の手順のコンテナ イメージの名前、タグ、ダイジェストを使用して、拡張された Kubernetes マニフェストをレンダリングします。

    skaffold render \
        --build-artifacts=artifacts.json \
        --digest-source=none \
        --interactive=false \
        --offline=true \
        --output=rendered.yaml \
        --update-check=false
    

    このコマンドは、次のフラグを使用しています。

    • --build-artifacts フラグは、前の手順の skaffold build コマンドからの出力ファイルを参照します。
    • --digest-source=none フラグは、コンテナ イメージ レジストリからのダイジェストを解決する代わりに、Skaffold が --build-artifacts フラグで提供されるファイルのダイジェスト値を使用することを意味します。
    • --offline=true フラグを使用すると、Kubernetes クラスタにアクセスせずにコマンドを実行できます。
    • --output フラグは、レンダリングされたマニフェストの出力ファイルを指定します。
  9. レンダリングされたマニフェストを表示します。

    cat rendered.yaml
    

    出力は次のようになります。

    apiVersion: v1
    kind: Pod
    metadata:
      name: getting-started
    spec:
      containers:
      - image: LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/skaffold-example:TAG@sha256:DIGEST
        name: getting-started

    この出力には次の値が含まれています。

    • TAG: Skaffold がイメージに割り当てたタグ
    • DIGEST: イメージ ダイジェストの値

digester の使用

digester は、Kubernetes Pod と Pod テンプレートの仕様のコンテナ イメージと init コンテナ イメージにダイジェストを追加します。タグを使用するコンテナ イメージの参照が、digester によって置き換えられます。

spec:
  containers:
  - image: gcr.io/google-containers/echoserver:1.10

イメージのダイジェストを使用する参照は、次のようになります。

spec:
  containers:
  - image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

digester は、Kubernetes クラスタで変更用 Admission Webhook として実行するか、kpt や kustomize コマンドライン ツールを使用してクライアントサイドの KRM 関数として実行できます。

digester KRM 関数の使用

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/digester-fn
    cd ~/container-image-digests-tutorial/digester-fn
    
  2. digester バイナリをダウンロードします。

    mkdir -p ${HOME}/bin
    export PATH=${HOME}/bin:${PATH}
    DIGESTER_VERSION=$(curl -sL https://api.github.com/repos/google/k8s-digester/releases/latest | jq -r .tag_name)
    curl -L "https://github.com/google/k8s-digester/releases/download/${DIGESTER_VERSION}/digester_$(uname -s)_$(uname -m)" --output ${HOME}/bin/digester
    chmod +x ${HOME}/bin/digester
    
  3. イメージ gcr.io/google-containers/echoserver を参照する Kubernetes Pod マニフェストを、タグ 1.10 を使用して作成します。

    cat << EOF > pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10
        ports:
        - containerPort: 8080
    EOF
    
  4. kpt を使用して digester の KRM 関数を実行します(マニフェストは、現在のディレクトリ(.)にあります)。

    kpt fn eval . --exec digester
    

    このコマンドを実行すると、kpt は現在のディレクトリでマニフェストのインプレース更新を行います。マニフェスト ファイルは変更せずに、kpt による更新後のマニフェストをコンソールに表示する場合は、--output unwrap フラグを追加します。

  5. 更新されたマニフェストを表示します。

    cat pod.yaml
    

    次のようなファイルが表示されます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
          ports:
            - containerPort: 8080

digester Admission Webhook を使用する

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/digester-webhook
    cd ~/container-image-digests-tutorial/digester-webhook
    
  2. kind を使用してローカルの Kubernetes クラスタを作成します。

    kind create cluster
    

    kind は、Docker を使用してローカルの Kubernetes クラスタを実行するためのコマンドライン ツールです。

  3. digester Webhook をデプロイします。

    DIGESTER_VERSION=$(curl -sL https://api.github.com/repos/google/k8s-digester/releases/latest | jq -r .tag_name)
    kustomize build "https://github.com/google/k8s-digester.git/manifests?ref=${DIGESTER_VERSION}" | kubectl apply -f -
    
  4. kind クラスタに digester-demo という Kubernetes Namespace を作成します。

    kubectl create namespace digester-demo
    
  5. digest-resolution: enabled ラベルを digester-demo Namespace に追加します。

    kubectl label namespace digester-demo digest-resolution=enabled
    

    digester Webhook は、このラベルを持つ Namespace の Pod にダイジェストを追加します。

  6. イメージ gcr.io/google-containers/echoserver を参照する Kubernetes Deployment マニフェストをタグ 1.10 を使用して作成します。

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-deployment
    spec:
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
        spec:
          containers:
          - name: echoserver
            image: gcr.io/google-containers/echoserver:1.10
            ports:
            - containerPort: 8080
    EOF
    
  7. digester-demo Namespace にマニフェストを適用します。

    kubectl apply --filename deployment.yaml --namespace digester-demo \
        --output jsonpath='{.spec.template.spec.containers[].image}{"\n"}'
    

    --output フラグは、kubectl にイメージ名をコンソールに出力するように指示します。次のような出力が表示されます。

    gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

    この出力は、digester Webhook がイメージのダイジェストを Deployment リソースの Pod テンプレート仕様に追加したことを示しています。

  8. Cloud Shell セッションでリソースを解放するために、Kind クラスタを削除します。

    kind delete cluster
    

kpt セッターの使用

kpt は、Kubernetes リソース マニフェストの管理、操作、カスタマイズ、適用を行うためのコマンドライン ツールです。

新しいイメージをビルドするときに kpt 関数カタログcreate-settersapply-setters KRM 関数を使用することで、Kubernetes マニフェストのイメージ ダイジェストを更新できます。

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/kpt
    cd ~/container-image-digests-tutorial/kpt
    
  2. 現在のディレクトリに kpt パッケージを作成します。

    kpt pkg init --description "Container image digest tutorial"
    
  3. イメージ gcr.io/google-containers/echoserver を参照する Kubernetes Pod マニフェストを、タグ 1.10 を使用して作成します。

    cat << EOF > pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10
        ports:
        - containerPort: 8080
    EOF
    
  4. kpt を使用して、そのマニフェスト フィールド用に echoimage という名前のセッターを作成します。ここで、既存の値は gcr.io/google-containers/echoserver:1.10 です。

    kpt fn eval . \
        --image gcr.io/kpt-fn/create-setters@sha256:0220cc87f29ff9abfa3a3b5643aa50f18d355d5e9dc9e1f518119633ddc4895c \
        -- "echoimage=gcr.io/google-containers/echoserver:1.10"
    
  5. マニフェストを確認します。

    cat pod.yaml
    

    次のようなファイルが表示されます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10 # kpt-set: ${echoimage}
        ports:
        - containerPort: 8080
  6. コンテナ イメージのダイジェストの値を取得します。

    DIGEST=$(gcloud container images describe \
        gcr.io/google-containers/echoserver:1.10 \
        --format='value(image_summary.digest)')
    
  7. 新しいフィールド値を設定します。

    kpt fn eval . \
        --image gcr.io/kpt-fn/apply-setters@sha256:4d4295727183396f0c3c6a75d2560254c2f9041a39e95dc1e5beffeb49cc1a12 \
        -- "echoimage=gcr.io/google-containers/echoserver:1.10@$DIGEST"
    

    このコマンドを実行すると、kpt はマニフェスト内の image フィールド値のインプレース置換を実行します。

  8. 更新されたマニフェストを表示します。

    cat pod.yaml
    

    次のようなファイルが表示されます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 # kpt-set: ${echoimage}
        ports:
        - containerPort: 8080

kustomize イメージ トランスフォーマーの使用

kustomize は、オーバーレイ、パッチ、トランスフォーマーを使用して Kubernetes マニフェストをカスタマイズできるコマンドライン ツールです。

kustomize イメージ トランスフォーマーを使用すると、既存のマニフェストに含まれているイメージ名、タグ、ダイジェストを更新できます。

次の kustomization.yaml スニペットは、Pod 仕様の image 値がトランスフォーマーの name 値と一致するイメージにトランスフォーマーの digest 値を使用するように、イメージ トランスフォーマーを構成します。

images:
- name: gcr.io/google-containers/echoserver
  digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

kustomize イメージ トランスフォーマーでイメージ ダイジェストを使用するには、次の操作を行います。

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/kustomize
    cd ~/container-image-digests-tutorial/kustomize
    
  2. kustomization.yaml ファイルを作成します。

    kustomize init
    
  3. タグ 1.10 を使用して、イメージ gcr.io/google-containers/echoserver を参照する Pod 仕様を含む Kubernetes マニフェストを作成します。

    cat << EOF > pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10
        ports:
        - containerPort: 8080
    EOF
    
  4. kustomization.yaml ファイルで、リソースとしてマニフェストを追加します。

    kustomize edit add resource pod.yaml
    
  5. イメージ トランスフォーマーを使用して、イメージのダイジェストを更新します。

    kustomize edit set image \
        gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
    
  6. kustomization.yaml ファイルでイメージ トランスフォーマーを表示します。

    cat kustomization.yaml
    

    次のようなファイルが表示されます。

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
    - pod.yaml
    images:
    - digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
      name: gcr.io/google-containers/echoserver
  7. 作成されたマニフェストを表示します。

    kustomize build .
    

    次のような出力が表示されます。

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
        name: echoserver
        ports:
        - containerPort: 8080
  8. 1 つのステップで kustomize トランスフォーマーを実行して生成されたマニフェストを Kubernetes クラスタに適用するには、--kustomize フラグを指定した kubectl apply コマンドを使用します。

    kubectl apply --kustomize .
    

    出力を後で適用する場合は、kustomize build コマンドの出力をファイルにリダイレクトします。

gke-deploy の使用

gke-deploy は、Google Kubernetes Engine(GKE)とともに使用するコマンドライン ツールです。gke-deploy は、kubectl コマンドライン ツールをラップし、Google が推奨する方法に従って作成するリソースを変更できます。

gke-deploy のサブコマンド(prepare または run)を使用すると、gke-deploy はイメージタグの代わりにダイジェストを使用し、イメージ ダイジェストで拡張したマニフェストをデフォルトで output/expanded/aggregated-resources.yaml ファイルに保存します。

gke-deploy run を使用すると、イメージタグをダイジェストに置き換え、拡張されたマニフェストを GKE クラスタに適用できます。このコマンドは便利ですが、デプロイ時にイメージタグが置換されます。タグに関連付けられたイメージが実際にデプロイされるまでに変更されていると、予期しないイメージがデプロイされる場合があります。本番環境のデプロイでは、マニフェストの生成と適用は別の手順で行うことをおすすめします。

Kubernetes Deployment マニフェストのイメージタグをイメージ ダイジェストに置き換えるには、次の操作を行います。

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/gke-deploy
    cd ~/container-image-digests-tutorial/gke-deploy
    
  2. gke-deploy をインストールします。

    go install github.com/GoogleCloudPlatform/cloud-builders/gke-deploy@latest
    
  3. イメージ gcr.io/google-containers/echoserver を参照する Kubernetes Deployment マニフェストをタグ 1.10 を使用して作成します。

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-deployment
    spec:
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
        spec:
          containers:
          - name: echoserver
            image: gcr.io/google-containers/echoserver:1.10
            ports:
            - containerPort: 8080
    EOF
    
  4. deployment.yaml マニフェストに基づいて拡張されたマニフェストを生成します。

    gke-deploy prepare \
        --filename deployment.yaml \
        --image gcr.io/google-containers/echoserver:1.10 \
        --version 1.10
    
  5. 拡張されたマニフェストを表示します。

    cat output/expanded/aggregated-resources.yaml
    

    次のような出力が表示されます。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/managed-by: gcp-cloud-build-deploy
        app.kubernetes.io/version: "1.10"
      name: echo-deployment
      namespace: default
    spec:
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
            app.kubernetes.io/managed-by: gcp-cloud-build-deploy
            app.kubernetes.io/version: "1.10"
        spec:
          containers:
          - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
            name: echoserver
            ports:
            - containerPort: 8080

    拡張されたマニフェストでは、イメージタグがダイジェストに置き換えられます。

    gke-deploy コマンドで使用した --version 引数により、Deployment の app.kubernetes.io/version ラベルと拡張されたマニフェストの Pod テンプレートのメタデータの値が設定されます。

    Cloud Build で gke-deploy を使用する方法については、Cloud Build のドキュメントで gke-deploy をご覧ください。

ko の使用

ko は、Go コンテナ イメージをビルドして Kubernetes クラスタにデプロイするためのコマンドライン ツールとライブラリです。ko は、Docker デーモンを使用せずにイメージをビルドするため、Docker をインストールできない環境でもイメージを使用できます。

ko サブコマンド build は、イメージをビルドして、コンテナ イメージ レジストリに公開するか、ローカルの Docker デーモンにロードします。

ko サブコマンド resolve は、次の処理を行います。

  • --filename 引数に指定した Kubernetes マニフェストの image フィールドでプレースホルダを検索し、ビルドするイメージを確認します。
  • イメージをビルドして公開します。
  • image 値のプレースホルダを、ビルドされたイメージの名前とダイジェストに置き換えます。
  • 拡張されたマニフェストを出力します。

ko サブコマンドの applycreaterun は、resolve と同じ手順を実行した後、拡張されたマニフェストを使用して kubectl applycreate、または run を実行します。

Go ソースコードからイメージをビルドし、イメージのダイジェストを Kubernetes Deployment マニフェストに追加するには、次の操作を行います。

  1. Cloud Shell で、このセクションで作成したファイルを保存するディレクトリを作成し、そのディレクトリに移動します。

    mkdir -p ~/container-image-digests-tutorial/ko
    cd ~/container-image-digests-tutorial/ko
    
  2. ko をダウンロードして PATH に追加します。

    mkdir -p ${HOME}/bin
    export PATH=${HOME}/bin:${PATH}
    KO_VERSION=$(curl -sL https://api.github.com/repos/ko-build/ko/releases/latest | jq -r .tag_name | cut -c2-)
    curl -L "https://github.com/ko-build/ko/releases/download/v${KO_VERSION}/ko_${KO_VERSION}_$(uname -s)_$(uname -m).tar.gz" | tar -zxC ${HOME}/bin ko
    
  3. app と呼ばれる新しいディレクトリに、example.com/hello-world というモジュール名で Go アプリを作成します。

    mkdir -p app/cmd/ko-example
    
    cd app
    
    go mod init example.com/hello-world
    
    cat << EOF > cmd/ko-example/main.go
    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("hello world")
    }
    EOF
    
  4. ko がイメージの公開に使用するイメージ リポジトリを定義します。

    export KO_DOCKER_REPO=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY
    

    この例では Artifact Registry を使用していますが、別のコンテナ イメージ レジストリで ko を使用できます。

  5. アプリのイメージをビルドして公開するには、次のいずれかの手順を実施します。

    • Go メイン パッケージのパスを指定してアプリのイメージをビルドし、公開します。

      ko build --base-import-paths ./cmd/ko-example
      

      オプションの引数 --base-import-paths を使用すると、ko はイメージ名としてメイン パッケージ ディレクトリの短縮名を使用します。

      ko は、イメージ名とダイジェストを stdout に次の形式で出力します。

      LOCATION-docker.pkg.dev/PROJECT_ID/ko-example@sha256:DIGEST

      この出力で、DIGEST はイメージ ダイジェストの値です。

    • ko を使用して、マニフェストのプレースホルダを、ビルドして公開するイメージの名前とダイジェストに置き換えます。

      1. Kubernetes Pod マニフェストを作成します。このマニフェストでは、image フィールドの値としてプレースホルダ ko://IMPORT_PATH_OF_YOUR_MAIN_PACKAGE を使用します。

        cat << EOF > ko-pod.yaml
        apiVersion: v1
        kind: Pod
        metadata:
          name: ko-example
        spec:
          containers:
          - name: hello-world
            image: ko://example.com/hello-world/cmd/ko-example
        EOF
        
      2. アプリのイメージをビルドして公開し、マニフェストのプレースホルダをイメージ名とダイジェストに置き換えます。

        ko resolve --base-import-paths --filename ko-pod.yaml
        

        ko は、イメージ名とダイジェストを含むマニフェストを stdout に出力します。

        apiVersion: v1
        kind: Pod
        metadata:
          name: ko-example
        spec:
          containers:
          - name: hello-world
            image: LOCATION-docker.pkg.dev/PROJECT_ID/ko-example@sha256:DIGEST

        この出力で、DIGEST はイメージ ダイジェストの値です。