Deploymentの動作を確認する 4

#はじめに
今回はDeploymentの「更新戦略」の動作を確認してみます。更新戦略というと何かすごいことをやりそうですが、これまで確認してきたアップデートをどのようにやるかの設定です。マニュアルの記載が「更新戦略」となっているので、このように記載しています。
[kubernetes.io](https://kubernetes.io/ja/docs/concepts/workloads/controllers/deployment/#deployment-spec%e3%81%ae%e8%a8%98%e8%bf%b0)

設定できる戦略は以下の2つです。

・Recreate
・RollingUpdate（デフォルト）

#Recreate
Recreateは、一度すべてのPodを削除してから新しいPodがデプロイされます。
そのため、業務は一度止まります。

##作成
Deploymentのマニフェストに「spec.strategy」のパラメータを設定します。

```sampleDepRecreate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-dep5
spec:
  strategy:        #これ
    type: Recreate #これ
  replicas: 3
  selector:
    matchLabels:
      app: nginx-dep
  template:
    metadata:
      labels:
        app: nginx-dep
    spec:
      containers:
        - name: nginx
          image: nginx:1.16
```

applyして、Deploymentを作成します。

```
$ kubectl apply -f sampleDepRecreate.yaml
deployment.apps/sample-dep5 created
$ kubectl get deployment
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
sample-dep5   3/3     3            3           46s
```
Deploymentの詳細を確認します。

```
$ kubectl describe deployment sample-dep5
Name:               sample-dep5
・・・
StrategyType:       Recreate
・・・
```

##アップデート時の動作確認
imageのバージョンを1.17に変更したマニフェストをapplyして反映します。そのときに、別ターミナルでReplicaSetの状態を監視します。

```
$ kubectl apply -f sampleDepRecreate.yaml
deployment.apps/sample-dep5 configured
```

```
$ kubectl get rs --watch
NAME                     DESIRED   CURRENT   READY   AGE
sample-dep5-597898b879   3         3         3       4m33s
sample-dep5-597898b879   0         3         3       4m45s
sample-dep5-597898b879   0         3         3       4m45s
sample-dep5-597898b879   0         0         0       4m45s <--+
sample-dep5-65fb458568   3         0         0       0s       | 稼働しているコンテナが
sample-dep5-65fb458568   3         0         0       0s       | ない期間
sample-dep5-65fb458568   3         3         0       0s <-----+
sample-dep5-65fb458568   3         3         1       2s
sample-dep5-65fb458568   3         3         2       2s
sample-dep5-65fb458568   3         3         3       2s
```

kubectl get rsコマンドに--watchオプションを付けると、ReplicaSetの状態に変化があったときに、ログが表示されます。（tail -f のような動作）
この例だと本当に数秒ですが、コンテナがない時間（＝業務が停止する時間）が発生しています。

#RollingUpdate
デフォルトの設定です。
業務が停止しないように、順次Pod（コンテナ）を入れ替えます。入れ替えの動作を設定するために以下のパラメーターがあります。

|パラメータ|概要|
|:---|:---|
|maxUnavailable|更新処理において利用不可となる最大のPod数を指定します。絶対値（1,2,など）、またはパーセンテージ（10%など）を指定します。|
|maxSurge|理想状態のPod数を超えて作成できる最大のPod数を指定します。絶対値（1,2,など）、またはパーセンテージ（10%など）を指定します。|
|progressDeadlineSeconds|システムがDeploymentの更新に失敗したと判断するまでに待つ秒数を指定します。
|minReadySeconds|新しく作成されたPodが利用可能となるために、最低どれくらいの秒数コンテナーがクラッシュすることなく稼働し続ければよいかを指定するものです。デフォルトでは0です|
詳細：[kubernetes.io](https://kubernetes.io/ja/docs/concepts/workloads/controllers/deployment/#maxunavailable)

ここでは、maxSurgeの動作を確認してみます。

maxSurgeの値が大きければ大きいほど、ローリングアップデートは早く終わります。その代わり、アップデートのための余分なリソースが必要となります。（システムの性能は落ちません）
maxUnavailableも値が大きければ大きいほど、ローリングアップデートは早く終わりますが、その代わり、システムの性能が落ちることになります。

##作成
以下のマニフェストを作成して、applyします。

```sampleDepRU.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-dep5
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  replicas: 3
  selector:
    matchLabels:
      app: nginx-dep
  template:
    metadata:
      labels:
        app: nginx-dep
    spec:
      containers:
        - name: nginx
          image: nginx:1.16
```

```
$ kubectl apply -f sampleDepRU.yaml
deployment.apps/sample-dep5 created
$ kubectl get deployments
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
sample-dep5   3/3     3            3           9s
```

##RollingUpdateの動作確認
imageのバージョンを1.17に変更したマニフェストをapplyして反映します。そのときに、別ターミナルでReplicaSetの状態を監視します。

```
$ kubectl apply -f sampleDepRU.yaml
deployment.apps/sample-dep5 configured
$ kubectl get rs -o wide
NAME                     DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES       SELECTOR
sample-dep5-597898b879   0         0         0       8m    nginx        nginx:1.16   app=nginx-dep,pod-template-hash=597898b879
sample-dep5-65fb458568   3         3         3       50s   nginx        nginx:1.17   app=nginx-dep,pod-template-hash=65fb458568
```

```
$ kubectl get rs --watch
NAME                     DESIRED   CURRENT   READY   AGE
sample-dep5-597898b879   3         3         3       6m57s
sample-dep5-65fb458568   1         0         0       0s
sample-dep5-65fb458568   1         0         0       1s
sample-dep5-65fb458568   1         1         0       1s
sample-dep5-65fb458568   1         1         1       5s     <--- nginx:1.17のPodが一つ追加（Podの合計4）
sample-dep5-597898b879   2         3         3       7m15s
sample-dep5-65fb458568   2         1         1       5s
sample-dep5-597898b879   2         3         3       7m15s
sample-dep5-65fb458568   2         1         1       5s
sample-dep5-597898b879   2         2         2       7m15s  <--- nginx:1.16のPodが一つ削除（Podの合計3）
sample-dep5-65fb458568   2         2         1       5s
sample-dep5-65fb458568   2         2         2       7s     <--- nginx:1.17のPodが一つ追加（Podの合計4）
sample-dep5-597898b879   1         2         2       7m17s
sample-dep5-65fb458568   3         2         2       7s
sample-dep5-597898b879   1         2         2       7m17s
sample-dep5-65fb458568   3         2         2       7s
sample-dep5-597898b879   1         1         1       7m17s  <--- nginx:1.16のPodが一つ削除（Podの合計3）
sample-dep5-65fb458568   3         3         2       7s
sample-dep5-65fb458568   3         3         3       9s     <--- nginx:1.17のPodが一つ追加（Podの合計4）
sample-dep5-597898b879   0         1         1       7m19s
sample-dep5-597898b879   0         1         1       7m19s
sample-dep5-597898b879   0         0         0       7m19s  <--- nginx:1.16のPodが一つ削除（Podの合計3）
```

分かりづらいですが、常に新しいReplicaSetのPod（nginx:1.17）を一つ追加してから、古いReplicaSetのPod（nginx:1.16）を一つ削除していることがわかります。
常にmaxSurgeで指定した値「1」を守っていることがわかりますね。

もし、maxSurgeが「0」、maxUnavailable「1」だった場合は、これとは逆で「一つ減らしてから一つ増やす」動作になります。

#まとめ
「更新戦略」をRecreateにするか、RollingUpdateにするかは、システムの要件次第ですので一概にこちらがいいとは言えません。また、RollingUpdateのパラメータもシステムの要件やインフラのリソースなども考慮して考える必要がありますので、最適なパラメータはシステムごとに変わるでしょう。
まずはどんな設定があるか、どんなパラメータがあるのかを知っておくことで、実際のシステムに活かせるのかなと思います。

個人的には、RollingUpdateを使うと一時的でもシステムが膨らむ場合がありますので、MWのライセンスが問題になりそうだなと思いましたが、きっとOSSだとその辺は考えないでいいんですかね。
Solarisメインにやってきた自分だと気になるところです。