EKS on Fargateのバージョンアップをやってみた(v1.20→v1.21)

## はじめに

本記事は [ZOZO Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) の9日目の記事です。

## 概要

株式会社ZOZOでWEARのSREをしている@wadasonです。

WEARでは大小様々なシステムを段階的にEKSへ移行していますが、最近新しいバージョンへのアップデートを実施しました。
そこで今回はチームでバージョンアップが初回だったということもあり、作業を行う上で気をつけたことや実施の流れについて書いていきます。

内容自体は目新しいものではありませんが、最後までお付き合いいただけると嬉しいです。

## 前提
利用している技術や各種バージョンは以下の通りです。

- Amazon EKS on Fargate
- Kubernetes 1.20 (→1.21)
- Cloud Formation
- その他の技術
  - kustomze / ArgoCD
  - ESO / LoadBaralcerController etc...

## それではやっていきましょう

### 新バージョンの変更点の確認

まずは変更点を確認します。

- [Kubernetes Release History v1.21](https://kubernetes.io/releases/#release-v1-21)
- [Amazon EKS Kubernetes versions](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html#kubernetes-1.21)

たまに英語版と日本語版では記述内容や更新のタイミングが異なる場合があるみたいです。なので英語版を見ると確実です。

### マニフェストのチェック

次に、アップデート対象のマニフェストを確認します。

#### restart時の挙動の確認
今回は初回だったので、pod再起動時の挙動も合わせて確認しました。

確認したことは下記の通りです。

- Deploymentのspec.strategy.type (今回はRollingUpdateにした)
- PodDisruptionBudgetが設定されていること
- Liveness Probeなどが設定されていること

#### Deprecated APIの確認

自動検知、、、といきたいところでしたが、
[Deprecated API Migration Guide](https://kubernetes.io/docs/reference/using-api/deprecation-guide)を目で見てチェックしました。

転職前に[swade1987/deprek8ion](https://github.com/swade1987/deprek8ion)が便利だったので使ってました。残念ですがこれ以上更新されることはなさそうです。
何かいいのがあれば教えてください。


### コントロールプレーンの更新

対象の1.21へ変更し、スタックを更新します。
更新すると、コントロールプレーンのバージョンが上がりますが、ノードのバージョンは変更されません。
したがってこの操作を行なっても、EKSで動いているシステムにすぐに影響が出るわけではありません。

※ ノードのバージョンは後ほど紹介するプロファイルの更新でバージョンが変更されます。また、EC2の場合は、nodeのバージョンを明示的にあげる必要があります。

```yaml
EKSCluster:
    Type: AWS::EKS::Cluster
    Properties:
      # 省略
      Version: '1.21' # ここを更新
```

### EKSアドオンの更新

今回は初回一発目のため、アドオンをCloud Formationで管理するように変更しています。
IaC管理が必須ではありませんが、IaCにするとkubectlによる手動の更新作業がなくなり、ヒューマンエラーを防ぐことができます。

以下はkube-proxyの例です。
[Managing the kube-proxy add-on](https://docs.aws.amazon.com/eks/latest/userguide/managing-kube-proxy.html)に従って、バージョンを選定しました。

```yaml
KubeProxy:
  Type: AWS::EKS::Addon
  Properties:
    AddonName: kube-proxy
    AddonVersion: v1.21.2-eksbuild.2 # ここを更新
    ClusterName: 'cluster-name'
    ResolveConflicts: OVERWRITE
```

ちなみに手動で行う場合は[Updating the kube-proxy Amazon EKS add-on](https://docs.aws.amazon.com/eks/latest/userguide/managing-kube-proxy.html)に書いてあるように手動でバージョンを更新する必要があります。

### Fargateプロファイルを更新

ここからがちょっと怖いわけですね。はい。

Fargateプロファイルのノードバージョンを変更するには、podの再起動が必要になります。
今回は`kubectl rollout restart`で行いました。

#### ノードバージョンの確認(作業前のバージョンを確認)
まずは、ノードバージョンを確認します。この時点ではバージョンが1.20です。

```
$ kubectl get node --all-namespaces

# --- 実行結果 ---
NAME                                                      STATUS   ROLES    AGE    VERSION
fargate-ip-XXXXX.AWS-REGION.compute.internal   Ready    <none>   127m   v1.20.x-eks-xxxxxx
fargate-ip-XXXXX.AWS-REGION.compute.internal   Ready    <none>   128m   v1.21.x-eks-xxxxxx
.
. (省略)
.
```

#### 再起動 or Apply
次に`kubectl rollout restart`を実行します。

実行の順番は、オペレータ(ArgoCDやLoadBaralcerControllerなど）、次に実際に稼働しているシステムにしました。

※ 対象のEKSクラスタではオペレータのダウンタイムは許容しており、アプリケーションは落とさないようにしています。

```
# オペレータはnamespace単位でrolloutしていきます。
$ kubectl rollout restart deployment　-n default
# 適宜ログ等見ながら動作確認

# アプリケーションは少し慎重にやりたいのでdeployment指定で一つづつ確認しました。
$ kubectl rollout restart deployment/app1　-n myapp
$ kubectl rollout restart deployment/app2　-n myapp
# 適宜ログ等見ながら動作確認
```

※ Deprecated APIの対応によりマニフェストの書き換えが生じた場合は`kubectl apply`に適宜置き換えてください。

#### ノードバージョンの確認(意図したバージョンに更新されているか)
`rollout restart`後に新たに作成されるFargateノードのバージョンを確認します。

```
$ kubectl get node --all-namespaces

# --- 実行結果 ---
NAME                                                      STATUS   ROLES    AGE    VERSION
fargate-ip-XXXXX.<AWS-REGION>.compute.internal   Ready    <none>   127m   v1.21.2-eks-06eac09
fargate-ip-XXXXX.<AWS-REGION>.compute.internal   Ready    <none>   128m   v1.21.2-eks-06eac09
.
. (省略)
.
```
無事`v1.21`から`v1.22`に変わっていることを確認したら完了です。

## いかがでしたか？

細かい対応内容はバージョンごとに異なるかもしれないですが、全体的な流れや確認の観点がイメージできたら幸いです。
個人的には、今回EKSアドオンをマネージドにしたら作業が楽になったと感じたのと、CIの時点でDeprecated APIを確認できるとずっと楽になるなと思ってます。

今回は担当しているシステムで初回ということもあり色々確認することも多かったんですが、これからさらにEKS周りの品質を上げていきたいと思っています！

## 参考
- https://kubernetes.io/releases
- https://kubernetes.io/docs/reference/using-api/deprecation-guide
- https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html
- https://docs.aws.amazon.com/eks/latest/userguide/managing-kube-proxy.html