フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

Kubernetesの障害時のPodへの接続断時間についてまとめ

この記事ではkubernetesで障害が発生した時の挙動接続断時間をまとめます。

結論

状況 Pod数=1 Pod数=2
Drain(ノードをクラスタから除外) 実施不可 瞬断
Pod削除(1つ) 瞬断 瞬断
Dockerプロセス停止 100% 断(復旧まで) 50% 断(–pod-eviction-timeoutの間)
ノード停止/kubelet停止 100% 断(復旧まで) 50% 断(–pod-eviction-timeoutの間)

※Pod数が増えた場合は(ノード数=Pod数ならば) 1 / ノード数 で算出できます

1 Podで起動している時

このような構成を考えてみましょう。

f:id:lirlia:20200419121614p:plain

Podが削除された場合

f:id:lirlia:20200419121716p:plain

この場合はkubernetesの宣言的な機構が働き2~3秒で復旧します。

Dockerプロセスが停止した時

f:id:lirlia:20200419130344p:plain

コンテナやpodを稼働させるDockerプロセスが停止したときは通信が全断します。Dockerプロセスを起動し直すまでは通信不可です。

nodeが停止&kubeletプロセスが停止した時

f:id:lirlia:20200419121625p:plain

MasterとNode間はkubeletプロセスが通信を行なっていますので、kubeletプロセスを停止したときはノードが停止している時と同じ挙動となります。

この場合はノードが復旧しPodが再起動するまで通信が全断となります。

複数Podで起動している時

このような構成を考えてみましょう。

f:id:lirlia:20200419140644p:plain

Nodeをクラスタから排除した場合

f:id:lirlia:20200419134312p:plain

kubectl drainコマンドを使って影響を受けないように排除した場合は該当のノード上で稼働しているPodが別のノードに移動します。アプリや通信量にもよりますが、即時に実行されるため瞬断以外は発生しません。

podが削除された場合

f:id:lirlia:20200419123927p:plain

この場合はkubernetesの宣言的な機構が働き2~3秒でpodが復旧します。アプリや通信量にもよりますが、即時に実行されるため瞬断以外は発生しません。

Dockerプロセスが停止した時

f:id:lirlia:20200419134733p:plain

コンテナやPodを稼働させるDockerプロセスが停止したときは、該当ノード上で動作するPodへの通信が失敗します。その後–pod-eviction-timeout(デフォルト5分)の値にしたがって接続ができないPodが振り分け先から排除されます。

–pod-eviction-timeoutの値の間(デフォルトで5分間)はダウンしたコンテナにもリクエストが飛んでしまうため、podが2つ同時に起動している場合は通信成功率が50%となります。

※Pod数が増えた場合は(ノード数=Pod数ならば) 1 / ノード数 で算出できます


これを回避するには–pod-eviction-timeoutの値を変更するか、コンテナに対してReadiness Probeを設定するかです。

f:id:lirlia:20200419123755p:plain

Readiness Probeを設定すると同一ノード上のkubeletから定期的に死活監視を行うことができ、Dockerプロセス停止時に迅速に停止したPodを検出しトラフィックの転送を中断することができます。

似た設定にliveness Probeもありますが、こちらはPodが正常に稼働しているかをチェックしPodを再起動する動作のため、そもそもDockerプロセスが停止しているときにはPodが再起動できないので効果がありません。

Nodeが停止&kubeletプロセスが停止した時

f:id:lirlia:20200419135238p:plain

MasterとNode間はkubeletプロセスが通信を行なっていますので、kubeletプロセスを停止したときはノードが停止している時と同じ挙動となります。

Dockerプロセスが停止した時と同じように–pod-eviction-timeout(デフォルト5分)の値にしたがって接続ができないPodが振り分け先から排除されます。

–pod-eviction-timeoutの値の間(デフォルトで5分間)はダウンしたPodにもリクエストが飛んでしまうためPodが2つ同時に起動している場合は通信成功率が50%となります。

※Pod数が増えた場合は(ノード数=Pod数ならば) 1 / ノード数 で算出できます

これを回避するには–pod-eviction-timeoutの値を変更したりNodeの数を増やすようにしましょう。


f:id:lirlia:20200419123755p:plain

Dockerプロセス停止時と異なりこのケースの場合はReadiness Probeが効果を発揮しません。というのもReadiness Probeは該当のノード上のkubeletプロセスが死活監視を行なっているため、ノード停止時にはそもそも動かないからです。

調整方法

–pod-eviction-timeoutの変更方法

/etc/kubernetes/manifest/kube-controller-manager.yamlを修正します。

  • 30sとすると30秒
  • 5m0sとすると5分30秒です
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-controller-manager
    tier: control-plane
  name: kube-controller-manager
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-controller-manager
    - --allocate-node-cidrs=true
+   - –pod-eviction-timeout="30s"

修正すると即時に反映されkube-controller-managerのPodが再起動されます。

参考

参考書籍