容量バッファを構成する

容量バッファは、Kubernetes CapacityBuffer CustomResourceDefinition(CRD)を使用して、クラスタの予備容量と事前プロビジョニングされた事前構成済み容量の保留状態を事前に管理することで、重要なワークロードの応答性と信頼性を向上させます。容量バッファを使用すると、クラスタ内で未使用のノード キャパシティを一定量、明示的に定義できます。この予約済み容量により、Pod のスケジューリング時間を短縮できます。

優先度の高いワークロードを迅速にスケールアップする必要がある場合、新しいワークロードはノードのプロビジョニングを待たずに空き容量をすぐに使用できます。このアプローチにより、レイテンシを最小限に抑え、需要の急増時のリソース競合を回避できます。

このページでは、容量バッファ(固定レプリカ バッファ、リソース上限バッファ、割合ベースのバッファ)を構成する方法について説明します。

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API を有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。gcloud CLI をインストール済みの場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
  • アクティブ バッファの場合はバージョン 1.35.2-gke.1842000、スタンバイ バッファの場合はバージョン 1.36.0-gke.2253000 以降の GKE クラスタを作成するか、アクセス権を持っている。
  • Standard クラスタでノード自動プロビジョニングを有効にします。Autopilot クラスタでは、ノード自動プロビジョニングはすでに有効になっています。ノード自動プロビジョニングは任意ですが、アクティブ バッファには推奨され、スタンバイ バッファには必須です。

前提条件となる Kubernetes オブジェクトを作成する

CapacityBuffer を構成するには、必要なすべてのオブジェクト(CapacityBuffer 自体、PodTemplate やワークロードなどの追加リソース)を保持する Namespace が必要です。PodTemplate と CapacityBuffer は同じ Namespace に存在する必要があります。Namespace を作成することも、default Namespace などの既存の Namespace を使用することもできます。

構成する CapacityBuffer のタイプに応じて、次のいずれかも必要になります。

  • PodTemplate: バッファ容量の単一ユニットのリソース要件を定義します。CapacityBuffer オブジェクトで指定された構成は、Pod テンプレートを参照します。
  • ワークロード: CapacityBuffer オブジェクトで参照する既存のワークロード。このガイドでは、Deployment オブジェクトをワークロードの例として使用しますが、容量バッファは次のリソースタイプをサポートしています。

    • デプロイ
    • ReplicaSet
    • StatefulSet
    • ReplicationController
    • ジョブ
    • scale サブリソースを実装する CustomResourceDefinitions(CRD)。

このセクションでは、これらのオブジェクトの例を示します。容量バッファで構成するワークロードがすでに存在する場合は、容量バッファを適用するに進みます。

Kubernetes ワークロードの例を作成する手順は次のとおりです。

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

    apiVersion: v1
    kind: Namespace
    metadata:
      name: capacity-buffer-example
      labels:
        name: capacity-buffer-example
    

    このマニフェストは、capacity-buffer-example という名前空間を作成します。

  2. 省略可: カスタム ComputeClass で容量バッファを使用するには、次のマニフェストを custom-compute-class.yaml として保存します。

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: ccc-example
      namespace: capacity-buffer-example
    spec:
      # Buffers are also created according to these priorities
      priorities:
      - machineFamily: n4
      - machineFamily: n4d
      - machineFamily: c4
      - machineFamily: c4d
      nodePoolAutoCreation:
        enabled: true
    

    このマニフェストは、GKE がプロビジョニングするノードのコンピューティング優先度を定義して制御するカスタム ComputeClass を作成します。詳細については、カスタム ComputeClass をご覧ください。

  3. 次のマニフェストを buffer-pod-template.yaml として保存します。

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: buffer-unit-template
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    template:
      spec:
        terminationGracePeriodSeconds: 0
        containers:
        - name: buffer-container
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              cpu: "1"
              memory: "1Gi"
            limits:
              cpu: "1"
              memory: "1Gi"
        # Optional: Using buffers with a custom ComputeClass /
        # controls the properties of the provisioned nodes.
        nodeSelector:
          cloud.google.com/compute-class: ccc-example
    

    このマニフェストは、バッファ容量の 1 単位(1 CPU と 1Gi メモリ)のリソース要件を定義する PodTemplate を作成します。この構成は、GKE がバッファ用にプロビジョニングする容量単位のサイズを指定します。たとえば、この PodTemplate を使用すると、クラスタがスケールアップした場合、GKE は使用可能なリソースが 1 CPU と 1 GiB 未満のノードをバッファの一部とみなしません。

  4. 次のマニフェストを sample-workload-deployment.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: critical-workload-ref
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: critical-workload
      template:
        metadata:
          labels:
            app: critical-workload
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sleep", "3600"]
            resources:
              requests:
                cpu: 100m
          # Optional: Using buffers with a custom ComputeClass /
          # controls the properties of the provisioned nodes.
          nodeSelector:
            cloud.google.com/compute-class: ccc-example
    

    このマニフェストは、10 個のレプリカを含む Deployment のサンプルを作成します。これは、次のセクションの割合ベースのバッファの例の参照オブジェクトです。

  5. マニフェストをクラスタに適用します。

    kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yaml
    
  6. GKE がオブジェクトを作成したことを確認します。

    kubectl get podtemplate -n capacity-buffer-example
    kubectl get deployment critical-workload-ref -n capacity-buffer-example
    

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

    NAME                   AGE
    buffer-unit-template   1m
    
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    critical-workload-ref   10/10   10           10          1m
    

容量バッファを適用する

このセクションでは、ワークロードに適用できるさまざまな種類の容量バッファの例を示します。

固定レプリカ バッファを構成する

固定レプリカで CapacityBuffer を構成すると、PodTemplate に基づいて必要なバッファ ユニットの正確な数を指定できます。

固定レプリカ数でバッファを作成するには、次の操作を行います。

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

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: fixed-replica-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      replicas: 3
      provisioningStrategy: "STRATEGY"
    

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

    • NAMESPACE: Namespace の名前(例: capacity-buffer-example)。
    • POD_TEMPLATE: リソース要件を定義する PodTemplate(buffer-unit-template など)。
    • STRATEGY: プロビジョニング戦略("buffer.x-k8s.io/active-capacity"(デフォルト)または "buffer.gke.io/standby-capacity")。

    このマニフェストは、PodTemplate を参照して特定の数のバッファ単位をリクエストする CapacityBuffer リソースを作成します。

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

    kubectl apply -f cb-fixed-replicas.yaml
    
  3. GKE が容量バッファを適用したことを確認します。

    kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACE
    

    ステータスの replicas フィールドには、マニフェストで定義したレプリカの数を反映する 3 が表示されます。STATUS フィールドには ReadyForProvisioning が表示されます。

リソース上限バッファを構成する

limits フィールドを使用して、PodTemplate サイズに基づいて計算された、バッファが使用するリソースの最大量を定義できます。

リソース上限バッファを作成する手順は次のとおりです。

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

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: resource-limit-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      limits:
        cpu: "5"
        memory: "5Gi"
      provisioningStrategy: "STRATEGY"
    

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

    • NAMESPACE: Namespace の名前(例: capacity-buffer-example)。
    • POD_TEMPLATE: リソース要件を定義する PodTemplate(buffer-unit-template など)。
    • STRATEGY: プロビジョニング戦略("buffer.x-k8s.io/active-capacity"(デフォルト)または "buffer.gke.io/standby-capacity")。

    このマニフェストは、合計上限が 5 個の CPU と 5 GiB のメモリの CapacityBuffer リソースを作成します。前の手順の PodTemplate の例を使用している場合は、各ユニットを 1 CPU と 1Gi メモリとして定義します。これにより、5 個のバッファ ユニットが生成されます。

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

    kubectl apply -f cb-resource-limits.yaml
    
  3. GKE が容量バッファを適用したことを確認します。

    kubectl get capacitybuffer resource-limit-buffer -n NAMESPACE
    

    CapacityBuffer のステータスを確認します。replicas フィールドには、定義した上限から導出された値が表示されます。前のセクションの PodTemplate の例を使用している場合は、5 バッファ単位が表示されます。これは、定義された上限内に収まる最大単位数です。

割合ベースのバッファを構成する

割合ベースのバッファを構成すると、既存のスケーラブル ワークロードの割合に基づいてバッファのサイズが動的に設定されます。容量バッファの割合は、Deployment、StatefulSet、ReplicaSet、Job など、スケール サブリソースを実装する Kubernetes スケーラブル オブジェクトでのみサポートされます。Pod テンプレートには replicas フィールドがないため、Pod テンプレートのバッファを割合で定義することはできません。

通常は、割合ベースのバッファではなく、固定レプリカまたはリソース上限戦略から始めることをおすすめします。ワークロードが少ない数またはゼロにスケールする場合、アクティブな Pod に比例して安全マージンがスケールするため、割合ベースのバッファは突然のスケールアップに対応しにくくなります。これは主に、レプリカ数が非常に少ない状態にスケールダウンしない大規模なデプロイに役立ちます。

割合ベースのバッファを作成する手順は次のとおりです。

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

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: percentage-buffer
      namespace: NAMESPACE
    spec:
      scalableRef:
        apiGroup: apps
        kind: Deployment
        name: SCALABLE_RESOURCE_NAME
      percentage: 20
      provisioningStrategy: "STRATEGY"
    

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

    • NAMESPACE: 名前空間の名前。
    • SCALABLE_RESOURCE_NAME: スケーラブル リソースの名前(例: critical-workload-ref)。
    • STRATEGY: プロビジョニング戦略("buffer.x-k8s.io/active-capacity"(デフォルト)または "buffer.gke.io/standby-capacity")。

    このマニフェストは、参照されるリソースのレプリカの 20% に相当するバッファサイズをリクエストする CapacityBuffer リソースを作成します。前のセクションの Deployment の例を使用している場合、レプリカの値は 10 に設定されます。

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

    kubectl apply -f cb-percentage-based.yaml
    
  3. GKE が容量バッファを適用したことを確認します。

    kubectl get capacitybuffer percentage-buffer -n NAMESPACE
    

    CapacityBuffer のステータスを確認します。replicas フィールドには、割合の計算結果の値が表示されます。前のセクションの Deployment の例を使用している場合は、2 バッファ ユニットが表示されます。これは、Deployment で定義された 10 個のレプリカの 20% です。

  4. Deployment を最大 20 個のレプリカに手動でスケーリングして、動的スケーリングをテストします。

    kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20
    

    CapacityBuffer コントローラが反応し、バッファを 4 つのレプリカに自動的にスケーリングします。

スタンバイ バッファの動作をカスタマイズする

アノテーションを使用すると、スタンバイ バッファの開始と更新の方法をカスタマイズできます。これらのアノテーションを CapacityBuffer リソースの metadata.annotations フィールドに追加します。

  • buffer.gke.io/standby-capacity-init-time: ノードが作成されてから一時停止されるまでのアクティブな時間。形式は期間文字列(5m1h など)です。デフォルトは 5m です。
  • buffer.gke.io/standby-capacity-refresh-frequency: 一時停止中のノードが更新される頻度。デフォルトは 1d です。

次の例は、スタンバイ バッファの動作をカスタマイズするためのこれらの省略可能なフィールドを含むマニフェストを示しています。

apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: customized-standby-buffer
  namespace: my-namespace
  annotations:
    buffer.gke.io/standby-capacity-init-time: "15m"
    buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
  podTemplateRef:
    name: buffer-unit-template
  replicas: 3
  provisioningStrategy: "buffer.gke.io/standby-capacity"

スタンバイ バッファに画像をプリロードする

スタンバイ ノードが再開されたときにワークロードの起動時間を短縮するには、DaemonSet を使用してコンテナ イメージをプリロードします。DaemonSet は、ノードが一時停止する前の起動期間中に実行されます。

DaemonSet を使用してイメージをプリロードする手順は次のとおりです。

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

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: image-prefetch-daemonset
      namespace: NAMESPACE
    spec:
      selector:
        matchLabels:
          name: image-prefetch
      template:
        metadata:
          labels:
            name: image-prefetch
        spec:
          tolerations:
          - key: "buffer.gke.io/standby-node-suspended"
            operator: "Exists"
          initContainers:
          - name: image-puller
            image: IMAGE_NAME
            command: ["sh", "-c", "true"]
          containers:
          - name: pause
            image: registry.k8s.io/pause:3.9
    

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

    • NAMESPACE: DaemonSet の Namespace(例: capacity-buffer-example)。
    • IMAGE_NAME: プリロードするイメージの名前(your-app-image:latest など)。
  2. DaemonSet マニフェストをクラスタに適用します。

    kubectl apply -f image-puller-daemonset.yaml
    
  3. DaemonSet が作成されたことを確認します。

    kubectl get daemonset image-prefetch-daemonset -n NAMESPACE
    
  4. 容量バッファが作成され、プロビジョニングの準備ができていることを確認します。

    kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

    ステータスを確認します。STATUS フィールドには ReadyForProvisioning が表示されます。

容量バッファのステータスとパフォーマンスをモニタリングする

容量バッファのステータスと健全性は、kubectl コマンドと Cloud Monitoring の指標を使用してモニタリングできます。

CapacityBuffer リソースのステータスを確認する

容量バッファの健全性を確認し、ワークロードを受け入れる準備ができていることを確認するには、次の操作を行います。

  1. クラスタ全体のすべての容量バッファのステータスを取得します。

    kubectl get capacitybuffer -A
    
  2. 特定のバッファの詳細なステータス、条件、イベントログを調べます。

    kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

一時停止されたスタンバイ バッファノードを特定する

スタンバイ バッファ VM は事前にプロビジョニングされますが、費用を削減するために一時停止状態に保たれます。これらの一時停止されたノードは、カスタム条件があるため識別できます。一時停止されたノード インスタンスを監査するには、次のコマンドを実行します。

kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'

True のステータスは、スタンバイ VM が一時停止していることを示します。ステータスが False または <none> の場合は、アクティブで実行中のノードを示します。

Cloud Monitoring を使用したパフォーマンスのモニタリング

容量バッファのパフォーマンスをモニタリングするには、Cloud Monitoring で次のリソースをモニタリングします。

  • 反応レイテンシ(cluster_autoscaler/reaction_time_milliseconds: CapacityBuffer の保留中の需要に基づいてクラスタ オートスケーラーがスケーリングの決定を行うまでの時間を追跡します。
  • クラスタ オートスケーラー ログ: "Capacity pod processor injecting ..." などのログエントリを検索して、アクティブなバッファ Pod の置換イベントをモニタリングします。

容量バッファを削除する

ワークロードに容量バッファが不要になった場合は、CapacityBuffer オブジェクトを削除します。これにより、プレースホルダ Pod が削除され、クラスタ オートスケーラーがノードをスケールダウンできるようになります。

kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE

CAPACITY_BUFFER_NAME は、削除する CapacityBuffer の名前に置き換えます。

トラブルシューティング

次のセクションでは、容量バッファに関する一般的な問題を解決する方法について説明します。

課金モデルが原因で容量バッファの準備ができていない

Pod ベースの課金モデル(Pod ごとの課金)を使用するワークロードの CapacityBuffer を作成した場合、容量バッファはプロビジョニングの準備が整いません。

この問題を特定するには、CapacityBuffer のステータスを確認します。

kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE

ステータスが False のタイプ ReadyForProvisioning の条件を探します。

この問題を解決するには、CapacityBuffer がノードベースの課金と互換性のあるワークロードまたは PodTemplate を参照していることを確認します。

カスタム スケーラブル リソースの権限エラー

カスタム スケーラブル オブジェクト(scalableRef フィールドを使用)で動作するように CapacityBuffer を構成すると、必要な権限がない場合、クラスタ オートスケーラーがバッファをスケーリングできないことがあります。

この問題を解決するには、次の例のように ClusterRoleClusterRoleBinding を作成して、必要な権限を手動で付与します。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-scale-getter
rules:
- apiGroups: ["api.example.com"]
  resources: ["customreplicatedresources/scale"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ca-custom-scale-getter
subjects:
- kind: User
  name: "system:cluster-autoscaler"
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: custom-scale-getter

RBAC の構成の詳細については、Kubernetes RBAC のドキュメントをご覧ください。

次のステップ