Kubernetesで安全にマシンタイプを変更するDrainとPodDisruptBudget
動機
プロジェクト開始のときは、machine typeはn1-standard-1
でした。
しかし、いろんなデプロイメントをするとクラスタのスペックが足りなくなりました。
今回はそのようなときに使える、安全にNodeのマシンタイプを移行するソリューションを記事にしました。
手順
最初の状態
以下のようなコマンドを叩いて、自分のNode Poolを確認します。
$ gcloud container node-pools list --cluster $(gcloud config get-value container/cluster) --region $(gcloud config get-value compute/region) NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION default-pool n1-standard-1 100 1.9.7-gke.6
やはり、デフォルトのNode Poolであるdefault-pool
が設定されていあります。
Nodeを取得すると以下のような結果になります。
$ kubectl get node NAME STATUS ROLES AGE VERSION gke-hoge-cluster-default-pool-8eb6b5df-9hjh Ready <none> 2d v1.9.7-gke.6 gke-hoge-cluster-default-pool-8eb6b5df-ctb5 Ready <none> 2d v1.9.7-gke.6
実際はこのような状態です。
Node Poolを追加
以下のコマンドよりNode Poolを追加します。
今回は--machine-type=n1-highmem-2
で2
つのNodeを追加します。
gcloud container node-pools create larger-pool --cluster migration-tutorial --machine-type=n1-highmem-2 --num-nodes=2
すると以下のようになります。
$ kubectl get node NAME STATUS ROLES AGE VERSION gke-hoge-cluster-larger-pool-8eb6b5df-ie24 Ready <none> 10s v1.9.7-gke.6 gke-hoge-cluster-larger-pool-8eb6b5df-eoa4 Ready <none> 10s v1.9.7-gke.6 gke-hoge-cluster-default-pool-8eb6b5df-9hjh Ready <none> 2d v1.9.7-gke.6 gke-hoge-cluster-default-pool-8eb6b5df-ctb5 Ready <none> 2d v1.9.7-gke.6
つまり、gke-xxx-xxx-larger-pool-xxx-xxx
のようなNode Poolが作成されたことが分かります。
図にすると以下のような感じです。
default-poolのDrain
kubectl drain NODE_NAME
というコマンドがあり、以下のような役割をします。
- PodをスケジューリングできないようにUnschedulableにする(
kubectl cordon
) - Podを退避(evict)する(
kubectl evict
)
これをdefault poolのノードでやっていきます。
kubectl drain gke-hoge-cluster-default-pool-8eb6b5df-9hjh --force --ignore-daemonsets kubectl drain gke-hoge-cluster-default-pool-8eb6b5df-ctb5 --force --ignore-daemonsets
またオプションは以下の通りです。
force
: Podを強制的に消すignore-daemonsets
: DaemonSetはevictせず、削除する
このようにすると以下のようになります。
古いNode Poolを削除する
以下のコマンドで削除することができます。
gcloud container node-pools delete default-pool --cluster $(gcloud config get-value container/cluster)
すると以下のようになっているはずです。
これで目的とするマシンタイプを変更することができました。
安全なDrainのためのPodDisruptionBudget
名前の通り、どのようにPod削除するかの予算を立てます。
いきなり
kubectl drain gke-hoge-cluster-default-pool-8eb6b5df-9hjh --force --ignore-daemonsets kubectl drain gke-hoge-cluster-default-pool-8eb6b5df-ctb5 --force --ignore-daemonsets
を同時にすると、Podが一つもReadyの状態ではなくなる可能性があり、これによってダウンタイムが発生してしまいます。
それを避けるために以下のように指定します。
apiVersion: policy/v1beta1 kind: PodDisruptionBudget metadata: name: myapp spec: maxUnavailable: 1 selector: matchLabels: run: myapp
ここでspec.maxUnavailable
としたのは、停止してよりPodの最大数です。
これによって、どんなに同時にdrainをしても一気にPodがevictされることがなくなり、ダウンタイムは発生しなくなります。
参考文献
異なるマシンタイプへのワークロードの移行 | Kubernetes Engine のチュートリアル | Google Cloud