GKE で複数の GPU を使用して LLM を提供する


このチュートリアルでは、効率的でスケーラブルな推論を行うために、GKE で複数の GPU を使用して大規模言語モデル(LLM)をデプロイして提供する方法について説明します。複数の L4 GPU を使用する GKE クラスタを作成し、次のいずれかのモデルを処理するインフラストラクチャを準備します。

必要な GPU の数はモデルのデータ形式によって異なります。このチュートリアルでは、各モデルで 2 つの L4 GPU を使用します。詳細については、GPU の量の計算をご覧ください。

このチュートリアルは、LLM の提供に Kubernetes コンテナ オーケストレーション機能を使用する ML エンジニア、プラットフォーム管理者、オペレーター、データおよび AI スペシャリストを対象としています。 Google Cloudのコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE Enterprise ユーザーロールとタスクをご覧ください。

このページを読む前に、次のことをよく理解しておいてください。

目標

このチュートリアルの内容は次のとおりです。

  1. クラスタとノードプールを作成する。
  2. ワークロードを準備する。
  3. ワークロードをデプロイする。
  4. LLM インターフェースを操作する。

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。
  • モデルによっては追加の要件があります。次の要件を満たしていることを確認してください。

環境を準備する

  1. Google Cloud コンソールで、Cloud Shell インスタンスを起動します。
    Cloud Shell を開く

  2. デフォルトの環境変数を設定します。

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export REGION=us-central1
    

    PROJECT_ID は、実際の Google Cloudプロジェクト ID に置き換えます。

GKE クラスタとノードプールを作成する

GKE Autopilot クラスタまたは GKE Standard クラスタの GPU で LLM を提供できます。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。

Autopilot

  1. Cloud Shell で、次のコマンドを実行します。

    gcloud container clusters create-auto l4-demo \
      --project=${PROJECT_ID} \
      --region=${REGION} \
      --release-channel=rapid
    

    GKE は、デプロイされたワークロードからのリクエストに応じた CPU ノードと GPU ノードを持つ Autopilot クラスタを作成します。

  2. クラスタと通信を行うように kubectl を構成します。

    gcloud container clusters get-credentials l4-demo --region=${REGION}
    

Standard

  1. Cloud Shell で次のコマンドを実行して、GKE 用 Workload Identity 連携を使用する Standard クラスタを作成します。

    gcloud container clusters create l4-demo --location ${REGION} \
      --workload-pool ${PROJECT_ID}.svc.id.goog \
      --enable-image-streaming \
      --node-locations=$REGION-a \
      --workload-pool=${PROJECT_ID}.svc.id.goog \
      --machine-type n2d-standard-4 \
      --num-nodes 1 --min-nodes 1 --max-nodes 5 \
      --release-channel=rapid
    

    クラスタの作成には数分かかることもあります。

  2. 次のコマンドを実行して、クラスタのノードプールを作成します。

    gcloud container node-pools create g2-standard-24 --cluster l4-demo \
      --accelerator type=nvidia-l4,count=2,gpu-driver-version=latest \
      --machine-type g2-standard-24 \
      --enable-autoscaling --enable-image-streaming \
      --num-nodes=0 --min-nodes=0 --max-nodes=3 \
      --node-locations $REGION-a,$REGION-c --region $REGION --spot
    

    GKE は、LLM 用に次のリソースを作成します。

    • Google Kubernetes Engine(GKE)Standard エディションの一般公開クラスタ。
    • 0 ノードにスケールダウンされた g2-standard-24 マシンタイプのノードプール。GPU をリクエストする Pod を起動するまで、GPU の料金は発生しません。このノードプールは Spot VM をプロビジョニングします。Spot VM はデフォルトの標準の Compute Engine VM よりも低価格ですが、可用性は保証されません。オンデマンド VM を使用するには、このコマンドから --spot フラグと text-generation-inference.yaml 構成の cloud.google.com/gke-spot ノードセレクタを削除します。
  3. クラスタと通信を行うように kubectl を構成します。

    gcloud container clusters get-credentials l4-demo --region=${REGION}
    

ワークロードを準備する

このセクションでは、使用するモデルに応じてワークロードを設定する方法について説明します。このチュートリアルでは、Kubernetes Deployment を使用してモデルをデプロイします。Deployment は、クラスタ内のノードに分散された Pod の複数のレプリカを実行できる Kubernetes API オブジェクトです。

Llama 3 70b

  1. デフォルトの環境変数を設定します。

    export HF_TOKEN=HUGGING_FACE_TOKEN
    

    HUGGING_FACE_TOKEN は、HuggingFace トークンに置き換えます。

  2. HuggingFace トークンの Kubernetes Secret を作成します。

    kubectl create secret generic l4-demo \
        --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \
        --dry-run=client -o yaml | kubectl apply -f -
    
  3. 次の text-generation-inference.yaml Deployment マニフェストを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: llm
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: llm
      template:
        metadata:
          labels:
            app: llm
        spec:
          containers:
          - name: llm
            image: us-docker.pkg.dev/deeplearning-platform-release/gcr.io/huggingface-text-generation-inference-cu121.2-1.ubuntu2204.py310
            resources:
              requests:
                cpu: "10"
                memory: "60Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "10"
                memory: "60Gi"
                nvidia.com/gpu: "2"
            env:
            - name: MODEL_ID
              value: meta-llama/Meta-Llama-3-70B-Instruct
            - name: NUM_SHARD
              value: "2"
            - name: MAX_INPUT_TOKENS
              value: "2048"
            - name: PORT
              value: "8080"
            - name: QUANTIZE
              value: bitsandbytes-nf4
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: l4-demo
                  key: HUGGING_FACE_TOKEN
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
              # mountPath is set to /tmp as it's the path where the HUGGINGFACE_HUB_CACHE environment
              # variable in the TGI DLCs is set to instead of the default /data set within the TGI default image.
              # i.e. where the downloaded model from the Hub will be stored
              - mountPath: /tmp
                name: ephemeral-volume
          volumes:
            - name: dshm
              emptyDir:
                  medium: Memory
            - name: ephemeral-volume
              ephemeral:
                volumeClaimTemplate:
                  metadata:
                    labels:
                      type: ephemeral
                  spec:
                    accessModes: ["ReadWriteOnce"]
                    storageClassName: "premium-rwo"
                    resources:
                      requests:
                        storage: 150Gi
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-l4"
            cloud.google.com/gke-spot: "true"

    このマニフェストの内容:

    • このモデルには 2 つの NVIDIA L4 GPU が必要なため、NUM_SHARD2 にする必要があります。
    • QUANTIZEbitsandbytes-nf4 に設定されているため、モデルは 32 ビットではなく 4 ビットで読み込まれます。これにより、GKE は必要な GPU メモリの量を減らし、推論速度を向上させることができます。ただし、モデルの精度は低下する可能性があります。リクエストする GPU を計算する方法については、GPU の量の計算をご覧ください。
  4. 次のようにマニフェストを適用します。

    kubectl apply -f text-generation-inference.yaml
    

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

    deployment.apps/llm created
    
  5. モデルのステータスを確認します。

    kubectl get deploy
    

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

    NAME          READY   UP-TO-DATE   AVAILABLE   AGE
    llm           1/1     1            1           20m
    
  6. 実行中のデプロイのログを表示します。

    kubectl logs -l app=llm
    

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

    {"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291}
    {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328}
    {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329}
    {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
    

Mixtral 8x7b

  1. デフォルトの環境変数を設定します。

    export HF_TOKEN=HUGGING_FACE_TOKEN
    

    HUGGING_FACE_TOKEN は、HuggingFace トークンに置き換えます。

  2. HuggingFace トークンの Kubernetes Secret を作成します。

    kubectl create secret generic l4-demo \
        --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \
        --dry-run=client -o yaml | kubectl apply -f -
    
  3. 次の text-generation-inference.yaml Deployment マニフェストを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: llm
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: llm
      template:
        metadata:
          labels:
            app: llm
        spec:
          containers:
          - name: llm
            image: us-docker.pkg.dev/deeplearning-platform-release/gcr.io/huggingface-text-generation-inference-cu124.2-3.ubuntu2204.py311
            resources:
              requests:
                cpu: "5"
                memory: "40Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "5"
                memory: "40Gi"
                nvidia.com/gpu: "2"
            env:
            - name: MODEL_ID
              value: mistralai/Mixtral-8x7B-Instruct-v0.1
            - name: NUM_SHARD
              value: "2"
            - name: PORT
              value: "8080"
            - name: QUANTIZE
              value: bitsandbytes-nf4
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: l4-demo
                  key: HUGGING_FACE_TOKEN          
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
              # mountPath is set to /tmp as it's the path where the HF_HOME environment
              # variable in the TGI DLCs is set to instead of the default /data set within the TGI default image.
              # i.e. where the downloaded model from the Hub will be stored
              - mountPath: /tmp
                name: ephemeral-volume
          volumes:
            - name: dshm
              emptyDir:
                  medium: Memory
            - name: ephemeral-volume
              ephemeral:
                volumeClaimTemplate:
                  metadata:
                    labels:
                      type: ephemeral
                  spec:
                    accessModes: ["ReadWriteOnce"]
                    storageClassName: "premium-rwo"
                    resources:
                      requests:
                        storage: 100Gi
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-l4"
            cloud.google.com/gke-spot: "true"

    このマニフェストの内容:

    • このモデルには 2 つの NVIDIA L4 GPU が必要なため、NUM_SHARD2 にする必要があります。
    • QUANTIZEbitsandbytes-nf4 に設定されているため、モデルは 32 ビットではなく 4 ビットで読み込まれます。これにより、GKE は必要な GPU メモリの量を減らし、推論速度を向上させることができます。ただし、これによりモデルの精度が低下する可能性があります。リクエストする GPU を計算する方法については、GPU の量の計算をご覧ください。
  4. 次のようにマニフェストを適用します。

    kubectl apply -f text-generation-inference.yaml
    

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

    deployment.apps/llm created
    
  5. モデルのステータスを確認します。

    watch kubectl get deploy
    

    デプロイの準備ができている場合、出力は次のようになります。

    NAME          READY   UP-TO-DATE   AVAILABLE   AGE
    llm           1/1     1            1           10m
    

    監視を終了するには、「CTRL + C」と入力します。

  6. 実行中のデプロイのログを表示します。

    kubectl logs -l app=llm
    

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

    {"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291}
    {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328}
    {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329}
    {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
    

Falcon 40b

  1. 次の text-generation-inference.yaml Deployment マニフェストを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: llm
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: llm
      template:
        metadata:
          labels:
            app: llm
        spec:
          containers:
          - name: llm
            image: us-docker.pkg.dev/deeplearning-platform-release/gcr.io/huggingface-text-generation-inference-cu121.1-4.ubuntu2204.py310
            resources:
              requests:
                cpu: "10"
                memory: "60Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "10"
                memory: "60Gi"
                nvidia.com/gpu: "2"
            env:
            - name: MODEL_ID
              value: tiiuae/falcon-40b-instruct
            - name: NUM_SHARD
              value: "2"
            - name: PORT
              value: "8080"
            - name: QUANTIZE
              value: bitsandbytes-nf4
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
              # mountPath is set to /data as it's the path where the HUGGINGFACE_HUB_CACHE environment
              # variable points to in the TGI container image i.e. where the downloaded model from the Hub will be
              # stored
              - mountPath: /data
                name: ephemeral-volume
          volumes:
            - name: dshm
              emptyDir:
                  medium: Memory
            - name: ephemeral-volume
              ephemeral:
                volumeClaimTemplate:
                  metadata:
                    labels:
                      type: ephemeral
                  spec:
                    accessModes: ["ReadWriteOnce"]
                    storageClassName: "premium-rwo"
                    resources:
                      requests:
                        storage: 175Gi
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-l4"
            cloud.google.com/gke-spot: "true"

    このマニフェストの内容:

    • このモデルには 2 つの NVIDIA L4 GPU が必要なため、NUM_SHARD2 にする必要があります。
    • QUANTIZEbitsandbytes-nf4 に設定されているため、モデルは 32 ビットではなく 4 ビットで読み込まれます。これにより、GKE は必要な GPU メモリの量を減らし、推論速度を向上させることができます。ただし、モデルの精度は低下する可能性があります。リクエストする GPU を計算する方法については、GPU の量の計算をご覧ください。
  2. 次のようにマニフェストを適用します。

    kubectl apply -f text-generation-inference.yaml
    

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

    deployment.apps/llm created
    
  3. モデルのステータスを確認します。

    watch kubectl get deploy
    

    デプロイの準備ができている場合、出力は次のようになります。

    NAME          READY   UP-TO-DATE   AVAILABLE   AGE
    llm           1/1     1            1           10m
    

    監視を終了するには、「CTRL + C」と入力します。

  4. 実行中のデプロイのログを表示します。

    kubectl logs -l app=llm
    

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

    {"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291}
    {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328}
    {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329}
    {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
    

ClusterIP タイプの Service を作成する

Pod をクラスタ内で公開し、他のアプリケーションから検出およびアクセスできるようにします。

  1. 次の llm-service.yaml マニフェストを作成します。

    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      selector:
        app: llm
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f llm-service.yaml
    

チャット インターフェースをデプロイする

Gradio を使用して、モデルを操作できるウェブ アプリケーションを作成します。Gradio は、chatbot のユーザー インターフェースを作成する ChatInterface ラッパーを含む Python ライブラリです。

Llama 3 70b

  1. gradio.yaml という名前のファイルを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gradio
      labels:
        app: gradio
    spec:
      strategy:
        type: Recreate
      replicas: 1
      selector:
        matchLabels:
          app: gradio
      template:
        metadata:
          labels:
            app: gradio
        spec:
          containers:
          - name: gradio
            image: us-docker.pkg.dev/google-samples/containers/gke/gradio-app:v1.0.4
            resources:
              requests:
                cpu: "512m"
                memory: "512Mi"
              limits:
                cpu: "1"
                memory: "512Mi"
            env:
            - name: CONTEXT_PATH
              value: "/generate"
            - name: HOST
              value: "http://llm-service"
            - name: LLM_ENGINE
              value: "tgi"
            - name: MODEL_ID
              value: "meta-llama/Meta-Llama-3-70B-Instruct"
            - name: USER_PROMPT
              value: "<|begin_of_text|><|start_header_id|>user<|end_header_id|> prompt <|eot_id|><|start_header_id|>assistant<|end_header_id|>"
            - name: SYSTEM_PROMPT
              value: "prompt <|eot_id|>"
            ports:
            - containerPort: 7860
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: gradio-service
    spec:
      type: LoadBalancer
      selector:
        app: gradio
      ports:
      - port: 80
        targetPort: 7860
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f gradio.yaml
    
  3. Service の外部 IP アドレスを探します。

    kubectl get svc
    

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

    NAME             TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    gradio-service   LoadBalancer   10.24.29.197   34.172.115.35   80:30952/TCP   125m
    
  4. EXTERNAL-IP 列の外部 IP アドレスをコピーします。

  5. 外部 IP アドレスと公開ポートを指定して、ウェブブラウザでモデル インターフェースを表示します。

    http://EXTERNAL_IP
    

Mixtral 8x7b

  1. gradio.yaml という名前のファイルを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gradio
      labels:
        app: gradio
    spec:
      strategy:
        type: Recreate
      replicas: 1
      selector:
        matchLabels:
          app: gradio
      template:
        metadata:
          labels:
            app: gradio
        spec:
          containers:
          - name: gradio
            image: us-docker.pkg.dev/google-samples/containers/gke/gradio-app:v1.0.4
            resources:
              requests:
                cpu: "512m"
                memory: "512Mi"
              limits:
                cpu: "1"
                memory: "512Mi"
            env:
            - name: CONTEXT_PATH
              value: "/generate"
            - name: HOST
              value: "http://llm-service"
            - name: LLM_ENGINE
              value: "tgi"
            - name: MODEL_ID
              value: "mixtral-8x7b"
            - name: USER_PROMPT
              value: "[INST] prompt [/INST]"
            - name: SYSTEM_PROMPT
              value: "prompt"
            ports:
            - containerPort: 7860
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: gradio-service
    spec:
      type: LoadBalancer
      selector:
        app: gradio
      ports:
      - port: 80
        targetPort: 7860
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f gradio.yaml
    
  3. Service の外部 IP アドレスを探します。

    kubectl get svc
    

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

    NAME             TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    gradio-service   LoadBalancer   10.24.29.197   34.172.115.35   80:30952/TCP   125m
    
  4. EXTERNAL-IP 列の外部 IP アドレスをコピーします。

  5. 外部 IP アドレスと公開ポートを指定して、ウェブブラウザでモデル インターフェースを表示します。

    http://EXTERNAL_IP
    

Falcon 40b

  1. gradio.yaml という名前のファイルを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gradio
      labels:
        app: gradio
    spec:
      strategy:
        type: Recreate
      replicas: 1
      selector:
        matchLabels:
          app: gradio
      template:
        metadata:
          labels:
            app: gradio
        spec:
          containers:
          - name: gradio
            image: us-docker.pkg.dev/google-samples/containers/gke/gradio-app:v1.0.4
            resources:
              requests:
                cpu: "512m"
                memory: "512Mi"
              limits:
                cpu: "1"
                memory: "512Mi"
            env:
            - name: CONTEXT_PATH
              value: "/generate"
            - name: HOST
              value: "http://llm-service"
            - name: LLM_ENGINE
              value: "tgi"
            - name: MODEL_ID
              value: "falcon-40b-instruct"
            - name: USER_PROMPT
              value: "User: prompt"
            - name: SYSTEM_PROMPT
              value: "Assistant: prompt"
            ports:
            - containerPort: 7860
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: gradio-service
    spec:
      type: LoadBalancer
      selector:
        app: gradio
      ports:
      - port: 80
        targetPort: 7860
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f gradio.yaml
    
  3. Service の外部 IP アドレスを探します。

    kubectl get svc
    

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

    NAME             TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    gradio-service   LoadBalancer   10.24.29.197   34.172.115.35   80:30952/TCP   125m
    
  4. EXTERNAL-IP 列の外部 IP アドレスをコピーします。

  5. 外部 IP アドレスと公開ポートを指定して、ウェブブラウザでモデル インターフェースを表示します。

    http://EXTERNAL_IP
    

GPU の量を計算する

GPU の数は、QUANTIZE フラグの値によって異なります。このチュートリアルでは、QUANTIZEbitsandbytes-nf4 に設定されています。これは、モデルが 4 ビットで読み込まれることを意味します。

700 億のパラメータ モデルでは、最低 40 GB の GPU メモリが必要です。これは 700 億 × 4 ビット(700 億 x 4 ビット = 35 GB)に相当し、5 GB のオーバーヘッドを考慮します。この場合、1 つの L4 GPU ではメモリが不足します。したがって、このチュートリアルの例では、2 つの L4 GPU メモリ(2 × 24 = 48 GB)を使用します。この構成は、L4 GPU で Falcon 40b または Llama 3 70b を実行するのに十分です。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

クラスタの削除

このガイドで作成したリソースが Google Cloud アカウントに課金されないようにするために、GKE クラスタを削除します。

gcloud container clusters delete l4-demo --region ${REGION}

次のステップ