【Kubernetes】Horizontal Pod AutoscalerとDeploymentのレプリカ管理について

2022.12.03
2024.03.24
Kubernetes
DeploymentHorizontal Pod Autoscaler

はじめに

HPA(Horizontal Pod Autoscaler)をデプロイした場合のレプリカ数の管理について解説していきます。

HPAとDeploymentのレプリカ管理

HPAを使っている場合、レプリカ数についての情報はHPAのspec.minReplicasspec.maxReplicasとDeploymentのspec.replicasに記載されることになってしまいます。

公式ドキュメントでは、HPAを使っている場合、Deploymentのspec.replicasはマニフェストから削除することが推奨されています。

Horizontal Pod Autoscaling

Horizontal Pod Autoscaling

In Kubernetes, a HorizontalPodAutoscaler automatically updates a workload resource (such as a Deployment or StatefulSet), with the aim of automatically scaling the workload to match demand. Horizontal scaling means that the response to increased load is to deploy more Pods. This is different from vertical scaling, which for Kubernetes would mean assigning more resources (for example: memory or CPU) to the Pods that are already running for the workload.

Deploymentでもレプリカ数を管理すると

まずHPAとDeploymentの両方でレプリカ数を管理しているとどうなるか見ていきます。

結論から言うと、Deploymentのマニフェストを反映するたびに一時的にDeploymentで指定されているレプリカ数になってしまいます

実際に試してみたいと思います。

Metrics Serverが必要な場合は、下記を参考にインストールしてください。

【Kubernetes】kubectl topでNodeとPodのリソース取得

【Kubernetes】kubectl topでNodeとPodのリソース取得

:::affiliate-message 本ページはAmazonアフィリエイトのリンクを含みます。

まずはDeploymentから用意します。

マニフェスト(deployment.yaml)は下記の通りです。レプリカ数は2にしてあります。

1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: nginx
5spec:
6  selector:
7    matchLabels:
8      run: nginx
9  replicas: 2
10  template:
11    metadata:
12      labels:
13        run: nginx
14    spec:
15      containers:
16      - name: nginx
17        image: nginx
18        resources:
19          limits:
20            cpu: 500m
21          requests:
22            cpu: 200m

Deploymentを作成します。

1kubectl apply -f deployment.yaml

もちろんレプリカ数は2になっています。

1❯ kubectl get pod
2NAME                     READY   STATUS    RESTARTS   AGE
3nginx-58cc49dd47-2hzlx   1/1     Running   0          69s
4nginx-58cc49dd47-m9sk5   1/1     Running   0          69s

次はHPAを用意します。

マニフェスト(hpa.yaml)は下記の通りです。最小のレプリカ数を3、最大を10にしています。

1apiVersion: autoscaling/v2
2kind: HorizontalPodAutoscaler
3metadata:
4  name: nginx-hpa
5spec:
6  scaleTargetRef:
7    apiVersion: apps/v1
8    kind: Deployment
9    name: nginx
10  minReplicas: 3
11  maxReplicas: 10
12  metrics:
13  - type: Resource
14    resource:
15      name: cpu
16      target:
17        type: Utilization
18        averageUtilization: 30

HPAを作成します。

1kubectl apply -f hpa.yaml

しばらくすると、HPAの設定した内容が反映され、Podが1つ作られ、レプリカ数が3になりました。

1❯ kubectl get pod
2NAME                     READY   STATUS    RESTARTS   AGE
3nginx-58cc49dd47-2hzlx   1/1     Running   0          6m14s
4nginx-58cc49dd47-g6lbs   1/1     Running   0          31s
5nginx-58cc49dd47-m9sk5   1/1     Running   0          6m14s
6
7❯ kubectl get hpa
8NAME        REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
9nginx-hpa   Deployment/nginx   0%/30%    3         10        3          2m7s

ここで再度、レプリカ数2のDeploymentのマニフェストを反映してみます。

1kubectl apply -f deployment.yaml

Podの挙動を見てみると、一度レプリカ数が2になってから、再度3に戻っています。つまり、Deploymentのレプリカ数を一時的に反映してから、HPAの最小レプリカ数が反映されているということになります。

1❯ kubectl get pod -w
2NAME                     READY   STATUS              RESTARTS   AGE
3nginx-58cc49dd47-2hzlx   1/1     Running             0          10m
4nginx-58cc49dd47-g6lbs   1/1     Running             0          5m7s
5nginx-58cc49dd47-m9sk5   1/1     Running             0          10m
6nginx-58cc49dd47-g6lbs   1/1     Terminating         0          5m9s
7nginx-58cc49dd47-g6lbs   0/1     Terminating         0          5m11s
8nginx-58cc49dd47-rtpv2   0/1     Pending             0          0s
9nginx-58cc49dd47-rtpv2   0/1     ContainerCreating   0          0s
10nginx-58cc49dd47-rtpv2   1/1     Running             0          3s

試してみた通り、Deploymentのマニフェストを反映するたびに一時的にDeploymentで指定されているレプリカ数になってしまうことが確認できました。

つまり、HPAが負荷を検知してスケールアウトしていたとしても、Deploymentを反映すると一時的にレプリカ数が少なくなってしまうという現象が起きる可能性があるということになります。

Deploymentからレプリカ数を削除すると

では、すでにDeploymentがデプロイされている状態で、マニフェストからspec.replicasを削除して反映するとどうなるでしょうか。

こちらも結論から言うと、一時的にレプリカ数が1になってからHPAで管理されているレプリカ数に戻ります。この場合は、spec.replicasをDeploymentのマニフェストから削除して初めて反映するタイミングだけになります。

実際に試してみます。

Deploymentからspec.replicasを削除します。

1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: nginx
5spec:
6  selector:
7    matchLabels:
8      run: nginx
9  #replicas: 2 # レプリカ数を削除
10  template:
11    metadata:
12      labels:
13        run: nginx
14    spec:
15      containers:
16      - name: nginx
17        image: nginx
18        resources:
19          limits:
20            cpu: 500m
21          requests:
22            cpu: 200m

マニフェストを反映してみます。

1kubectl apply -f deployment.yaml

すると、一時的にレプリカ数が1になってから、HPAの最小レプリカ数の3まで戻っています。

1❯ kubectl get pod -w
2NAME                     READY   STATUS              RESTARTS   AGE
3nginx-58cc49dd47-2hzlx   1/1     Running             0          31m
4nginx-58cc49dd47-m9sk5   1/1     Running             0          31m
5nginx-58cc49dd47-rtpv2   1/1     Running             0          19m
6nginx-58cc49dd47-m9sk5   1/1     Terminating         0          31m
7nginx-58cc49dd47-2hzlx   1/1     Terminating         0          31m
8nginx-58cc49dd47-2hzlx   0/1     Terminating         0          31m
9nginx-58cc49dd47-m9sk5   0/1     Terminating         0          31m
10nginx-58cc49dd47-mvdgw   0/1     Pending             0          0s
11nginx-58cc49dd47-4s6jx   0/1     Pending             0          0s
12nginx-58cc49dd47-mvdgw   0/1     ContainerCreating   0          0s
13nginx-58cc49dd47-4s6jx   0/1     ContainerCreating   0          0s
14nginx-58cc49dd47-mvdgw   1/1     Running             0          7s
15nginx-58cc49dd47-4s6jx   1/1     Running             0          9s

安全にDeploymentからレプリカ数を削除する方法

Deploymentからspec.replicasを削除するのが推奨されているとはいえ、単純に削除して反映してしまうと一時的にレプリカ数が1になってしまうのは本番環境などではインパクトが大きいかと思います。

このレプリカ数が1になってしまう現象を回避する場合は、下記の手順でDeploymentのspec.replicasを削除します。

  1. kubectl apply edit-last-applied deployment/<deployment_name>を実行し、エディタ上でspec.replicasを削除する
  2. マニフェストのspec.replicasを削除する
  3. spec.replicasが削除されたマニフェストを反映する

実際に試してみます。

spec.replicasが削除されていないDeploymentを反映します。

1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: nginx
5spec:
6  selector:
7    matchLabels:
8      run: nginx
9  replicas: 2
10  template:
11    metadata:
12      labels:
13        run: nginx
14    spec:
15      containers:
16      - name: nginx
17        image: nginx
18        resources:
19          limits:
20            cpu: 500m
21          requests:
22            cpu: 200m
1kubectl apply -f deployment.yaml

下記を実行して、エディタ上からspec.replicasを削除して、保存します。

1kubectl apply edit-last-applied deployment/nginx
1# Please edit the 'last-applied-configuration' annotations below.
2# Lines beginning with a '#' will be ignored, and an empty file will abort the edit.
3#
4apiVersion: apps/v1
5kind: Deployment
6metadata:
7  annotations: {}
8  name: nginx
9  namespace: default
10spec: # replicasを削除します
11  selector:
12    matchLabels:
13      run: nginx
14  template:

そうすると、Podの数はHPAで管理されている数のままになっています。

1❯ kubectl get pod
2NAME                     READY   STATUS    RESTARTS   AGE
3nginx-58cc49dd47-4s6jx   1/1     Running   0          17m
4nginx-58cc49dd47-rtpv2   1/1     Running   0          37m
5nginx-58cc49dd47-sgtcn   1/1     Running   0          2m40s

次に、Deploymentのマニフェストからspec.replicasを削除します。

1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: nginx
5spec: # replicasを削除します
6  selector:
7    matchLabels:
8      run: nginx
9  template:
10    metadata:
11
12...

これを反映させてみると、unchangedとなりレプリカ数も3のままになっています。

1❯ kubectl apply -f deployment.yaml
2deployment.apps/nginx unchanged

これで安全にDeploymentからspec.replicasを削除することができました。

まとめ

  • HPAを使っている場合、Deploymentのspec.replicasは削除するのが推奨されている
  • HPAとDeploymentでレプリカ数を管理していると、Deploymentのマニフェストを反映するたびに一時的にDeploymentで指定されているレプリカ数になってしまう
  • すでにデプロイされているDeploymentのマニフェストからspec.replicasを削除すると、次回反映時に一時的にレプリカ数が1になってしまう
  • 安全にDeploymentからspec.replicasを削除するにはkubectl apply edit-last-applied deployment/<deployment_name>で削除してから、マニフェストのspec.replicasを削除する

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee