Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

EKS 更新を始める前に確認しておきたい事前知識

はじめに

こんにちは、 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/v1beta1PodDisruptionBudget をリソースとして持ったまま 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 に依存している場合は、不適切な挙動を起こしてしまいます。

例えば、deschedulerversion: 0.26.0 は 2023.02 現在最新版ですが、これは Kubernetes 1.26 向けのものであり、これ以前のバージョンの Kubernetes に導入するとエラーになってしまいます。

具体的な対応内容例

artifacthub.io で Helm について versionappVersion を確認しながら、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-amiCHANGELOG を見るとわかります。

具体的な対応内容例

Launch Template の AMI の設定を更新してください。 Terraform で管理している場合は aws_ami という Data Source があるため、これを活用することで容易に適切な AMI のバージョンを取得することができます。

まとめ

EKS 更新の際に考慮すべき内容をまとめました。 最後に強調したい点は以下の通りです。

  • Kubernetes は Manifests というインターフェースによってすべてのリソースを管理している
  • Manifests にはバージョンがあり、Kubernetes のバージョン更新に伴い廃止されるものがある
    • 結果、自作のものだけでなく、Helm や EKS Addons などすべてのリソースに影響が出る可能性がある

ここでは、Helm や EKS Addons を例にしたものの、あくまで今のデファクトとして挙げたにすぎません。トラブルが起きた際には、様々なバージョン管理の仕組みがあり、またそれら全てが Manifests を触っているということを念頭においてもらえると、より幅広い問題にも立ち向かえると思います。

また、やや話はそれますが、Kubernetes は即時的に不具合が発生する場合と遅れて不具合になる場合の 2 つがあります。そのぐらいエラーに対して頑健な作りをしています。 よって、ログモニターは厚く仕掛けておき、人間が目視で確認しなくても不具合に気づける仕組みづくりはしっかりとしていきましょう。 こうすることで、バージョン更新時にも自信を持って取り組むことができるようになります。

*1:厳密に image tag を必ず示しているかは Chart の設計によるものの、appVersion によって image tag が決まるものが多い

*2:EKS Addons がリリースされる以前は、自前で kubectl を使って Manifests を apply していました。驚くべきことに Helm も存在せず、手動による apply をしなければなりませんでした