Kubernetesで夜間停止を行う
Kubernetesを利用していた際に、特定のサービスのみ日中は処理量に応じてスケーリングしつつも、夜間は停止させたいといた要件があった。最初は、HPAは最小レプリカ数が1以上なため、スケーリングと停止の両立難しいかと思っていた。
しかし、調べてみるとHPAにスケーリングを停止させるための機能があり、今回はそれを利用することで実現した。
この記事では、その方法を紹介する。
HPAで夜間停止を実現する方法
HPAの下記機能で指定時間帯の停止を実現した。
If the target's desired replica count is set to 0, and the HPA's minimum replica count is greater than 0, the HPA stops adjusting the target (and sets the ScalingActive Condition on itself to false) until you reactivate it by manually adjusting the target's desired replica count or HPA's minimum replica count.
Implicit maintenance-mode deactivation | Kubernetes
HPAはターゲットのレプリカ数が0になると、再度レプリカ数が戻されるまでスケーリングを停止する仕様となっている。
これを利用して、停止時刻と開始時刻にレプリカ数を変化させるJobを起動させることで夜間停止を実現できる。
これは停止するためのCronJobの例。
apiVersion: batch/v1
kind: CronJob
metadata:
name: nginx-stopper
spec:
schedule: 00 12 * * *
startingDeadlineSeconds: 300
jobTemplate:
spec:
template:
spec:
serviceAccountName: nginx-controller
containers:
- name: kubectl
image: bitnami/kubectl:1.24
command:
- /bin/sh
- -c
- kubectl scale deployment.v1.apps/nginx --replicas=0
restartPolicy: OnFailure
指定時刻に起動され、kubectl scale deployment.v1.apps/nginx --replicas=0
でターゲットのレプリカ数を0にする。
これにより、再度レプリカ数をもとに戻されるまでの間は、HPAのスケーリングが停止する。
なお、レプリカ数を戻すためのCronJobは下記のレプリカ数変更処理を変えるだけでよい。
このJobに渡されている権限は下記。レプリカ数を変更するためには、これらの権限が必要となる。
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: nginx-controller
rules:
- apiGroups:
- apps
resources:
- deployments
resourceNames:
- nginx
verbs:
- get
- apiGroups:
- apps
resources:
- deployments/scale
resourceNames:
- nginx
verbs:
- get
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: nginx-controller
subjects:
- kind: ServiceAccount
name: nginx-controller
roleRef:
kind: Role
name: nginx-controller
apiGroup: rbac.authorization.k8s.io
起動用CronJobのマニフェストなども確認したい場合は、下記に全部あげているのでこちらを確認してもらいたい。
どのような挙動になるのか
ここからは、実際に利用した場合にどのような挙動となるのかについて記載していく。
デプロイしているのは、先程載せたGistのマニフェストとなっている。
まず始めに対象のマニフェストをapplyして各種リソースを作成する。
(HPAを利用するので事前にmetrics-serverをデプロイしている)
$ kubectl apply -f k8s-scaling-controller.yaml
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
metrics-server-6894588c69-vls6v 1/1 Running 0 9m29s
nginx-578c684cf6-6j97b 1/1 Running 0 18s
停止用CronJobが起動する時刻になると、Jobが起動する。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
metrics-server-6894588c69-vls6v 1/1 Running 0 9m49s
nginx-578c684cf6-6j97b 1/1 Running 0 38s
nginx-stopper-27635566-5gn7h 0/1 ContainerCreating 0 10s
Jobにより、nginxのレプリカ数が0になったので対象のPodが削除される。
これにより、停止期間が始まる。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
metrics-server-6894588c69-vls6v 1/1 Running 0 9m53s
nginx-stopper-27635566-5gn7h 0/1 Completed 0 14s
停止期間中のHPAを確認すると下記状態となっている。
ScalingActive
がFalse
となっており、HPAによるスケーリング処理が停止していることがわかる。
$ kubectl describe hpa nginx-hpa
# 不要なパラメータについては省略
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True SucceededGetScale the HPA controller was able to get the target's current scale
ScalingActive False ScalingDisabled scaling is disabled since the replica count of the target is zero
停止終了時刻になると開始用のCronJobが起動する。
これにより、再度nginxのレプリカ数がもとに戻され、Podが起動する。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
metrics-server-6894588c69-vls6v 1/1 Running 0 11m
nginx-578c684cf6-x5vvs 1/1 Running 0 5s
nginx-starter-27635568-htrn2 0/1 Completed 0 5s
nginx-stopper-27635566-5gn7h 0/1 Completed 0 2m5s
その後、再度HPAを確認すると下記状態になっている。
ScalingActive
がTrue
となっており、HPAのスケーリングが行われる状態になっていることがわかる。
$ kubectl describe hpa nginx-hpa
# 不要なパラメータについては省略
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True ReadyForNewScale recommended size matches current size
ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
ScalingLimited True TooFewReplicas the desired replica count is less than the minimum replica count
といった挙動をとるので、この機能を活用することで夜間停止が可能となる。
Discussion