はじめに
こんにちは、 Gunosy Tech Lab 所属の hyamamoto です。 もう 2 月ということで時間の流れが早いことをひしひしと感じています。
さて、EKS のバージョンアップの季節がやってきました。 皆さん EKS の更新は無事済ませましたか? それともすでに今回バージョンは終わらせて悠々と過ごされていますか?
便利な EKS ですが、バージョンアップ作業には定期的に向き合う必要があります。 一方で、バージョンアップ作業とそれに伴うメンテナンスは頻繁に行うものではないため、始めるときの心理的なハードルは高いです。 そこで、今回は EKS のバージョンアップに向けて確認しておきたいことをまとめてみました。 あくまでここで紹介する内容は具体的な手順にフォーカスしたものではなく、バージョンアップに際し「何」を「なぜ」考慮すべきかということをまとめたものになります。
EKS のバージョン更新時のメンテナンスは必要?
そもそも EKS のバージョンアップ作業時にはメンテナンスが必要なのでしょうか?
EKS は一定期間でそのクラスターバージョンを更新し、古いもののサポートを切ります。 これは人間の作業の有無に関わらず自動的に行われるものです。 であれば、特に工数を取らずバージョンアップを待つというのも手に思えます。 特に Kubernetes の場合その優秀なコントローラーのおかげで、バージョンアップ自体でダウンタイムを起こすことは考えにくいです。
しかしながら、この方法は想像に容易いように不適切なアプローチになります。 それはなぜでしょうか? ここで不適切な内容の言語化は重要になります。 というのも、その不適切と言われる内容を解消していくことが EKS バージョン更新時に必要な作業になるためです。
Kubernetes は何をする?
上記で述べた「不適切な内容」を言語化する前に、Kubernetes が何を行うツールなのかということに少し目を向けます。
Kubernetes は Manifests と呼ばれる定義ファイルに基づいて、コンピュートリソースやネットワークリソースを中心にクラウドインフラ上にリソースを配置します。 ここで重要な点は Kubernetes は最終的にクラウドインフラに手を加えているということです。
言い換えると、Kubernetes は Manifests というインターフェースを通じて、クラウドインフラへの CRUD 部分を隠蔽し、実行・管理してくれるツールになります。 よって EKS はサービスとして Manifests を解釈して AWS へのリクエストを行う機能を提供していると言えます。
よって、以下の内容を心に留めておく必要があります。
- Manifests はインターフェースである
- EKS は Manifests を解釈して AWS へのリクエストを行う
バージョン更新時に考慮すべきこと
それでは本題であるバージョン更新時に考慮すべき内容を挙げていきます。
1. Manifests のサポートが切れる
Manifests は上記でも述べた通り Kubernetes を使う上でのインターフェースになります。 他のインターフェースと同様、Manifests においてその仕様は開発が進むごとに変更が加えられます。 一方で、突然そのインターフェースの仕様が変更され Manifests が使えなくなることは避けられるべきです。
そこで Kubernetes は apiVersion
という Manifests の仕様にバージョンに対するフィールドを持っています。
それに加え対象リソースを kind
によって指定することで、この apiVersion
の仕様によって kind
を管理するという命令に替えられます。
下記は PodDisruptionBudget を指定する際の例です。
apiVersion: policy/v1beta1 kind: PodDisruptionBudget
apiVersion
の導入によりユーザーはインターフェースを選択することができるようになり、破壊的な変更に対しても柔軟に対応できるようになりました。
しかしながら、Kubernetes の開発者目線からだと実装した apiVersion
すべてをいつまでもサポートするということは、セキュリティー面やメンテナンスコストから適切とは言い難いです。
そこで、Kubernetes は一定期間の移行期間を設けた後、過去バージョンについてはサポートを切る意思決定をしています。
例えば、上記の policy/v1beta1
における PodDisruptionBudget は v1.25 のタイミングでサポートが切られます。つまり、policy/v1beta1
の PodDisruptionBudget
をリソースとして持ったまま Kubernetes のバージョンを v1.25 に更新すると、途端にこの機能は使えなくなってしまいます。
これが Kubernetes の更新の際にもっとも考慮すべき項目になります。 言い換えると、バージョンアップ時に行う作業のほとんどは Manifests のサポートが切れる事による対応がほとんどです。
具体的な対応内容例
自作した Manifests すべてに対して、apiVersion と kind を洗い出し、更新時にサポートが切れるものがあれば修正してください。 また、古いバージョンの Manifests の洗い出し方法については下記のページが参考になります。
2. Helm などで導入しているサードパーティのサポートが切れる
Kubernetes を利用している場合、ほとんどの人が autoscaler などのサードパーティツールを導入していると思います。
これに関してもバージョンアップ時にサポートが切れる可能性があります。
というのも、サードパーティツールもまた Manifests により記述されており、そのサポートが切れることで動作しなくなるためです。
よって、実質的な要因は 1.
と同じになります。
ここで、サードパーティツールを 1.
と区別して紹介しているのには理由があります。
サードパーティツールには自分たちで作成するアプリと異なり、Kubernetes API そのものを扱うツール (Custom Controller) も多くあるためです。
言い換えると、サードパーティツールがそのアプリ内部で Manifests を生成し Kubernetes API を実行している可能性があります。
よって、サードパーティツールがどの apiVersion
によって Kubernetes API を叩いているかということにも目を向ける必要があります。
サードパーティツールを管理するデファクトである Helm を例にすると、Helm には version (Chart version) と appVersion の 2 つのバージョンがあります。
version (Chart version)
version
(Chart version) はサードパーティツールをデプロイするための Manifests の内容を示すバージョンです。
よって、この Manifests 自体が古いままだとサードパーティツール自体が実行できなくなってしまいます。
appVersion
appVersion
はサードパーティツールの image tag を示すバージョンで、サードパーティツールのロジックを決めるものです*1。
よって、サードパーティツールがデプロイされている Kubernetes のバージョンに対して、そのロジックが古すぎる API や新しすぎる API に依存している場合は、不適切な挙動を起こしてしまいます。
例えば、descheduler の version: 0.26.0
は 2023.02 現在最新版ですが、これは Kubernetes 1.26 向けのものであり、これ以前のバージョンの Kubernetes に導入するとエラーになってしまいます。
具体的な対応内容例
artifacthub.io で Helm について version
と appVersion
を確認しながら、Kubernetes のバージョンに対応したものの中で最新のバージョンを利用するように設定してください。
3. EKS Addons
EKS Addons は Kubernetes を EKS 上で運用するにあたって必須なツールを AWS が管理してくれるものです*2。 EKS Addons も Helm と同様に Manifests を Kubernetes に apply してくれていることに差分はありません。このため、Kubernetes のバージョン更新に伴い、そのバージョンに適したバージョンを選択して更新する必要があります。
具体的な対応内容例
Addon の設定を適切なバージョンに更新してください。 また、最近知ったのですが Terraform の AWS Provider には aws_eks_addon という Data Source があり、これを活用することで Kubernetes のバージョンに対応した Addon のバージョンを取得することができ便利です。
4. AMI のバージョン更新
EC2 のインスタンス本体を実行するイメージ (AMI) も Kubernetes に最適化されたものが AWS から提供されています。 AMI のバージョンを更新する必要がある理由の一つとして kubelet のバージョンが挙げられます。 kubelet はノードにおける Kubernates のエージェントです。 下記のドキュメントからわかるように kubelet には Kubernetes のバージョンに対応したバージョンを利用する必要があります。
よって、kubelet を含んでいる AMI のバージョンを更新する必要があります。 なお、AMI が kubelet のバージョンを管理していることは、amazon-eks-ami の CHANGELOG を見るとわかります。
具体的な対応内容例
Launch Template の AMI の設定を更新してください。 Terraform で管理している場合は aws_ami という Data Source があるため、これを活用することで容易に適切な AMI のバージョンを取得することができます。
まとめ
EKS 更新の際に考慮すべき内容をまとめました。 最後に強調したい点は以下の通りです。
- Kubernetes は Manifests というインターフェースによってすべてのリソースを管理している
- Manifests にはバージョンがあり、Kubernetes のバージョン更新に伴い廃止されるものがある
- 結果、自作のものだけでなく、Helm や EKS Addons などすべてのリソースに影響が出る可能性がある
ここでは、Helm や EKS Addons を例にしたものの、あくまで今のデファクトとして挙げたにすぎません。トラブルが起きた際には、様々なバージョン管理の仕組みがあり、またそれら全てが Manifests を触っているということを念頭においてもらえると、より幅広い問題にも立ち向かえると思います。
また、やや話はそれますが、Kubernetes は即時的に不具合が発生する場合と遅れて不具合になる場合の 2 つがあります。そのぐらいエラーに対して頑健な作りをしています。 よって、ログモニターは厚く仕掛けておき、人間が目視で確認しなくても不具合に気づける仕組みづくりはしっかりとしていきましょう。 こうすることで、バージョン更新時にも自信を持って取り組むことができるようになります。