K8s Node障害時の振る舞いについての検証記録


k8sクラスタのノードの一つが、ハードウェア障害などでダウンした場合の振る舞いについて検証した記録です。


## 検証システムの構成

[Kubenetes v1.10 クラスタをVagrantで構築したメモ](https://qiita.com/MahoTakara/items/28cd766d0447140b7ae3)のVagrantで構築したk8sクラスタを利用して、障害時の振る舞いについて、調べてみました。

マスターノードであるk8s1にもNodePortが動作していますから、このk8s1をロードバランサーに見立て、HTTPクライアントからk8s1のTCP31514をアクセスして、k8s2とk8s3のNginxのウェブサーバーをアクセスします。 そして、 k8s2 仮想サーバーの模擬障害としてシャットダウンした場合のクライアント視点での動作、ポッドのマイグレーションについて検証します。

![スクリーンショット 2018-04-17 0.22.38.png](https://qiita-image-store.s3.amazonaws.com/0/42829/5bc33fb9-9d1f-003b-3840-000e3379890f.png "スクリーンショット 2018-04-17 0.22.38.png")



## 正常稼働の状態

初期状態として、すべてが正常に稼働している状態の動作を確認しておきます。 
この画面の表示は、上から順に、以下３種類のコマンドの結果です。

* kubectl get node
* kubectl get deployment
* kubectl get pod -o wide


~~~
Mon Apr 16 13:30:03 UTC 2018
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    1d        v1.10.1
k8s2      Ready     node      1d        v1.10.1
k8s3      Ready     node      1d        v1.10.1
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-webserver   6         6         6            6           1m
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-webserver-69878cbf8d-9cf64   1/1       Running   0          1m        10.244.2.43   k8s3
nginx-webserver-69878cbf8d-9vhr9   1/1       Running   0          1m        10.244.2.45   k8s3
nginx-webserver-69878cbf8d-jpw25   1/1       Running   0          1m        10.244.1.49   k8s2
nginx-webserver-69878cbf8d-kjgcf   1/1       Running   0          1m        10.244.2.44   k8s3
nginx-webserver-69878cbf8d-lbbqh   1/1       Running   0          1m        10.244.1.50   k8s2
nginx-webserver-69878cbf8d-xrqpr   1/1       Running   0          1m        10.244.1.48   k8s2
~~~

### クライアントのアクセス状況

クライアントからのアクセスは、すべて`HTTP 200 OK`が返されます。




## ノード障害発生後のノード停止検知

サーバーのハードウェア障害停止を想定して、`vagrant k8s2 halt`を実行してシャットダウンします。 
約30秒後に、次の様にコマンドの結果が変化します。

* kubectl get node は、k8s2のNodeのステータスが変わり、Ready から NodeReady へ変わります。
* kubectl get deployment は、AVAILABLE（存在数）が 6から3へ減ります。
* kubectl get pod は、変化がありません。

~~~
Mon Apr 16 13:30:46 UTC 2018
NAME      STATUS     ROLES     AGE       VERSION
k8s1      Ready      master    1d        v1.10.1
k8s2      NotReady   node      1d        v1.10.1
k8s3      Ready      node      1d        v1.10.1
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-webserver   6         6         6            3           2m
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-webserver-69878cbf8d-9cf64   1/1       Running   0          2m        10.244.2.43   k8s3
nginx-webserver-69878cbf8d-9vhr9   1/1       Running   0          2m        10.244.2.45   k8s3
nginx-webserver-69878cbf8d-jpw25   1/1       Running   0          2m        10.244.1.49   k8s2
nginx-webserver-69878cbf8d-kjgcf   1/1       Running   0          2m        10.244.2.44   k8s3
nginx-webserver-69878cbf8d-lbbqh   1/1       Running   0          2m        10.244.1.50   k8s2
nginx-webserver-69878cbf8d-xrqpr   1/1       Running   0          2m        10.244.1.48   k8s2
~~~


### HTTPクライアントのアクセス状況

ノードの障害が発生して、約３０秒間は、リクエストが割り振られるために、HTTPクライアントで、エラーが発生します。しかし、Nodeの停止を検知すると、リクエストの分配が止まり、HTTPクライアントのエラーは無くなります。

* サーバーが停止してから約30秒間は、HTTPアクセスのタイムアウトが発生します この時のタイムアウト時間は３秒です。
* 30秒経過後、ノードのステータスが、Ready から NotReady に変化すると、k8s2 へ割り振られなくなり、すべて`HTTP 200 OK`が返される様になります。





## ノード障害発生後のポッド・マイグレーション開始

ノードの障害停止から、約５分後に、ポッドのマイグレーションが開始されます。 DESIRED 6 の値と AVAILABLE 3 の値が同じになる様に、残存するワーカーノード k8s3 上でポッドを起動します。 停止したk8s2のポッドのSTATUSは、不明(Unknown)として表示される様になります。

~~~
Mon Apr 16 13:35:09 UTC 2018
NAME      STATUS     ROLES     AGE       VERSION
k8s1      Ready      master    1d        v1.10.1
k8s2      NotReady   node      1d        v1.10.1
k8s3      Ready      node      1d        v1.10.1
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-webserver   6         6         6            6           6m
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-webserver-69878cbf8d-4qgck   1/1       Running   0          12s       10.244.2.46   k8s3
nginx-webserver-69878cbf8d-9cf64   1/1       Running   0          6m        10.244.2.43   k8s3
nginx-webserver-69878cbf8d-9vhr9   1/1       Running   0          6m        10.244.2.45   k8s3
nginx-webserver-69878cbf8d-jm6c2   1/1       Running   0          12s       10.244.2.47   k8s3
nginx-webserver-69878cbf8d-jpw25   1/1       Unknown   0          6m        10.244.1.49   k8s2
nginx-webserver-69878cbf8d-kjgcf   1/1       Running   0          6m        10.244.2.44   k8s3
nginx-webserver-69878cbf8d-lbbqh   1/1       Unknown   0          6m        10.244.1.50   k8s2
nginx-webserver-69878cbf8d-x4946   1/1       Running   0          12s       10.244.2.48   k8s3
nginx-webserver-69878cbf8d-xrqpr   1/1       Unknown   0          6m        10.244.1.48   k8s2
~~~

### HTTPクライアントのアクセス状況

HTTPクライアントでは、エラーは発生しません。 すべて `HTTP 200 OK`の結果が返ります。



## 障害ノードの復旧後の動作

障害停止したk8s2が、復旧してオンラインに戻った状態からの動作を想定して振る舞いを確認します。 k8s2のブートが完了して、約20秒後に、ノードのSTATUSが Readyに戻り、ポッドのSTATUSがUnknownのものを終了させます。 その後は、ポッドは、k8s3で稼働を続けk8s2へ再スケジュールされる事はありません。 k8s3へ偏ったポッドをk8s2にも均等に配置される様に、リスケジュールしたい場合は、アプリケーションのポッドをロールアウトする事で、均等に配置される様になります。 

~~~
Mon Apr 16 13:38:52 UTC 2018
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    1d        v1.10.1
k8s2      Ready     node      1d        v1.10.1
k8s3      Ready     node      1d        v1.10.1
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-webserver   6         6         6            6           10m
NAME                               READY     STATUS        RESTARTS   AGE       IP            NODE
nginx-webserver-69878cbf8d-4qgck   1/1       Running       0          3m        10.244.2.46   k8s3
nginx-webserver-69878cbf8d-9cf64   1/1       Running       0          10m       10.244.2.43   k8s3
nginx-webserver-69878cbf8d-9vhr9   1/1       Running       0          10m       10.244.2.45   k8s3
nginx-webserver-69878cbf8d-jm6c2   1/1       Running       0          3m        10.244.2.47   k8s3
nginx-webserver-69878cbf8d-kjgcf   1/1       Running       0          10m       10.244.2.44   k8s3
nginx-webserver-69878cbf8d-lbbqh   0/1       Terminating   0          10m       <none>        k8s2
nginx-webserver-69878cbf8d-x4946   1/1       Running       0          3m        10.244.2.48   k8s3
~~~

### HTTPクライアントのアクセス状況

HTTPクライアントでは、エラーは発生しません。 すべて `HTTP 200 OK`の結果が返ります。


## 復旧後にポッドの配置をリバランスするには？

この偏った状態では、次にk8s3で障害が発生した時に５分以上は完全に停止する事になります。 したがって、ポッドの配置をリバランスして、リスクを減らしたいと思うのですが、ポッドの配置をリバランスするという事は、実行中のポッドを停止させることを意味しており、自動的リバランスの機能はしばらく実装されない様な事が、Issuesに書かれていました。  そこで、タグ名を更新したコンテナを `kubectl apply -f new_version_apl.yaml` によって、ロールアウトする事で、リバランスする事ができます。

~~~
Mon Apr 16 15:57:21 UTC 2018
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    1d        v1.10.1
k8s2      Ready     node      1d        v1.10.1
k8s3      Ready     node      1d        v1.10.1
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-webserver   6         6         6            6           2h
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-webserver-5dbb4f8976-2l62j   1/1       Running   0          1h        10.244.2.49   k8s3
nginx-webserver-5dbb4f8976-dnrhr   1/1       Running   0          1h        10.244.1.66   k8s2
nginx-webserver-5dbb4f8976-fqxrp   1/1       Running   0          1h        10.244.1.68   k8s2
nginx-webserver-5dbb4f8976-pmnr5   1/1       Running   0          1h        10.244.2.50   k8s3
nginx-webserver-5dbb4f8976-qgwxb   1/1       Running   0          1h        10.244.1.65   k8s2
nginx-webserver-5dbb4f8976-vrqjm   1/1       Running   0          1h        10.244.1.67   k8s2
~~~



# まとめ

障害発生時直後の振る舞いは、ドキュメントされる事も少なくて、設計上の振る舞いが記載され、実装結果の振る舞いが、諸所の条件から異なる事も少なくなく、実際に検証しないと確信が持てないことが多いものです。 今回、K8s v1.10の最新バージョンをvagrantの仮想環境に作りましたから、心おきなく、模擬障害を発生させて、ノードロスト時の振る舞いを確認することができました。

クライアントにエラーを検知するのは、発生から約30秒間だけで、ノード障害を検知した後はクライアントでエラーが発生する事はありませんでした。また、障害停止したノードが復旧した後は、自動的に再配置（リスケジュール）される事はなく、ロールアウトする事で、リバランスされる事が解りました。

ノード数が２で実験しましたが、ノード数が多いほど、ノード障害時の影響を受けるポッドの割合が減らせる事になります。また、マイグレーションが発生するまで、約5分を要するので、ノードが１台ロスとしても、負荷に耐えらえるポッド数を配置しておく必要もあります。