先日リリースしたアプリケーションが CPU 使ってなくてスカスカだったので、ノードのマシンタイプを n1-standard から f1-micro に変えました。今後もときどき行うことになりそうなので手順を残します。このアプリケーションはストレージを全く使っていないため、ストレージを利用している場合にはこの手順ではうまくいかないかもしれません。注意してください。
マシンタイプの違うノードにダウンタイムゼロで移行する
$ gcloud container node-pools create f1-micro-pool --machine-type f1-micro --num-nodes=2 --zone=asia-east1-c
まず移行先のノードを作成するためにノードプールを作成します。ここでマシンタイプやゾーン、初期のノード数などを指定します。ディスクサイズもここで指定できます。
ノードプールの作成は、インスタンステンプレートの作成、インスタンスグループの作成、そしてインスタンスの作成が順番に行われるので少し時間がかかります。
$ kubectl get nodes -w
新しいノードプールのノードが作成されるのを待ちます。ノードが作成されたら Pod の移行を始めます。
$ kubectl cordon gke-cluster-1-default-pool-0218fc84-ae26
$ kubectl cordon gke-cluster-1-default-pool-0218fc84-l9ev
まず削除予定のノードで新しく Pod が作成されないように Unschedulable にします。それには、cordon サブコマンドを使います。cordon は、Kubernetes v1.2 で追加されました。
$ kubectl drain gke-cluster-1-default-pool-0218fc84-ae26
$ kubectl drain gke-cluster-1-default-pool-0218fc84-l9ev
ノードのステータスが、 SchedulingDisabled
になったことを確認したら、今度はノードから Pod を削除して移行先のノードに移動させます。それには、drain サブコマンドを使います。drain は Kubernetes v1.2 で追加されました。
drain は、ノードを Unscheduable にしてからそのノード上の Pod を全て削除するサブコマンドです。今回事前に cordon を使いノードを Unschedulable にしているは、最初のノードに drain を実行した際にもう一つの削除予定のノードに Pod が作成されることがあるため、事前に削除予定のノード全てを Unschedulable にしました。
ここまでで、削除予定のノードは Unschedulable になり、そのノード上の全ての Pod は削除されています。今回この手順を実行したアプリケーションは、Ingress を使いサービスを公開していましたが、ダウンタイムは発生しませんでした。
$ gcloud container node-pools delete default-pool
最後に不要になったノードプールを削除します。ノードプールの削除は、作成と同様にインスタンステンプレートやインスタンスグループ、インスタンスの削除を伴うため少し時間がかかります。
感想
GKE のノードプールは非常によく出来ていると感じました。複数のノードプールを作成してタイプの違う Pod をそれぞれに割り当てることもできますし、動的にノードを作成、削除を行うこともできるようです。
また公式のブログエントリによると複数ゾーンにまたがるノードプールの作成もできるようなので簡単に BCP を達成することもできそうです。GKE スゴい。