kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Deployment に revisionHistoryLimit を設定して ReplicaSet のリビジョン数を制御する

Kubernetes で Deployment を使うときにマニフェストを修正して kubectl apply コマンドを繰り返し実行すると,ReplicaSet のリビジョンが増えていく.サンプルとして Deploymentimagenginx:1.8-alpinenginx:1.9-alpinenginx:1.10-alpine と修正しながらマニフェストを適用していくと以下のようになる.kubectl rollout history コマンドを使うとリビジョンも確認できる.また kubectl apply--record オプションを付けると操作履歴を記録できる.

# nginx:1.8-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit created

# nginx:1.9-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.10-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

$ kubectl rollout history deployment sandbox-deployment-revision-history-limit
deployment.apps/sandbox-deployment-revision-history-limit
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=deployment.yaml --record=true
2         kubectl apply --filename=deployment.yaml --record=true
3         kubectl apply --filename=deployment.yaml --record=true

$ kubectl get deployments,replicasets
NAME                                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/sandbox-deployment-revision-history-limit   3/3     3            3           91s

NAME                                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/sandbox-deployment-revision-history-limit-769f75d55b   0         0         0       90s
replicaset.apps/sandbox-deployment-revision-history-limit-7b94db8c49   0         0         0       51s
replicaset.apps/sandbox-deployment-revision-history-limit-7f87f5f547   3         3         3       28s

また Deploymentkubectl rollout undo コマンドを使うと過去のリビジョンにロールバックできる.さらに --to-revision オプションと組み合わせれば,指定したリビジョンにロールバックすることもできる.ロールバックをしてもリビジョンは増えていく.

$ kubectl rollout undo deployment sandbox-deployment-revision-history-limit
deployment.apps/sandbox-deployment-revision-history-limit rolled back

$ kubectl rollout undo deployment sandbox-deployment-revision-history-limit --to-revision 1
deployment.apps/sandbox-deployment-revision-history-limit rolled back

$ kubectl rollout history deployment sandbox-deployment-revision-history-limit
deployment.apps/sandbox-deployment-revision-history-limit
REVISION  CHANGE-CAUSE
3         kubectl apply --filename=deployment.yaml --record=true
4         kubectl apply --filename=deployment.yaml --record=true
5         kubectl apply --filename=deployment.yaml --record=true

リビジョン数のデフォルト値は 10

残る ReplicaSet のリビジョン数は Deployment.spec.revisionHistoryLimit フィールドで設定できる.デフォルトは 10 となる.ドキュメントの表現だと「古いリビジョン (old revision)」となる.よって DESIRED = 0 になって残っている ReplicaSet のことを指す.

kubernetes.io

まず「デフォルト値」を確認するために,引き続き nginx:1.11-alpine から nginx:1.18-alpine まで修正しながらマニフェストを繰り返し適用していく.すると,ReplicaSet の古いリビジョン数は「10個」になった.

# nginx:1.11-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.12-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.13-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.14-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.15-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.16-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.17-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

# nginx:1.18-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

$ kubectl get deployments,replicasets
NAME                                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/sandbox-deployment-revision-history-limit   3/3     3            3           5m

NAME                                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/sandbox-deployment-revision-history-limit-54f45b4c75   0         0         0       98s
replicaset.apps/sandbox-deployment-revision-history-limit-59b7cf78b9   0         0         0       2m16s
replicaset.apps/sandbox-deployment-revision-history-limit-6cb4d85b97   0         0         0       72s
replicaset.apps/sandbox-deployment-revision-history-limit-6d9d558bb6   0         0         0       84s
replicaset.apps/sandbox-deployment-revision-history-limit-6dfdf56756   0         0         0       60s
replicaset.apps/sandbox-deployment-revision-history-limit-769f75d55b   0         0         0       4m59s
replicaset.apps/sandbox-deployment-revision-history-limit-7b94db8c49   0         0         0       4m20s
replicaset.apps/sandbox-deployment-revision-history-limit-7dccdcc475   3         3         3       37s
replicaset.apps/sandbox-deployment-revision-history-limit-7f87f5f547   0         0         0       3m57s
replicaset.apps/sandbox-deployment-revision-history-limit-8565fb55f8   0         0         0       2m35s
replicaset.apps/sandbox-deployment-revision-history-limit-c544754bd    0         0         0       117s

次に nginx:1.19-alpine に修正してマニフェストを適用すると,以下のように最初に作られた replicaset.apps/sandbox-deployment-revision-history-limit-769f75d55b が削除された.なお,ドキュメントには The rest will be garbage-collected in the background. と書かれているため,kubectl apply のタイミングではなく,裏側で削除されていると言える.

# nginx:1.19-alpine
$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

$ kubectl get deployments,replicasets
NAME                                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/sandbox-deployment-revision-history-limit   3/3     3            3           6m

NAME                                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/sandbox-deployment-revision-history-limit-54f45b4c75   0         0         0       2m38s
replicaset.apps/sandbox-deployment-revision-history-limit-59b7cf78b9   0         0         0       3m16s
replicaset.apps/sandbox-deployment-revision-history-limit-6cb4d85b97   0         0         0       2m12s
replicaset.apps/sandbox-deployment-revision-history-limit-6d9d558bb6   0         0         0       2m24s
replicaset.apps/sandbox-deployment-revision-history-limit-6dfdf56756   0         0         0       2m
replicaset.apps/sandbox-deployment-revision-history-limit-7b94db8c49   0         0         0       5m20s
replicaset.apps/sandbox-deployment-revision-history-limit-7dccdcc475   0         0         0       97s
replicaset.apps/sandbox-deployment-revision-history-limit-7f87f5f547   0         0         0       4m57s
replicaset.apps/sandbox-deployment-revision-history-limit-8565fb55f8   0         0         0       3m35s
replicaset.apps/sandbox-deployment-revision-history-limit-c544754bd    0         0         0       2m57s
replicaset.apps/sandbox-deployment-revision-history-limit-f9f7485cd    3         3         3       25s

.spec.revisionHistoryLimit を設定する

最後に Deployment のマニフェストに .spec.revisionHistoryLimit: 2 を追加する.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-deployment-revision-history-limit
  labels:
    app: nginx
spec:
  replicas: 3
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19-alpine
        ports:
        - containerPort: 80

マニフェストを適用して,リビジョン数を確認すると,自動的に削除されていた.

$ kubectl apply -f deployment.yaml --record
deployment.apps/sandbox-deployment-revision-history-limit configured

$ kubectl get deployments,replicasets
NAME                                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/sandbox-deployment-revision-history-limit   3/3     3            3           8m

NAME                                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/sandbox-deployment-revision-history-limit-6dfdf56756   0         0         0       4m
replicaset.apps/sandbox-deployment-revision-history-limit-7dccdcc475   0         0         0       3m37s
replicaset.apps/sandbox-deployment-revision-history-limit-f9f7485cd    3         3         3       2m25s

まとめ

Kubernetes で Deployment.spec.revisionHistoryLimit フィールドを設定するとリビジョン数を制御できる.ドキュメントにはリビジョンを多く残すと,etcd のリソースを消費したり,kubectl get replicasets コマンドの結果が見にくくなると書いてある.最適値は状況によって異なるとは思うけど,デフォルト値 10 は多すぎるようにも感じる..spec.revisionHistoryLimit フィールドを覚えておこう!