Kubernetes kubectl rollout コマンドでdeploymentをロールバックしてみる
概要
kubectl rollout コマンドでデプロイ履歴を確認してロールバックするやり方を調べてみる
コマンド
オプション
help を確認するといくつかのオプションがあるみたいですね。
$ kubectl rollout --help
Manage the rollout of a resource.
Valid resource types include:
* deployments
* daemonsets
* statefulsets
Examples:
# Rollback to the previous deployment
kubectl rollout undo deployment/abc
# Check the rollout status of a daemonset
kubectl rollout status daemonset/foo
Available Commands:
history View rollout history
pause Mark the provided resource as paused
restart Restart a resource
resume Resume a paused resource
status Show the status of the rollout
undo Undo a previous rollout
Usage:
kubectl rollout SUBCOMMAND [options]
Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).
$
コマンド 実行結果
以下からはコマンドを実行したらどうなるのかを見ていきます。
テスト環境作成
まずは、ロールバックを操作するテスト環境を準備します。
$ kubectl create deployment test-dev --image=nginx
deployment.apps/test-dev created
$
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/test-dev-79894bfd64-s2c7k 1/1 Running 0 14s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/test-dev 1/1 1 1 14s
NAME DESIRED CURRENT READY AGE
replicaset.apps/test-dev-79894bfd64 1 1 1 14s
$
kubectl rollout history
ロールアウト履歴を表示するコマンドですね。
起動したばかりなので、1つだでけですね。
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
$
kubectl rollout restart
リソースを再起動だけするコマンドですね。
何も変更しないでリソースを再起動することができます。
$ kubectl rollout restart deploy test-dev
deployment.apps/test-dev restarted
$
・入れ替わりましたね
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/test-dev-57b8b64d5c-bcpcd 1/1 Running 0 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/test-dev 1/1 1 1 6m27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/test-dev-57b8b64d5c 1 1 1 30s
replicaset.apps/test-dev-79894bfd64 0 0 0 6m27s
$
・履歴が増えましたね
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 <none>
$
kubectl rollout status
ロールアウトのステータスを表示するらしいですが、
どんな時に利用するコマンドなんだろう?
$ kubectl rollout status deploy test-dev
deployment "test-dev" successfully rolled out
$
kubectl rollout pause /kubectl rollout resume
pauseは提供されたリソースを一時停止して、設定変更が反映をストップし
それをresumeで再開し反映させるみたいです。
kubectl rollout pause deploy nodeselector --to-revision=1
・状態確認
kubectl get all
kubectl rollout status deploy test-dev
kubectl rollout history deploy test-dev
・停止
kubectl rollout pause deploy test-dev
・レプリカ数変更
kubectl scale deployment test-dev --replicas=2
・状態確認
kubectl get all
kubectl rollout status deploy test-dev
kubectl rollout history deploy test-dev
・再開
kubectl rollout resume deploy test-dev
・状態確認
kubectl get all
kubectl rollout status deploy test-dev
kubectl rollout history deploy test-dev
結果
・状態確認
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/test-dev-57b8b64d5c-bcpcd 1/1 Running 0 15m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/test-dev 1/1 1 1 21m
NAME DESIRED CURRENT READY AGE
replicaset.apps/test-dev-57b8b64d5c 1 1 1 15m
replicaset.apps/test-dev-79894bfd64 0 0 0 21m
$ kubectl rollout status deploy test-dev
deployment "test-dev" successfully rolled out
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 <none>
$
・停止
$ kubectl rollout pause deploy test-dev
deployment.apps/test-dev paused
$
・ステータス確認→何も変化なし
$ kubectl rollout status deploy test-dev
deployment "test-dev" successfully rolled out
$
・レプリカ数変更
$ kubectl scale deployment test-dev --replicas=2
deployment.apps/test-dev scaled
$
・状態確認→レプリカ数変更は影響外みたい・・
$ kubectl rollout pause deploy test-dev
deployment.apps/test-dev paused
$ kubectl rollout status deploy test-dev
deployment "test-dev" successfully rolled out
$ kubectl scale deployment test-dev --replicas=2
deployment.apps/test-dev scaled
$
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/test-dev-57b8b64d5c-bcpcd 1/1 Running 0 17m
pod/test-dev-57b8b64d5c-l8wrr 1/1 Running 0 15s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/test-dev 2/2 2 2 23m
NAME DESIRED CURRENT READY AGE
replicaset.apps/test-dev-57b8b64d5c 2 2 2 17m
replicaset.apps/test-dev-79894bfd64 0 0 0 23m
$
$ kubectl rollout status deploy test-dev
deployment "test-dev" successfully rolled out
$
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 <none>
・イメージ変えてみる★
$ kubectl get deployment test-dev -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
test-dev 1/1 1 1 27m nginx nginx app=test-dev
$
$ kubectl set image deployment test-dev nginx=nginx:1.17
deployment.apps/test-dev image updated
$
$ kubectl get deployment test-dev -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
test-dev 1/1 0 1 30m nginx nginx:1.17 app=test-dev
$
・状態確認
$ kubectl rollout status deploy test-dev
Waiting for deployment "test-dev" rollout to finish: 0 out of 1 new replicas have been updated...
^C$
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/test-dev-57b8b64d5c-bcpcd 1/1 Running 0 27m 10.44.0.3 kubenode01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/test-dev 1/1 0 1 33m nginx nginx:1.17 app=test-dev
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/test-dev-57b8b64d5c 1 1 1 27m nginx nginx app=test-dev,pod-template-hash=57b8b64d5c
replicaset.apps/test-dev-79894bfd64 0 0 0 33m nginx nginx app=test-dev,pod-template-hash=79894bfd64
$
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 <none>
$
$ kubectl describe po test-dev-57b8b64d5c-bcpcd
Name: test-dev-57b8b64d5c-bcpcd
Namespace: default
Priority: 0
Node: kubenode01/192.168.56.3
Start Time: Wed, 07 Sep 2022 21:07:24 +0000
Labels: app=test-dev
pod-template-hash=57b8b64d5c
Annotations: kubectl.kubernetes.io/restartedAt: 2022-09-07T21:07:24Z
Status: Running
IP: 10.44.0.3
IPs:
IP: 10.44.0.3
Controlled By: ReplicaSet/test-dev-57b8b64d5c
Containers:
nginx:
Container ID: docker://aa51762136bc498874163e17e318a01ac22b5cc13041ba69e380f4c271d975a1
Image: nginx ★変わってないですね
Image ID: docker-pullable://nginx@sha256:b95a99feebf7797479e0c5eb5ec0bdfa5d9f504bc94da550c2f58e839ea6914f
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 07 Sep 2022 21:07:29 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jw7cx (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-jw7cx:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 28m default-scheduler Successfully assigned default/test-dev-57b8b64d5c-bcpcd to kubenode01
Normal Pulling 28m kubelet Pulling image "nginx"
Normal Pulled 28m kubelet Successfully pulled image "nginx" in 2.924743053s
Normal Created 28m kubelet Created container nginx
Normal Started 28m kubelet Started container nginx
$
・再開
$ kubectl rollout resume deploy test-dev
deployment.apps/test-dev resumed
$
・状態確認
$ kubectl rollout status deploy test-dev
Waiting for deployment "test-dev" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "test-dev" rollout to finish: 1 old replicas are pending termination...
deployment "test-dev" successfully rolled out
$
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/test-dev-6d497d69dd-wlhnz 1/1 Running 0 43s 10.44.0.2 kubenode01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/test-dev 1/1 1 1 36m nginx nginx:1.17 app=test-dev
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/test-dev-57b8b64d5c 0 0 0 30m nginx nginx app=test-dev,pod-template-hash=57b8b64d5c
replicaset.apps/test-dev-6d497d69dd 1 1 1 43s nginx nginx:1.17 app=test-dev,pod-template-hash=6d497d69dd
replicaset.apps/test-dev-79894bfd64 0 0 0 36m nginx nginx app=test-dev,pod-template-hash=79894bfd64
$
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
$
$ kubectl describe po test-dev-6d497d69dd-wlhnz
Name: test-dev-6d497d69dd-wlhnz
Namespace: default
Priority: 0
Node: kubenode01/192.168.56.3
Start Time: Wed, 07 Sep 2022 21:36:49 +0000
Labels: app=test-dev
pod-template-hash=6d497d69dd
Annotations: kubectl.kubernetes.io/restartedAt: 2022-09-07T21:07:24Z
Status: Running
IP: 10.44.0.2
IPs:
IP: 10.44.0.2
Controlled By: ReplicaSet/test-dev-6d497d69dd
Containers:
nginx:
Container ID: docker://dcad22edc173592fc491658f69906d8b2c98017d2656d435ba3e64190bbe066a
Image: nginx:1.17 ★ 変わった!!★
Image ID: docker-pullable://nginx@sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a6420d8ae16ef37c92d1eb26699
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 07 Sep 2022 21:37:04 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-k8c2c (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-k8c2c:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 98s default-scheduler Successfully assigned default/test-dev-6d497d69dd-wlhnz to kubenode01
Normal Pulling 97s kubelet Pulling image "nginx:1.17"
Normal Pulled 84s kubelet Successfully pulled image "nginx:1.17" in 13.522400996s
Normal Created 83s kubelet Created container nginx
Normal Started 83s kubelet Started container nginx
$
kubectl rollout restart
履歴のバージョンから前の状態に戻すコマンドですね。
・状態確認
kubectl get all
kubectl rollout history deploy test-dev
・履歴から戻してみる
kubectl rollout undo deploy test-dev --to-revision=1
・状態確認
kubectl get all
kubectl rollout status deploy test-dev
kubectl rollout history deploy test-dev
・結果
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/test-dev-6d497d69dd-wlhnz 1/1 Running 0 5m12s 10.44.0.2 kubenode01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/test-dev 1/1 1 1 40m nginx nginx:1.17 app=test-dev
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/test-dev-57b8b64d5c 0 0 0 34m nginx nginx app=test-dev,pod-template-hash=57b8b64d5c
replicaset.apps/test-dev-6d497d69dd 1 1 1 5m12s nginx nginx:1.17 app=test-dev,pod-template-hash=6d497d69dd ★いまはこれ
replicaset.apps/test-dev-79894bfd64 0 0 0 40m nginx nginx app=test-dev,pod-template-hash=79894bfd64
$
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
$
$ kubectl rollout undo deploy test-dev --to-revision=1
deployment.apps/test-dev rolled back
$
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/test-dev-79894bfd64-78g2v 1/1 Running 0 13s 10.44.0.3 kubenode01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/test-dev 1/1 1 1 43m nginx nginx app=test-dev
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/test-dev-57b8b64d5c 0 0 0 37m nginx nginx app=test-dev,pod-template-hash=57b8b64d5c
replicaset.apps/test-dev-6d497d69dd 0 0 0 8m18s nginx nginx:1.17 app=test-dev,pod-template-hash=6d497d69dd
replicaset.apps/test-dev-79894bfd64 1 1 1 43m nginx nginx app=test-dev,pod-template-hash=79894bfd64 ★戻った
$
・履歴1が消えて、4が増えましたね
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
2 <none>
3 <none>
4 <none>
$
テスト環境削除
テスト環境を削除します。
$ kubectl delete deployment test-dev
deployment.apps "test-dev" deleted
$
$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d
$
その他
履歴の調べ方
現在起動しているリソースのリビジョンを確認したい際には、
describe で詳細を表示して確認できます。
これの例だと「revision: 2」ですね。
$ kubectl describe deploy test-dev | grep revision
Annotations: deployment.kubernetes.io/revision: 2
$
履歴にアップデート情報記録
通常の履歴だけだと、数字だけなので、変更履歴がいまいちわかりませんが、
オプション「 --record」を付与してコマンド実行すると、履歴から何を
したのかある程度、わかる情報が残るようになります。
ただ、最新バージョンだとこれは非推奨のようです。
https://github.com/kubernetes/website/commit/e6b2f5acbf62b61b1dd7691248aac53b02dfbf5f
$ kubectl create deployment test-dev --image=nginx
deployment.apps/test-dev created
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
$
$ kubectl set image deployment test-dev nginx=nginx:1.17 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/test-dev image updated
$ kubectl rollout history deploy test-dev
deployment.apps/test-dev
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment test-dev nginx=nginx:1.17 --record=true ★何したか残る!
$
参考情報
Deployment
https://kubernetes.io/ja/docs/concepts/workloads/controllers/deployment/
kubectlリファレンスドキュメント
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#rollout