異なるマシンタイプへのワークロードの移行

このチュートリアルでは、アプリケーションのダウンタイムを発生させずに、Google Kubernetes Engine(GKE)クラスタで実行されているワークロードを同じクラスタ内の新しいノードセットに移行する方法を示します。この移行方法は、異なるマシンタイプのノードにワークロードを移行する場合に有効です。

背景

ノードプールとは、マシンタイプ(CPU とメモリ)の認証スコープを含め、すべてが同じように構成されたマシンからなるサブセットです。ノードプールはクラスタ内のノードからなるサブセットです。1 つのコンテナ クラスタに 1 つ以上のノードプールを含めることができます。

Compute Engine クラスタのマシン プロファイルを変更する必要がある場合、新しいノードプールを作成し、その新しいプールにワークロードを移行することができます。

ダウンタイムを発生させずにワークロードを移行するには、次の操作を行います。

  • 既存のノードプールをスケジュール不可に設定します。
  • 既存のノードプールで実行されているワークロードをドレインします。
  • 既存のノードプールを削除します。

既存のノードプールをドレインすると、Kubernetes(GKE クラスタのオーケストレーション システム)は、強制排除されたポッドを新しいノードプールに対して自動的に再スケジュールします。

目標

  • GKE クラスタを作成する。
  • サンプル ウェブ アプリケーションをクラスタにデプロイする。
  • 新しいノードプールを作成する。
  • ダウンタイムを発生させずにポッドを新しいノードプールに移行する。

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud Console で Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。 これには数分かかることがあります。
  4. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

このチュートリアルで使用されている以下のコマンドライン ツールをインストールします。

  • gcloud は、Kubernetes Engine クラスタの作成と削除に使用されます。gcloud は、Google Cloud SDK に含まれています。
  • kubectl は、Kubernetes Engine で使用されるクラスタ オーケストレーション システムである Kubernetes の管理に使用されます。gcloud を使用して kubectl をインストールできます。
    gcloud components install kubectl

GitHub からサンプルコードのクローンを作成します。

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/migrating-node-pool

gcloud コマンドライン ツールのデフォルトの設定

次のようにしてデフォルト値を設定しておくと、gcloud コマンドライン ツールでプロジェクト ID および Compute Engine ゾーン オプションを入力する時間が節約されます。
gcloud config set project project-id
gcloud config set compute/zone compute-zone

GKE クラスタの作成

最初のステップは、アプリケーションのワークロードを実行するコンテナ クラスタを作成することです。次のコマンドを実行して、デフォルトのマシンタイプ(e2-medium)に設定された 5 つのノードからなる新しいクラスタを作成します。

gcloud container clusters create migration-tutorial --num-nodes=5

レプリケートされたアプリケーションのデプロイの実行

以下のマニフェストでは、サンプル ウェブ アプリケーション コンテナ イメージの 6 つのレプリカのデプロイについて説明しています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app
        image: gcr.io/google-samples/hello-app:1.0

このマニフェストをデプロイするには、次のコマンドを実行します。

kubectl apply -f node-pools-deployment.yaml

次のコマンドを実行すると、開始したポッドのリストが表示されます。

kubectl get pods
出力:
NAME                   READY     STATUS    RESTARTS   AGE
web-2212180648-80q72   1/1       Running   0          10m
web-2212180648-jwj0j   1/1       Running   0          10m
web-2212180648-pf67q   1/1       Running   0          10m
web-2212180648-pqz73   1/1       Running   0          10m
web-2212180648-rrd3b   1/1       Running   0          10m
web-2212180648-v3b18   1/1       Running   0          10m

大規模マシンタイプのノードプールの作成

デフォルトでは、GKE によって、新しいクラスタごとに default-pool という名前のノードプールが作成されます。

gcloud container node-pools list --cluster migration-tutorial
出力:
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  e2-medium      100           1.16.13-gke.401

異なるマシンタイプや認証スコープなど、構成の異なるインスタンスを導入するには、新しいノードプールを作成する必要があります。

次のコマンドは、e2-highmem-2 マシンタイプの 5 つのハイメモリ インスタンスを含む larger-pool という名前の新しいノードプールを作成します。

gcloud container node-pools create larger-pool \
  --cluster=migration-tutorial \
  --machine-type=e2-highmem-2 \
  --num-nodes=5

これでコンテナ クラスタに存在するノードプールが 2 つになりました。

gcloud container node-pools list --cluster migration-tutorial
出力:
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  e2-medium      100           v1.16.13-gke.401
larger-pool   e2-highmem-2   100           v1.16.13-gke.401

新しいノードプールのインスタンスが GKE クラスタに追加されています。

kubectl get nodes
出力:
NAME                                                STATUS    AGE       VERSION
gke-migration-tutorial-default-pool-56e3af9a-059q   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-0ng4   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-k6jm   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-lkrv   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-p9j4   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-2rhk    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-4bb2    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-7fl0    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-cx9q    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-hs6p    Ready     4m        v1.16.13-gke.401

ワークロードの移行

新しいノードプールを作成しても、ワークロードはまだ default-pool で実行されています。ポッドが実行され、使用可能になっている間、Kubernetes はポッドの再スケジュールを行いません。

次のコマンドを実行して、ポッドが実行されているノードを確認します(NODE 列を参照)。

kubectl get pods -o=wide
出力:
NAME                          READY     STATUS    IP         NODE
web-2212180648-80q72          1/1       Running   10.8.3.4   gke-migration-tutorial-default-pool-56e3af9a-k6jm
web-2212180648-jwj0j          1/1       Running   10.8.2.5   gke-migration-tutorial-default-pool-56e3af9a-0ng4
web-2212180648-pf67q          1/1       Running   10.8.4.4   gke-migration-tutorial-default-pool-56e3af9a-lkrv
web-2212180648-pqz73          1/1       Running   10.8.2.6   gke-migration-tutorial-default-pool-56e3af9a-0ng4
web-2212180648-rrd3b          1/1       Running   10.8.4.3   gke-migration-tutorial-default-pool-56e3af9a-lkrv
web-2212180648-v3b18          1/1       Running   10.8.1.4   gke-migration-tutorial-default-pool-56e3af9a-p9j4

これらのポッドを新しいノードプールに移行するには、次の操作を行います。

  1. 既存のノードプールを閉鎖する: これにより、既存のノードプール(default-pool)内のノードがスケジュール不可に設定されます。スケジュール不可に設定されると、Kubernetes はこれらのノードに新しいポッドをスケジュールしなくなります。

  2. 既存のノードプールをドレインする: これにより、既存のノードプール(default-pool)のノードで実行されているワークロードが正常に強制排除されます。

上記の操作を行うと、既存のノードプールで実行されているポッドが正常に終了し、Kubernetes が使用可能な他のノードにポッドを再スケジュールします。この場合、使用可能なノードは larger-pool ノードプール内にしかありません。

Kubernetes がアプリケーションを正常に終了するには、コンテナで SIGTERM 信号を処理する必要があります。この信号は、クライアントとのアクティブな接続を終了し、データベース トランザクションを適切に commit または中止するために使用されます。ポッド内のコンテナを停止するまでに Kubernetes が待機する時間をポッド マニフェストの spec.terminationGracePeriodSeconds フィールドに指定できます。デフォルトは 30 秒です。詳細については、Kubernetes のドキュメントでポッドの終了に関する説明をご覧ください。

まず、default-pool 内のノードを閉鎖します。次のコマンドを実行して、このノードプールに含まれているノードの一覧を表示します。

kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool

kubectl cordon NODE コマンドを実行して、各ノードを閉鎖します。NODE は前のコマンドで確認した名前で置き換えます。各ノードに次のコマンドを実行して、ノードをスケジュール不可にします。

for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do
  kubectl cordon "$node";
done
出力:
node "gke-migration-tutorial-default-pool-56e3af9a-059q" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-0ng4" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-k6jm" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-lkrv" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-p9j4" cordoned

ノードのリストで、default-pool ノードのステータスが SchedulingDisabled になります。

kubectl get nodes
出力:
NAME                                                STATUS                     AGE       VERSION
gke-migration-tutorial-default-pool-56e3af9a-059q   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-0ng4   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-k6jm   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-lkrv   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-p9j4   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-2rhk    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-4bb2    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-7fl0    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-cx9q    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-hs6p    Ready                      1h        v1.16.13-gke.401

次に、各ノードのポッドを正常にドレインします。ドレインを実行するには、kubectl drain コマンドを実行して各ノードのポッドを強制排除します。

kubectl drain --force NODE コマンドも実行できます。NODE は、kubectl cordon コマンドに渡した名前のリストで置き換えます。

default-pool の各ノードに次のシェルコマンドを実行して、割り当てられた最大猶予期間の 10 秒間でポッドを強制排除することによって、ノードをドレインします。

for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do
  kubectl drain --force --ignore-daemonsets --delete-local-data --grace-period=10 "$node";
done

このコマンドが完了すると、ポッドが larger-pool ノードで実行されます。

kubectl get pods -o=wide
出力:
NAME                   READY     STATUS    IP         NODE
web-2212180648-3n9hz   1/1       Running   10.8.9.4   gke-migration-tutorial-larger-pool-b8ec62a6-cx9q
web-2212180648-88q1c   1/1       Running   10.8.7.4   gke-migration-tutorial-larger-pool-b8ec62a6-2rhk
web-2212180648-dlmjc   1/1       Running   10.8.9.3   gke-migration-tutorial-larger-pool-b8ec62a6-cx9q
web-2212180648-hcv46   1/1       Running   10.8.5.4   gke-migration-tutorial-larger-pool-b8ec62a6-hs6p
web-2212180648-n0nht   1/1       Running   10.8.6.4   gke-migration-tutorial-larger-pool-b8ec62a6-7fl0
web-2212180648-s51jb   1/1       Running   10.8.8.4   gke-migration-tutorial-larger-pool-b8ec62a6-4bb2

古いノードプールの削除

web デプロイのすべてのポッドが Kubernetes によって、larger-pool に再スケジュールされたら、不要になった default-pool を削除します。次のコマンドを実行して、default-pool を削除します。

gcloud container node-pools delete default-pool --cluster migration-tutorial

このオペレーションが完了すると、コンテナ クラスタ内のノードプールは larger-pool だけになります。

gcloud container node-pools list --cluster migration-tutorial
出力:
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
larger-pool   e2-highmem-2   100           1.16.13-gke.401

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

  • コンテナ クラスタを削除する: この手順では、コンテナ クラスタを構成するリソース(コンピューティング インスタンス、ディスク、ネットワーク リソースなど)を削除します。

    gcloud container clusters delete migration-tutorial

次のステップ