EKSクラスターのバージョンアップ方法

# 前提
今回は、EKSをFargateで使っている場合のKubernetesクラスターを1.21から1.22に更新します。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/update-cluster.html

# 手順
## 1.現在のバージョンを確認
```
$ kubectl version --short

Server Version: v1.21.12-eks-a64ea69
```

```
$ kubectl get nodes

NAME                                                       STATUS   ROLES    AGE     VERSION
fargate-ip-XX-XX-101-114.ap-northeast-1.compute.internal   Ready    <none>   4d17h   v1.21.2-eks-06eac09
fargate-ip-XX-XX-101-127.ap-northeast-1.compute.internal   Ready    <none>   9d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-101-66.ap-northeast-1.compute.internal    Ready    <none>   12d     v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-134.ap-northeast-1.compute.internal   Ready    <none>   12d     v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-158.ap-northeast-1.compute.internal   Ready    <none>   8d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-176.ap-northeast-1.compute.internal   Ready    <none>   8d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-185.ap-northeast-1.compute.internal   Ready    <none>   11d     v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-210.ap-northeast-1.compute.internal   Ready    <none>   11d     v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-31.ap-northeast-1.compute.internal    Ready    <none>   8d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-102-52.ap-northeast-1.compute.internal    Ready    <none>   8d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-103-101.ap-northeast-1.compute.internal   Ready    <none>   7d20h   v1.21.2-eks-06eac09
fargate-ip-XX-XX-103-143.ap-northeast-1.compute.internal   Ready    <none>   8d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-103-157.ap-northeast-1.compute.internal   Ready    <none>   12d     v1.21.2-eks-06eac09
fargate-ip-XX-XX-103-171.ap-northeast-1.compute.internal   Ready    <none>   8d      v1.21.2-eks-06eac09
fargate-ip-XX-XX-103-208.ap-northeast-1.compute.internal   Ready    <none>   6d21h   v1.21.2-eks-06eac09
```
## 2. クラスター更新前にpodを複数にして冗長化
クラスター更新前にpodを複数にして冗長化しておくほうが良い
→更新途中にサービスが停止する可能性をなくすため。

## 3. クラスターのバージョンを更新
eksctlを使ってクラスターのバージョンを更新
```
eksctl upgrade cluster --name <my-cluster> --approve
```

## 4.VPC CNI、CoreDNS、および kube-proxy アドオンを更新する
### kube-proxyを更新する
kube-proxy デプロイの現在のバージョンを確認します。
```
kubectl get daemonset kube-proxy \
    --namespace kube-system \
    -o=jsonpath='{$.spec.template.spec.containers[:1].image}'
```
例）XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/eks/kube-proxy:v1.21.2-eksbuild.2

下記の内容をもとにkube-proxy アドオンを更新する
https://docs.aws.amazon.com/en_us/eks/latest/userguide/managing-kube-proxy.html#kube-proxy-default-versions-table
```
kubectl set image daemonset.apps/kube-proxy \
     -n kube-system \
     kube-proxy=XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/eks/kube-proxy:v1.22.6-eksbuild.1
```

[kube-proxy のセルフマネージド型アドオンを更新する]
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/managing-kube-proxy.html#updating-kube-proxy-add-on

### CoreDNS を更新する
現在使用している、CoreDNS アドオンのバージョンを確認します。
```
kubectl describe deployment coredns \
    --namespace kube-system \
    | grep Image \
    | cut -d "/" -f 3
```
例）coredns:v1.8.4-eksbuild.1

現在の CoreDNS イメージを取得します。
```
kubectl get deployment coredns \
    --namespace kube-system \
    -o=jsonpath='{$.spec.template.spec.containers[:1].image}'
```
例）XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/eks/coredns:v1.8.4-eksbuild.1

CoreDNS 1.8.3 以降に更新する場合は、endpointslices 権限を system:coredns Kubernetes clusterrole に追加する
```
kubectl edit clusterrole system:coredns -n kube-system

...
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
  - watch
...
```
下記の内容をもとにCoreDNSを更新する
https://docs.aws.amazon.com/en_us/eks/latest/userguide/managing-coredns.html#updating-coredns-add-on

```
kubectl set image --namespace kube-system deployment.apps/coredns \
    coredns=XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/eks/coredns:v1.8.7-eksbuild.1
```

[CoreDNS アドオンの管理]
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/managing-coredns.html#updating-coredns-add-on

### VPC CNIを更新する
#### AWSコンソールから更新する方法
1.19 以降に更新し、Amazon EKS アドオンを使用している場合は、Amazon EKS コンソールで[Clusters] (クラスター) をクリックし、左のナビゲーションペインで更新したクラスター名を選択します。更新可能なアドオンごとに、新しいバージョンが利用可能であることを知らせる通知がコンソールに表示されます。アドオンを更新するには、[設定] タブを開き、次に [アドオン] タブを表示します。更新があるアドオンが表示されているボックスで [今すぐ更新] を選択し、使用可能なバージョンを選択してから、[更新] を選択します。

#### eksctlで更新する方法
AWS Management Console 以外の方法で 1.18 以降のクラスターを作成した場合は、Amazon EKS によってセルフマネージド型アドオンがインストールされているので、手動で更新する。

現在のAmazon VPC CNI アドオンバージョンを確認する
```
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
```
現在のCNIのdeploymentを取得しておく
```
kubectl get daemonset aws-node -n kube-system -o yaml > aws-k8s-cni-old.yaml
```
最新版のdeploymentを取得する（ここではv1.11.2）
```
curl -o aws-k8s-cni.yaml https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.11.2/config/master/aws-k8s-cni.yaml
```
aws-k8s-cni.yamlのリージョンを置換する
```
 sed -i.bak -e 's|us-west-2|ap-northeast-1|' aws-k8s-cni.yaml
```
デプロイする
```
kubectl apply -f aws-k8s-cni.yaml
```

Amazon VPC CNI アドオンの管理
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/managing-vpc-cni.html#updating-vpc-cni-add-on
### 5.aws-load-balancer-controllerの更新
aws-load-balancer-controllerなどもそのままでは失敗の可能性があるので
よくよく注意する。

例えば、Kubernetes v1.2.2とaws-load-balancer-controller v2.3.0は互換性がないのでアップデートしないといけない。
https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/2495
```
helm upgrade aws-load-balancer-controller eks/aws-load-balancer-controller \
    --set clusterName=<クラスター名> \
    --set serviceAccount.create=false \
    --set region=ap-northeast-1 \
    --set vpcId=<VPCのID> \
    --set serviceAccount.name=<aws-load-balancer-controller用のサービスアカウント名> \
    --set image.repository=XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/amazon/aws-load-balancer-controller \
    -n kube-system
```

## 6. クラスターのバージョンアップが終わった後、Nodeを更新する
Fargateの場合、Fargate Nodeとpodは１対１の関係にあるため、podを再度デプロイすればNodeが更新される。
つまり、podを削除すれば更新される。
ただし、更新途中にサービスが停止する可能性あるので、クラスター更新前にpodを複数にして冗長化しておくほうが良い。


```
kubectl delete pod <pod名> -n <ネームスペース名>
```