【Kubernetes】Horizontal Pod AutoscalerとDeploymentのレプリカ管理について
はじめに
HPA(Horizontal Pod Autoscaler)をデプロイした場合のレプリカ数の管理について解説していきます。
HPAとDeploymentのレプリカ管理
HPAを使っている場合、レプリカ数についての情報はHPAのspec.minReplicas
、spec.maxReplicas
とDeploymentのspec.replicas
に記載されることになってしまいます。
公式ドキュメントでは、HPAを使っている場合、Deploymentのspec.replicas
はマニフェストから削除することが推奨されています。
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のリソース取得
:::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
を削除します。
kubectl apply edit-last-applied deployment/<deployment_name>
を実行し、エディタ上でspec.replicas
を削除する- マニフェストの
spec.replicas
を削除する 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
を削除する