はじめに
HPA(Horizontal Pod Autoscaler)をデプロイした場合のレプリカ数の管理について解説していきます。
HPAとDeploymentのレプリカ管理
HPAを使っている場合、レプリカ数についての情報はHPAのspec.minReplicas
、spec.maxReplicas
とDeploymentのspec.replicas
に記載されることになってしまいます。
公式ドキュメントでは、HPAを使っている場合、Deploymentのspec.replicas
はマニフェストから削除することが推奨されています。
Deploymentでもレプリカ数を管理すると
まずHPAとDeploymentの両方でレプリカ数を管理しているとどうなるか見ていきます。
結論から言うと、Deploymentのマニフェストを反映するたびに一時的にDeploymentで指定されているレプリカ数になってしまいます。
実際に試してみたいと思います。
Metrics Serverが必要な場合は、下記を参考にインストールしてください。

まずはDeploymentから用意します。
マニフェスト(deployment.yaml
)は下記の通りです。レプリカ数は2にしてあります。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
run: nginx
replicas: 2
template:
metadata:
labels:
run: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: 500m
requests:
cpu: 200m
Deploymentを作成します。
kubectl apply -f deployment.yaml
もちろんレプリカ数は2になっています。
❯ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-58cc49dd47-2hzlx 1/1 Running 0 69s
nginx-58cc49dd47-m9sk5 1/1 Running 0 69s
次はHPAを用意します。
マニフェスト(hpa.yaml
)は下記の通りです。最小のレプリカ数を3、最大を10にしています。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 30
HPAを作成します。
kubectl apply -f hpa.yaml
しばらくすると、HPAの設定した内容が反映され、Podが1つ作られ、レプリカ数が3になりました。
❯ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-58cc49dd47-2hzlx 1/1 Running 0 6m14s
nginx-58cc49dd47-g6lbs 1/1 Running 0 31s
nginx-58cc49dd47-m9sk5 1/1 Running 0 6m14s
❯ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx 0%/30% 3 10 3 2m7s
ここで再度、レプリカ数2のDeploymentのマニフェストを反映してみます。
kubectl apply -f deployment.yaml
Podの挙動を見てみると、一度レプリカ数が2になってから、再度3に戻っています。つまり、Deploymentのレプリカ数を一時的に反映してから、HPAの最小レプリカ数が反映されているということになります。
❯ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
nginx-58cc49dd47-2hzlx 1/1 Running 0 10m
nginx-58cc49dd47-g6lbs 1/1 Running 0 5m7s
nginx-58cc49dd47-m9sk5 1/1 Running 0 10m
nginx-58cc49dd47-g6lbs 1/1 Terminating 0 5m9s
nginx-58cc49dd47-g6lbs 0/1 Terminating 0 5m11s
nginx-58cc49dd47-rtpv2 0/1 Pending 0 0s
nginx-58cc49dd47-rtpv2 0/1 ContainerCreating 0 0s
nginx-58cc49dd47-rtpv2 1/1 Running 0 3s
試してみた通り、Deploymentのマニフェストを反映するたびに一時的にDeploymentで指定されているレプリカ数になってしまうことが確認できました。
つまり、HPAが負荷を検知してスケールアウトしていたとしても、Deploymentを反映すると一時的にレプリカ数が少なくなってしまうという現象が起きる可能性があるということになります。
Deploymentからレプリカ数を削除すると
では、すでにDeploymentがデプロイされている状態で、マニフェストからspec.replicas
を削除して反映するとどうなるでしょうか。
こちらも結論から言うと、一時的にレプリカ数が1になってからHPAで管理されているレプリカ数に戻ります。この場合は、spec.replicas
をDeploymentのマニフェストから削除して初めて反映するタイミングだけになります。
実際に試してみます。
Deploymentからspec.replicas
を削除します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
run: nginx
#replicas: 2 # レプリカ数を削除
template:
metadata:
labels:
run: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: 500m
requests:
cpu: 200m
マニフェストを反映してみます。
kubectl apply -f deployment.yaml
すると、一時的にレプリカ数が1になってから、HPAの最小レプリカ数の3まで戻っています。
❯ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
nginx-58cc49dd47-2hzlx 1/1 Running 0 31m
nginx-58cc49dd47-m9sk5 1/1 Running 0 31m
nginx-58cc49dd47-rtpv2 1/1 Running 0 19m
nginx-58cc49dd47-m9sk5 1/1 Terminating 0 31m
nginx-58cc49dd47-2hzlx 1/1 Terminating 0 31m
nginx-58cc49dd47-2hzlx 0/1 Terminating 0 31m
nginx-58cc49dd47-m9sk5 0/1 Terminating 0 31m
nginx-58cc49dd47-mvdgw 0/1 Pending 0 0s
nginx-58cc49dd47-4s6jx 0/1 Pending 0 0s
nginx-58cc49dd47-mvdgw 0/1 ContainerCreating 0 0s
nginx-58cc49dd47-4s6jx 0/1 ContainerCreating 0 0s
nginx-58cc49dd47-mvdgw 1/1 Running 0 7s
nginx-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を反映します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
run: nginx
replicas: 2
template:
metadata:
labels:
run: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: 500m
requests:
cpu: 200m
kubectl apply -f deployment.yaml
下記を実行して、エディタ上からspec.replicas
を削除して、保存します。
kubectl apply edit-last-applied deployment/nginx
# Please edit the 'last-applied-configuration' annotations below.
# Lines beginning with a '#' will be ignored, and an empty file will abort the edit.
#
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
name: nginx
namespace: default
spec: # replicasを削除します
selector:
matchLabels:
run: nginx
template:
そうすると、Podの数はHPAで管理されている数のままになっています。
❯ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-58cc49dd47-4s6jx 1/1 Running 0 17m
nginx-58cc49dd47-rtpv2 1/1 Running 0 37m
nginx-58cc49dd47-sgtcn 1/1 Running 0 2m40s
次に、Deploymentのマニフェストからspec.replicas
を削除します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec: # replicasを削除します
selector:
matchLabels:
run: nginx
template:
metadata:
...
これを反映させてみると、unchanged
となりレプリカ数も3のままになっています。
❯ kubectl apply -f deployment.yaml
deployment.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
を削除する