21
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kubernetes ver1.24新機能「non-graceful node shutdown」

Last updated at Posted at 2022-06-14

はじめまして。NECソリューションイノベータの毛利と申します。

今日は、Kubernetes v1.24で新しく実装された機能「non-graceful node shutdown」について紹介したいと思います。
私もコミュニティでの議論やコードレビューに参加したので、この機能が実装され、無事にリリースされてとても嬉しいです!

TL;DR

  • Kubernetes ver1.24で「non-graceful node shutdown」機能が新しく実装された。
  • Persistent Volume(以降「PV」)がアタッチされたpodが動いている場合、ホストノードがハードウェア障害などで正常なシャットダウンができなかった時でも、non-graceful node shutdown機能を使うことでpodの削除・PVのデタッチができるようになる。

背景

まずはこの機能が生まれた背景から説明したいと思います。
KubernetesクラスタのWorkerノードがハードウェア故障等によりダウンした際、Controllerノードはその障害ノード上の pod 群を他のノード上で再作成します。
現状、 kubectl delete pod -f コマンドによりpodを強制削除することで回避することが可能ですが、podがたくさんある場合は大変ですよね。

slide14.PNG

この件に関しては数年前からKubernetesコミュニティで議論が行われていたものの、実装方針についてなかなか結論が出ず議論が停滞していました。

non-graceful node shutdown機能の概要

workerノードがダウンした際に、そのノードに対してユーザは node.kubernetes.io/out-of-service taint(ver1.24で新規追加)を付与する必要があります。

kube-controller-managerのPod GC Controllerは、podの状態を確認し、Terminating 状態のpodを見つけると、そのpodが動いているノードの状態が NotReady になっている、かつ、ノードに node.kubernetes.io/out-of-service taintが付与されている場合は、Terminating 状態のpodを強制削除します。また、 effectに NoExecute を設定して node.kubernetes.io/out-of-service taintを付与すると、 node.kubernetes.io/out-of-service taintが付与されたノード上のpodはevictされ、また、そのノード上に新しくpodがスケジューリングされなくなります。(podがtolerationを持つ場合以外は)

podが強制削除されると、attachdetach reconciler(Podに対するPVのアタッチ/デタッチを管理する役割を持つkube-controller-managerのVolume Controllerの仕組み)はノードに node.kubernetes.io/out-of-service taintが付与されているかどうかをチェックします。taintが付与されていると、デフォルトで設定されている6分間の待機時間を待つことなく、ボリュームの強制デタッチを行います。taintについては https://kubernetes.io/docs/reference/labels-annotations-taints/ に記載されています。

ちなみに、reconcilerというのは、Kubernetesリソースの「あるべき姿」に「実際の姿」を合わせる処理を定期的に行う仕組みです。Kubernetesに詳しい方なら常識だと思うので偉そうに言うことじゃないですけど、、あと調べるとたくさん出てきます。

機能実装のPull Request(以降「PR」)は https://github.com/kubernetes/kubernetes/pull/108486 です。そんなに難しい箇所はないと思うので、見てみると面白いと思います。実際にロジックが変更されているのは以下の2つのファイルです。

  • pkg/controller/podgc/gc_controller.go
  • pkg/controller/volume/attachdetach/reconciler/reconciler.go

graceful node shutdown機能との違い

「non-graceful node shutdown」と聞いて、ver1.21でβ実装された「graceful node shutdown」を思い出した方も多いと思います。
なので、ここでは non-graceful node shutdown 機能と graceful node shutdown 機能の違いを説明します。

ドキュメント https://kubernetes.io/ja/docs/concepts/architecture/nodes/#graceful-node-shutdown で説明されていますが、 graceful node shutdown というのは、ノードで shutdown シグナルが発生した際に、そのノードの上のpod終了までの猶予期間を設定できる機能です。

ノードのシャットダウン時にその上のpodが異常終了してしまう、という課題を解決するために提案された機能なのですが、ハードウェア障害などでノードがシャットダウンしてしまった場合は、 shutdown シグナルによるシャットダウンではなく意図せぬシャットダウンなので(例えば電プチとかですね)、シャットダウンまで待つ、ということができないという課題があります。そこで今回提案されたのが non-graceful node shutdown 機能です。

non-graceful node shutdown機能を使ってみよう

まず、non-graceful node shutdown機能はver1.24ではα機能のためデフォルトでは無効になっています。有効にするには NodeOutOfServiceVolumeDetach Feature Gateを有効にする必要があります。NodeOutOfServiceVolumeDetach Feature Gateについては https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features に書かれています。

準備ができたらさっそく動作確認してみましょう。
私の環境では以下のノードを用意しました。Controllerノード1台、Workerノード2台です。

$ kubectl get nodes
NAME                 STATUS   ROLES           AGE    VERSION
test-control-plane   Ready    control-plane   103s   v1.24.0-beta.0.113+7380fc735aca59-dirty
test-worker          Ready    <none>          69s    v1.24.0-beta.0.113+7380fc735aca59-dirty
test-worker2         Ready    <none>          69s    v1.24.0-beta.0.113+7380fc735aca59-dirty

CSIドライバは、私の環境ではNFSサーバを使っているのでNFS CSIドライバを使いました。NFS CSIドライバについてはこちら https://github.com/kubernetes-csi/csi-driver-nfs

動作確認に使うサンプルアプリも用意しましょう。NFS CSIドライバにはサンプルアプリが用意されているのでそれを使います。https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/hack/verify-examples.sh を実行するとアプリが作成されます。

$ kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/statefulset-nfs-0                 1/1     Running   0          71s

NAME                               READY   AGE
statefulset.apps/statefulset-nfs   1/1     71s

PVCも作成されています。

$ kubectl get pvc
NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistent-storage-statefulset-nfs-0   Bound    pvc-e174d35e-0a83-4fbb-bf8f-28aa8ec8b7f8   10Gi       RWO            nfs-csi        109s

こちらのサンプルアプリは、1秒おきに現在時刻をファイルに出力するというものになっています。

$ more /home/yuiko/foo/pvc-e174d35e-0a83-4fbb-bf8f-28aa8ec8b7f8/outfile
Fri May 13 04:34:27 UTC 2022
Fri May 13 04:34:29 UTC 2022
Fri May 13 04:34:30 UTC 2022

podが動いているノードを確認しましょう。

$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE           NOMINATED NODE   READINESS GATES
statefulset-nfs-0                 1/1     Running   0          2m48s   10.244.1.3   test-worker2   <none>           <none>

test-worker2ですね。

私はKubernetes環境としてKind( https://kind.sigs.k8s.io/ )を使っているのですが、Kindのノードの正体はdockerコンテナなので、こんな感じでworkerノードを止めます。

$ docker stop test-worker2

test-worker2の状態がNotReadyになっていることが確認できました。

$ kubectl get nodes 
NAME                 STATUS     ROLES           AGE     VERSION
test-control-plane   Ready      control-plane   10m     v1.24.0-beta.0.113+7380fc735aca59-dirty
test-worker          Ready      <none>          9m30s   v1.24.0-beta.0.113+7380fc735aca59-dirty
test-worker2         NotReady   <none>          9m30s   v1.24.0-beta.0.113+7380fc735aca59-dirty

podの状態もTerminatingになり、そのまま他のノードにevictしません、、

$ kubectl get pods
NAME                              READY   STATUS        RESTARTS   AGE
statefulset-nfs-0                 1/1     Terminating   0          11m

ダウンしているtest-worker2ノードにout-of-service Taintを付与します。

$ kubectl taint nodes test-worker2 node.kubernetes.io/out-of-service=nodeshutdown:NoExecute
node/test-worker2 tainted

podがtest-workerノードに移動しました!

$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
statefulset-nfs-0                 1/1     Running   0          6s    10.244.2.4   test-worker   <none>           <none>

PVとPVCも確認してみましょう。STATUSが Bound になっていますね。

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                          STORAGECLASS   REASON   AGE
pvc-e174d35e-0a83-4fbb-bf8f-28aa8ec8b7f8   10Gi       RWO            Delete           Bound    default/persistent-storage-statefulset-nfs-0   nfs-csi                  1d
$ kubectl get pvc
NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistent-storage-statefulset-nfs-0   Bound    pvc-e174d35e-0a83-4fbb-bf8f-28aa8ec8b7f8   10Gi       RWO            nfs-csi         1d

サンプルアプリの出力ファイルも見てみましょう。

$ tail /home/yuiko/foo/pvc-e174d35e-0a83-4fbb-bf8f-28aa8ec8b7f8/outfile
Fri May 13 05:15:38 UTC 2022
Fri May 13 05:15:39 UTC 2022
Fri May 13 05:15:40 UTC 2022
Fri May 13 05:21:56 UTC 2022 ←6分ほどファイル出力されていない
Fri May 13 05:21:57 UTC 2022
Fri May 13 05:21:58 UTC 2022

本来は1秒おきに現在時刻が出力されるはずですが、途中6分ほどファイル出力が行われていないことがわかります。

今後の予定

コミュニティでの議論の結果、ver1.24では手動でtaintをノードに付与することでノードからのボリュームデタッチが許可される、という方針で合意形成がされましたが、将来的にはこのtaintを自動で付与したいという話も出ています。

以下のKEPのセクションにこのように記載されています。
https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/2268-non-graceful-shutdown#goals
Once the feature in this KEP is developed and tested, we plan to work on automatic way of detecting and fencing node for shutdown/failure use cases and re-evaluating some approaches listed in the Alternatives section.

まとめ

今回はKubernetes ver1.24で新しく実装された「non-graceful node shutdown」機能を紹介しました。長年コミュニティで問題視されていたので、今回のリリースで恩恵を受ける方はたくさんいらっしゃると思います!ガンガン使ってコミュニティにもフィードバックを投げましょう!

おまけ

この件は、もともとは社内で改善要望が出たことがきっかけでコミュニティでの開発に参加したのですが、私が参加するだいぶ前から議論が行われており、他の企業でも改善要望が多かったことがうかがえます。Kubernetesを始めとする比較的大きいOSSコミュニティでは、新しい機能の実装を提案する場合はKEPと呼ばれる機能提案書のようなものを提出し、KEPが承認されれば開発に進むことができます。今回、KEPの承認に向けて議論はかなりの長期戦になり、とても大変でした、、。本件がsig-nodeとsig-storageの両方に関係するためステークホルダーが多いのもその原因かと思います。方向性の合意ができてKEPが無事承認された後は機能実装はトントン拍子に進み、ver1.24の開発期間に機能実装PRまで一気に完了しました!

参考

21
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?