Kubernetes

Kubernetes kubectl rollout コマンドでdeploymentをロールバックしてみる

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

人気記事

1

Kubernetes kubectl rollout コマンドでdeploymentをロールバックしてみる 概要 kubectl rollout コマンドでデプロイ履歴を確認してロールバックするやり方 ...

2

  terraformのバージョン管理どうすればいいのか? terraformの複数バージョンを簡単に動かしたい terraformのインストール方法が分からない と、疑問を抱えている人の疑 ...

3

本記事では どんな環境にterraformをインストールできるの? terraformのインストールどうしたらいいの? terraformのどのバージョンをインストールすればいいの? と、困っている人 ...

4

Kubernetes kubectl version コマンドでバージョンを調べてみる 概要 kubectl version は、Kubernetes の Client、Serverのバージョンを確認 ...

-Kubernetes