Skip to main content

常にいまいち

[Kubernetes]HPA使用時のreplicasの設定

DeploymentとHorizontalPodAutoscaler(HPA)の組み合わせでハマった箇所があったため、検証結果と検証用の資料をまとめた。

検証環境

結論

  • 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にならない

説明

Deploymentに紐づくPodの数は replicas に設定された数字と等しくなるが replicas が未設定の場合は1になる。 一方でHorizontal Pod Autoscaler(HPA)を使用すると、Deploymentの replicas は負荷状況に合わせて自動で変更される。では以下のようなユースケースの場合どのような挙動となるだろうか?

手順

  1. replicas = 3としてDeploymentを適用する
  2. HPAを有効化する
  3. HPAでreplicasが10に増加した
  4. 1で適用したDeploymentを修正して適用したが、その時Deploymentのreplicasは3のままだった

問題

この手順を踏むと4の実施後にreplicasは3に戻ってしまう。 規模が大きくなってくるとデプロイ時にscale inすることになるため望ましくない挙動だろう。

対策

  1. 最後にapplyされたDeploymentを開いてreplicasを削除する
    • kubectl apply edit-last-applied deployment ${target} を使う
  2. 以降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されるマニフェストから以下の内容で変更差分が構築される。

  1. last-applied-configurationに存在し、マニフェストに無いフィールドを削除対象とする
  2. マニフェストに存在し、現在のリソースに含まれない/値が一致しないフィールドを追加/更新する

今回のreplicasにおいては、last-applied-configurationにもマニフェストにも存在しないため、変更対象にならなかったわけである。

疑問点2: スケールアウト後にHPAを削除した場合どうなる?

スケールアウト後にHPAを削除してしまった場合Pod数はどうなるのだろうか。 これは単純でlast-applied Deploymentがreplicasありでも、replicas無しでもPod数は現在の数をキープする。 誤って削除してしまったとしても、Pod数が足りなくなる前に再度作成しなおせば問題はない。