Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

Kubernetesの既存DeploymentにHPAを導入する際の注意点

こんにちは。2022年10月に入社したスタディプラスのSREグループの蜂須賀です。
今回はKubernetesの既存DeploymentにHPA(Horizontal Pod Autoscaler)を追加した際の話を紹介します。

経緯

スタディプラスではKubernetesでシステムを構築しておりますが、 一部のDeploymentはreplicasの設定によってレプリカ数を複数台固定で起動するように設定していました。 レプリカ数はHPAによって負荷に応じて調整した方がシステムの安定性向上につながるので導入することを決めました。
新規Deploymentと違い、既存DeploymentにHPAを導入する際にはreplicasの設定を削除する工程が必要になります。
今回はHPAに必要なメトリクスサーバやHPAの設定については割愛し、replicasの設定の削除を中心に話していきます。

Deploymentからreplicasの設定を削除する理由

そもそもなぜreplicasの設定を削除する必要があるかと言いますと、HPAによってレプリカ数を調整しているにもかかわらず、再デプロイした際にマニフェストのレプリカ数に戻されてしまうからです。
デプロイ時に使用されるkubectl applyコマンドは「適用するマニフェスト」と「実際のリソース」と比較して、設定値に差分があれば「適用するマニフェスト」の値を正として反映させます。
HPAはDeploymentのreplicasの値を変えることでレプリカ数を指定しているので、マニフェストからreplicasの設定を削除する必要があります。

Deploymentのreplicasの設定を残した場合のレプリカ数の遷移

  • 適用したマニフェスト(HPA側で最小レプリカ数は5に設定されている想定)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3 
  • 実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 5   # HPAによってレプリカ数が5に変更された。
  • もう一度マニフェストを適用した時の実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3   # 「実際のリソース」と「適用するマニフェスト」を比較して、差分があることを検知したため「適用するマニフェスト」の「3」に変更された。

Deploymentのreplicasの設定を削除した場合のレプリカ数の遷移

  • 適用したマニフェスト(HPA側で最小レプリカ数は5に設定されている想定)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
#  replicas: 3  # replicasの設定を削除。
  • 実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 5   # HPAによって、レプリカ数が5に設定された。
  • もう一度マニフェストを適用した時の実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 5   # 「マニフェスト」にreplicasの設定がないので変更されない。

前回適用したDeploymentのマニフェストからreplicasの設定を削除

Deploymentからreplicasの設定を削除したマニフェストをそのままデプロイすると初回デプロイではレプリカ数が1になってしまいます。
kubectl applyコマンドは「適用するマニフェスト」と「前回適用したマニフェスト」を比較して、「適用するマニフェスト」から削除されたものを検知し、「実際のリソース」から設定を削除します。
「実際のリソース」からreplicasの設定が削除されるとレプリカ数はデフォルト値の1になります。 これを防ぐために「前回適用したマニフェスト」からもreplicasの設定を削除することで、削除の検知をさせなくする必要があります。

削除方法

「前回適用したマニフェスト」はDeploymentのlast-applied-configurationに保存されているので、直接編集してreplicasの設定を削除します。

編集エディターを起動させます。(Deploymentがnginxの想定)

kubectl edit deployment nginx

以下のような表示が出るので、kubectl.kubernetes.io/last-applied-configuration"replicas":3,の部分を削除します。

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"nginx","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"name":"nginx"}},"template":   {"metadata":{"labels":{"name":"nginx"}},"spec":{"containers":[{"image":"nginx:latest","name":"nginx","ports":[{"containerPort":80}]}]}}}}

last-applied-configurationを編集しない場合のレプリカ数の遷移

  • 前回適用したマニフェスト/適用前の実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3   # HPAまだ入れていない想定なのでマニフェスト適用時と実際のリソースは変わらず。
  • 適用するマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  • 適用後の実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
#  replicas: 3  # 「前回適用したマニフェスト」からreplicasの設定がなくなったことを検知して削除される。レプリカ数は3→1(デフォルト)に変更される、

last-applied-configurationを編集した場合のレプリカ数の遷移

  • 実際に前回適用したマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  • Kubernetesに保存されている前回適用したマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
#  replicas: 3
  • 適用前の実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  • 適用するマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  • 適用後の実際のリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3   # 「適用するマニフェスト」と「前回適用したマニフェスト」にreplicasの設定がないので、削除されない。

まとめ

上記の方法でreplicasの設定を削除してからデプロイすることで、レプリカ数を下げずにHPAの導入ができました。
HPA以外にも、Deploymentの設定値をKubernetes側で変更する仕組みを導入する際には同じような手順が必要になるのでご参考にしてください。