k8sの実験（その４：node pool のアップグレード）

[k8s の実験（その3：pod の作成・削除）](https://qiita.com/intrajp/items/d569d44e1635b5d29648)のつづき。

クラスタがどんどんアップグレードされちゃうので、node pool のバージョンが古くなってきました。
ちなくみ、サービスを 1秒も切らすことなく、node pool をアップグレードしたいです。
実験ですが、このページどおりにやってみます。
https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer?hl=ja

以下を追加します。これで、ReplicaSetができることになります。

```
replicas: 3 
```

適用します。
```
$ gcloud container clusters get-credentials cluster-1 --region=asia-northeast1-a
$ kubectl apply -f web-deployment.yaml
```

確認します。

```
$ kubectl get pod,replicaset,deployment
NAME                       READY   STATUS    RESTARTS   AGE
pod/web-xxxx-xxxx   1/1     Running   0          6m7sZZ
pod/web-xxxx-yyyy   1/1     Running   0          6m7s
pod/web-xxxx-zzzz   1/1     Running   0          6m7s

NAME                             DESIRED   CURRENT   READY   AGE
replicaset.apps/web-xxxx   3         3         3       6m7s

NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/web   3/3     3            3           6m8s
```

サービスを開始します。

```
$ kubectl apply -f web-service.yaml
```

確認します。

```
$ kubectl get service web
NAME   TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
web    NodePort   10.56.2.xxx   <none>        8080:32758/TCP   12h
```

HTTP(S) ウェブサーバー アプリケーションを公開するには、Ingress リソースを作成する必要があります。

```
$ kubectl apply -f basic-ingress.yaml
```

EXTERNAL-IPがしばらくしたら取れます。
アプリケーションに対応するロードバランサの外部 IP アドレスを調べます。

```
$ kubectl get ingress basic-ingress
NAME            CLASS    HOSTS   ADDRESS         PORTS   AGE
basic-ingress   <none>   *       34.xxx.xxx.xxx   80      72s
```

では、この外部IPをcurlコマンドで5秒毎に監視してみます。

```
#!/bin/bash

EXTERNAL_IP="34.xxx.xxx.xxx"
NOW=$(date '+%Y-%m-%d-%H-%M-%S')
#echo "${NOW}"
#exit 1
FILE="check_web_ingress_${NOW}.txt"
function check_web()
{
    echo "========" >> "${FILE}"
    date '+%Y-%m-%d-%H-%M-%S' >> "${FILE}"
    curl -s "${EXTERNAL_IP}" >> "${FILE}"
    sleep 5
}

while :
do
    check_web
done
```

tail -f で目視確認します。
リソース確認用のスクリプトです。
デフォルトラベル（cloud.google.com/gke-nodepool=default-pool）を利用します。

```
#/bin/bash
 
NOW=$(date '+%Y-%m-%d-%H-%M-%S')
OUTFILE="blue_green_ingress_"${NOW}".txt"
 
function get_resource_info()
{
    echo "========" >> $OUTFILE
    date >> $OUTFILE
    #echo "---vm---" >> $OUTFILE
    #gcloud compute instances list >> $OUTFILE
    #echo "---node-pools---" >> $OUTFILE
    #gcloud container node-pools list --cluster cluster-1 --zone=asia-northeast1-a >> $OUTFILE
    echo "---nodes default-pool---" >> $OUTFILE
    kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool >> $OUTFILE
    sleep 5
}

while :
do
    get_resource_info
done
```

これも、tail -f で目視確認します。
PodDistrubtionBudgetも設定します。

```
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
  namespace: default
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: web
```

設定します。

```
$ kubectl apply -f web-pdb.yaml 
poddisruptionbudget.policy/web created
```

確認します。

```
$ kubectl get pdb
NAME   MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
web    N/A             1                 0                     16s
```

これで、まず、クラスターをアップグレードして、終わったら、 node pool を blue/green でアップグレードします。
外形監視の方で、サービスが切れないか見ていましたけど、うーん、やっぱり切れちゃうのか。

考え直して、Nodepool soak duration の値を 3600 にし、readynessgateも作成しておきました。
また、Batch node count: 1 of 3 nodes (33%) にしてみました。
これで、なんとかサービスを切らすことなくアップグレード出来たようだ。
ただし、アップグレードがなかなか終わらなくて、次のコマンドを実行する必要がありました。

```
gcloud container node-pools complete-upgrade [NODE_POOL] --cluster [CLUSTER] --zone=[ZONE]
```

なお、現在の node pool に nodepool=old というラベルを追加して、新しいバージョンの　node pool を作っておき、old を condorn, drain, delete を手動で実行することでも、web サービスの　tail -f の外形監視で切れないのが確認出来ました。

cordon と drain のコマンドを参考に書いておきます。
```
$ kubectl cordon -l "nodepool=old"
$ kubectl drain --ignore-daemonsets --delete-emptydir-data -l "nodepool=old"
```

とりあえず、1秒もサービスを切らすことなくアップグレードすることは、blue/greenアップグレードの方法で、Nodepool soak duration の値を 3600 にし、readynessgateも作成してアップグレードする方法と、[移行の方法](https://cloud.google.com/kubernetes-engine/docs/tutorials/migrating-node-pool?hl=ja)でできました。Nodepool soad duration の値を 3600 にするのは長いので、確認していいと思ったら、そこで、アップグレードが終了したという指示を出しています。

なお、経費節減のために、クラスタ、node pool ともに、"e2-small", "pd-standard", --spot に直して、コマンドラインから作成しています。

（参考）
https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer?hl=ja
https://kubernetes.io/docs/tasks/run-application/configure-pdb/
https://qiita.com/toshihirock/items/5adaece0206127121551
https://cloud.google.com/kubernetes-engine/docs/tutorials/migrating-node-pool?hl=ja