新しい会話を開始

未解決

1 Rookie

 • 

63 メッセージ

20

2024年4月24日 04:13

コンテナ事始め(8) Kubernetesワークロードの障害時のふるまい

前回の投稿「コンテナ事始め(7) Kubernetesのワークロード管理を理解する」はこちらから。

こんにちは。デル・テクノロジーズでクラウド、コンテナ関連を担当している平原です。前回はKubernetes (以下K8s) におけるワークロード管理の考え方について説明をしましたが、現実の場面において、PodやReplicaSetが使われることはなく、一般的なワークロードについて言えばDeploymentまたはStatefulSetで管理されることが多いでしょう。そこで今回はこの2つのワークロード形態における障害時のふるまいを考察してみたいと思います。障害パターンは例を挙げればキリがありませんが、ここではPod障害とWorkerノード障害について考えてみます。Masterノードは通常3重化されているのでここでは考慮外とします。

Pod障害時の場合

Pod障害は非常にシンプルです。問題のあるPodはTerminateされ、それぞれのyamlファイルで指定された ”replicas” を維持するように新しいPodが再起動します。

下記はPod障害発生前後の状態です。Deploymentでは、障害が起きたPod (末尾 -llnhh) がTerminate処理と同時にそれに代わるPod (末尾 -zvxpt) が再起動します。

StatefulSetでは、障害が起きたPod “stateful-test-0” が完全にTerminateされた後、同じPod名で新しいPodが再起動します。

Workerノード障害時の場合

Workerノード障害では両者の挙動が変わってきます。末尾 “-vphgt” のWorkerにちょうどDeplymentとStatefulSetのPodがデプロイされているので、このノードをシャットダウンし、障害状態を作ってみます。OpenShift (K8s) 上でノードが “Not Ready” になると、デフォルトでは300秒後に回復処理が走ります。

Deploymentでは、障害ノード上のPod (末尾 -dc6mk) のTerminateと同時に新しいPod (末尾 -zn4mx) が再起動します。

一方のStatefulSetでは、Pod “stateful-test-2” はTerminateしたままで新しいPodは再起動されません。Pod障害時のところで説明したように新しいPodが同じPod名で再起動するために、古いPodは完全にTerminateされなければならないのですが、ノードダウンでノード上のkubeletが動いていないためにTerminate処理がハングしてしまっているからです。

では、StatefulSetで新しいPodを再起動させるためにはどうしたら良いのでしょうか?そのためには「手動で」障害が起きているWorkerノード上の当該Podを強制削除するか、Workerノードそのものを削除してあげることで新しいPodを再起動してあげることができます。

ここでは、kubectl delete podコマンドに “—force —grace-period=0” オプションを付けてあげることでPod “stateful-test-2” を強制削除、コンテナ再作成をさせることができました。ただ、この時も ”Running” 状態には出来ませんでした。それは、Pod “stateful-test-2” にアタッチしていたPersistent Volume Claimが “RWO” モードだったため、前のPodがPVCを掴んでいる状態が残っていたためと思われます。回避方法としては PVCを “RWO” ではなく “RWX” にしてあげれば起動出来るものと推察されますが、fsyncなどを利用するシビアなディスク書き込みを行うようなアプリケーションではRWOのブロックデバイスが必須となるので、それも完全な解決策とはならないかもしれません。

これってバグなの?

一見使いにくい、劣っているように見えるStatefulSet。そもそもこんな挙動は不具合、バグなんじゃないの?と思われるかもしれませんがこれは規定どおりの挙動です。それはStatefulSetがデータが壊れないことを最優先にする設計思想に立っているからです。たとえば下図のようなActive-Standbyの仕組みを考えてみます。Workerノード全体が障害を起こしている場合、この時はその上で動いているアプリケーションPodも死んでいるので、例えばStatefulSetではなくDeploymentを使っても問題ないかもしれません。しかしMasterノードとWorkerノード間で通信障害が起きていた場合はどうでしょう?Workerノードの状態は “Not Ready” であるにも関わらずノードは生きています。いわゆる「半死」状態です。この半死状態のノードではPodは正常に動き続けているかもしれません。その状態で不用意にPodが再起動してしまったら二重アクセスでデータ破壊を起こす可能性も考えられます。このようなリスクも想定して、StatefulSetでは元のPodが無い状態を確認してからでないと新しいPodが起動しないようになっているのです。

解決策ってあるの?

StatefulSetで管理されるアプリケーションは一般的にはミッションクリティカルに属するものと言えます。そうしたアプリケーションが障害時にもう少しスマートに復旧できる方法は無いのか?実は当社ストレージとの組み合わせならそれが可能なのです。次回はその具体的ソリューションを紹介いたします。

レスポンスがありません。
イベントは見つかりませんでした!

Top