EKS Auto Mode のクラスターをバージョンアップグレードしてみた#AWSreInvent
昨日 EKS に自己管理モードが追加されました。
セットアップの簡単さ、コンピュートノードのスケーリングについて楽にするだけでなく、運用上悩みの種になりがちなバージョンアップ作業もシンプルにしてくれると記載されているので試してみました。
Auto Mode simplifies the version update process by handling the coordination of control plane updates with node replacements, while maintaining workload availability through pod disruption budgets.
https://docs.aws.amazon.com/eks/latest/userguide/auto-upgrade.html
3 行まとめ
- コントロールプレーンの明示的なアップグレードが必要な点は今までと変わりません。アップグレードインサイト等を活用してアプリケーション側の準備をした上でアップグレード作業に移る必要があります。
- 自分でインストールしたアドオンのアップグレード対応は必要です。ただし、Auto Mode を使うことで、そもそも自己管理のアドオンが減ります。
- コントロールをアップグレードすると、自動でデータプレーンもアップグレードされます。意図しないアプリケーションへの影響を避けるため、Pod Disruption Budget(PDB)を設定しましょう。
EKS Auto Mode における Kubernetes バージョンアップグレード
CoreDNS
KubeProxy
AWS Load Balancer Controller
Karpenter
AWS EBS CSI Driver
https://docs.aws.amazon.com/eks/latest/userguide/auto-upgrade.html
上記コンポーネントは EKS 管理となるため、ユーザーがバージョンを管理する必要がなくなります。
You are still responsible for updating:
Apps and workloads deployed to your cluster
Self-managed add-ons and controllers
Amazon EKS Add-ons
https://docs.aws.amazon.com/eks/latest/userguide/auto-upgrade.html
公式ドキュメントには各種アプリケーションやアドオンのアップデートはユーザーの責務と書かれています。
Auto Mode simplifies the version update process by handling the coordination of control plane updates with node replacements, while maintaining workload availability through pod disruption budgets.
https://docs.aws.amazon.com/eks/latest/userguide/auto-upgrade.html
また、EKS Auto Mode は PDB を活用して、可用性を損なわないようにバージョンアップグレード作業を簡素化すると記載されています。
PDB とは?
Pod が同時に利用不可とになる数(割合)を制限する Kubernetes の機能です。
個別のリソース(kind=PodDisruptionBudget)としてデプロイし、minAvailable または maxUnavailable のいずれか一方を指定することで一時的な中断がどの程度許容されるかを指定可能です。
やってみた
Nginx の Pod を 5 個立てた状態で、Auto Mode の EKS を 1.30 から 1.31 に上げてみました。
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: nginx
replicas: 5
template:
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
resources:
requests:
cpu: "0.5"
まずは、特に PDB を設定せずに実行してみます。
コントロールプレーンのアップグレード開始後、9 分くらいでアップグレードが完了します。
その後、特に操作不要でデータプレーン側のアップグレードが走ります。(コントロールプレーンアップグレードから、データ側の更新が走るまでの時間はまちまちでしたが、大体 10 分以内には新規ノードが起動されていました。)
元々 amazon/eks-auto-standard-1.30-x86_64-20241125 で起動されていましたが、amazon/eks-auto-standard-1.31-x86_64-20241125 に更新されて EC2 が作成されています。
その後、下記時系列で Pod を配置するノードの変更が行われました。
08:25:21:新規インスタンスの Run Instance が走る
08:25:45-46:全ての Pod が新規ノード上で Start する
08:25:48:旧ノードの TerminateInstances が走る
08:26:00-01:新規ノード上の Pod の state が Running になる
今回は PDB を指定していないので、Pod が新しいノード上で起動完了する前に、既存ノードから Pod が追い出されて TerminateInstances が走っています。瞬断を許容するアップグレード方法になっているため、もう少し安全に Pod の配置し直しを行いたい方が多いと思います。
それでは PDB を設定していきましょう。
こんな感じで設定できます。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: nginx-pdb
spec:
maxUnavailable: "20%"
selector:
matchLabels:
app.kubernetes.io/name: nginx
describe コマンドを実行することで、Allowed disruptions(中断が許容される Pod の数)、Current(現在の正常な Pod の数)、Total(Pod 数) を確認できます。今回で言うと、maxUnavailableを 20% にしているため、5 個の Pod の内、同時に中断しても良いのは 1 つまでとなります。
$ kubectl describe pdb nginx-pdb
Name: nginx-pdb
Namespace: default
Max unavailable: 20%
Selector: app.kubernetes.io/name=nginx
Status:
Allowed disruptions: 1
Current: 5
Desired: 4
Total: 5
Events: <none>
この状態で再度アップグレードを行ってみます。
2 つ以上の Pod の中断が許容されないので、一つずつ Pod が新しいノードに移動します。(アップグレード途中は下記のような状態になります)
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-65bb6f97b6-bcgrw 1/1 Running 0 22m 10.0.10.116 i-0cf5dc1a2c85ce87a <none> <none>
nginx-65bb6f97b6-n89w4 1/1 Running 0 11s 10.0.10.162 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-w27pk 1/1 Running 0 48s 10.0.10.160 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-xc8cs 1/1 Running 0 21s 10.0.10.161 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-xv62j 0/1 ContainerCreating 0 1s <none> i-042113a3937d08313 <none> <none>
最終的に起動時刻が各コンテナごとに違うことがわかります。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-65bb6f97b6-ljq6s 1/1 Running 0 26s 10.0.10.164 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-n89w4 1/1 Running 0 46s 10.0.10.162 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-w27pk 1/1 Running 0 83s 10.0.10.160 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-xc8cs 1/1 Running 0 56s 10.0.10.161 i-042113a3937d08313 <none> <none>
nginx-65bb6f97b6-xv62j 1/1 Running 0 36s 10.0.10.163 i-042113a3937d08313 <none> <none>
時系列に直すと下記のようになりました。
11:14:08:新規インスタンスの Run Instance が走る
11:15:21:4 つ目の Pod が Running 状態になる
11:15:31:旧ノードの TerminateInstances が走る
11:15:32:最後の Pod が Running になる
新しいノード上で 4 つ目のコンテナが起動したので、5 つ目は起動に失敗しても PDB の要件を満たせなくなることはありません。
したがって、4 つ目のコンテナが Running になったタイミングで、最後に残っていた Pod の eviction と Termination Instance が走った形になります。
まとめ
Auto Mode を利用して、バージョンアップをシンプルにするってどういうことだろうと思っていたのですが、やってみて理解できました。
自動で更新を行ってくれているので、アップグレードインサイト等を利用した事前の確認や、PDB の設計がより重要になった形です。
また、バージョンアップグレード時のチェックを入念に実施したい場合は、Auto Mode を利用しつつ、クラスターごと Blue/Green アップグレードすることも可能です。
ただ、バージョンアップ作業にかかる時間は少ないに越したことが無いので、是非 Auto Mode を有効活用していきたいですね!