Amazon Web Services ブログ
Amazon EKS で Multus を使用した Karpenter ノードのデプロイ
この記事は、こちらのブログ「Deploying Karpenter Nodes with Multus on Amazon EKS 」(2024年5月24日公開)を翻訳したものです。
コンテナベースの通信事業者のワークロードでは、トラフィックやネットワークの分離のために Multus CNIをよく使用します。Amazon Elastic Kubernetes Service(Amazon EKS)は Multus CNI をサポートしており、複数のネットワークインターフェイスをアタッチし、Kubernetes ベースのアプリケーションに対して高度なネットワーク構成や分離を適用することができます。AWS でアプリケーションを実行する利点の 1 つは、リソースの弾力性(スケールアウトおよびスケールイン)です。ノードの弾力性は、Karpenter のようなクラスターオートスケーラーを使用することで実現できます。Karpenter は、アプリケーションの需要に応じて最適なコンピュートリソースを自動的に起動します。Karpenter は、迅速かつシンプルな Kubernetes クラスターのプロビジョニングを目的として設計されており、Amazon EKS ノードグループの外部でグループレスのノードをプロビジョニングします。
目的
この投稿では、Multus インターフェイス付きの EKS ノードプールを Karpenter でプロビジョニングされるデプロイモデルを紹介します。このデプロイモデルは、特に通信事業者のワークロードに推奨されますが、これに限定されるものではありません。このモデルは、Karpenter をグループレスのノードプールおよびオートスケーリングソリューションとして活用することを目的としています。グループレスのワーカー(ノードプール)は、Multus CNI を必要とするアプリケーション Pod 用であり、一方でAmazon EKS マネージド型ノードグループのワーカーは、プラグイン、アドオン、および Karpenter 自体など、Multus CNI を必要としないポッドを実行します。この投稿では、Karpenter が複数の Elastic Network Interface(ENI)を持つワーカーのリアルタイムスケーリングを管理し、スケーラビリティとネットワーク分離の厳しい要件を満たす方法も示します。
なぜこのようなデプロイモデルなのか?
Karpenter の主なユースケースは、デプロイ時やスケールアウトイベント時に Kubernetes クラスターのワーカーノードをプロビジョニングすることです。この投稿では、Karpenter のもう一つのユースケースとして、Multus CNI を使用するアプリケーションをホスティングするノードプールをプロビジョニングする方法を紹介します。このデプロイモデルは、アプリケーションのワーカーノードを Amazon EKS マネージド型ノードグループから切り離します。このアプローチの利点は、1)アプリケーションワーカーは特定のインスタンスタイプやサイズに限定されず、インスタンスのタイプやファミリーの幅広い選択肢を利用できること。2)アプリケーションのスケールアウト機能が Amazon Elastic Compute Cloud(Amazon EC2)Auto Scaling グループに結びつかず、Amazon EKS マネージド型ノードグループを通じて Auto Scaling グループを利用する場合よりも、柔軟にスケールできることです。また、EC2 Auto Scaling グループに依存しないため、Karpenter は Amazon EC2 fleet API を直接使用してワーカーノードを迅速にプロビジョニングできます。これはアプリケーションのスケールアウトシナリオにおいてかなり重要です。標準の Karpenter ベースのノードプロビジョニングは、単一の VPC サブネットに接続されたノードを作成するため、Multus CNI をサポートしていません。この投稿では、EC2NodeClass を使用することにより、user-data を活用した ENI 管理を導入することで、Karpenter を介して Multus をサポートするソリューションを提供します。
デプロイ
このセクションで説明される手順の詳細は、こちらの GitHub リポジトリを参照しています。
このデプロイは、Multus CNI を使用したアプリケーション Pod を Karpenter で柔軟に実行できることを示しています。Karpenter を介して Multus 用の ENI を作成およびアタッチするアプローチを適用し、併せて Karpenter のスケーリング機能も実演します。
前提条件
この投稿の手順を進めるには、以下の前提条件が必要です。
環境設定
このセットアップでは、VPC、EKS クラスター、EKS マネージド型ノードグループ、セキュリティグループ、および関連するVPCコンポーネントを作成します。
1. ここでは CloudShell 環境を使用して EKS クラスターを構成し、サンプルアプリケーションをデプロイします。CloudShell コンソールに移動し、この GitHub リポジトリをダウンロードして、必要なツール(awscli、kubectl、eksctl、helmなど)をインストールするための次のスクリプトを実行します。
2. テンプレート `vpc-infra-mng.yaml` を使用して AWS CloudFormation スタックを作成します。2つのアベイラビリティゾーン(例:`us-west-2a` および `us-west-2b`)を選択します。スタック名を `karpenterwithmultus` とします(このスタック名は後で CloudShell 環境で使用します)。他のパラメータはデフォルトのままにしておくことができます。次の AWS Command Line Interface (AWS CLI) コマンドを使用するか、AWS マネジメントコンソールの CloudFormation メニューを使用してスタックを作成します。
次の手順を実行する前に、最初の CloudFormation スタック作成が完了していることを確認してください。EKSクラスターとワーカーノードの構築には約15分かかる場合があります。
結果として得られるアーキテクチャは次の図のようになります。
3. CloudShell で、Karpenter バージョン、EKS クラスター名、および AWS リージョンを定義するために環境変数を作成します。パラメータ値を環境に応じて変更して、CloudShell コンソールに移動して次のコマンドを実行します。
注:
`VPC_STACK_NAME`は、CloudFormationテンプレート`vpc-infra-mng.yaml`で指定した名前を使います。
デフォルトのリージョンに注意してください。後のステップで、`nodepool.yaml`にはアベイラビリティゾーン(AZ)を指定します。
この例では CloudShell を admin ノードとして使用します。CloudShell がタイムアウトすると、環境変数が失われます。CloudShell 以外の admin ノードを使用しても問題ないです。
Kubeconfig を更新し、Amazon EKS コントロールプレーンへのアクセスをテストします。
エラーが表示されなければ、K8Sクラスターへのアクセスが確認されます。
プラグインの設定
4. Multus CNI をインストールします。Multus CNI は、Kubernetes 用のコンテナネットワークインターフェースプラグインであり、Pod に複数のネットワークインターフェースをアタッチできます。Multus CNI と VPC CNI が Amazon EKS でどのように機能するかについて理解したい場合は、こちらの Amazon Container の記事を参照してください。
5. Multus の IP アドレスレンジを専有させるために Multus サブネット用の CIDR 予約が必要です。CIDR 予約で明示的なフラグを設定すると、VPC が ENI などの VPC リソースを作成する際にこれらの CIDR ブロックに使わないようになります。次の CIDR 予約コマンドを Multus サブネットで実行し、/27 の IP レンジを確保します。
注:エラーが発生した場合、例えば`subnet ID doesn’t exist`のエラーが表示された場合は、正しい AWS_DEFAULT_REGION 環境変数が定義されているかどうかを確認してください。
6. Whereabouts プラグインをインストールします。Whereabouts は、前のステップで設定した Multus Pod IP アドレスを管理するために使用する IPAM CNI プラグインです。Whereabouts を使用した Multus Pod IP アドレスは、Custom Resource Definition(CRD)Network-Attachment-Definitions(NAD)を介して定義されます。
7. クラスターに NetworkAttachmentDefinitions を適用します。これは、後でアプリケーション Pod を作成するときに、Pod 上の Multus インターフェースのコンフィグになります。このファイルを確認すると、前のステップで設定した CIDR 予約プレフィックスが定義されていることがわかります。
IAM ロールの設定
8. Karpenter IAM ロールおよび Karpenter に必要なその他の前提条件を作成します。このステップが完了すると、「Successfully created/updated stack – <Karpenter-${CLUSTER_NAME}>」というメッセージが表示されるはずです。
9. Multus に必要な AWS Identity and Access Management (IAM) ポリシーを作成し、それを Karpenter ノードロールにアタッチします。EC2NodeClass の userdata セクションには、Karpenter でプロビジョニングされたノードに ENI を作成、アタッチ、およびコンフィグするためのスクリプトが含まれています。ノードには、Karpenter ノードロールに適切なポリシーをアタッチする必要があります。
10.(オプション)スポットインスタンスを使用するためのロールを、下記のコマンドで作成します。
既にロールが正常に作成されている場合は、次のようなメッセージが表示されます。
# An error occurred (InvalidInput) when calling the CreateServiceLinkedRole operation: Service role name AWSServiceRoleForEC2Spot has been taken in this account, please try a different suffix.
注:このステップはオプションであり、Karpenter ノードプールでスポットインスタンスを使用したい場合にのみ必要です。
Karpenter のインストール
11. Karpenter をインストールします。
12. Karpenter Pod が `Running` 状態にあるか確認するために次のコマンドを実行します。
13. `nodepool.yaml` ファイルに含まれる Multus サブネットタグ名、AZ、およびセキュリティグループタグ名を更新します。Karpenter ノードプール構成の詳細については、こちらの Karpenter の記事を参照してください。
`nodepool.yaml` を正しい AZ 名で更新し、次のコマンドを実行します。この例では、`us-west-2a` および `us-west-2b` を使用しています。
次のコマンドを使用して EKS クラスター名を更新します。
Karpenter ノードプール構成を適用します。
注:`config/nodepool.yaml` ファイルを確認すると、EC2NodeClass の userdata セクションがカスタマイズされていることがわかります。userdata 内のスクリプトは、Amazon EC2 ノードプールの作成時に MULTUS ENI をプロビジョニング、アタッチ、およびコンフィグします。これはノードプール上の MULTUS ENI LCM を設定するところです。追加のノードチューニングが必要な場合は、userdata セクションに追加することができます。
ノードプールコンフィグにエラーがある場合は、Karpenter コントローラーのログを確認してください。
14. ノードプール内のノードで Multus DaemonSet Pod とアプリケーション Pod が同時にスケジュールされると競合状態が発生します。この課題を解決するために、Karpenter のノードプールを `StartupTaints` で構成する必要があります。`StartupTaint` は、Multus が準備完了するまでアプリケーション Pod が新しいノードにスケジュールされるのを防ぎます。Multus が準備できたら Taint が削除されます。Taint の削除を自動化するために、この投稿では DaemonSet ベースのソリューションを使用します。
まず、Taint を削除するまたの DaemonSet 用のネームスペースを作成します。
DaemonSet `daemonset-clear-taints` がノード上の Taint を削除できるようにするための RBAC コントロールを提供する必要があります。次のコマンドで、`cleartaints` ネームスペースに限定された Service Account 、Service Account Role 、および Role Binding を作成します。
`cleartaints` というネームスペースで、`daemonset-clear-taints` という名前の DaemonSet を作成して適用します。
DaemonSet Pod を確認します。Karpenter ノードプールでのみ実行されるため、この時点では DaemonSet は表示されません。
Node-Latency-For-K8s のデプロイ
15.(オプション)ノードプールのスケールアウト速度に関するデータを収集するために、Node-Latency-For-K8s ソリューションをデプロイできます。Node-Latency-For-K8s は、ノード起動遅延を分析するためのオープンソースツールです。このツールは、ノードがインスタンス化されるから、アプリケーション Pod が実行されるまでの各フェーズでかかった時間を測定します。後のステップではいくつかの例を取り上げます。
サンプルアプリケーションのデプロイ
16. サンプルアプリケーションをデプロイします。次のコマンドは、各 AZ に1つのアプリケーションレプリカを持つ Deployment をインストールします。これにより、Karpenter がアプリケーションをスケジュールできるようにノードプールの作成がトリガーされます。
`multitool-deployment-az1.yaml`、`multitool-deployment-az2.yaml` の各ファイルで、正しい AZ 名に更新します。
各 Deployment には `karpenter-node` というアフィニティキーがあり、これによりアプリケーション Pod はラベル「`karpenter-node`」が付いたワーカーノードにのみスケジュールされます。Deployment が作成されるときに、Karpenter ノードプールはラベルを割り当てるため、これらの Deployment の Pod をスケジュール/実行するためにノードをスケールします。
次のコマンドを使用して、Karpenter が新しい Amazon EKS ワーカーノードをスケーリングするのを監視します。
Karpenter のログを確認します。
Karpenter が新しい EC2 インスタンスを起動し、EKS クラスターに参加し、`Ready` 状態になると、`Pending` 状態のポッドが `Running` 状態に移行します。
次の図のように、Multus インターフェースを持つ Karpenter ワーカーが追加されたアーキテクチャが完成します。
17. 次のコマンドを使用して、アプリケーション Pod が `Running` 状態であることを確認します。
`kubectl describe pod` または `kubectl exec` を使用して Pod を確認し、Multus インターフェースとアドレスを確認できます。
1つのポッドを選択し、次の `exec` コマンドを実行して Multus Pod の IP アドレスを確認します。`net1` および `net2` インターフェースが Multus インターフェースとして表示されます。Amazon EC2 ワーカー上では、Multus ENI はそれぞれ `eth1` および `eth2` と同じサブネットに属しています。
注:Multus Pod IP アドレスを確認します。これらの IP は、ステップ 6 で定義した NetworkAttachmentDefinitions ファイルで設定した範囲に属しています。
(オプション)Karpenter ノードプールのプロビジョニングにかかる時間を調べるために、Node-Latency-For-K8s のログを新しく作成されたノードで確認できます。`node-latency-for-k8s-node-latency-for-k8s-chart-xxxxx` Pod のログを取得します。例として、ログの取得に約5分かかる場合があります。
注:起動時に実行される userdata スクリプト(約20-25秒)は、ノードが Ready になるまでの時間に加算されます。userdata スクリプトを使用しない場合、Karpenterノードの Readby になる時間は約30秒です。
(オプション)Multus Pod IP の自動割り当て
Pod への Multus 接続には、Multus IP をワーカーノード上の対応する Multus ENI のセカンダリIPとして割り当てることが重要です。この GitHub リンクを使用して、InitContainer ベースの IP 管理ソリューションまたは Sidecar ベースの IP 管理ソリューションをアプリケーション Pod 内で使用して、Multus IP を自動的に Multus ENI にセカンダリ IP として割り当てることができます。
スケーリング
18. 次のコマンドを使用してスケールアウトを実行し、Karpenter を使用したノードの追加スケーリングをテストし、ノードのスケーリングを監視します。
19.(オプション)Karpenter のスケールアウト速度に関するデータをもう一度収集します。新しく作成されたノードプールワーカーで `node-latency-for-k8s-node-latency-for-k8s-chart-xxxxx` Pod のログを取得します。
20. Karpenter は、`Pending` 状態のポッドの数に応じて必要なノードを自動的にプロビジョニングする柔軟性があります。レプリカの数を増やすことで、スケールインとスケールアウトをもう一度行うことができます。Karpenter がプロビジョニングしたインスタンスタイプとサイズを注目してください。
スケールイン:
Karpenter が既存のノードプールを終了するのを待ち、終了したら再度スケールアウトします。この例では、ネットワークアドレス定義で利用可能な IP アドレスの数の制限まで Pod をスケールアウトできます。
クリーンアップ
CloudFormation スタックを逆の順序で全て削除します。
結論
この投稿では、Karpenter を Multus CNI と組み合わせて使用し、Multus が使用する ENI のライフサイクルをどのように管理するかを示しました。Karpenter でプロビジョニングされたノードプールのワーカーには、Multus 対応のインターフェースがアタッチされます。また、Karpenter をオートスケーリングソリューションとして使用する利点も示しました。Karpenter は、Kubernetes クラスターでワークロードを実行する際に、効率とコストを次のように改善します:
- Kubernetes スケジューラーが未スケジュールとしてマークしたポッドを監視する。
- Pod によって要求されたスケジューリング制約(リソースリクエスト、ノードセレクター、アフィニティ、トレランス、トポロジスプレッド制約)を評価する。
- Pod の要件を満たすノードをプロビジョニングする。
- ノードが不要になったときにノードを削除する。
Karpenter は、アプリケーションのスケーリング要件に対応するための柔軟なツールです。
Karpenter とベストプラクティスに関する詳細は、AWS GitHub リンクを参照してください。
著者
Rolando Jr Hilvano
Rolando Jr Hilvano is a Principal Solutions Architect in the Worldwide Telecom Business Unit at Amazon Web Services (AWS). He specializes in 5G space and works with telecom partners and customers in building and deploying Cloud Native Telco workloads on AWS.
Ashutosh Tulsi
Ashutosh Tulsi is a Principal Solutions Architect in the AWS Worldwide Telecom Business unit working with Communication Service Providers (CSPs) and Telco ISV Partners. His goal is to enable CSP’s achieve Operational and Cost efficiencies by providing solutions that assist in migrating the 4G / 5G Networks to the AWS Cloud.
Young Jung
Dr. Young Jung is a Principal Solutions Architect in the AWS Worldwide Telecom Business Unit. His primary focus and mission are to help telco Core/RAN partners and customers to design and build cloud-native NFV solutions on AWS environment. He also specializes in Outposts use cases of telco industry for telco’s edge service implementation powered by AWS services and technologies.
Neb Miljanovic
Neb Miljanovic is an AWS Telco Partner Solutions Architect supporting migration of Telecommunication Vendors into public cloud space. He has extensive experience in 4G/5G/IMS Core architecture and his mission is to apply that experience to migration of 4G/5G/IMS Network Functions to AWS using cloud-native principles.
Sudhir Shet
Sudhir Shet is a Principal Partner Solutions Architect in the AWS Global Telecom IBU team, specializes in IMS and 5G, working with various global telecom partners and CSPs to create cloud-native 5G/IMS NFV solutions on AWS.
翻訳はソリューションアーキテクトの陳誠が担当しました。