KubernetesのRollingUpdate/Rollbackを試してみて「ほえ～っ！！！」ってする

こんにちは
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回はGKE環境を使ってKubernetesのローリングアップデート及びロールバックを実際に試してみようと思います。

# 検証方法

以下が検証イメージです。
まずGKE環境上でDockerfileとindex.htmlファイルを作成し検証用のDockerイメージを作成します。
作成したイメージをGoogle Container Registry（≒docker hub的なもの）にpush。
DeploymentとLoadBalancer用のyamlを用意し、それを元にGKE環境にデプロイ。Firefoxを使ってDeploymentに接続してindex.htmlファイルの中身を確認。
その後index.htmlの内容を書き換えて再度イメージを作成しpush。
yamlを書き換えてdeploymentを更新。更新出来たらFirefoxでindex.htmlファイルの中身が更新されていることを確認。
この流れを2,3度繰り返していきます。

![名称未設定ファイル-ページ12 drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/0b36e988-d48d-4c44-963a-faacd8601996)

# 用語

Dockerfile
---
>Docker は Dockerfile から命令を読み込み、自動的にイメージをビルドできます。 Dockerfile はテキストファイルであり、イメージを作り上げるために実行するコマンドライン命令を、すべてこのファイルに含められます。

docker buildコマンド
---
>docker build を実行すると、順次コマンドライン命令を自動化した処理を行い、ビルド結果となるイメージが得られます。

https://docs.docker.jp/engine/reference/builder.html#dockerfile

GCR(Google Container Registry)
---

>Docker コンテナ イメージを保存、管理、保護。Container Registry では、Docker イメージの一元的な管理と脆弱性分析を行えます。また、きめ細かなアクセス制御によって、どのユーザーに何へのアクセスを許可するかを決定できます。

https://cloud.google.com/container-registry?hl=ja

kubectl applyコマンド
---
>applyはKubernetesリソースを定義するファイルを通じてアプリケーションを管理します。kubectl applyを実行して、クラスター内のリソースを作成および更新します。これは、本番環境でKubernetesアプリケーションを管理する推奨方法です。

https://kubernetes.io/ja/docs/reference/kubectl/cheatsheet/#kubectl-apply

kubectl createとkubectl applyの際については以下がグラフィカルで分かりやすいと思いました。
kubectl applyで無いとkubectl diffコマンドで差分がきれいに出せないのかなと思っています。多分。
基本的にapplyを使うのが正解なのかなと思っています。

https://tenzen.hatenablog.com/entry/2019/11/24/033035

# 環境

GKEでautopilotでk8sクラスタを自動構築しています。
2台のノードでクラスタ化されています。
```
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ kubectl get node -o wide
NAME                                            STATUS   ROLES    AGE   VERSION            INTERNAL-IP   EXTERNAL-IP     OS-IMAGE                             KERNEL-VERSION   CONTAINER-RUNTIME
gk3-my-k8s-cluster-default-pool-13c33173-fjcl   Ready    <none>   15m   v1.25.7-gke.1000   10.128.0.6    34.31.37.35     Container-Optimized OS from Google   5.15.65+         containerd://1.6.18
gk3-my-k8s-cluster-default-pool-dda5f4e0-zrgs   Ready    <none>   15m   v1.25.7-gke.1000   10.128.0.7    35.188.98.215   Container-Optimized OS from Google   5.15.65+         containerd://1.6.18
```

# Dockerfileを使ってイメージを作成し、GCRにpushする(1回目)

まず以下のhtmlファイルを用意しました。
このファイルをDockerfileを使い作成するDockerイメージに組み込みますが、バージョンアップをする時に"ver1.0!"の部分を少しずつ変化させます。
```index.html
<h1>Hello GKE!</h1>
<h2>This is apache2 pod ver1.0!</h2>
```

Dockerfileは以下を用意。
『httpdのDockerイメージを使用し、そのイメージの中にあるindex.htmlはGKE上に用意したものを使用してね！』的な事が書いていると思って頂ければいいと思います。
```Dockerfile
FROM httpd

COPY index.html /usr/local/apache2/htdocs/
```

イメージ化します。GCRにpushする都合上、イメージの名前の付け方に気を付けます。
"gcr.io/"のあとの部分は各個人のプロジェクトIDを確認して調整をしてください。
```
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ docker build -t gcr.io/western-antonym-●●●●●●/apache2:1.0 .
```

プロジェクトIDはGCPのトップ画面の赤で塗りつぶしたところに書いています。
<img width="1115" alt="GCP" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/c4fbdf66-8afa-4b0e-b467-d8b5a99bdcd7">

この後GKEにGCRを認識？させます
※もしかしたら、この部分はいらないかもしれません。
```
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ gcloud auth configure-docker
WARNING: Your config file at [/home/ohtsuka_honban/.docker/config.json] contains these credential helper entries:

{
  "credHelpers": {
    "gcr.io": "gcloud",
    "us.gcr.io": "gcloud",
    "eu.gcr.io": "gcloud",
    "asia.gcr.io": "gcloud",
    "staging-k8s.gcr.io": "gcloud",
    "marketplace.gcr.io": "gcloud"
  }
}
Adding credentials for all GCR repositories.
WARNING: A long list of credential helpers may cause delays running 'docker build'. We recommend passing the registry name to configure only the registry you are using.
gcloud credential helpers already registered correctly.
```

GCRに作成したイメージをpushします
```
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ docker push gcr.io/western-antonym-●●●●●●/apache2:1.0
The push refers to repository [gcr.io/western-antonym-●●●●●●/apache2]
90003dd9562f: Pushed 
76554aaac635: Layer already exists 
12ef76c76336: Layer already exists 
ce0966b9747d: Layer already exists 
1f1fd2176485: Layer already exists 
8553b91047da: Layer already exists 
1.0: digest: sha256:e4ec01a71471dec8ebbe0dc65372b715142c5dd4b9640f0a3df0d3fbf071ac36 size: 1573
```

WebコンソールでGCRを開き、push出来ているかを確認します。
問題なさそうですね。
<img width="1122" alt="GKE2023051301" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/1f115311-2aa5-4faa-9649-20257f641523">

# GKEにDeploymentとLoadBalancerをデプロイし、Webブラウザでindex.htmlを確認する(1回目)

Deployment用に用意したyamlファイルは以下
strategyの部分がローリングアップデートやロールバックに関連してくるものになります。
今回は"rollingUpdate"を指定していますが"Recreate"というstrategyもあるみたいです。何も指定しないと"rollingUpdate"が勝手に選択されるのですが、勉強の為入力しています。
"maxSurge: 1"というのは「宣言したPod数を超えて作れるPod数を1とする」ということを指定し、"maxUnavailable: 0"というのは「停止状態になる最大Pod数を0とする」ということを指定しています。
```apache2-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache2-deployment
  labels:
    name: apache2-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      name: apache2 
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        name: apache2 
    spec:
      containers:
      - name: apache2-con
        image: gcr.io/western-antonym-●●●●●●/apache2:1.0
        ports:
        - containerPort: 80
```

自分で書いていて"maxSurge: 1"と"maxUnavailable: 0"が腑に落ちなかったので、少しググってみたのですが、以下の記事が分かりやすかったです。

ざっくりですが
- "yamlで指定されたreplicasの数"+"yamlで指定されたmaxSurgeの数"＝"ローリングアップデート/ロールバック時の最大のpodの数"（私の場合、2 + 1 = 3）
- "yaml指定されたreplicasの数"+"yamlで指定されたmaxUnavailableの数"＝"ローリングアップデート/ロールバック時の最小のpodの数"（私の場合、2 - 0 = 2）

ということになるのだと思います。
「ローリングアップデート/ロールバックの際podの数は2以上3以下で維持せよ！」ということをKubernetesに指示していることになるのだと思います。

https://tech-lab.sios.jp/archives/18553

デプロイしていきます。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl apply -f apache2-deployment.yaml 
Warning: Autopilot set default resource requests for Deployment default/apache2-deployment, as resource requests were not specified. See http://g.co/gke/autopilot-defaults
deployment.apps/apache2-deployment created
```

結果を確認します。2つpodが作成されていることが分かりますね。
また、Deploymentとそれに合わせてReplicasetも作成されています。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl get all -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP               NODE                                      NOMINATED NODE   READINESS GATES
pod/apache2-deployment-7868df7b76-d8tnd   1/1     Running   0          37s   10.109.128.138   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>
pod/apache2-deployment-7868df7b76-jbmbq   1/1     Running   0          37s   10.109.128.139   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>


NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.110.0.1   <none>        443/TCP   94m   <none>


NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                                      SELECTOR
deployment.apps/apache2-deployment   2/2     2            2           37s   apache2-con   gcr.io/western-antonym-386513/apache2:1.0   name=apache2


NAME                                            DESIRED   CURRENT   READY   AGE   CONTAINERS    IMAGES                                      SELECTOR
replicaset.apps/apache2-deployment-7868df7b76   2         2         2       38s   apache2-con   gcr.io/western-antonym-386513/apache2:1.0   name=apache2,pod-template-hash=7868df7b76
```

LoadBalacerをデプロイします。
今回用意したyamlファイルは以下です。
```apache2-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
  name: apache2-loadbalancer
spec:
  type: LoadBalancer
  selector:
    name: apache2
  ports:
  - protocol: TCP
    port: 60080
    targetPort: 80
```

デプロイします。結果も問題なさそうです。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl apply -f apache2-loadbalancer.yaml 
service/apache2-loadbalancer created

ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl get svc -o wide
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)           AGE   SELECTOR
apache2-loadbalancer   LoadBalancer   10.110.0.162   35.238.40.41   60080:30377/TCP   43s   name=apache2
kubernetes             ClusterIP      10.110.0.1     <none>         443/TCP           95m   <none>
```

この時のイメージです。
Replicasetは今後増えていくので、（私が）ごちゃごちゃしないように名前を書いておきます。
![名称未設定ファイル-ページ13 drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/a2630a58-5ede-4dc0-8f96-d0b81300836a)

Webブラウザで確認してみます。
指定したhtmlファイルが表示されていますね。
<img width="468" alt="GKE2023051302" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/9fa84a7f-ae10-45b1-828a-12f43cc2c252">

# Dockerfileを使ってイメージを作成し、GCRにpushする(2回目)

index.htmlの"ver1.0!"を"ver1.1!"にしたものをベースにdockerイメージ"apache2:1.1"を作成し、GCRにpushします。
```
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ cat index.html 
<h1>Hello GKE!</h1>
<h2>This is apache2 pod ver1.1!</h2>
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ docker build -t gcr.io/western-antonym-●●●●●●/apache2:1.1 .
ohtsuka_honban@cloudshell:~/yaml/docker (western-antonym-●●●●●●)$ docker push gcr.io/western-antonym-●●●●●●/apache2:1.1
```

GCRにアップロードされていますね。
<img width="1119" alt="GKE2023051303" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/2ff67c5a-bbdb-4de2-8a34-81cbc2a3c126">

# GKEにDeploymentとLoadBalancerをデプロイし、Webブラウザでindex.htmlを確認する(2回目)

ローリングアップデート用のyamlを用意します。
pod用のイメージを更新したのみで他は変更ありません。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ cp -p apache2-deployment.yaml apache2-deployment-1.1.yaml
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ diff apache2-deployment.yaml apache2-deployment-1.1.yaml
23c23
<         image: gcr.io/western-antonym-386513/apache2:1.0
---
>         image: gcr.io/western-antonym-386513/apache2:1.1
```

kubectl applyでDeploymentに対してアップデートを行っていきます。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl apply -f apache2-deployment-1.1.yaml 
deployment.apps/apache2-deployment configured
```
kubectl get all -o wideの出力結果をwatchコマンドでリアルタイムで追っていきます。
ローリングアップデートの途中の出力結果が以下となります。
"apache2:1.1"をイメージとしたReplicasetである"apache2-deployment-67f8d54489"が作成され、そのReplicaset内で管理されているpod"apache2-deployment-67f8d54489-dt997"が作成を開始しています。
```
NAME                                      READY   STATUS    RESTARTS   AGE   IP               NODE                                      NOMINATED NODE   READINESS GATES
pod/apache2-deployment-67f8d54489-dt997   0/1     Pending   0          8s    <none>           <none>                                    <none>           <none>
pod/apache2-deployment-7868df7b76-d8tnd   1/1     Running   0          10m   10.109.128.138   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>
pod/apache2-deployment-7868df7b76-jbmbq   1/1     Running   0          10m   10.109.128.139   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)           AGE     SELECTOR
service/apache2-loadbalancer   LoadBalancer   10.110.0.162   35.238.40.41   60080:30377/TCP   9m32s   name=apache2
service/kubernetes             ClusterIP      10.110.0.1     <none>         443/TCP           104m    <none>

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                                      SELECTOR
deployment.apps/apache2-deployment   2/2     1            2           10m   apache2-con   gcr.io/western-antonym-386513/apache2:1.1   name=apache2

NAME                                            DESIRED   CURRENT   READY   AGE   CONTAINERS    IMAGES                                      SELECTOR
replicaset.apps/apache2-deployment-67f8d54489   1         1         0       9s    apache2-con   gcr.io/western-antonym-386513/apache2:1.1   name=apache2,pod-template-hash=67f8d54489
replicaset.apps/apache2-deployment-7868df7b76   2         2         2       10m   apache2-con   gcr.io/western-antonym-386513/apache2:1.0   name=apache2,pod-template-hash=7868df7b76
```

最終的な状態は以下となります。ver1.0のpodが削除され、1.1のpodのみが稼働しています。
個人的に意外だと思ったのがver1.0のreplicasetが残るんだということです。恐らくロールバックの時に内部的に設定値を見る為とかに残しているのかなと思っているのですがどうなんでしょう。。。？
```
NAME                                      READY   STATUS    RESTARTS   AGE   IP               NODE                                      NOMINATED NODE   READINESS GATES
pod/apache2-deployment-67f8d54489-4hzkj   1/1     Running   0          68s   10.109.128.141   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>
pod/apache2-deployment-67f8d54489-v6nnw   1/1     Running   0          68s   10.109.128.142   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)           AGE    SELECTOR
service/apache2-loadbalancer   LoadBalancer   10.110.0.162   35.238.40.41   60080:30377/TCP   13m    name=apache2
service/kubernetes             ClusterIP      10.110.0.1     <none>         443/TCP           108m   <none>

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                                      SELECTOR
deployment.apps/apache2-deployment   2/2     2            2           14m   apache2-con   gcr.io/western-antonym-386513/apache2:1.1   name=apache2

NAME                                            DESIRED   CURRENT   READY   AGE     CONTAINERS    IMAGES                                      SELECTOR
replicaset.apps/apache2-deployment-67f8d54489   2         2         2       4m24s   apache2-con   gcr.io/western-antonym-386513/apache2:1.1   name=apache2,pod-template-hash=67f8d54489
replicaset.apps/apache2-deployment-7868df7b76   0         0         0       14m     apache2-con   gcr.io/western-antonym-386513/apache2:1.0   name=apache2,pod-template-hash=7868df7b76
```

上記のローリングアップデートをイメージに起こすと以下の様になるかと思います。
まずver1.1のpodの作成が開始されます。まだ作成完了していないので通信先は双方ver1.0のpodになります。
![名称未設定ファイル-ページ13のコピー drawio (1)](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/352262b7-3138-44b3-919d-8bedf36d2977)

ver1.1のpodの作成が完了すると宛先をそちらに変更し、2つのうち1つのver1.0 podは削除。それと同時にもうひとつver1.1のpodの作成を開始します。
この時、恐らく残ったver1.0にもロードバランシングしていると思います。今後要検証かと。。。
![名称未設定ファイル-ページ13のコピーのコピー drawio (1)](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/7dbe0046-7105-4996-ba69-ee7d8b667c1f)

1つ前で作成を開始したver1.1のpodの作成が完了するとver1.0に振られていた宛先をそちらに変更。
役割を終えたver1.0のpodを削除します。
![名称未設定ファイル-ページ13のコピーのコピーのコピー drawio (1)](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/399ef75c-35a9-4920-8201-11d1bcac5a26)

kubectl rollout statusで確認してみます。問題無くローリングアップデートが出来たと書いていますね。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl rollout status deployment
deployment "apache2-deployment" successfully rolled out
```

kubectl rollout historyコマンドも見てみます。
過去のものはREVISIONとして管理されているようですね。
REVISION 1がver1.0のもの。2がver1.1のものになります。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl rollout history deployment
deployment.apps/apache2-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
```

kubectl diffコマンドを見てみます。
-fでyamlファイルを指定し、そのyamlファイルと現状稼動しているDeploymentの差分を出しているようですね。
現に稼働しているapache2-deployment-1.1.yamlでdiffをかけても何も出力されておりません。
```
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl diff -f apache2-deployment.yaml 
diff -u -N /tmp/LIVE-4004392298/apps.v1.Deployment.default.apache2-deployment /tmp/MERGED-3784003542/apps.v1.Deployment.default.apache2-deployment
--- /tmp/LIVE-4004392298/apps.v1.Deployment.default.apache2-deployment  2023-05-12 23:45:16.669876027 +0000
+++ /tmp/MERGED-3784003542/apps.v1.Deployment.default.apache2-deployment        2023-05-12 23:45:16.670876121 +0000
@@ -7,7 +7,7 @@
     kubectl.kubernetes.io/last-applied-configuration: |
       {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"name":"apache2-deployment"},"name":"apache2-deployment","namespace":"default"},"spec":{"replicas":2,"selector":{"matchLabels":{"name":"apache2"}},"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}},"template":{"metadata":{"labels":{"name":"apache2"}},"spec":{"containers":[{"image":"gcr.io/western-antonym-●●●●●●/apache2:1.1","name":"apache2-con","ports":[{"containerPort":80}]}]}}}}
   creationTimestamp: "2023-05-12T23:25:59Z"
-  generation: 2
+  generation: 3
   labels:
     name: apache2-deployment
   name: apache2-deployment
@@ -33,7 +33,7 @@
         name: apache2
     spec:
       containers:
-      - image: gcr.io/western-antonym-●●●●●●/apache2:1.1
+      - image: gcr.io/western-antonym-●●●●●●/apache2:1.0
         imagePullPolicy: IfNotPresent
         name: apache2-con
         ports:
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$ kubectl diff -f apache2-deployment-1.1.yaml 
ohtsuka_honban@cloudshell:~/yaml (western-antonym-●●●●●●)$
```

Webブラウザでアクセスします。ver1.1が表示されていますね。
<img width="509" alt="GKE2023051304" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/0c3dbc0b-1f23-4816-a2f8-bbf9870fe5ed">



# Dockerfileを使ってイメージを作成し、GCRにpushする(3回目)

端折りますが、htmlを1.2に変更しイメージを作成し、GCRにpushします。
```
ohtsuka_honban@cloudshell:~/yaml/docker$ cat index.html 
<h1>Hello GKE!</h1>
<h2>This is apache2 pod ver1.2!</h2>
ohtsuka_honban@cloudshell:~/yaml/docker$ docker build -t gcr.io/western-antonym-●●●●●●/apache2:1.2 .
ohtsuka_honban@cloudshell:~/yaml/docker$ docker push gcr.io/western-antonym-●●●●●●/apache2:1.2
```

GCRで確認します。
<img width="1119" alt="GKE2023051305" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/00e2137b-c2f7-44f3-8ae8-224de1f05b77">


# GKEにDeploymentとLoadBalancerをデプロイし、Webブラウザでindex.htmlを確認する(3回目)

ローリングアップデート用のyamlを用意し、更新をかけます。
```
ohtsuka_honban@cloudshell:~/yaml$ cp -p apache2-deployment-1.1.yaml apache2-deployment-1.2.yaml 
ohtsuka_honban@cloudshell:~/yaml$ vi apache2-deployment-1.2.yaml
ohtsuka_honban@cloudshell:~/yaml$ diff apache2-deployment-1.1.yaml apache2-deployment-1.2.yaml 
23c23
<         image: gcr.io/western-antonym-●●●●●●/apache2:1.1
---
>         image: gcr.io/western-antonym-●●●●●●/apache2:1.2
ohtsuka_honban@cloudshell:~/yaml$ kubectl apply -f apache2-deployment-1.2.yaml
deployment.apps/apache2-deployment configured
```

途中経過をwatchします。
ver1.2をベースとしたReplicaset"apache2-deployment-8596d9c558"が作成されており、併せてそのReplicaset配下のpod"apache2-deployment-8596d9c558-l6nqr"が作成されています。
```
NAME                                      READY   STATUS              RESTARTS   AGE   IP               NODE                                      NOMINATED NODE   READINESS GATES
pod/apache2-deployment-67f8d54489-4hzkj   1/1     Running             0          65m   10.109.128.141   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>
pod/apache2-deployment-67f8d54489-v6nnw   1/1     Running             0          65m   10.109.128.142   gk3-my-k8s-cluster-pool-1-458925f9-kpcw   <none>           <none>
pod/apache2-deployment-8596d9c558-l6nqr   0/1     ContainerCreating   0          95s   <none>           gk3-my-k8s-cluster-pool-1-09501b89-mjg7   <none>           <none>

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)           AGE    SELECTOR
service/apache2-loadbalancer   LoadBalancer   10.110.0.162   35.238.40.41   60080:30377/TCP   78m    name=apache2
service/kubernetes             ClusterIP      10.110.0.1     <none>         443/TCP           173m   <none>

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                                      SELECTOR
deployment.apps/apache2-deployment   2/2     1            2           79m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.2   name=apache2

NAME                                            DESIRED   CURRENT   READY   AGE   CONTAINERS    IMAGES                                      SELECTOR
replicaset.apps/apache2-deployment-67f8d54489   2         2         2       69m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.1   name=apache2,pod-template-hash=67f8d54489
replicaset.apps/apache2-deployment-7868df7b76   0         0         0       79m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.0   name=apache2,pod-template-hash=7868df7b76
replicaset.apps/apache2-deployment-8596d9c558   1         1         0       96s   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.2   name=apache2,pod-template-hash=8596d9c558
```

最終的には以下になりました。
```
NAME                                      READY   STATUS    RESTARTS   AGE     IP               NODE                                      NOMINATED NODE   READINESS GATES
pod/apache2-deployment-8596d9c558-6hb4b   1/1     Running   0          15s     10.109.128.197   gk3-my-k8s-cluster-pool-1-09501b89-mjg7   <none>           <none>
pod/apache2-deployment-8596d9c558-l6nqr   1/1     Running   0          2m14s   10.109.128.194   gk3-my-k8s-cluster-pool-1-09501b89-mjg7   <none>           <none>

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)           AGE    SELECTOR
service/apache2-loadbalancer   LoadBalancer   10.110.0.162   35.238.40.41   60080:30377/TCP   79m    name=apache2
service/kubernetes             ClusterIP      10.110.0.1     <none>         443/TCP           173m   <none>

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                                      SELECTOR
deployment.apps/apache2-deployment   2/2     2            2           80m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.2   name=apache2

NAME                                            DESIRED   CURRENT   READY   AGE     CONTAINERS    IMAGES                                      SELECTOR
replicaset.apps/apache2-deployment-67f8d54489   0         0         0       69m     apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.1   name=apache2,pod-template-hash=67f8d54489
replicaset.apps/apache2-deployment-7868df7b76   0         0         0       80m     apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.0   name=apache2,pod-template-hash=7868df7b76
replicaset.apps/apache2-deployment-8596d9c558   2         2         2       2m15s   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.2   name=apache2,pod-template-hash=8596d9c558
```

遷移をイメージに起こします。

![名称未設定ファイル-ページ17 drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/f7509703-9f98-4e00-a2b3-7cf7d55f25e8)
![名称未設定ファイル-ページ17のコピー drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/4091a111-d183-48f0-9150-466d56a9df60)
![名称未設定ファイル-ページ17のコピーのコピー drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/c0f13e28-5848-452d-9dc0-94564e561e0e)

rollout historyを見てみます。REVISIONが1つ増えていますね。
```
ohtsuka_honban@cloudshell:~/yaml$ kubectl rollout history deployment
deployment.apps/apache2-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
```

Webブラウザで確認します。
ver1.2になっていますね。
<img width="409" alt="GKE2023051306" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/58d7e48d-d508-48c4-b3d9-414726cc53eb">

# ロールバックをやってみる

kubectl rollout undoコマンドでREVISIONを指定することでそのREVISIONの状態にロールバックすることが出来るようです。実際に試してみます。
今回は2世代前のREVISION 1、つまりver1.0の時に戻してみます。
```
ohtsuka_honban@cloudshell:~/yaml$ kubectl rollout undo deployment apache2-deployment --to-revision=1
deployment.apps/apache2-deployment rolled back

ohtsuka_honban@cloudshell:~/yaml$ kubectl rollout status deployment
Waiting for deployment "apache2-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "apache2-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "apache2-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "apache2-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "apache2-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "apache2-deployment" successfully rolled out
```

ロールバックの結果です。
Replicasのところを見るのが分かりやすいですが、ver1.0のReplicas"apache2-deployment-7868df7b76"が2になっていますね。
```
NAME                                      READY   STATUS    RESTARTS   AGE   IP               NODE                                      NOMINATED NODE   READINESS GATES
pod/apache2-deployment-7868df7b76-4lxc5   1/1     Running   0          40s   10.109.128.200   gk3-my-k8s-cluster-pool-1-09501b89-mjg7   <none>           <none>
pod/apache2-deployment-7868df7b76-f9cnf   1/1     Running   0          40s   10.109.128.199   gk3-my-k8s-cluster-pool-1-09501b89-mjg7   <none>           <none>

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)           AGE    SELECTOR
service/apache2-loadbalancer   LoadBalancer   10.110.0.162   35.238.40.41   60080:30377/TCP   89m    name=apache2
service/kubernetes             ClusterIP      10.110.0.1     <none>         443/TCP           3h3m   <none>

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                                      SELECTOR
deployment.apps/apache2-deployment   2/2     2            2           90m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.0   name=apache2

NAME                                            DESIRED   CURRENT   READY   AGE   CONTAINERS    IMAGES                                      SELECTOR
replicaset.apps/apache2-deployment-67f8d54489   0         0         0       79m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.1   name=apache2,pod-template-hash=67f8d54489
replicaset.apps/apache2-deployment-7868df7b76   2         2         2       90m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.0   name=apache2,pod-template-hash=7868df7b76
replicaset.apps/apache2-deployment-8596d9c558   0         0         0       12m   apache2-con   gcr.io/western-antonym-●●●●●●/apache2:1.2   name=apache2,pod-template-hash=8596d9c558
```

Webブラウザで確認するとver1.0になっていますね。ロールバック完了です。コマンド1つでrollbackできるのは凄いなと思いました。
<img width="400" alt="GKE2023051307" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/e5c393b3-b3d1-452a-b112-c8ae9e49d274">

rollout historyを見てみます。
1が消えて4が出来ましたね。恐らくGKEの設定で3世代管理迄と決まっており、今回ロールバックをしたので、一番古い世代が消えたのでしょう。設定変更もできるっぽい気がします。試してはいませんが。。。
```
ohtsuka_honban@cloudshell:~/yaml$ kubectl rollout history deployment
deployment.apps/apache2-deployment 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>
4         <none>
```

ロールバックをイメージに起こします。
![名称未設定ファイル-ページ20 drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/6f53dd0e-b2c1-46e1-995c-591073cdf70d)
![名称未設定ファイル-ページ20のコピー drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/90ba04e9-4973-41c0-a31c-76900c85363a)
![名称未設定ファイル-ページ20のコピーのコピー drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/4394a8a5-7cbd-4bad-b6df-15bb69198806)