[Kubernetes]HPA使用時のreplicasの設定
DeploymentとHorizontalPodAutoscaler(HPA)の組み合わせでハマった箇所があったため、検証結果と検証用の資料をまとめた。
検証環境
- Kubernetes version: 1.14.10-gke.27
- 検証資料: https://github.com/ques0942/k8s-hpa-sample
結論
- HPA使用時はDeploymentにreplicasを設定しないほうが良い
- replicasありのDeploymentに後からHPAを適用したい場合
- replicas無しのDeploymentをapplyすると一時的にPodは1つになる
kubectl apply edit-last-applied deployment ${target}
でDeploymentからreplicasを削除できる
- HPAでスケールアウトした後HPAを削除してもPod数はそのまま
- 最後にapplyしたDeploymentがreplicasを持たない場合、kubectl editでreplicasを書き換えたとしてもその後replicas無しのDeploymentをapplyしてもPod数は1にならない
- 詳細は後述するがkubectl applyの差分計算ロジックによる挙動
説明
Deploymentに紐づくPodの数は replicas
に設定された数字と等しくなるが replicas
が未設定の場合は1になる。
一方でHorizontal Pod Autoscaler(HPA)を使用すると、Deploymentの replicas
は負荷状況に合わせて自動で変更される。では以下のようなユースケースの場合どのような挙動となるだろうか?
手順
- replicas = 3としてDeploymentを適用する
- HPAを有効化する
- HPAでreplicasが10に増加した
- 1で適用したDeploymentを修正して適用したが、その時Deploymentのreplicasは3のままだった
問題
この手順を踏むと4の実施後にreplicasは3に戻ってしまう。 規模が大きくなってくるとデプロイ時にscale inすることになるため望ましくない挙動だろう。
対策
- 最後にapplyされたDeploymentを開いてreplicasを削除する
kubectl apply edit-last-applied deployment ${target}
を使う
- 以降applyするDeploymentにはreplicasを含めない
単純にreplicasを含まないDeploymentをapplyすると、一時的にPod数は1になるため注意。
疑問点1: replicasが無いDeploymentをkubectl editしたらどうなる?
replicasありのDeploymentの後にreplicas無しのDeploymentをapplyすると、replicasは一時的に1になりscale inを起こしてしまう。
では、replicas無しのDeploymentをapplyした後にkubectl editでreplicasを書き換えた場合、replicasありのDeploymentをapplyした状態と同じになるのだろうか?
トラブルシュート中にkubectl editでreplicasを修正して急場を凌いだが、後日リリース時にscale inが起こって死というのは避けたいシナリオである。
実際に検証を行ったが、嬉しいことにkubectl editで直接修正した場合はreplicas無しのDeploymentと同じ挙動となった。
これはkubectl applyの差分計算ロジックを考えると納得できる。
kubectl applyの対象となったリソースにはlast-applied-configuration
というアノテーションで最後にapplyされたマニフェストが保存され、それと現在のリソースの状態、applyされるマニフェストから以下の内容で変更差分が構築される。
- last-applied-configurationに存在し、マニフェストに無いフィールドを削除対象とする
- マニフェストに存在し、現在のリソースに含まれない/値が一致しないフィールドを追加/更新する
今回のreplicasにおいては、last-applied-configurationにもマニフェストにも存在しないため、変更対象にならなかったわけである。
疑問点2: スケールアウト後にHPAを削除した場合どうなる?
スケールアウト後にHPAを削除してしまった場合Pod数はどうなるのだろうか。 これは単純でlast-applied Deploymentがreplicasありでも、replicas無しでもPod数は現在の数をキープする。 誤って削除してしまったとしても、Pod数が足りなくなる前に再度作成しなおせば問題はない。