GKE 上の x86 アプリケーションを Arm のマルチ アーキテクチャに移行する


このチュートリアルでは、Google Kubernetes Engine(GKE)クラスタで x86(Intel または AMD)プロセッサを使用してノード用にビルドされたアプリケーションを、x86 ノードまたは Arm ノードで動作するマルチ アーキテクチャ(マルチ アーキテクチャ)アプリケーションに移行する方法について説明します。このチュートリアルは、既存の x86 互換ワークロードを Arm で実行するプラットフォーム管理者、アプリ オペレータ、アプリ デベロッパーを対象としています。

GKE クラスタでは、Tau T2A Arm マシンシリーズを使用して Arm ノードでワークロードを実行できます。T2A ノードは、x86(Intel または AMD)プロセッサを使用するほかのノードと同様に GKE クラスタで実行できます。スケールアウトやコンピューティング負荷の高いワークロードに適しています。

詳細については、GKE での Arm ワークロードをご覧ください。

このチュートリアルは、Kubernetes と Docker の知識があることを前提としています。このチュートリアルでは、Google Kubernetes Engine と Artifact Registry を使用します。

目標

このチュートリアルでは、次のタスクを行います。

  • Docker を使用してコンテナ イメージを Artifact Registry に保存します。
  • x86 互換のワークロードを GKE クラスタにデプロイします。
  • x86 互換のワークロードを再ビルドして Arm で実行します。
  • Arm ノードプールを既存のクラスタに追加します。
  • Arm ノードで実行する Arm 互換のワークロードをデプロイします。
  • 複数のアーキテクチャでワークロードを実行するマルチ アーキテクチャ イメージをビルドします。
  • 1 つの GKE クラスタ内の複数のアーキテクチャでワークロードを実行します。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Enable the APIs

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。

Cloud Shell を起動する

このチュートリアルでは、Google Cloud でホストされているリソースを管理するためのシェル環境である Cloud Shell を使用します。

Cloud Shell には、Google Cloud CLIkubectl コマンドライン ツールがプリインストールされています。gcloud CLI は Google Cloud の主要なコマンドライン インターフェースを提供し、kubectl は Kubernetes クラスタに対してコマンドを実行するための主要なコマンドライン インターフェースを提供します。

Cloud Shell を起動します。

  1. Google Cloud コンソールに移動します。

    Google Cloud コンソール

  2. コンソールの右上隅にある [Cloud Shell をアクティブにする] ボタン をクリックします。

コンソール内に Cloud Shell セッションが表示されます。このシェルで gcloud コマンドと kubectl コマンドを実行します。

環境を準備する

このセクションでは、チュートリアルに沿って環境を準備します。

gcloud CLI のデフォルトの設定を構成する

プロジェクト ID、ゾーン、新しいクラスタの名前の環境変数を設定します。

export PROJECT_ID=PROJECT_ID
export ZONE=us-central1-a
export CLUSTER_NAME=my-cluster

PROJECT_ID は、始める前にでこのチュートリアル用に選択したプロジェクト ID に置き換えます。

このチュートリアルでは、us-central1-a にリソースを作成します。Tau T2A マシンシリーズを利用できるロケーションの一覧については、利用可能なリージョンとゾーンをご覧ください。

Git リポジトリのクローンを作成する

  1. リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  2. 現在の作業ディレクトリを、前の手順でクローンを作成したリポジトリに変更します。

    cd kubernetes-engine-samples/workloads/migrate-x86-app-to-multi-arch/
    

GKE クラスタを作成して x86 アプリケーションをデプロイする

このチュートリアルの最初の部分では、x86 ノードを持つクラスタを作成し、x86 アプリケーションをデプロイします。サンプル アプリケーションは、HTTP リクエストに応答するサービスです。これは Golang プログラミング言語でビルドされています。

この設定は、x86 互換アプリケーションと x86 ノードを使用した一般的なクラスタ環境を示しています。

GKE クラスタを作成する

まず、x86 プロセッサを搭載したノードを使用して GKE を作成します。この構成では、x86 アプリケーションを実行するための一般的なクラスタ環境を作成します。

クラスタを作成します。

gcloud container clusters create $CLUSTER_NAME \
    --release-channel=rapid \
    --zone=$ZONE \
    --machine-type=e2-standard-2 \
    --num-nodes=1 \
    --async

後のステップで特定の機能のデモを行えるよう、このクラスタでは自動スケーリングが無効になっています。

クラスタの作成が完了するまで数分かかることがあります。--async フラグを指定すると、このオペレーションをバックグラウンドで実行中に、次の手順の操作ができます。

Arm ノードのみを含むクラスタを作成することもできますが、このチュートリアルでは、x86 ノードのみを含むクラスタを作成してから、x86 のみのアプリケーションに Arm との互換性を持たせるプロセスについて学習します。

Artifact Registry Docker リポジトリを作成する

  1. Artifact Registry に、Docker イメージを保存するリポジトリを作成します。

    gcloud artifacts repositories create docker-repo \
          --repository-format=docker \
          --location=us-central1 \
          --description="Docker repository"
    
  2. Docker コマンドライン ツールを構成して、Artifact Registry でこのリポジトリに対して認証します。

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

x86 イメージをビルドし、Artifact Registry に push する

  1. x86 互換バージョンのアプリケーションをビルドします。

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1 . 
    
  2. イメージを Artifact Registry に push します。

    docker push us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1
    

x86 アプリケーションをデプロイする

  1. 次のスクリプトを実行して、クラスタの準備ができていることを確認します。

    echo
    echo -ne "Waiting for GKE cluster to finish provisioning"
    gke_status=""
    while [ -z $gke_status ]; do
       sleep 2
       echo -ne '.'   
       gke_status=$(gcloud container clusters list --format="value(STATUS)" --filter="NAME=$CLUSTER_NAME AND STATUS=RUNNING")
    done
    echo
    echo "GKE Cluster '$CLUSTER_NAME' is $gke_status" 
    echo
    

    クラスタの準備ができると、出力は次のようになります。

    GKE Cluster 'my-cluster' is RUNNING
    
  2. クラスタ認証情報を取得して、kubectl がクラスタの Kubernetes API に接続できるようにします。

    gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID
    
  3. kustomize を使用してイメージを更新し、x86 アプリケーションをデプロイします。

    $(cd k8s/overlays/x86 && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/x86
    
  4. アプリケーションをインターネットに公開するために Service をデプロイします。

    kubectl apply -f k8s/hello-service.yaml
    
  5. Service の外部 IP アドレス hello-service のプロビジョニングが完了したことを確認します。

    echo
    echo -ne "Waiting for External IP to be provisioned"
    external_ip=""
    while [ -z $external_ip ]; do
       sleep 2
       echo -ne '.'
       external_ip=$(kubectl get svc hello-service --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}")
    done
    echo
    echo "External IP: $external_ip"
    echo
    

    外部 IP アドレスがプロビジョニングされると、出力は次のようになります。

    External IP: 203.0.113.0
    
  6. HTTP リクエストを発行して、Deployment が期待どおりに動作するかテストします。

    curl -w '\n' http://$external_ip
    

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

    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64
    

    出力は、この x86 互換デプロイが amd64 アーキテクチャのデフォルト ノードプール内のノードで実行されていることを示しています。クラスタのデフォルト ノードプールのノードには x86(Intel または AMD)プロセッサが搭載されています。

Arm ノードをクラスタに追加する

このチュートリアルの次のパートでは、Arm ノードを既存のクラスタに追加します。これらのノードは、Arm で実行するように再ビルドされた Arm 互換バージョンのアプリケーションがデプロイされる場所です。

チェックポイント

ここまでで、次の目標を達成しました。

  • x86 ノードを使用して GKE クラスタを作成します。
  • Docker を使用して x86 互換のコンテナ イメージを Artifact Registry に保存します。
  • x86 互換のワークロードを GKE クラスタにデプロイします。

x86 ノードと x86 互換ワークロードでクラスタ環境を構成しました。現在 Arm ノードと Arm 互換ワークロードを使用していない場合、この構成は既存のクラスタ環境と同様です。

クラスタに Arm ノードプールを追加する

既存のクラスタに Arm ノードプールを追加します。

gcloud container node-pools create arm-pool \
    --cluster $CLUSTER_NAME \
    --zone $ZONE \
    --machine-type=t2a-standard-2 \
    --num-nodes=1

t2a-standard-2 マシンタイプは、Tau T2A マシンシリーズ(プレビュー版)の Arm VM です。

x86 ノードを含むノードプールを作成する際と同じ方法で、Arm ノードを含むノードプールを作成します。このノードプールが作成されると、このクラスタで x86 ノードと Arm ノードの両方が実行されます。

既存のクラスタに Arm ノードプールを追加する方法について詳しくは、GKE クラスタに Arm ノードプールを追加するをご覧ください。

x86 ベースのノードで実行されている既存のアプリケーションをスケールアップする

複数のアーキテクチャ タイプのノードを 1 つのクラスタでシームレスに連携させることができます。Arm ノードには taint が自動的に配置されるため、GKE は、x86 ノードで実行されている既存のワークロードをクラスタ内の Arm ノードにスケジューリングしません。これは、既存のアプリケーションをスケールアップすることで確認できます。

  1. ワークロードを更新して、最大 6 つのレプリカにスケーリングします。

    $(cd k8s/overlays/x86_increase_replicas && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/x86_increase_replicas/
    
  2. 30 秒待ってから、次のコマンドを実行してデプロイのステータスを確認します。

    kubectl get pods -l="app=hello" --field-selector="status.phase=Pending"
    

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

    NAME                                    READY   STATUS    RESTARTS   AGE
    x86-hello-deployment-6b7b456dd5-6tkxd   0/1     Pending   0          40s
    x86-hello-deployment-6b7b456dd5-k95b7   0/1     Pending   0          40s
    x86-hello-deployment-6b7b456dd5-kc876   0/1     Pending   0          40s
    

    この出力では、x86 ベースのノードに空きが残っていないため、保留中ステータスの Pod が表示されます。クラスタ オートスケーラーが無効になり、Arm ノードが taint されるため、ワークロードは使用可能な Arm ノードにデプロイされません。この taint によって、GKE が Arm ノードに x86 ワークロードをスケジューリングすることが禁止されます。Arm ノードにデプロイするには、Deployment が Arm ノードと互換性があることを示す必要があります。

  3. 実行状態の Pod を確認します。

    kubectl get pods -l="app=hello" --field-selector="status.phase=Running" -o wide
    

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

    NAME                                    READY   STATUS    RESTARTS   AGE   IP            NODE                                        NOMINATED NODE   READINESS GATES
    x86-hello-deployment-6b7b456dd5-cjclz   1/1     Running   0          62s   10.100.0.17   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    x86-hello-deployment-6b7b456dd5-mwfkd   1/1     Running   0          34m   10.100.0.11   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    x86-hello-deployment-6b7b456dd5-n56rg   1/1     Running   0          62s   10.100.0.16   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    

    この出力の NODE 列は、Deployment のすべての Pod がデフォルト プールでのみ実行されていることを示しています。つまり、x86 と互換性のある Pod は x86 ノードにのみスケジュールされます。Arm ノードプールの作成前にすでにスケジュールされていた元の Pod は同じノードで引き続き実行されます。

  4. 次のコマンドを実行してサービスにアクセスし、出力を確認します。

    for i in $(seq 1 6); do curl -w '\n' http://$external_ip; done
    

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

    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    

    この出力は、リクエストを処理するすべての Pod が x86 ノードで実行されていることを示しています。一部の Pod は、既存の x86 ノードにスペースがなく、Arm ノードにスケジュールされないため、保留状態のままで応答できません。

Arm で実行するようにアプリケーションを再ビルドする

前のセクションでは、Arm ノードプールを既存のクラスタに追加しました。既存の x86 アプリケーションをスケールアップしても、ワークロードは Arm ノードにスケジューリングされませんでした。このセクションでは、Arm 互換になるようにアプリケーションを再ビルドし、このアプリケーションがクラスタ内の Arm ノードで実行できるようにします。

この例では、docker build を使用してこれらの手順を完了します。この 2 段階のアプローチは次のとおりです。

  • 第 1 ステージ: Arm にコードをビルドします。
  • 第 2 ステージ: 実行可能ファイルをリーンコンテナにコピーします。

次の手順で操作すると、x86 互換イメージに加えて Arm 互換イメージが作成されます。

実行可能ファイルを別のコンテナにコピーする 2 番目のステップは、コンテナをビルドするためのベスト プラクティスの一つです。つまり、可能な限り小さいイメージをビルドすることです。

このチュートリアルでは、Golang プログラミング言語でビルドされたサンプル アプリケーションを使用します。Golang では、環境変数 GOOSGOARCH をそれぞれ指定することで、アプリケーションを異なるオペレーティング システムと CPU プラットフォームにクロスコンパイルできます。

  1. cat Dockerfile_arm を実行して、Arm 用に作成された Dockerfile を確認します。

    #
    # Build: 1st stage
    #
    FROM golang:1.18-alpine as builder 
    WORKDIR /app
    COPY go.mod .
    COPY hello.go .
    RUN GOARCH=arm64 go build -o /hello && \
       apk add --update --no-cache file && \
       file /hello
    

    ここに示されているスニペットは、最初のステージのみを示しています。このファイルには、両方のステージが含まれています。

    このファイルで GOARCH=arm64 を設定すると、Go コンパイラに Arm 命令セット用のアプリケーションのビルドが指示されます。最初のステージのベースイメージは Linux Alpine イメージであるため、GOOS を設定する必要はありません。

  2. Arm のコードをビルドし、Artifact Registry に push します。

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1 -f Dockerfile_arm .
    docker push us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1
    

アプリケーションの Arm バージョンをデプロイする

アプリケーションが Arm ノードで動作するようにビルドされたので、このアプリケーションをクラスタ内の Arm ノードにデプロイできます。

  1. cat k8s/overlays/arm/add_arm_support.yaml を実行して add_arm_support.yaml を調べます。

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

       nodeSelector:
          kubernetes.io/arch: arm64
    

    この nodeSelector は、ワークロードを Arm ノードでのみ実行することを指定します。nodeSelector を使用すると、GKE は Arm ノード上の taint に一致する toleration を追加し、GKE がこれらのノード上のワークロードをスケジュールできるようにします。このフィールドの設定の詳細については、デプロイ用に Arm ワークロードを準備するをご覧ください。

  2. Arm 互換バージョンのアプリケーションのレプリカを 1 つデプロイします。

    $(cd k8s/overlays/arm && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/arm
    
  3. 5 秒待ってから、Arm デプロイが curl リクエストに応答していることを確認します。

    for i in $(seq 1 6); do curl -w '\n' http://$external_ip; done
    

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

    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:arm-hello-deployment-69b4b6bdcc-n5l28, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    

    この出力には、curl リクエストに応答する x86 互換アプリケーションと Arm 互換アプリケーションの両方からのレスポンスが含まれています。

アーキテクチャ間でワークロードを実行するマルチ アーキテクチャ イメージをビルドする

前のセクションで説明した戦略を使用して、x86 と Arm に別々のワークロードをデプロイできますが、これには 2 つのビルドプロセスと 2 つのコンテナ イメージを維持して整理する必要があります。

x86 と Arm プラットフォームの両方でアプリケーションをシームレスにビルドして実行するのが理想的です。このアプローチをおすすめします。1 つのマニフェストを使用して複数のアーキテクチャ プラットフォームでアプリケーションを実行するには、マルチアーキテクチャ(マルチアーキテクチャ)イメージを使用する必要があります。マルチアーキテクチャ イメージの詳細については、Arm ワークロード用のマルチアーキテクチャ イメージをビルドするをご覧ください。

マルチ アーキテクチャ イメージを使用するには、アプリケーションが次の前提条件を満たしていることを確認する必要があります。

  • アプリケーションにアーキテクチャ プラットフォーム固有の依存関係がない。
  • すべての依存関係は、マルチ アーキテクチャまたは少なくともターゲット プラットフォーム向けにビルドされている必要がある。

このチュートリアルで使用するサンプル アプリケーションは、これらの前提条件を両方とも満たしています。ただし、マルチアーキテクチャ イメージを本番環境にデプロイする前に、独自のアプリケーションをテストすることをおすすめします。

マルチアーキテクチャ イメージをビルドして push する

ワークロードが次の前提条件を満たしている場合、Docker Buildx を使用してマルチアーキテクチャ イメージをビルドできます。

  • ベースイメージが複数のアーキテクチャをサポートしている。これを確認するには、ベースイメージで docker manifest inspect を実行し、アーキテクチャ プラットフォームのリストを確認します。このセクションの最後で画像を検査する方法の例をご覧ください。
  • このアプリケーションでは、アーキテクチャ プラットフォームごとに特別なビルドステップは必要ありません。特別な手順が必要な場合は、Buildx では不十分な場合があります。プラットフォームごとに個別の Dockerfile を用意し、docker manifest create を使用してマニフェストを手動で作成する必要があります。

サンプル アプリケーションのベースイメージは Alpine で、複数のアーキテクチャをサポートしています。また、アーキテクチャ プラットフォーム固有の手順もないため、Buildx を使用してマルチアーキテクチャ イメージをビルドできます。

  1. cat Dockerfile を実行して Dockerfile を検査します。

    # This is a multi-stage Dockerfile. 
    # 1st stage builds the app in the target platform
    # 2nd stage create a lean image coping the binary from the 1st stage
    
    #
    # Build: 1st stage
    #
    FROM golang:1.18-alpine as builder 
    ARG BUILDPLATFORM    
    ARG TARGETPLATFORM
    RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM"  
    WORKDIR /app
    COPY go.mod .
    COPY hello.go .
    RUN go build -o /hello && \
       apk add --update --no-cache file && \
       file /hello   
    
    #
    # Release: 2nd stage
    #
    FROM alpine
    WORKDIR /
    COPY --from=builder /hello /hello
    CMD [ "/hello" ]
    

    この Dockerfile では、ビルドステージとリリース ステージの 2 つのステージが定義されています。x86 アプリケーションのビルドに使用したものと同じ Dockerfile を使用します。

  2. 次のコマンドを実行して、新しい docker buildx ビルダーを作成して使用します。

    docker buildx create --name multiarch --use --bootstrap
    

    新しいビルダーが作成されたので、--platform フラグを使用して、linux/amd64linux/arm64 の両方と互換性のあるイメージをビルドして push できます。このフラグで指定されたプラットフォームごとに、Buildx はターゲット プラットフォームにイメージをビルドします。Buildx は linux/arm64 イメージをビルドする際に、arm64 ベースイメージをダウンロードします。第 1 ステージで、arm64arm64 golang:1.18-alpine イメージにバイナリをビルドします。第 2 ステージで、arm64 Alpine Linux イメージがダウンロードされ、そのイメージのレイヤにバイナリがコピーされます。

  3. イメージをビルドして push します。

    docker buildx build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1 -f Dockerfile --platform linux/amd64,linux/arm64 --push .
    

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

    => [linux/arm64 builder x/x] ..
    => [linux/amd64 builder x/x] ..
    

    この出力は、2 つのイメージ(linux/arm64 用と linux/amd64 用)が生成されたことを示しています。

  4. 新しいマルチ アーキテクチャ イメージのマニフェストを検査します。

    docker manifest inspect us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1
    

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

    {
       "schemaVersion": 2,
       "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
       "manifests": [
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 739,
             "digest": "sha256:dfcf8febd94d61809bca8313850a5af9113ad7d4741edec1362099c9b7d423fc",
             "platform": {
                "architecture": "amd64",
                "os": "linux"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 739,
             "digest": "sha256:90b637d85a93c3dc03fc7a97d1fd640013c3f98c7c362d1156560bbd01f6a419",
             "platform": {
                "architecture": "arm64",
                "os": "linux"
             }
          }
       ]
    

    この出力では、manifests セクションには、amd64 プラットフォーム アーキテクチャのマニフェストと arm64 プラットフォーム アーキテクチャのマニフェストの 2 つのマニフェストが含まれています。

    このコンテナ イメージをクラスタにデプロイすると、GKE はノードのアーキテクチャに一致するイメージのみを自動的にダウンロードします。

アプリケーションのマルチ アーキテクチャ バージョンをデプロイする

  1. マルチアーキテクチャ イメージをデプロイする前に、元のワークロードを削除します。

    kubectl delete deploy x86-hello-deployment arm-hello-deployment
    
  2. cat k8s/overlays/multiarch/add_multiarch_support.yaml を実行して、add_multiarch_support.yaml Kustomize オーバーレイを検査します。

    出力には、次の toleration セットが含まれます。

       tolerations:
          - key: kubernetes.io/arch
             operator: Equal
             value: arm64
             effect: NoSchedule
    

    この toleration は、すべての Arm ノードに設定された taint と一致するため、クラスタ内の Arm ノードでワークロードを実行できます。このワークロードがクラスタ内のどのノードでも実行できるようになったため、toleration のみが必要になりました。toleration のみを使用して、GKE は x86 ノードと Arm ノードの両方にワークロードをスケジューリングできます。GKE がワークロードをスケジューリングできる場所を指定する場合は、ノードセレクタとノード アフィニティ ルールを使用します。これらのフィールドの設定の詳細については、デプロイ用の Arm ワークロードの準備をご覧ください。

  3. 6 つのレプリカを含むマルチ アーキテクチャ コンテナ イメージをデプロイします。

    $(cd k8s/overlays/multiarch && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/multiarch
    
  4. 10 秒待ってから、アプリケーションのすべてのレプリカが実行されていることを確認します。

    kubectl get pods -l="app=hello" -o wide
    

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

    NAME                                         READY   STATUS    RESTARTS   AGE   IP            NODE                                        NOMINATED NODE   READINESS GATES
    multiarch-hello-deployment-65bfd784d-5xrrr   1/1     Running   0          95s   10.100.1.5    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-7h94b   1/1     Running   0          95s   10.100.1.4    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-7qbkz   1/1     Running   0          95s   10.100.1.7    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-7wqb6   1/1     Running   0          95s   10.100.1.6    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-h2g2k   1/1     Running   0          95s   10.100.0.19   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    multiarch-hello-deployment-65bfd784d-lc9dc   1/1     Running   0          95s   10.100.0.18   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    

    この出力には、Pod が Arm ノードプール内のノードとデフォルト(x86)ノードプール内の他のノードの両方で実行されていることを示す NODE 列が含まれています。

  5. 次のコマンドを実行してサービスにアクセスし、出力を確認します。

    for i in $(seq 1 6); do curl -w '\n' http://$external_ip; done
    

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

    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7qbkz, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:multiarch-hello-deployment-65bfd784d-lc9dc, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-5xrrr, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7wqb6, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7h94b, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7wqb6, CPU PLATFORM:linux/arm64
    

    アーキテクチャ プラットフォーム全体で実行中の Pod がリクエストに応答していることがわかります。

マルチ アーキテクチャ イメージをビルドしてデプロイし、複数のアーキテクチャ間でワークロードをシームレスに実行しました。

クリーンアップ

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

チュートリアルが終了したら、作成したリソースをクリーンアップして、割り当ての使用量を減らし、課金を停止できます。以下のセクションで、リソースを削除または無効にする方法を説明します。

プロジェクトを削除する

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

サービス、クラスタ、リポジトリを削除する

プロジェクト全体を削除しない場合は、チュートリアル用に作成したクラスタとリポジトリを削除します。

  1. kubectl delete を実行して、アプリケーションの Service を削除します。

    kubectl delete service hello-service
    

    このコマンドにより、Deployment の公開時に作成した Compute Engine ロードバランサが削除されます。

  2. gcloud container clusters delete を実行して、クラスタを削除します。

    gcloud container clusters delete $CLUSTER_NAME --zone $ZONE
    
  3. リポジトリを削除します。

    gcloud artifacts repositories delete docker-repo —location=us-central1 --async
    

次のステップ