はじめに
こんにちは、 IT 本部 IT 基盤部 第三グループの前田洋太です。IT 基盤部では、組織横断的に複数のサービスのインフラ運用を行っており、サービスの安定的な稼働のための運用やコスト削減に取り組んでいます。
サービスの運用工数を減らし、インフラコストの最適化を行うことはビジネス上の重要な課題です。本記事では、その目的のために私達のチームが取り組んだ Amazon EKS の Auto Mode への移行プロジェクトをもとに、機能の概要、従来抱えていた課題と移行理由、移行方法、移行の際の注意点についてご紹介します。
この記事が、EKS Auto Mode の利用や既存クラスターからの移行を検討されている皆様の参考になれば幸いです。
本記事の内容
- EKS Auto Mode の概要
- 抱えていた課題と移行理由
- クラスターアップグレードの手間
- アドオン管理などの運用の手間
- マネージドノードグループから Karpenter に移行することによるコスト最適化
- 上記と Auto Mode 加算料金のトレードオフ
- 我々の移行方法
- 既存クラスターを Auto Mode へ切り替えるのではなく、Auto Mode で新規クラスターを作成して移行
- マネージドに切り替えた点・引き続きセルフマネージドで運用している点
- 移行中・後の注意点
- ロードバランサーの意図しない再作成
- ノード上の Pod 数上限
EKS Auto Mode とは
EKS Auto Mode は、AWS が提供する EKS において、マネージドな範囲をクラスター自体からさらに広げるサービスです。Auto Mode を使用することで、コンピュートリソースやロードバランシング、ネットワーキングなど、管理の大部分を AWS に任せることができます。
たとえば、ワーカーノードの管理やマネージドな Karpenter によるオートスケール、最大 21 日周期での自動的な入れ替えによるノードの更新などは、Auto Mode を使用することで自動化できます。また、クラスターアドオンの管理の自動化やロードバランサーの自動作成などの機能も提供されています。
詳しくは 公式のドキュメント をご覧ください。
なぜ Auto Mode への移行を決めたのか
ここでは、私達が Auto Mode への移行を決めた理由をご紹介します。
移行前の課題
非 Auto Mode クラスターの運用を行う中で、我々はいくつかの課題を抱えていました。それは主に
- クラスターアップグレードの手間
- アドオン運用の手間
- ワーカーノードのコスト最適化
の 3点です。
クラスターアップグレードの手間
クラスターアップグレード(Kubernetes のバージョンアップグレード)は、多くの運用担当者の悩みの種ではないでしょうか。API が非推奨になったり廃止されたりしていないかを確認し、コントロールプレーン、ワーカープレーンを順次バージョンアップする作業はかなりの工数を要します。
API の確認は Upgrade Insights や OSS のツールを使用することで自動化できますが、クラスター自体の更新作業は依然として手動で行う必要があります。
アドオン管理の運用負荷
EKS では、kube-proxy や CoreDNS などのアドオンを追加することでさまざまな機能拡張が行えますが、非 Auto Mode クラスターの場合、これらの導入や運用(バージョン管理など)は手動で行う必要があります。
とくに、クラスターアップグレードの際にはバージョンの変更が必要になる場合があるほか、アドオンのバージョンアップに伴う設定変更が必要になる可能性もあります。
ノードグループにおける、コスト最適化とスケーラビリティの課題
ワーカーノードの管理にはマネージドノードグループを使用していました。マネージドノードグループは、ワーカーノードの起動・停止・削除などの管理を自動化してくれるサービスです。これ自体便利なものではありますが、1つのノードグループでは vCPU、メモリ、GPU などが揃ったインスタンスタイプだけを指定できる、オンデマンドインスタンスとスポットインスタンスのどちらかしか指定できないなど、コスト最適化の文脈では制約が多いです。
また、マネージドノードグループはオートスケーリンググループに紐づいており、そのためオートスケーリングの速度がそれほど速くないという課題もありました。
移行の目的
上記の課題を解決するために Auto Mode で提供される機能の活用が効果的だと考え、 Auto Mode への移行を検討しました。
クラスターアップグレードの省力化
Auto Mode では、クラスターアップグレードの手間を大幅に削減できます。ユーザーは、事前に API 変更などの影響を確認したのち、バージョンアップをトリガーするだけでよく、あとはコントロールプレーンもワーカーノードも自動的にアップグレードされます。ワーカーノードについては、アップグレード前後のバージョンのノードを1つずつ自動で入れ替えてくれますので、Pod Disruption Budgets の設定を適切に行なっていれば、サービスの中断もありません。
今回移行したクラスターは EKS に移行してからまだアップグレードを行なっておらず、これから実績を重ねるにあたって、最初の一歩を踏み出す前に手順を簡略化しておくことの価値は大きいと判断しました。
アドオン管理の効率化による運用工数の削減
Auto Mode では、kube-proxy や CoreDNS, VPC CNI など、いくつかの定番アドオンの管理を自動化できます。これにより、ユーザーはアドオンの管理に関する運用負荷を削減できます。
今回移行したクラスターでは、Auto Mode で自動管理できるアドオンのみを利用していたのでこれによる運用削減の効果は大きいと判断しました。
Karpenter 導入によるコスト最適化
Karpenter は、OSS のオートスケーリングツールです。Karpenter を使用することで、ワーカーノードの起動・停止・削除などの管理を自動化できます。Karpenter ではノードの管理にNodePool/NodeClassを用いるのですが、これに複数のインスタンスファミリー/インスタンスタイプを指定することで、Pod が要求する計算リソースという制約のもとでのコスト最適化を自動的に行うことができます。
Auto Mode では、ワーカーノードの管理にマネージドな Karpenter を使用できます。ユーザーはあらかじめ用意されたいくつかのNodePoolから使いたいものを選択するだけですぐに使用できるようになります。もちろん、ユーザーが自分でNodePool/NodeClassを作成することもできます。
今回移行したクラスターでは、EC2 上で稼働していたサービスを EKS に移行して間もなかったこともあり、管理の手間のためにマネージドノードグループは1つだけでした。1つのマネージドノードグループでは オンデマンド/スポットの片方しか選べませんし、複数のインスタンスタイプを指定する際には CPU、メモリ、GPU のサイズも揃える必要があり、コスト最適化を考えるとやや使いづらい面があります。また、ノードグループを複数管理する手間も考えると、Karpenter を導入することでコスト最適化の効果が大きいと判断しました。
コストに関する検討
Auto Mode を利用することで、コスト削減の効果は大きいと考えていましたが、Auto Mode の追加料金と、コスト削減効果のトレードオフを考慮する必要がありました。
EKS で Auto Mode を有効化すると、通常のインスタンス料金に追加で Auto Mode 加算料金がかかります。具体的な金額は 公式のドキュメント をご覧いただきたいですが、オンデマンド料金の 12% 程度の追加料金がかかります。
今回移行したクラスターでは以下の2点から手間やコストの削減の効果が追加料金を上回ると判断し、Auto Mode への移行を決定しました:
- 元々のインスタンスタイプ・インスタンス数が小さく、加算料金の金額がそれほど大きくない
- Karpenter を導入することでインスタンスコストの最適化が期待でき、追加料金を考慮しても移行前よりインスタンスコストが下がる可能性が高かった
移行アプローチ
移行方針:新規クラスターへの移行
今回の移行では新規クラスターを作って切り替えるという方針としました。既存クラスターのインプレースアップグレードではなく新規作成を選んだ理由は以下の2点です。
- 設定のしやすさ・試行錯誤の行いやすさなどの、準備段階のメリット
- 移行の際の安全性
Auto Mode は比較的新しい機能であり、現時点では、ドキュメントやベストプラクティスが充実しているとは言えない状況です。そのため、開発環境であっても既存のクラスターとは分離された環境として作成しセットアップを進めていきました。また、既存クラスターの設定が充実しているとは言えず、その状態での運用が最適であるとも言えない状況であったため、Auto Mode としての標準的な設定を新規に行ったクラスターを用意することで、移行後の運用を最適化する意図もありました。
その他にも、クラスターを 2 つ用意することで、万が一のことがあった際にも移行前のクラスターにすぐに戻すことができるという安全性も大きなメリットでした。
具体的な移行ステップ
移行の際には、以下のようなステップを踏みました。ここではそれぞれのステップごとにご紹介します。
- 新規 EKS Auto Mode クラスターの構築
- アプリケーションの移行と動作検証
- トラフィックの切り替え
1. 新規 EKS Auto Mode クラスターの構築
我々のチームでは、まず Terraform を用いて EKS Auto Mode が有効化された新しいクラスターを構築しました。Terraform では EKS のモジュール が提供されているので、これを利用することで簡単にクラスターを構築できます。 我々は、このモジュールのバージョン 20.31 を使用しており、以下の情報もそれに合わせたものになっています。
構築にあたり、いくつかの設定項目で注意が必要でした。
ワーカーノード: Auto Mode では、マネージドなノードグループの代わりに Karpenter が標準で利用できます。Karpenter は、さまざまなインスタンスタイプやスポットインスタンスを柔軟に扱え、ノードの起動も高速です。
さらに、Auto Mode ではビルトインNodePoolとして、標準的なオンデマンドインスタンスのNodePoolがほとんど設定なしで使用できます。そのため、Karpenter 特有の設定である NodePool や NodeClass を独自で作成する必要はありません。詳しくは 公式ドキュメント をご覧ください。
ただし、ビルトインNodePoolには管理の手間を減らせるメリットがある一方で、あらかじめ用意されているものしか使えないという制約があり、使用できるインスタンスタイプなどに制限があったり、オンデマンドインスタンスしか使えなかったりといくつかの制限があります。コストを抑えるために T 系のインスタンスタイプを利用したかったこと、また将来的にスポットインスタンスの活用も視野に入れていたことから、我々はカスタムの NodePool と NodeClass を設定することにしました。
サブネット:
Terraform の EKS モジュールには control_plane_subnet_ids
と subnet_ids
という 2 つの input パラメーターがあり、それぞれ「コントロールプレーンのサブネット ID」、「ノードグループのサブネット ID」という説明がなされています。ノードグループ以外の方法でワーカーノードを管理する場合についてはとくに言及されていませんでした。
では、EKS Auto Mode において、Karpenter + AWS が標準で用意しているビルトインのNodePoolを使用した場合はどのサブネットにノードが作成されるのでしょうか。
GitHub で公開されているモジュールのコードを読むと、Auto Mode のNodePoolは、control_plane_subnet_ids
で指定されたサブネットに作成されることがわかりました。本来は、コントロールプレーンはインターネットに出られない intra サブネット、ワーカーノードは インターネットに出られる private サブネットに作成されるべきですが、上記の理由から、control_plane_subnet_ids
と subnet_ids
の両方に対し private サブネットの id を設定する必要があります。(control_plane_subnet_ids
が指定されていない場合 subnet_ids
が使用されるので、実際には subnet_ids
のみを指定してもよいです。)
さもないと、ワーカーノードがインターネットに出られないため、コンテナイメージを取得できずに Pod の起動に失敗するなどの問題が発生します。
執筆時点での最新バージョンである 21.0.7 でも、
Auto Mode の example
では subnet_ids = module.vpc.private_subnets
のみを指定しているので、おそらく同様の仕様になっていると思われます。
IAM ロール:
Auto Mode はクラスターやノードを管理するために、従来の権限に加えて AmazonEKSComputePolicy
や AmazonEKSBlockStoragePolicy
などの追加の IAM ポリシーが必要になります。
Terraform の EKS モジュールを利用する場合、とくに意識することなくデフォルトで適切なロールが作成されました。
アドオン: kube-proxy、CoreDNS、VPC CNI といった基本的なコンポーネントに加え、Karpenter や Load Balancer Controller もマネージドアドオンとして提供されます。これにより、これまで自前で管理する必要があったこれらのコンポーネントの運用負荷が軽減されます。
従来は、Terraform でこれらのアドオンを導入する設定を書いていましたが、マネージドに切り替わるためこういった設定の記述が不要になりました。
ロードバランサー: Auto Mode では、Ingress/IngressClass/IngressClassParams という Kubernetes custom resource によるロードバランサーの管理もマネージドにできます。その方法については 公式ドキュメント をご覧ください。
この方法には ALB の管理をマネージドにできるというメリットがあるのですが、今回は既存のクラスターと同じように、ALB を手動で作成しています。そのようにした理由は以下です:
- 現時点で Terraform で管理されている ALB の設定があり、その設定をそのまま流用する方が、新たに Ingress/IngressClass/IngressClassParams を設定するより手間が少ない
- IngressClassParams の書き方についての資料が少なく、設定方法がわかりづらかった
- クラスターの設定を変更した際、まれに ALB の作り替えが発生することがあり、DNS レコードの不整合が起きて障害につながる可能性がある
3 については詳細な資料は提供されていないようですが、
- 設定変更によりクラスターの再作成が行われる際に ALB も再作成される
- IngressClassParams の scheme など一部項目では、設定を変更した際に(クラスターの作り替えは行われないが) ALB が再作成される
といったことがあり、手間やリスクを完全に回避できないということと、既存クラスターで使用している ALB をそのまま再利用できるということから判断して、手動で ALB を作成することにしました。
2. アプリケーションの移行と動作検証
新しいクラスターの準備が整った後、次に行ったのはアプリケーションと監視ツールのデプロイです。
アプリケーション: 基本的には、新しいクラスターに対して既存のデプロイメントマニフェストを適用するだけです。ただし、後述するトラフィックの切り替えをスムーズに行うため、ALB のターゲットグループは、既存クラスター用と新しい Auto Mode クラスター用の2つを用意しました。それに伴い、TargetGroupBinding (TGB) もそれぞれのクラスター用に準備しています。1つのターゲットグループに複数の TGB を適用すると、最後に適用されたもの以外がドレインされてしまうため、このような構成にしています。
監視ツール: 監視には Prometheus、Loki、Grafana を利用しています。これらもアプリケーションと同様に、新しいクラスターにデプロイします。ただし、kube-proxy など、Auto Mode によってマネージドになったコンポーネントは監視対象から除外しました。
これらの設定変更を行った上で、開発環境 と QA 環境で動作に問題がないことを検証しました。
3. トラフィックの切り替え
アプリケーションの動作検証が完了したら、いよいよトラフィックを新しいクラスターに切り替えます。我々は、ALB を共用し、リスナールールでターゲットグループを切り替える方法を採用しました。
具体的な手順は以下の通りです。
- 新しいターゲットグループの作成: まず、Terraform の設定ファイルで新しいクラスター用のターゲットグループを作成し、
apply
して ALB にアタッチします。 - リクエストを処理するクラスターの切り替え: 次に、新しいクラスターがすべてのリクエストを処理するように設定します。これは、ALB のリスナールールの優先度 (priority) を調整し、新しいクラスターのターゲットグループへ向かうルールの優先度を高くすることで実現しました。
- 旧クラスターの切り離し: 最後に、Terraform の設定ファイルで旧クラスター用の TargetGroupBinding をコメントアウトし、
apply
を実行します。これにより、ALB から旧クラスターへのトラフィックが完全に流れなくなります。
この方法のメリットは、DNS の設定を変更する必要がなく、ユーザー影響を最小限に抑えながら安全にトラフィックを移行できる点です。また、万が一新しいクラスターに問題が発生した場合でも、リスナールールの優先度を元に戻し、旧クラスター用の TGB を再度有効化するだけで、迅速に切り戻しが可能です。
移行後の変化と注意点
今回の移行プロジェクトで得られた知見と移行後にわかった注意点をまとめます。
移行後の変化
移行後にあった良い変化を以下にまとめます。
運用工数の削減
移行後、アドオンのバージョン管理やNodePoolの管理など、運用負荷が軽減されました。また、Kubernetes 運用で避けて通れない定期的なバージョンアップも、Auto Mode では非常に簡単に行えるようになりました。
コスト削減
元々のクラスターでは、最適化されていないマネージドノードグループを使用しており、インスタンスにムダな費用がかかっていました。Karpenter とカスタム NodePool/NodeClass を使用することでインスタンスコストを最適化でき、Auto Mode の加算料金込みでも従来の 56 % に削減できました。
移行後にわかった注意点
max-pods-per-node
の設定と Pod 密度
EKS Auto Mode では、ワーカーノードの max-pods-per-node
の設定がデフォルト値から変更できません。このため、たとえひとつひとつの Pod の要求する計算資源が小さくてもワーカーノード上の Pod 密度を高めることができない場合があります。そうなると、Pod の要求リソースの合計に対して過剰な台数のインスタンスが作成されることになり、コスト最適化の妨げになる可能性があります。
issue も作成されていますが、現時点では変更できるようなオプションは提供されていないとのことです。
まとめ
今回の移行プロジェクトでは、EKS Auto Mode を導入することで、運用工数の削減やコスト削減の効果が期待できることを確認しました。
また、移行後にわかった注意点を踏まえて、今後の運用を最適化するための知見を得ることができました。
この記事が、EKS Auto Mode を導入する際の参考になれば幸いです。
最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。