セカンダリ ブートディスクを使用してデータまたはコンテナ イメージをプリロードする


このページでは、Google Kubernetes Engine(GKE)でセカンダリ ブートディスクを使用して、新しいノードにデータまたはコンテナ イメージをプリロードし、ワークロードの起動レイテンシを改善する方法について説明します。これにより、ワークロードではコールド スタートの高速化と、プロビジョニングされたリソースの全体的な使用率の向上が実現します。

このページを読む前に、Google Cloud、Kubernetes、コンテナ、YAML、containerd ランタイム、Google Cloud CLI について理解しておいてください。

概要

Standard クラスタの GKE バージョン 1.28.3-gke.1067000 以降と Autopilot クラスタの GKE バージョン 1.30.1-gke.1329000 以降では、セカンダリ ブートディスクを使用してノードプールを構成できます。GKE には、ノードをプロビジョニングして、ML モデルやコンテナ イメージなどのデータをプリロードするように指示できます。プリロードされたコンテナ イメージやセカンダリ ディスクのデータを使用すると、ワークロードに次のようなメリットがあります。

  • 大規模なコンテナ イメージの pull やデータのダウンロード時のレイテンシの短縮
  • 自動スケーリングの高速化
  • メンテナンス イベントやシステムエラーなどの中断からの迅速な復元

以降のセクションでは、GKE Autopilot クラスタと Standard クラスタでセカンダリ ブートディスクを構成する方法について説明します。

セカンダリ ブートディスクの仕組み

セカンダリ ブートディスクにプリロードされたコンテナ イメージまたはデータを使用することで、ワークロードの起動を高速化できます。セカンダリ ブートディスクには次の特性があります。

  • セカンダリ ブートディスクは、分散ブロック ストレージを基盤とする Persistent Disk です。ディスク イメージがゾーンですでに使用されている場合、同じディスク イメージから作成される後続のディスクの作成時間は短くなります。
  • セカンダリ ブートディスクのタイプは、ノードのブートディスクと同じです。
  • セカンダリ ブートディスクのサイズは、ディスク イメージのサイズによって決まります。

ノードプールにセカンダリ ブートディスクを追加しても、ノードのプロビジョニング時間は増加しません。GKE は、ノードのプロビジョニング プロセスと並行して、ディスク イメージからセカンダリ ブートディスクをプロビジョニングします。

ベスト プラクティス:

プリロードされたコンテナ イメージをサポートするため、GKE は、セカンダリ ブートディスクからコンテナ イメージを読み取るプラグインを使用して containerd ランタイムを拡張します。コンテナ イメージはベースレイヤで再利用されます。

大きなベースレイヤはセカンダリ ブートディスクにプリロードし、小さな上位レイヤをコンテナ レジストリから pull できます。

始める前に

始める前に、次の作業が完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。

要件

セカンダリ ブートディスクの使用には、次の要件が適用されます。

  1. クラスタが GKE Standard で、GKE バージョン 1.28.3-gke.1067000 または GKE Autopilot でバージョン 1.30.1-gke.1329000 を実行している。
  2. ディスク イメージを変更するときは、新しいノードプールを作成する必要があります。既存のノードのディスク イメージの更新はサポートされていません。
  3. セカンダリ ブートディスク機能を使用するようにイメージ ストリーミングを構成します。
  4. containerd ノードイメージで Container-Optimized OS を使用します。Autopilot ノードはデフォルトでこのノードイメージを使用します。
  5. ビルド時にデータが準備されたディスク イメージを準備するか、プリロードされたコンテナ イメージを使用してディスク イメージを準備します。クラスタがディスク イメージにアクセスしてノードに読み込まれるようにします。

    ベスト プラクティス:

    CI / CD パイプラインでディスク イメージを自動化します。

制限事項

セカンダリ ブートディスクには次の制限があります。

  • 既存ノードのセカンダリ ブートディスクを更新することはできません。新しいディスク イメージを接続するには、新しいノードプールを作成します。

セカンダリ ブートディスクを準備する

セカンダリ ブートディスクを準備するときに、コンテナ イメージをプリロードする場合は [イメージ] タブを選択し、データをプリロードする場合は [データ] タブを選択して、次の手順を完了します。

画像

GKE には、仮想マシン(VM)を作成してディスク上のコンテナ イメージを pull し、そのディスクからディスク イメージを作成する gke-disk-image-builder というツールが用意されています。

複数のプリロードされたコンテナ イメージを含むディスク イメージを作成するには、次の操作を行います。

  1. gke-disk-image-builder の実行ログを保存する Cloud Storage バケットを作成します。
  2. gke-disk-image-builder を使用してディスク イメージを作成します。
go run ./cli \
    --project-name=PROJECT_ID \
    --image-name=DISK_IMAGE_NAME \
    --zone=LOCATION \
    --gcs-path=gs://LOG_BUCKET_NAME \
    --disk-size-gb=10 \
    --container-image=docker.io/library/python:latest \
    --container-image=docker.io/library/nginx:latest

次のように置き換えます。

  • PROJECT_ID: Google Cloud プロジェクトの名前。
  • DISK_IMAGE_NAME: ディスクのイメージの名前。例: nginx-python-image
  • LOCATION: クラスタのロケーション
  • LOG_BUCKET_NAME: 実行ログを保存する Cloud Storage バケットの名前。例: gke-secondary-disk-image-logs/

gke-disk-image-builder を使用してディスク イメージを作成すると、Google Cloud によってプロセスを完了するために複数のリソース(VM インスタンス、一時ディスク、永続ディスクなど)が作成されます。実行後、イメージ ビルダーは、作成したディスク イメージを除くすべてのリソースをクリーンアップします。

データ

次の手順で、データソースとしてカスタム ディスク イメージを作成します。

  1. 空のディスクで VM を作成する
  2. SSH で VM に接続する
    1. 空のディスクをマウントする
    2. 空のディスクにデータをダウンロードする
  3. ディスクからカスタム イメージを作成する

セカンダリ ブートディスクを構成する

セカンダリ ブートディスクは、GKE Autopilot クラスタまたは GKE Standard クラスタで構成できます。

ベスト プラクティス:

フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用します。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。

GKE Autopilot を使用する

このセクションでは、ディスク イメージの許可リストを作成し、既存の GKE Autopilot クラスタでディスク イメージを許可します。次に、セカンダリ ブートディスクを使用するように Pod ノードセレクタを変更します。

プロジェクトでディスク イメージを許可する

このセクションでは、GKE が Google Cloud プロジェクトのディスク イメージからセカンダリ ブートディスクを含むノードを作成できるように GCPResourceAllowlist を作成します。

  1. 次のマニフェストを allowlist-disk.yaml として保存します。

    apiVersion: "node.gke.io/v1"
    kind: GCPResourceAllowlist
    metadata:
      name: gke-secondary-boot-disk-allowlist
    spec:
      allowedResourcePatterns:
      - "projects/PROJECT_ID/global/images/.*"
    

    PROJECT_ID は、ディスク イメージをホストするプロジェクト ID に置き換えます。

  2. 次のようにマニフェストを適用します。

    kubectl apply -f allowlist-disk.yaml
    

    GKE は、プロジェクト内のすべてのディスク イメージからセカンダリ ブートディスクを含むノードを作成します。

セカンダリ ブートディスクを使用するように Pod ノードセレクタを更新する

このセクションでは、GKE がセカンダリ ブートディスクを使用してノードを作成するように Pod 仕様を変更します。

  1. Pod テンプレートに nodeSelector を追加します。

    nodeSelector:
        cloud.google.com.node-restriction.kubernetes.io/gke-secondary-boot-disk-DISK_IMAGE_NAME=CONTAINER_IMAGE_CACHE.PROJECT_ID
    

    次のように置き換えます。

    • DISK_IMAGE_NAME: ディスク イメージの名前。
    • PROJECT_ID: ディスク イメージをホストするプロジェクト ID。
  2. kubectl apply コマンドを使用して、Pod テンプレートを使用して Kubernetes 仕様を適用します。

  3. セカンダリ ブートディスク キャッシュが使用中であることを確認します。

    kubectl get events --all-namespaces
    

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

    75s         Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm   Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  4. イメージ pull のレイテンシを確認します。

    kubectl describe pod POD_NAME
    

    POD_NAME は、Pod の名前で置き換えます。

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

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

キャッシュに保存されたコンテナ イメージに想定されるイメージ pull のレイテンシは、イメージサイズに関係なく大幅に短縮されます。

GKE Standard を使用する

GKE Standard クラスタとノードプールを作成するには、次の手順を完了します。セカンダリ ブートディスクにコンテナ イメージをプリロードするのか、データをプリロードするかに応じて、[イメージ] タブまたは [データ] タブを選択します。

画像

セカンダリ ブートディスクを構成するには、Google Cloud CLI または Terraform を使用します。

gcloud

  1. イメージ ストリーミングを有効にして GKE Standard クラスタを作成します。

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-image-streaming
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • LOCATION: クラスタのロケーション。
    • VERSION: 使用する GKE のバージョン。GKE のバージョンは 1.28.3-gke.1067000 以降にする必要があります。
  2. 同じプロジェクトにセカンダリ ブートディスクを含むノードプールを作成します。

    gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location LOCATION \
    --enable-image-streaming \
    --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE
    

    次のように置き換えます。

    • NODE_POOL_NAME: ノードプールの名前。
    • CLUSTER_NAME: 既存のクラスタの名前。
    • LOCATION: クラスタのコンピューティング ゾーン(カンマ区切り)。
    • DISK_IMAGE_NAME: ディスク イメージの名前。

    別のプロジェクトのディスク イメージからセカンダリ ブートディスクを含むノードプールを作成するには、別のプロジェクトでセカンダリ ブートディスクを使用するの手順を完了します。

  3. Pod テンプレートに nodeSelector を追加します。

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  4. セカンダリ ブートディスク キャッシュが使用中であることを確認します。

    kubectl get events --all-namespaces
    

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

    75s       Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  5. 次のコマンドを実行して、イメージ pull レイテンシを確認します。

    kubectl describe pod POD_NAME
    

    POD_NAME は、Pod の名前で置き換えます。

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

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

キャッシュに保存されたコンテナ イメージの想定されるイメージ pull レイテンシは、イメージサイズに関係なく数秒以内にする必要があります。

Terraform

  1. Terraform を使用してデフォルト ノードプールを持つクラスタを作成するには、次の例をご覧ください。

    resource "google_container_cluster" "default" {
      name               = "default"
      location           = "us-central1-a"
      initial_node_count = 1
      # Set `min_master_version` because secondary_boot_disks require GKE 1.28.3-gke.106700 or later.
      min_master_version = "1.28"
      # Setting `deletion_protection` to `true` would prevent
      # accidental deletion of this instance using Terraform.
      deletion_protection = false
    }
  2. 同じプロジェクトにセカンダリ ブートディスクを含むノードプールを作成します。

    resource "google_container_node_pool" "secondary-boot-disk-container" {
      name               = "secondary-boot-disk-container"
      location           = "us-central1-a"
      cluster            = google_container_cluster.default.name
      initial_node_count = 1
    
      node_config {
        machine_type = "e2-medium"
        image_type   = "COS_CONTAINERD"
        gcfs_config {
          enabled = true
        }
        secondary_boot_disks {
          disk_image = ""
          mode       = "CONTAINER_IMAGE_CACHE"
        }
      }
    }

    Terraform の使用方法の詳細については、GKE での Terraform のサポートをご覧ください。

  3. Pod テンプレートに nodeSelector を追加します。

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  4. セカンダリ ブートディスク キャッシュが使用中であることを確認します。

    kubectl get events --all-namespaces
    

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

    75s       Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  5. 次のコマンドを実行して、イメージ pull レイテンシを確認します。

    kubectl describe pod POD_NAME
    

    POD_NAME は、Pod の名前で置き換えます。

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

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

キャッシュに保存されたコンテナ イメージの想定されるイメージ pull レイテンシは、イメージサイズに関係なく数秒以内にする必要があります。

Terraform の使用方法の詳細については、GKE での Terraform のサポートをご覧ください。

データ

セカンダリ ブートディスクとプリロード データを構成するには、Google Cloud CLI または Terraform を使用します。

gcloud

  1. イメージ ストリーミングを有効にして GKE Standard クラスタを作成します。

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-image-streaming
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • LOCATION: クラスタのロケーション。
    • VERSION: 使用する GKE のバージョン。GKE バージョンは、1.28.3-gke.1067000 以降である必要があります。
  2. --secondary-boot-disk フラグを使用して、セカンダリ ブートディスクを含むノードプールを作成します。

    gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location LOCATION \
    --enable-image-streaming \
    --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME
    

    次のように置き換えます。

    • NODE_POOL_NAME: ノードプールの名前。
    • CLUSTER_NAME: 既存のクラスタの名前。
    • LOCATION: クラスタのコンピューティング ゾーン(カンマ区切り)。
    • DISK_IMAGE_NAME: ディスク イメージの名前。

    別のプロジェクトのディスク イメージからセカンダリ ブートディスクを含むノードプールを作成するには、別のプロジェクトでセカンダリ ブートディスクを使用するの手順を完了します。

    プリロードされたデータを含むセカンダリ ディスクが各ノードに存在するノードプールが作成されます。GKE は、セカンダリ ブートディスクをノードにアタッチしてマウントします。

  3. 必要に応じて、hostPath ボリューム マウントを使用して、Pod コンテナにセカンダリ ディスク イメージをマウントできます。次のマニフェストを使用して Pod リソースを定義し、hostPath ボリューム マウントを使用してそのコンテナにデータディスクをプリロードします。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-name
    spec:
      containers:
      ...
      volumeMounts:
      - mountPath: /usr/local/data_path_sbd
        name: data_path_sbd
    ...
    volumes:
      - name: data_path_sbd
        hostPath:
            path: /mnt/disks/gke-secondary-disks/gke-DISK_IMAGE_NAME-disk
    

    DISK_IMAGE_NAME は、ディスク イメージの名前に置き換えます。

Terraform

  1. Terraform を使用してデフォルト ノードプールを持つクラスタを作成するには、次の例をご覧ください。

    resource "google_container_cluster" "default" {
      name               = "default"
      location           = "us-central1-a"
      initial_node_count = 1
      # Set `min_master_version` because secondary_boot_disks require GKE 1.28.3-gke.106700 or later.
      min_master_version = "1.28"
      # Setting `deletion_protection` to `true` would prevent
      # accidental deletion of this instance using Terraform.
      deletion_protection = false
    }
  2. 同じプロジェクトにセカンダリ ブートディスクを含むノードプールを作成します。

    resource "google_container_node_pool" "secondary-boot-disk-data" {
      name               = "secondary-boot-disk-data"
      location           = "us-central1-a"
      cluster            = google_container_cluster.default.name
      initial_node_count = 1
    
      node_config {
        machine_type = "e2-medium"
        image_type   = "COS_CONTAINERD"
        gcfs_config {
          enabled = true
        }
        secondary_boot_disks {
          disk_image = ""
        }
      }
    }

    Terraform の使用方法の詳細については、GKE での Terraform のサポートをご覧ください。

  3. 必要に応じて、hostPath ボリューム マウントを使用して、Pod コンテナにセカンダリ ディスク イメージをマウントできます。次のマニフェストを使用して Pod リソースを定義し、hostPath ボリューム マウントを使用してそのコンテナにデータディスクをプリロードします。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-name
    spec:
      containers:
      ...
      volumeMounts:
      - mountPath: /usr/local/data_path_sbd
        name: data_path_sbd
    ...
    volumes:
      - name: data_path_sbd
        hostPath:
            path: /mnt/disks/gke-secondary-disks/gke-DISK_IMAGE_NAME-disk
    

    DISK_IMAGE_NAME は、ディスク イメージの名前に置き換えます。

セカンダリ ブートディスクを使用したクラスタの自動スケーリング

ノードプールを作成し、セカンダリ ブートディスクでクラスタの自動スケーリングを構成するには、Google Cloud CLI を使用します。

  gcloud container node-pools create NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --location LOCATION \
      --enable-image-streaming \
      --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE \
      --enable-autoscaling \
      --num-nodes NUM_NODES \
      --min-nodes MIN_NODES \
      --max-nodes MAX_NODES

次のように置き換えます。

  • NODE_POOL_NAME: ノードプールの名前。
  • CLUSTER_NAME: 既存のクラスタの名前。
  • LOCATION: クラスタのコンピューティング ゾーン(カンマ区切り)。
  • DISK_IMAGE_NAME: ディスク イメージの名前。
  • MIN_NODES: 指定したノードプールで自動的にスケーリングするゾーンの最小ノード数。GKE バージョン 1.24 以降でノードプール全体の最小ノード数を指定するには、--total-min-nodes を使用します。フラグ --total-min-nodes--total-max-nodes は、フラグ --min-nodes--max-nodes と相互に排他的です。
  • MAX_NODES: 指定したノードプールで自動的にスケーリングするゾーンの最大ノード数。GKE バージョン 1.24 以降でノードプール全体のノードの最大数を指定するには、--total-max-nodes を使用します。フラグ --total-min-nodes--total-max-nodes は、フラグ --min-nodes--max-nodes と相互に排他的です。

セカンダリ ブートディスクを使用したノードの自動プロビジョニング

GKE 1.30.1-gke.1329000 以降では、ワークロードのリソース需要を満たすためにノードプールを自動的に作成および削除するよう、ノードの自動プロビジョニングを構成できます。

  1. 次のように、GKE ノードの自動プロビジョニング用のセカンダリ ブートディスクにディスク イメージ許可リスト カスタム リソースを作成します。

    apiVersion: "node.gke.io/v1"
    kind: GCPResourceAllowlist
    metadata:
      name: gke-secondary-boot-disk-allowlist
    spec:
      allowedResourcePatterns:
      - "projects/<PROJECT_ID>/global/images/.*"
    

    PROJECT_ID は、ディスク イメージをホストするプロジェクト ID に置き換えます。

  2. クラスタに許可リスト カスタム リソースをデプロイするには、次のコマンドを実行します。

    kubectl apply -f ALLOWLIST_FILE
    

    ALLOWLIST_FILE は、マニフェスト ファイル名に置き換えます。

  3. セカンダリ ブートディスクを使用するように Pod ノードセレクタを更新します。

    nodeSelector:
        cloud.google.com.node-restriction.kubernetes.io/gke-secondary-boot-disk-DISK_IMAGE_NAME=CONTAINER_IMAGE_CACHE.PROJECT_ID
    

    次のように置き換えます。

    • DISK_IMAGE_NAME: ディスク イメージの名前。
    • PROJECT_ID: ディスク イメージをホストするプロジェクト ID。

別のプロジェクトでセカンダリ ブートディスクを使用する

セカンダリ ブートディスクを含むノードプールを作成する場合は、--secondary-boot-disk フラグを使用して、別のプロジェクトのディスク イメージを使用するように GKE に指示できます。

  1. 別のプロジェクトのディスク イメージから、セカンダリ ブートディスクを含むノードプールを作成するには、--secondary-boot-disk フラグを使用します。例:

    gcloud beta container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location LOCATION \
        --enable-image-streaming \
        --secondary-boot-disk=disk-image=projects/IMAGE_PROJECT_ID/global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE
    
    

    次のように置き換えます。

    • DISK_IMAGE_NAME: ディスク イメージの名前。
    • IMAGE_PROJECT_ID: ディスク イメージが属するプロジェクトの名前。

    プリロードされたデータを含むセカンダリ ディスクが各ノードに存在するノードプールが作成されます。これにより、セカンダリ ブートディスクがノードにアタッチされ、マウントされます。

  2. クラスタ サービス アカウントに Compute イメージ ユーザーのロールを追加して、別のプロジェクトに属するディスク イメージへのアクセス権を付与します。

    • デフォルトのコンピューティング サービス アカウント: CLUSTER_PROJECT_NUMBER@cloudservices.gserviceaccount.com
    • GKE サービス アカウント: service-CLUSTER_PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
    gcloud projects add-iam-policy-binding IMAGE_PROJECT_ID \
        --member serviceAccount:CLUSTER_PROJECT_NUMBER@cloudservices.gserviceaccount.com \
        --role roles/compute.imageUser
    
    gcloud projects add-iam-policy-binding IMAGE_PROJECT_ID \
        --member serviceAccount:service-CLUSTER_PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com \
        --role roles/compute.imageUser
    

次のステップ