概要
GKEに用意されているノードの自動アップグレードは便利ですが、インスタンスの再起動を考慮していない構成・設定だとアプリケーションサービスが停止します。
解決している問題は少ないですがアプリケーションサービスが停止するケースと解決方法をまとめました。
環境
- Kubernetes(GKE): >= v1.6
アプリケーションサービスが停止するケース
Podの配置が偏っている
spec.replicas: 2
のDeploymentをapply
すると、以下の図のように1つのインスタンスに偏るケースが発生します。
ノードのアップグレードは1台づつkubectl drain
するため、PodA
が同じタイミングでterminate
されます。
この状態になるとPodA
と通信ができないので、アプリケーションサービスの停止につながります。
解決方法
-
PodDisruptionBudgetを設定する
-
kubectl drain
実行時にmaxAvailable
を設定することでPodの起動数を調整可能 -
minAvailable
を利用する場合、spec.replicas
の数値が小さいとALLOWED DISRUPTIONS
の数値が0になるので注意
-
-
PodAffinityを設定する
- 必須ではないがアップグレード時間が短縮し、耐障害が向上
Podの配置が偏っている(kube-dns)
namespace=kube-system
のkube-dnsについても同様の問題が発生します(GKE v1.6で確認)。
前の問題と同様にPodDisruptionBudget
を設定することは可能です。
しかしEvict処理で別インスタンスに移動したPodがなぜかterminate
され、kubectl drain
の処理がタイムアウトするまで処理が停止します。
これはkube-dns-autoscaler
が独自にkube-dns
のPodをコントロールしているためだと思います。
解決方法
解決できていません。
kube-dnsにPodDisruptionBudget
の設定するIssueもあるので将来的には解消されると思います。
kube-dnsの起動は数秒なので、10秒程度のダウンタイムを許容できるアプリケーションサービスであれば問題になりません。
kube-dns
をdelete pod
することで、インスタンスを移動させる事も可能ですが、アップグレード中に再び偏る可能性があるので効果は薄いです。
Statefulなアプリケーションの再起動処理が考慮されていない
これは単純に永続化が必要なデータにPersistentVolumeの設定がされていないミスや、StatefulSets
なアプリケーション、ミドルウェアの初期化スクリプトが漏れているケースです。
例えばRedisClusterの場合、init-containersの処理でクラスターに復帰したり、リシャーディングするスクリプトが必要となります。
解決方法も個々の対応となるので本記事には記載しません。
ノード数が3未満になっている
クラスターを作るときにノード数が3未満だと以下の警告がでます。
理由が記載されいませんが、n1-standard-16
のなどの高いリソースを持つマシーンタイプ2台でも同じ警告がでるため、リソース以外の理由が考えられます。
解決方法
深く考えることをやめて、ノード数を3以上にする。
その他のアプリケーションサービスが停止するケース
- ネットワーク関連のエラーが発生してしまう
- Golangアプリで
getsockopt: no route to host
のエラーが発生- 名前解決まではできていたが詳しくは未調査
- Golangアプリで