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を修正して適用したが、その時replicasは3のままだった

問題

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

対策

  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になり縮退を起こしてしまう。 では、replicas無しのDeploymentをapplyした後にkubectl editでreplicasを書き換えた場合、replicasありのDeploymentをapplyした状態と同じになるのだろうか? トラブルシュート中にkubectl editでreplicasを修正して急場を凌いだが、後日リリース時に縮退が起こって死というのは避けたいシナリオである。 実際に検証を行ったが、嬉しいことに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数が足りなくなる前に再度作成しなおせば問題はない。