KubernetesのPDBでminAvailableに1を設定するとdrainに失敗する
普段、PodDisruptionBudget(PDB)には以下の設定を入れているのですが、
maxUnavailable: 1
テスト環境など pod を冗長化させていない場合に、drain(ドレイン)など pod の削除と作成が同時に発生する場面で通信断が発生します。
「rollout restart deployment」のような動きをしてくれるといいのですが、このあたりとは仕組みが異なるようです。
今回は minAvailable を設定した時の挙動と問題について紹介していきます。
やりたかったこと
pod が 1 台しか起動していない状態で drain が実行された時、移行先の node(ノード)で新しい pod が起動した後、移行元の pod が削除されてほしい。
minAvailable に 1 を設定すれば、最低でも 1 台の pod が起動していないといけないハズなので、drain 時の挙動も変わるのではないかという想定でした。
PodDisruptionBudget(PDB)の設定
PDB の設定では、以下の 2 つを同時に定義することができません。
・maxUnavailable
・minAvailable
よって、元々設定していた maxUnavailable の設定を削除し、新たに minAvailable の設定を追加します。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: hoge
spec:
minAvailable: 1
selector:
matchLabels:
app: hoge
この時、以下の両方のコマンドの挙動はこれまでと変わらず、特に問題なく操作できました。
kubectl rollout restart deployment hoge
kubectl delete pod hoge-xxxxxxxxxx-xxxxx
ただ、minAvailable を設定したにも関わらず「delete pod」の動きに変化がない・・・。
これまでと変わらず pod の作成と削除が同時に発生するので、このケースでは minAvailable の設定は考慮されないのか。
これだと通信断が発生するので、drain(ドレイン)の動きにも期待が持てません。
drain(ドレイン)時に発生したエラー
では、この hoge のアプリが存在する node(ノード)を cordon して、別の node に移してみましょう。
drain 時に cordon されますが、明示的に cordon しておきます。
kubectl cordon [node]
それでは drain を実行。
kubectl drain –delete-emptydir-data –ignore-daemonsets [node]
順調に pod の入れ替えが発生していくのですが、PDB の設定を変更したアプリのみ以下のエラーが発生します。
evicting pod hoge-xxxxxxxxxx-xxxxx
error when evicting pods/”hoge-xxxxxxxxxx-xxxxx” (will retry after 5s): Cannot evict pod as it would violate the pod’s disruption budget.
どうやら pod を削除できないというエラーのようです。
原因と対策
同様の問題を探ってみたところ、以下の記事に行き当たりました。
minAvailable の設定前と設定後の「poddisruptionbudgets.policy」の結果を確認してみると確かに異なります。
maxUnavailable: 1
「Allowed disruptions」が 1 になっています。
Name: hoge
Namespace: xxxxxx
Max unavailable: 1
Selector: app=hoge
Status:
Allowed disruptions: 1
Current: 1
Desired: 0
Total: 1
Events: <none>
minAvailable: 1
「Allowed disruptions」が 0 になっています。
Name: hoge
Namespace: xxxxxx
Min available: 1
Selector: app=hoge
Status:
Allowed disruptions: 0
Current: 1
Desired: 1
Total: 1
Events: <none>
まとめ
deployment では replicas が 1 なので、この場合だと難しそうですね。
kubectl get deployment hoge -o yaml
ちなみに、スケールの設定は HorizontalPodAutoscaler(HPA)で設定しており、minReplicas が 1、maxReplicas が 3 です。
やはり 1 台だけで稼働させているテスト的な環境では、drain 時の一時的な通信断は避けられないかなぁ。