🦉

Kubernetesで夜間停止を行う

2022/07/19に公開

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のマニフェストなども確認したい場合は、下記に全部あげているのでこちらを確認してもらいたい。

https://gist.github.com/x-color/ea7d6a12489b11aa4232de0c93ed3bfc

どのような挙動になるのか

ここからは、実際に利用した場合にどのような挙動となるのかについて記載していく。
デプロイしているのは、先程載せた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を確認すると下記状態となっている。
ScalingActiveFalseとなっており、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を確認すると下記状態になっている。
ScalingActiveTrueとなっており、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