View a markdown version of this page

CLI を使用して AI/ML ワークロード用の Amazon EKS クラスターを設定する - Amazon EKS

このページの改善にご協力ください

このユーザーガイドに貢献するには、すべてのページの右側のペインにある「GitHub でこのページを編集する」リンクを選択してください。

CLI を使用して AI/ML ワークロード用の Amazon EKS クラスターを設定する

ヒント

今後開催予定の Amazon EKS AI/ML ワークショップに登録してください。

このセクションでは、CLI コマンドを使用して Amazon EKS でトレーニングまたは推論ワークロードを実行するために必要なインフラストラクチャを作成する手順について説明します。ステップには、EKS クラスターの作成、EKS Auto Mode または Karpenter を使用した GPU 対応ノードの作成、Prometheus と Grafana を使用したモニタリングスタック、モデルの重み付け用の Amazon S3 ストレージが含まれます。

これらの機能が EKS クラスターで EC2 インスタンスをプロビジョニングおよび自動スケールする方法の詳細については、EKS Auto ModeKarpenter のドキュメントを参照してください。

高レベルアーキテクチャとワークフロー

Karpenter NodeClass および NodePool を使用した EKS クラスター、Amazon Managed Service for Prometheus への Grafana および Prometheus モニタリングスタックの書き込み、モデルの重み付け用の Amazon S3 バケット、および番号付きワークフローステップを示す高レベルアーキテクチャ

この図は、このセクションのセットアップの AWS 高レベルアーキテクチャを示しています。右側の番号付きステップは、以下のステップで設定を完了する順序を示しています。

前提条件

重要

EKS クラスター、GPU インスタンス、Application Load Balancer、Amazon Managed Service for Prometheus など、このチュートリアルで作成するリソースには料金が発生します。終了したリソースは、継続的な料金の発生を回避するために削除してください。

eksctl バージョンを確認します。

eksctl version

0.227.0 より前のバージョンを使用している場合は、eksctl インストールガイドに従って最新のリリースにアップグレードします。

環境変数を設定する

これらのステップ全体で、以下のクラスター名と AWS リージョンの一貫性を維持します。変更すると、後続のコマンドが間違った EKS クラスターをターゲットにする可能性があります。

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

利用可能なすべての AZ を使用すると、耐障害性が向上し、GPU キャパシティを取得する可能性が高くなります。

export AZS=$(aws ec2 describe-availability-zones \ --region ${AWS_REGION} \ --query "AvailabilityZones[?ZoneId!='use1-az3' && ZoneId!='usw1-az2' && ZoneId!='cac1-az3'].ZoneName" \ --output text | tr '\t' ',') echo $AZS
重要

Amazon EKS はこれらのゾーンでのコントロールプレーン配置をサポートしていないため、アベイラビリティーゾーン use1-az3usw1-az2、および cac1-az3 は除外されます。これらのゾーンのいずれかにサブネットを持つクラスターを作成すると、UnsupportedAvailabilityZoneException が発生します。

正常な出力:

us-east-2a,us-east-2b,us-east-2c

出力に表示される AZ はリージョンによって異なります。この例では、us-east-2 リージョンで利用可能な AZ を示しています。

クラスターと GPU NodePool を作成する

このセクションでは、EKS クラスターと GPU 対応ノードを作成するための 2 つのパスを以下の図に示します。ガイド全体で 1 つのオプションのみを選択してください。

  • EKS Auto Mode — EKS Auto Mode には、コアネットワーク、ストレージ、ロードバランシングアドオンに加えて、EKS ノードモニタリングエージェント、自動ノード修復、高速コンテナプル用の SOCI スナップショッター、デフォルトの NodeClass の GPU 準備などのトレーニングおよび推論ワークロードの機能が含まれています。NVIDIA デバイスプラグインは、EKS Auto Mode が GPU 対応ノードに使用する Bottlerocket 高速 AMI に含まれています。

  • セルフマネージド Karpenter — EKS Auto Mode のない EKS クラスターでは、トレーニングおよび推論ワークロードに必要なコンポーネントのインストールおよび設定を自分で行う必要があります。これには、ネットワーキングアドオン (VPC CNI、CoreDNS、kube-proxy)、Karpenter、EKS ノードモニタリングエージェント、NVIDIA デバイスプラグイン、高速コンテナプル用の SOCI スナップショットターが含まれます。

EKS クラスターオプション: EKS Auto Mode とセルフマネージド Karpenter

NodePool を備えた EKS Auto Mode クラスターと、セルフマネージド Karpenter、CoreDNS、VPC CNI、NVIDIA デバイスプラグイン、EKS Pod Identity エージェント、Node Monitoring Agent、kube-proxy、NodeClass および NodePool を備えた EKS 標準クラスターの 2 つのクラスターオプションを並べて比較したもの

以下の各ステップで、パス (EKS Auto Mode、Karpenter) を選択し、一貫してそのパスに従います。選択したパスのステップを完了すると、GPU NodePool を備えた EKS クラスターが GPU ワークロードをスケジュールできるようになります。

ステップ 1: クラスターを作成する

まず、EKS クラスターを作成し、GPU ワークロードに必要なクラスターコンポーネントをインストールします。

EKS Auto Mode では、1 つの eksctl create cluster --enable-auto-mode コマンドで GPU ワークロードに対応する EKS クラスターをプロビジョニングします。

セルフマネージド Karpenter では、eksctl create cluster コマンドはコアネットワーキングアドオンをプロビジョニングします。その後、Karpenter 機能ゲートを介して自動ノード修復を有効にし、EKS ノードモニタリングエージェントをインストールして、NVIDIA デバイスプラグインをインストールするための追加のステップが必要です。

EKS Auto Mode

EKS Auto Mode クラスターを作成する

eksctl create cluster \ --name=$CLUSTER_NAME \ --region=$AWS_REGION \ --enable-auto-mode \ --version=1.36 \ --zones=$AZS

このコマンドの完了には数分かかります。完了すると、eksctl は新しくプロビジョニングされたクラスターで動作するように kubeconfig ファイルを自動的に更新します。クラスターが動作していることを確認します。

kubectl get pods --all-namespaces

正常な出力:

NAMESPACE NAME READY STATUS RESTARTS AGE kube-system metrics-server-55cf976ddd-cz2mw 1/1 Running 0 3m kube-system metrics-server-55cf976ddd-wrjvv 1/1 Running 0 3m

EKS Auto Mode では、VPC CNI、kube-proxy、および CoreDNS はマネージドコンポーネントとして実行され、kube-system ではポッドとして表示されません。

デフォルトの StorageClass を作成する

GPU ワークロードでは、多くの場合、モデルの重みをキャッシュするなど、永続ストレージが必要になります。これにより、Kubernetes はポッドを再起動するたびに再ダウンロードする必要がなくなります。EKS Auto Mode にはブロックストレージ機能が組み込まれているため、Amazon EBS CSI ドライバーをインストールする必要はありません。Auto Mode プロビジョナーを参照する StorageClass を作成します。

cat << EOF | kubectl apply -f - apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: gp3 annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: ebs.csi.eks.amazonaws.com volumeBindingMode: WaitForFirstConsumer parameters: type: gp3 encrypted: "true" EOF

このコマンドは gp3 StorageClass を作成し、storageclass.kubernetes.io/is-default-class 注釈でクラスターのデフォルトとしてマークします。storageClassName を省略した PersistentVolumeClaim は、この StorageClass を使用します。volumeBindingMode: WaitForFirstConsumer 設定は、Kubernetes がポッドをスケジュールするまでボリュームの作成を遅らせるため、EBS ボリュームはポッドと同じアベイラビリティーゾーンに配置されます。

Self-managed Karpenter

Helm をパブリック ECR に認証する

eksctl は、Amazon Public ECR から Karpenter Helm チャートをプルします。Helm のインストールステップで 403 エラーが発生しないように、クラスターを作成する前に認証します。

aws ecr-public get-login-password --region us-east-1 \ | helm registry login --username AWS --password-stdin public.ecr.aws

パブリック ECR は、us-east-1 でホストされているグローバルサービスです。EKS クラスターがどのリージョンにあるかに関係なく、ここで --region us-east-1 を使用します。

正常な出力: Login Succeeded

Karpenter で EKS クラスターを作成する

Karpenter バージョンは、後で使用するために環境変数に保存します。最新の Karpenter バージョンについては、GitHub の Karpenter リリースを参照してください。

export KARPENTER_VERSION=1.14.0
例クラスター設定 YAML
cat << EOF > /tmp/cluster-karpenter.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ${AWS_REGION} version: "1.36" tags: karpenter.sh/discovery: ${CLUSTER_NAME} availabilityZones: [$(echo $AZS | sed 's/,/, /g')] autoModeConfig: enabled: false iam: withOIDC: true karpenter: version: "${KARPENTER_VERSION}" withSpotInterruptionQueue: true managedNodeGroups: - name: system instanceTypes: ["m6i.2xlarge", "m5.2xlarge", "m6a.2xlarge", "m5a.2xlarge", "m7i.2xlarge"] desiredCapacity: 2 minSize: 2 maxSize: 3 labels: node-role: system tags: karpenter.sh/discovery: ${CLUSTER_NAME} addons: - name: eks-pod-identity-agent - name: eks-node-monitoring-agent - name: aws-ebs-csi-driver EOF

system マネージドノードグループには、単一のタイプではなく、同じサイズ (8 vCPU、32 GiB) の複数のインスタンスタイプが一覧表示されます。1 つのタイプがアベイラビリティーゾーンで一時的に使用できない場合、ノードグループの Auto Scaling グループは別のタイプにフォールバックされるため、InsufficientInstanceCapacity 起動の失敗を回避できます。オンデマンドマネージドノードグループでは、ノードサイズが均一になるように、一覧表示されているすべてのインスタンスタイプに同じ vCPU とメモリがある必要があります。

設定ファイルを使用してクラスターを作成します:

eksctl create cluster -f /tmp/cluster-karpenter.yaml

このコマンドの実行には約 15 分かかります。アドオンと Karpenter コントローラーのホスティング専用のマネージドノードグループを持つ EKS クラスターを作成します。Karpenter は、スポット中断キューを有効にしてインストールされるため、スポット中断と再調整の推奨事項を処理できます。autoModeConfig.enabled: false 設定により、このクラスターが EKS Auto Mode を使用しないことが明示的になるため、このパスにインストールされた Karpenter コンポーネントがノード管理を担当します。

また、クラスターは EKS Pod Identity AgentEKS ノードモニタリングエージェント、および Amazon EBS CSI ドライバーを EKS アドオンとしてインストールします。EKS Pod Identity はガイドの後半で使用します。EKS ノードモニタリングエージェントはすべてのノードで実行され、カーネルログを読み取り、AcceleratedHardwareReadyKernelReadyNetworkingReady などのノード条件を設定します。Karpenter 自動ノード修復は、これらのノード条件を使用して異常なノードを置き換えるタイミングを決定します。

クラスターが動作していることを確認します。

kubectl get pods --all-namespaces

予想される出力には、Karpenter、CoreDNS、kube-proxy、aws-node (VPC CNI)、EKS Pod Identity Agent、および EKS ノードモニタリングエージェントが含まれます。

NAMESPACE NAME READY STATUS RESTARTS AGE karpenter karpenter-567547464c-s6vkx 1/1 Running 0 3m40s karpenter karpenter-567547464c-x7gmw 1/1 Running 0 3m40s kube-system aws-node-b6gf2 2/2 Running 0 12m kube-system aws-node-lcphh 2/2 Running 0 12m kube-system coredns-7d4dcbf4fb-ccvrr 1/1 Running 0 16m kube-system coredns-7d4dcbf4fb-qbhk2 1/1 Running 0 16m kube-system eks-node-monitoring-agent-h79vm 1/1 Running 0 9m45s kube-system eks-node-monitoring-agent-tf4dw 1/1 Running 0 9m45s kube-system eks-pod-identity-agent-5jbtc 1/1 Running 0 12m kube-system eks-pod-identity-agent-rwcrc 1/1 Running 0 12m kube-system kube-proxy-p4bmq 1/1 Running 0 12m kube-system kube-proxy-v5nwr 1/1 Running 0 12m kube-system metrics-server-5b966ff79c-hr58p 1/1 Running 0 9m22s kube-system metrics-server-5b966ff79c-szs2d 1/1 Running 0 9m22s

Karpenter 機能ゲートを有効にする

EKS Auto Mode は、デフォルトで自動ノード修復と静的キャパシティを有効にします。セルフマネージド Karpenter では、NodeRepair 機能ゲートと静的 NodePools の StaticCapacity ゲートを明示的に有効にする必要があります。これにより、保留中のポッドに応じてスケーリングするのではなく、spec.replicas を通じて固定ノード数が維持されます。Karpenter では、どちらのゲートもデフォルトでアルファとオフになっています。以下のコマンドは、Karpenter デプロイにパッチを適用して両方のゲートを有効にします。デプロイ環境を更新すると、Karpenter ポッドのロールアウトがトリガーされます。

kubectl set env deployment/karpenter -n karpenter \ FEATURE_GATES=NodeRepair=true,StaticCapacity=true

正常な出力:

deployment.apps/karpenter env updated

Karpenter ポッドがロールアウトするのを待ちます。

kubectl rollout status deployment/karpenter -n karpenter

NVIDIA デバイスプラグインをインストールする

EKS 最適化 AL2023 AMI には NVIDIA デバイスプラグインは含まれていません (EKS Auto Mode で使用される Bottlerocket AMI とは異なります)。Helm 経由でインストールして、クラスターのポッドで GPU リソースを使用できるようにします。

helm repo add nvdp https://nvidia.github.io/k8s-device-plugin helm repo update
cat << 'EOF' > /tmp/nvdp-values.yaml mofedEnabled: false nodeSelector: amiFamily: al2023 gfd: enabled: true nfd: worker: tolerations: - operator: "Exists" EOF
helm install nvidia-device-plugin nvdp/nvidia-device-plugin \ --namespace kube-system \ -f /tmp/nvdp-values.yaml
  • mofedEnabled: false: AWS が使用しない Mellanox OFED (InfiniBand) のチェックを無効にします

  • nodeSelector.amiFamily: al2023: DaemonSet を AL2023 ノードのみにスコープします (Bottlerocket には既にプラグインが組み込まれています)

  • gfd.enabled: true: GPU Feature Discovery ラベルを有効にします (nvidia.com/gpu.productnvidia.com/gpu.memory など)

NVIDIA デバイスプラグインがインストールされていることを確認します。一致するラベルを持つ GPU NodePool がプロビジョニングされるまで、デバイスプラグインポッドはゼロであることが想定されています。

kubectl get daemonset nvidia-device-plugin -n kube-system

正常な出力:

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE nvidia-device-plugin 0 0 0 0 0 amiFamily=al2023 2m5s

次に、汎用 NodePool を作成します。system マネージドノードグループは、アドオンとコントローラーを実行します。汎用 Karpenter NodePoolを追加して、非 GPU ワークロードが system ノードにランディングすることなくオンデマンドでスケーリングできるようにします。GPU NodePoolステップ 2 で後ほど作成されます。

汎用 EC2NodeClass および NodePool YAML

cat << EOF | kubectl apply -f - apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: general-purpose spec: role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} securityGroupSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} tags: karpenter.sh/discovery: ${CLUSTER_NAME} --- apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: general-purpose spec: template: spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: general-purpose requirements: - key: karpenter.sh/capacity-type operator: In values: ["on-demand"] - key: karpenter.k8s.aws/instance-category operator: In values: ["c", "m", "r"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["4"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 1000Gi EOF

この NodePool にはテイントがないため、GPU テイントを許容しない Pod はこの NodePool にスケジュールできます。

デフォルトの StorageClass を作成する

GPU ワークロードでは、多くの場合、モデルの重みをキャッシュするなど、永続ストレージが必要になります。これにより、Kubernetes はポッドを再起動するたびに再ダウンロードする必要がなくなります。Amazon EBS CSI ドライバーは、このステップの前半でクラスター設定の addons: ブロックによって既にインストールされているため、StorageClass を作成するだけで済みます。

cat << EOF | kubectl apply -f - apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: gp3 annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: ebs.csi.aws.com volumeBindingMode: WaitForFirstConsumer parameters: type: gp3 encrypted: "true" EOF

このコマンドは gp3 StorageClass を作成し、storageclass.kubernetes.io/is-default-class 注釈でクラスターのデフォルトとしてマークします。storageClassName を省略した PersistentVolumeClaim は、この StorageClass を使用します。volumeBindingMode: WaitForFirstConsumer 設定は、Kubernetes がポッドをスケジュールするまでボリュームの作成を遅らせるため、EBS ボリュームはポッドと同じアベイラビリティーゾーンに配置されます。

警告

EKS Auto Mode パスとセルフマネージド Karpenter パスの両方において、ノードの自動修復は NodePools によってプロビジョニングされたノードでも同じように動作します。EKS Auto Mode と Karpenter の自動ノード修復は、PodDisruptionBudgets、karpenter.sh/do-not-disrupt 注釈、および terminationGracePeriod をバイパスする強力な中断方法です。自動ノード修復は、AcceleratedHardwareReady 条件が False に設定されたノードについては置き換えまで 10 分待機し、他の修復条件については 30 分待機します。

ロードバランシングを設定する

このガイドの後のステップでは、AWS Application Load Balancer (ALB) を介して Grafana (および推論ウォークスルーではモデルエンドポイント) を公開します。ロードバランシングの前提条件を今すぐセットアップして、これらのセクションがそれ以上のセットアップなしで Ingress を作成できるようにします。

ALB は、AWS リソースタグに基づいて VPC サブネットに配置されます。インターネット向けロードバランサーに使用されるパブリックサブネットには kubernetes.io/role/elb = 1 のタグを付け、内部ロードバランサーに使用されるプライベートサブネットには kubernetes.io/role/internal-elb = 1 のタグを付ける必要があります。このクラスターを eksctl で作成したため、これらのタグは eksctl が作成したサブネットに既に存在します。独自の VPC またはインポートされたサブネットを持ち込む場合は、手動でそれらにタグ付けします。詳細については、「EKS Auto Mode のサブネットにタグを付ける」を参照してください。

ロードバランサー IngressClass を作成する

残りのセットアップはパスによって異なります。EKS Auto Mode には組み込みの ALB コントローラーが含まれているため、IngressClass を自分で作成します。セルフマネージド Karpenter では、Helm で AWS Load Balancer Controller をインストールする必要があります。Helm チャートによって IngressClass が自動的に作成されます。

EKS Auto Mode

EKS Auto Mode には組み込みの ALB コントローラーが含まれているため、追加のコンポーネントをインストールする必要はありません。組み込みコントローラーを指す alb という名前の IngressClass を作成します。後で作成する各 Ingress は、このクラスを名前で参照し、注釈を使用して独自のスキームやその他のオプションを設定します。

cat << EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: alb spec: controller: eks.amazonaws.com/alb EOF
Self-managed Karpenter

AWS Load Balancer Controller は EKS マネージドアドオンではないため、EBS CSI ドライバーと同じように eksctl クラスター設定 addons: ブロックに入ることはできません。Helm を使用してそれをインストールします。

IAM ポリシーをダウンロードします

コントローラーには、ALB を作成および管理するための IAM アクセス許可が必要です。公式 IAM ポリシー JSON をダウンロードします。

curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json

IAM ポリシーを作成します。

aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json

Pod Identity の関連付けを作成します

クラスターはステップ 1eks-pod-identity-agent アドオンを既にインストールしているため、EKS Pod Identity を使用できます。IAM ポリシーをコントローラーのサービスアカウントにバインドする Pod Identity 関連付けを作成します。

eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --region ${AWS_REGION} \ --namespace kube-system \ --service-account-name aws-load-balancer-controller \ --permission-policy-arns arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):policy/AWSLoadBalancerControllerIAMPolicy

Helm を使用してインストールする

EKS チャート Helm リポジトリを追加します。

helm repo add eks https://aws.github.io/eks-charts helm repo update

クラスターの VPC ID を検索します。Helm 値は、コントローラーがサブネットを検出できるようにするために必要です。

VPC_ID=$(aws eks describe-cluster \ --name ${CLUSTER_NAME} \ --region ${AWS_REGION} \ --query 'cluster.resourcesVpcConfig.vpcId' \ --output text)

Load Balancer Controller をインストールします。nodeSelector と許容値は、GPU または汎用 Karpenter 起動ノードとキャパシティを競合するのではなく、クラスタークリティカルなインフラストラクチャとともに system マネージドノードグループにコントローラーを配置します。

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ --namespace kube-system \ --version 3.4.2 \ --set clusterName=${CLUSTER_NAME} \ --set region=${AWS_REGION} \ --set vpcId=${VPC_ID} \ --set serviceAccount.create=true \ --set serviceAccount.name=aws-load-balancer-controller \ --set "nodeSelector.node-role=system" \ --set "tolerations[0].key=CriticalAddonsOnly" \ --set "tolerations[0].operator=Exists"

コントローラーが実行されていることを確認します。使用可能な 2 つのレプリカをレポートする必要があります。

kubectl get deployment aws-load-balancer-controller -n kube-system

IngressClass を検証する

Helm チャートは、alb という名前の IngressClass をコントローラーのインストールの一部として作成し、セルフマネージドコントローラー ingress.k8s.aws/alb を指しています。手動で作成する必要はありません。それが存在することを確認します:

kubectl get ingressclass alb

正常な出力:

NAME CONTROLLER PARAMETERS AGE alb ingress.k8s.aws/alb <none> 22s

両方のパスに alb IngressClass が追加されました。Grafana および推論セクションは ingressClassName: alb を参照し、Ingress ごとの注釈を通じて ALB スキーム、送信元 IP 許可リスト、およびその他の動作を設定します。

ステップ 2: 動的 GPU NodePool を作成する

スポットキャパシティをオンデマンドをフォールバックとして使用して、生成が 4 を超え 7 未満の G ファミリー GPU インスタンスを動的にプロビジョニングする NodePool を定義します。EKS Auto Mode パスと Karpenter パスはどちらも同じ NodePool API を使用しますが、唯一の違いはそれが指す NodeClass です。EKS Auto Mode では、バンドルされた default NodeClass は既に適切な AMI を選択し、SOCI 並列プルを設定しているため、NodePool は作成する唯一のオブジェクトです。セルフマネージド Karpenter では、AMI を固定して SOCI を調整するカスタム EC2NodeClass も必要です。

重要

G7 EC2 インスタンスタイプには NVIDIA ドライバーバージョン 595 以降が必要です。EKS 最適化高速 AMI には現在、G7 インスタンスをサポートしていない NVIDIA ドライバーバージョン 580 が含まれています。このステップの NodePool は、Karpenter が G7 インスタンスを選択しないように、インスタンスの世代を 7 未満に制限します。Amazon EKS で G7 インスタンスを使用するには、NVIDIA ドライバーバージョン 595 でカスタム AMI を構築する必要があります。詳細については、「GPU インスタンス向けに EKS 最適化高速 AMI を使用する」を参照してください。

EKS Auto Mode

EKS Auto Mode では、バンドルされた default NodeClass は GPU インスタンスの Bottlerocket AMI を自動的に選択します。これには、プリインストールされた NVIDIA ドライバー、NVIDIA デバイスプラグイン、SOCI 並列プルが含まれます。default NodeClass を参照する NodePool を適用するだけです。

cat << 'EOF' | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs spec: nodeClassRef: group: eks.amazonaws.com kind: NodeClass name: default taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand"] - key: eks.amazonaws.com/instance-category operator: In values: ["g"] - key: eks.amazonaws.com/instance-generation operator: Gt values: ["4"] - key: eks.amazonaws.com/instance-generation operator: Lt values: ["7"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

この NodePool は、生成が 4 より大きく 7 より小さい G ファミリー GPU インスタンス (G5G6e など) をプロビジョニングします。EKS Auto Mode は、これらの制約内でインスタンスタイプを選択します。

Self-managed Karpenter

セルフマネージド Karpenter には、デフォルトの NodeClass は含まれません。まず、EKS 最適化 NVIDIA AL2023 AMI エイリアスを固定し、FastImagePull 機能ゲートを介して SOCI を有効にし、コンテナ化されたイメージキャッシュをローカル NVMe に移動するように instanceStorePolicy: RAID0 を設定する EC2NodeClass を作成します。次に、それを参照する NodePool を作成します。

EC2NodeClass を作成する

cat << EOF | kubectl apply -f - apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: gpu-inf labels: guide: ai-eks-docs spec: role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} securityGroupSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} tags: karpenter.sh/discovery: ${CLUSTER_NAME} instanceStorePolicy: RAID0 userData: | apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: featureGates: FastImagePull: true EOF

instanceStorePolicy: RAID0 はローカル NVMe ディスクを RAID-0 アレイにアセンブルします。al2023@latest AMI エイリアスは EKS 最適化 AL2023 AMI に解決されます。Karpenter が GPU インスタンスタイプを起動すると、プリインストールされている NVIDIA ドライバーを含む AL2023_x86_64_NVIDIA 高速バリアントが自動的に選択されます。

FastImagePull 機能ゲートは、イメージレイヤーを同時にダウンロードおよび解凍する SOCI スナップショッター並列プルモードを有効にします。これは、G、P、および Trn インスタンスファミリーの EKS Auto Mode の動作と一致します。

その他の SOCI チューニングオプション (イメージあたりの同時ダウンロード数、チャンクサイズなど) については、Karpenter SOCI 設計図を参照してください。

EC2NodeClass を検証します。

kubectl get ec2nodeclass gpu-inf

正常な出力: READY TrueFalse の場合は、kubectl describe ec2nodeclass gpu-inf を実行し、サブネットタグまたはセキュリティグループタグがないかどうか条件を確認します。

GPU NodePool を作成する

cat << EOF | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs amiFamily: al2023 spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: gpu-inf taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand"] - key: karpenter.k8s.aws/instance-category operator: In values: ["g"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["4"] - key: karpenter.k8s.aws/instance-generation operator: Lt values: ["7"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

ノードテンプレートの amiFamily: al2023 ラベルは、NVIDIA デバイスプラグイン DaemonSet がこれらのノードを選択するために使用するものです。Karpenter は、これらの制約内でインスタンスタイプを選択します。nvidia.com/gpu:NoSchedule テイントにより、GPU 対応ポッドのみがこれらのノードでスケジュールされます。

NodePool が作成されたことを確認します。

kubectl get nodepool gpu-inf

正常な出力:

NAME NODECLASS NODES READY AGE gpu-inf default 0 True 8s

セルフマネージド Karpenter パスでは、NODECLASS 列に default ではなく gpu-inf が表示されます。

ステップ 3: サンプルポッドでテストする

nvidia-smi ポッドを使用して GPU NodePool のセットアップをテストします。

cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nvidia-smi labels: guide: ai-eks-docs spec: tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["nvidia-smi"] resources: limits: nvidia.com/gpu: 1 restartPolicy: OnFailure EOF

ポッドがスケジュールされ、正常に完了していることを確認します。

kubectl get pods

正常な出力:

NAME READY STATUS RESTARTS AGE nvidia-smi 0/1 Completed 0 67s

STATUS: Completed は、nvidia-smi コマンドが実行され、終了したことを意味します。ポッドログをチェックして、ノードによって検出された GPU を確認します。

kubectl logs nvidia-smi

正常な出力:

+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.159.03 Driver Version: 580.159.03 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA L4 On | 00000000:35:00.0 Off | 0 | | N/A 42C P8 16W / 72W | 0MiB / 23034MiB | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+

出力には、GPU モデル、ドライバーバージョン、CUDA バージョン、利用可能なメモリが表示されます。この例では、Karpenter は 24 GB のメモリを持つ NVIDIA L4 GPU を持つ G6 インスタンスをプロビジョニングしました。42C は現在の GPU 温度で、P8 は低電力アイドル状態です。これは、ワークロードが GPU を使用していないため、予想される状態です。16W/72W は現在の電力消費量と最大電力容量を示し、0MiB/23034MiB は現在の GPU メモリ使用量と利用可能な合計を示します。ポッドは nvidia-smi を実行して終了しただけなので、GPU を使用するワークロードはありません。そのため、メモリは 0 で、電力はアイドル状態です。NVIDIA GPU ドライバーバージョン (580.159.03) は Bottlerocket AMI から、CUDA バージョン (13.0) はコンテナイメージから取得されます。GPU モデルとメモリは、Karpenter が選択するインスタンスタイプによって異なります。G5 インスタンスには NVIDIA A10G GPU (24 GB)、G6 インスタンスには NVIDIA L4 GPU (24 GB)、G6e インスタンスには NVIDIA L40S GPU (48 GB) があります。

Karpenter と Kubernetes スケジューラがどのように連携してノードをプロビジョニングし、ポッドを配置したかを理解するには、ポッドのライフサイクルイベントを確認します。

kubectl describe po nvidia-smi

正常な出力:

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 60s default-scheduler 0/2 nodes are available: 2 node(s) had untolerated taint(s). no new claims to deallocate, preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling. Normal Nominated 59s eks-auto-mode/compute Pod should schedule on: nodeclaim/gpu-inf-vxcnj Normal Scheduled 24s default-scheduler Successfully assigned default/nvidia-smi to i-0fb17a09bc4203164 Warning FailedCreatePodSandBox 21s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "7f85e25b220c8fb245187758dbbbc8efb3d40f3e49e13054404880daf4c3b2f0": plugin type="aws-cni" name="aws-cni" failed (add): add cmd: failed to setup network policy Normal Pulling 7s kubelet spec.containers{nvidia-smi}: Pulling image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" Normal Pulled 5s kubelet spec.containers{nvidia-smi}: Successfully pulled image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" in 1.237s (1.237s including waiting). Image size: 37442701 bytes. Normal Created 5s kubelet spec.containers{nvidia-smi}: Container created Normal Started 5s kubelet spec.containers{nvidia-smi}: Container started

これらのイベントは、ポッドスケジューリングシーケンスを示しています。まず、GPU ノードが存在しないため、ポッドはスケジュールに失敗します (FailedScheduling)。Karpenter が新しい NodeClaim をノミネートします (Nominated)。ノードが準備完了になるとスケジューラがポッドを割り当てます (Scheduled)。その後、コンテナイメージがプルされて起動します。EKS Auto Mode には、SOCI (Seekable OCI) 並列プルが最初からインストールされ、G、P、および Trn インスタンスでそのまま使用できるように設定されています。SOCI 並列プルのため、コンテナイメージは 2 秒未満 (1.237 秒) で ECR からプルされたことに注意してください。

NodeClaim は、Karpenter が特定のノードをプロビジョニングするために作成するリクエストです。インスタンスタイプ、キャパシティタイプ、AZ、ノードの準備が整っているかどうかが表示されます。

kubectl get nodeclaims

予想される NodeClaim 出力:

NAME            TYPE         CAPACITY   ZONE         NODE                  READY   AGE
gpu-inf-vxcnj   g6.4xlarge   spot       us-east-2c   i-0fb17a09bc4203164   True    51s

インスタンスタイプと AZ は異なります。世代が 4 より大きく 7 より小さい G ファミリーインスタンスが対象です。

kubectl describe pod nvidia-smi における FailedCreatePodSandBox 警告は一時的なものであり、想定された動作です。VPC CNI はノードの結合後に非同期的に初期化し、kubelet は自動的に再試行します。ポッドが ContainerCreating の状態のままである場合は、kubectl describe node <node-name> でノードイベントを確認します。

ヒント

ノードが表示されない場合は、容量不足エラーを確認します。

kubectl get events | grep InsufficientCapacityError

Karpenter は、使用できないサービスを 3 分間キャッシュします。NodePool で許可されたインスタンスタイプと AZ を拡張すると、ランディングキャパシティの可能性が高まります。

注記

Karpenter によって起動されたスポットインスタンスは EC2 スポットリクエストコンソールに表示されません。Karpenter は type: instant で EC2 CreateFleet API を使用します。インスタンスは、spot ライフサイクルとともに EC2 インスタンスコンソールに表示されます。

ステップ 4: NodePool にリザーブドキャパシティを追加する (オプション)

スポット/オンデマンドフォールバックで最初にリザーブドキャパシティを使用するには、オンデマンドキャパシティ予約 (ODCR) を作成して NodeClass にアタッチし、ステップ 2 の動的 NodePool を更新して reserved キャパシティも許可します。予約 API コールは両方のパスで同じです。EKS Auto Mode とセルフマネージド Karpenter は異なる NodeClass タイプを使用するため、NodeClass アタッチメントは異なります。

警告

以下のコマンドを実行すると、aws ec2 cancel-capacity-reservation --capacity-reservation-id <id> でキャンセルするまで、リザーブドインスタンスタイプの料金が発生します。

キャパシティ予約を作成する:

CR_AZ="us-east-2a" INSTANCE_TYPE="g6e.4xlarge" aws ec2 create-capacity-reservation \ --instance-type $INSTANCE_TYPE \ --instance-platform Linux/UNIX \ --availability-zone "$CR_AZ" \ --instance-count 1 \ --instance-match-criteria open \ --end-date-type unlimited

InsufficientInstanceCapacity エラーが発生した場合は、CR_AZ を別の AZ に変更して再試行します。

キャパシティ予約 ID を検索し、以下のステップでシェル変数に保存します。

CAPACITY_RESERVATION_ID=$(aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=instance-type,Values=${INSTANCE_TYPE}" \ --query 'CapacityReservations[0].CapacityReservationId' \ --output text \ --region ${AWS_REGION}) echo "Capacity reservation ID: ${CAPACITY_RESERVATION_ID}"

次に、パスに NodeClass と NodePool の変更を適用します。

EKS Auto Mode

EKS Auto Mode では、バンドルされた default NodeClass は読み取り専用であるため、予約を参照するカスタム NodeClass を作成し、NodeClass を指すように NodePool を更新して、capacity-type リストに reserved キャパシティを追加します。

例カスタム NodeClass YAML
NODE_ROLE=$(kubectl get nodeclass default -o jsonpath='{.spec.role}') cat << EOF | kubectl apply -f - apiVersion: eks.amazonaws.com/v1 kind: NodeClass metadata: name: gpu-inf labels: guide: ai-eks-docs spec: role: "$NODE_ROLE" subnetSelectorTerms: - tags: alpha.eksctl.io/cluster-name: "$CLUSTER_NAME" kubernetes.io/role/internal-elb: "1" securityGroupSelectorTerms: - tags: aws:eks:cluster-name: "$CLUSTER_NAME" capacityReservationSelectorTerms: - id: "$CAPACITY_RESERVATION_ID" EOF

kubernetes.io/role/internal-elb: "1" タグにより、ノードはプライベートサブネットでのみ起動されます。

NodePool を更新して ODCR-backed NodeClass を使用し、キャパシティタイプとして reserved を含めます。

例更新された NodePool YAML
cat << EOF | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs spec: nodeClassRef: group: eks.amazonaws.com kind: NodeClass name: gpu-inf taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand", "reserved"] - key: eks.amazonaws.com/instance-category operator: In values: ["g"] - key: eks.amazonaws.com/instance-generation operator: Gt values: ["4"] - key: eks.amazonaws.com/instance-generation operator: Lt values: ["7"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF
Self-managed Karpenter

セルフマネージド Karpenter の場合は、ステップ 2 で作成した EC2NodeClasscapacityReservationSelectorTerms を追加して再適用します。フィールド名と構造は、もう一方のタブに表示されている EKS Auto Mode NodeClass と一致します。

例更新された EC2NodeClass YAML
cat << EOF | kubectl apply -f - apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: gpu-inf labels: guide: ai-eks-docs spec: role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} securityGroupSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} tags: karpenter.sh/discovery: ${CLUSTER_NAME} instanceStorePolicy: RAID0 capacityReservationSelectorTerms: - id: "$CAPACITY_RESERVATION_ID" userData: | apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: featureGates: FastImagePull: true EOF

ステップ 2 からの変更点は、新しい capacityReservationSelectorTerms フィールドのみです。他のすべてのフィールドは同じままです。

NodePool を更新して、キャパシティタイプとして reserved を含めます。

例更新された NodePool YAML
cat << EOF | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inf spec: template: metadata: labels: guide: ai-eks-docs amiFamily: al2023 spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: gpu-inf taints: - key: nvidia.com/gpu effect: NoSchedule requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand", "reserved"] - key: karpenter.k8s.aws/instance-category operator: In values: ["g"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["4"] - key: karpenter.k8s.aws/instance-generation operator: Lt values: ["7"] - key: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

Karpenter は、reserved を最もコスト効率の高いオプションとして扱い、最初に起動します。予約がいっぱいになると、スポットまたはオンデマンドにフォールバックします。

変更を適用したら、Karpenter がリザーブドキャパシティを優先し、スポットまたはオンデマンドにフォールバックすることを確認します。ポッドごとに 1 GPU をリクエストする 2 レプリカデプロイをデプロイします。ODCR は 1 インスタンス用であるため、最初のポッドは Karpenter をトリガーしてリザーブドノードを起動します。2 番目のポッドはリザーブドノードに収まらず、Karpenter がスポットキャパシティまたはオンデマンドキャパシティから別のノードを起動するようにトリガーします。

cat << 'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: gpu-overflow-test labels: guide: ai-eks-docs spec: replicas: 2 selector: matchLabels: app: gpu-overflow-test template: metadata: labels: app: gpu-overflow-test guide: ai-eks-docs spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["sh", "-c", "nvidia-smi && sleep infinity"] resources: limits: nvidia.com/gpu: 1 EOF

実行して終了したステップ 3 の nvidia-smi テストポッドとは異なり、このデプロイではポッドの実行 (sleep infinity) が維持されるため、ポッドは GPU を保持し、ノードを解放しません。

異なるノードでスケジュールされたポッドを確認します。

kubectl get pods -l app=gpu-overflow-test -o wide

正常な出力:

NAME                                 READY   STATUS    RESTARTS   AGE     IP                NODE                  NOMINATED NODE   READINESS GATES
gpu-overflow-test-59b97944fb-lq56c   1/1     Running   0          2m42s   192.168.186.240   i-057692590480155da   <none>           <none>
gpu-overflow-test-59b97944fb-z4zcx   1/1     Running   0          2m42s   192.168.130.64    i-0521ecd1849fa0578   <none>           <none>

2 つのポッドがそれぞれ異なるノードで実行されています。

NodeClaims でキャパシティタイプを確認します。

kubectl get nodeclaims

正常な出力:

NAME            TYPE          CAPACITY    ZONE         NODE                  READY   AGE
gpu-inf-shg5w   g6e.xlarge    reserved    us-east-2a   i-0ea91fdeef65b8cb6   True    2m2s
gpu-inf-ssnqf   g6e.2xlarge   spot        us-east-2b   i-00ccf7ce65cf3f6ca   True    112s

予約ノードが最初に起動され、その後に予約がいっぱいになるとスポットノードまたはオンデマンドノードが起動されます。

テストデプロイをクリーンアップする:

kubectl delete deployment gpu-overflow-test

モニタリング

クラスター、ノード、GPU メトリクスを収集するモニタリングスタックを Amazon Managed Service for Prometheus (AMP) にインストールし、Grafana で視覚化します。kube-prometheus-stack Helm チャートは、Prometheus をデプロイしてメトリクスを AMP にスクレイプおよびリモート書き込みし、ダッシュボード用のセルフマネージド Grafana もデプロイします。NVIDIA DCGM Exporter は GPU 固有のメトリクス (使用率、メモリ、温度、電力、NVLink、テンソルアクティビティ) を追加します。

Prometheus、Grafana、およびオペレーターは、GPU ノードに nvidia.com/gpu:NoSchedule テイントがあるため、デフォルトで非 GPU ノードに配置されます。Node-exporter と DCGM Exporter はどちらも GPU ノードで実行されるため、ホストメトリクスと GPU メトリクスをフリート全体でスクレイプできます。

新しいターミナルを開いた場合は、クラスター名とリージョンを設定します。

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

AMP ワークスペースを作成する

メトリクスを保存する AMP ワークスペースを作成します。

aws amp create-workspace \ --alias "amp-ws-${CLUSTER_NAME}" \ --region ${AWS_REGION}

ワークスペース ID を取得します。

AMP_WORKSPACE_ID=$(aws amp list-workspaces \ --alias "amp-ws-${CLUSTER_NAME}" \ --query 'workspaces[0].workspaceId' \ --output text \ --region ${AWS_REGION}) echo "AMP Workspace ID: ${AMP_WORKSPACE_ID}"

リモート書き込みエンドポイントを取得します。

AMP_ENDPOINT=$(aws amp describe-workspace \ --workspace-id ${AMP_WORKSPACE_ID} \ --query 'workspace.prometheusEndpoint' \ --output text \ --region ${AWS_REGION}) echo "AMP Endpoint: ${AMP_ENDPOINT}"

IAM ポリシーと EKS Pod Identity の関連付けを作成する

Prometheus がメトリクスをリモート書き込みし、Grafana がメトリクスをクエリできるようにする IAM ポリシーを作成します。

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) AMP_POLICY_ARN=$(aws iam create-policy \ --policy-name "${CLUSTER_NAME}-amp-grafana-policy" \ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Sid\": \"AllowAMPReadWrite\", \"Effect\": \"Allow\", \"Action\": [\"aps:ListWorkspaces\", \"aps:DescribeWorkspace\", \"aps:GetMetricMetadata\", \"aps:GetSeries\", \"aps:QueryMetrics\", \"aps:RemoteWrite\", \"aps:GetLabels\"], \"Resource\": \"arn:aws:aps:${AWS_REGION}:${ACCOUNT_ID}:workspace/*\"}, {\"Sid\": \"AllowCloudWatchMetrics\", \"Effect\": \"Allow\", \"Action\": [\"cloudwatch:DescribeAlarmsForMetric\", \"cloudwatch:ListMetrics\", \"cloudwatch:GetMetricData\", \"cloudwatch:GetMetricStatistics\"], \"Resource\": \"*\"}]}" \ --query 'Policy.Arn' \ --output text) echo "AMP Policy ARN: ${AMP_POLICY_ARN}"

Prometheus と Grafana のモニタリング名前空間とサービスアカウントを作成します。

kubectl create namespace monitoring kubectl create serviceaccount amp-iamproxy-ingest-service-account -n monitoring kubectl create serviceaccount grafana-sa -n monitoring

EKS Pod Identity の関連付けを作成して、サービスアカウントを IAM ポリシーにリンクします。

eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name amp-iamproxy-ingest-service-account \ --role-name "${CLUSTER_NAME}-amp-ingest-role" \ --permission-policy-arns ${AMP_POLICY_ARN} \ --region ${AWS_REGION} eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name grafana-sa \ --role-name "${CLUSTER_NAME}-grafana-role" \ --permission-policy-arns ${AMP_POLICY_ARN} \ --region ${AWS_REGION}

両方の EKS Pod Identity の関連付けが作成されていることを確認します。

eksctl get podidentityassociation --cluster ${CLUSTER_NAME} --region ${AWS_REGION}

予想される出力には、monitoring 名前空間に amp-iamproxy-ingest-service-accountgrafana-sa の両方を含める必要があります。

kube-prometheus-stack をインストールする

Helm リポジトリを追加します。

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update

この値ファイルは、Prometheus、Grafana、およびオペレーターの nodeSelector を省略します。GPU ノードの nvidia.com/gpu:NoSchedule テイントは GPU ノードからそれらを保持するため、デフォルトでシステムまたは汎用プールに配置されます。Node-exporter はワイルドカード許容範囲を使用するため、GPU ノードを含むすべてのノードで実行され、フリート全体でメトリクスを収集します。

値ファイルでは、[ロードバランシングを設定する] で作成した alb IngressClass を使用して、ブラウザアクセス用にインターネット向け ALB をプロビジョニングするように Grafana Ingressも設定されます。alb.ingress.kubernetes.io/inbound-cidrs 注釈はロードバランサーを独自の IP アドレスに制限するので、インストールする前に設定します。

Grafana は、デフォルトの認証情報を使用して HTTP 経由でパブリックにアクセス可能です

Grafana にはデフォルトの管理者認証情報が含まれており、モニタリングデータへの完全な管理アクセスを提供します。インターネット向けロードバランサーは、このインターフェイスをプレーンテキスト HTTP 経由でパブリックインターネットに配置します。自動スキャナーは、数分以内にパブリックロードバランサーを検出します。alb.ingress.kubernetes.io/inbound-cidrs 注釈を使用してアクセスを制限し、送信元 IP 許可リストは完全な保護ではなく、最小限の保護として扱う必要があります。また、デフォルトの Grafana 管理者パスワードも変更します。体制を強化するには、スキームを internal に設定して内部スキーム (VPC または接続された VPN 内からのみ到達可能) を使用し、TLS 証明書を追加します。

パブリック IP アドレスを検索し、/32 CIDR として保存します。値ファイルは、MY_CIDR 環境変数からこれを読み取ります:

export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32" echo $MY_CIDR

結果は 203.0.113.4/32 のようになります。ネットワークがアドレスを動的に割り当てる場合、IP アドレスは時間の経過とともに変化する可能性があるため、203.0.113.0/24 などのより広い範囲を設定することを検討してください。

値ファイルを作成します。

例 kube-prometheus-stack 値ファイル
cat << EOF > /tmp/kube-prometheus-values.yaml alertmanager: enabled: false prometheus-adapter: enabled: false prometheus: serviceAccount: create: false name: amp-iamproxy-ingest-service-account prometheusSpec: serviceAccountName: amp-iamproxy-ingest-service-account enableRemoteWriteReceiver: true retention: 2h scrapeInterval: 30s evaluationInterval: 30s podMonitorSelectorNilUsesHelmValues: false serviceMonitorSelectorNilUsesHelmValues: false resources: requests: cpu: 500m memory: 1Gi limits: memory: 8Gi remoteWrite: - url: "${AMP_ENDPOINT}api/v1/remote_write" sigv4: region: "${AWS_REGION}" queueConfig: maxSamplesPerSend: 1000 maxShards: 200 capacity: 2500 prometheusOperator: resources: requests: cpu: 100m memory: 128Mi limits: memory: 256Mi kube-state-metrics: resources: requests: cpu: 50m memory: 128Mi limits: memory: 512Mi grafana: enabled: true ingress: enabled: true ingressClassName: alb labels: guide: ai-eks-docs annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/inbound-cidrs: ${MY_CIDR} alb.ingress.kubernetes.io/load-balancer-name: grafana-ai-eks-docs alb.ingress.kubernetes.io/healthcheck-path: /api/health serviceAccount: create: false name: grafana-sa resources: requests: cpu: 100m memory: 256Mi limits: memory: 1Gi grafana.ini: auth.sigv4: enabled: true sidecar: datasources: defaultDatasourceEnabled: false plugins: - grafana-amazonprometheus-datasource additionalDataSources: - name: Amazon-Managed-Prometheus type: grafana-amazonprometheus-datasource access: proxy url: "${AMP_ENDPOINT}" isDefault: true jsonData: sigV4Auth: true defaultRegion: "${AWS_REGION}" sigV4Region: "${AWS_REGION}" editable: true dashboardProviders: dashboardproviders.yaml: apiVersion: 1 providers: - name: default orgId: 1 folder: 'GPU Monitoring' type: file disableDeletion: false editable: true options: path: /var/lib/grafana/dashboards/default dashboards: default: nvidia-dcgm: gnetId: 25261 revision: 1 datasource: - name: DS_PROMETHEUS value: Amazon-Managed-Prometheus vllm: gnetId: 25263 revision: 1 datasource: - name: DS_PROMETHEUS value: Amazon-Managed-Prometheus vllm-load-analysis: gnetId: 25494 revision: 1 datasource: - name: DS_PROMETHEUS value: Amazon-Managed-Prometheus prometheus-node-exporter: resources: requests: cpu: 50m memory: 64Mi limits: memory: 128Mi tolerations: - operator: Exists EOF

変数が正しく入力されたことを確認します。

grep -E "url:|region:" /tmp/kube-prometheus-values.yaml

完全な AMP エンドポイント URL (https://aps-workspaces…​ で始まる) とリージョンが表示されます。いずれかが空の場合は、変数を再エクスポートしてファイルを再作成します。

チャートをインストールします。

helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \ --namespace monitoring \ -f /tmp/kube-prometheus-values.yaml

ポッドが実行中であることを確認します。

kubectl get pods -n monitoring

正常な出力:

NAME                                                       READY   STATUS    RESTARTS   AGE
kube-prometheus-stack-grafana-7c58f54f77-rftrj             3/3     Running   0          4m
kube-prometheus-stack-kube-state-metrics-d68dcbc84-5smxq   1/1     Running   0          4m
kube-prometheus-stack-operator-5895df479f-ttm47            1/1     Running   0          4m
kube-prometheus-stack-prometheus-node-exporter-t9q7s       1/1     Running   0          4m
kube-prometheus-stack-prometheus-node-exporter-x6vfb       1/1     Running   0          4m
prometheus-kube-prometheus-stack-prometheus-0              2/2     Running   0          4m

スタックは、以下のコンポーネントをデプロイします。

  • Prometheus (StatefulSet): メトリクスをスクレイプし、AMP にリモート書き込みします

  • Grafana: ダッシュボードと視覚化、AMP データソースで事前設定済み

  • kube-state-metrics: Kubernetes オブジェクトの状態 (ポッドのステータス、リソースリクエスト/制限、NodeClaim の状態) に関するメトリクスを生成します

  • node-exporter (DaemonSet、ノードごとに 1 つ): ホストレベルのメトリクス (CPU、メモリ、ディスク、ネットワーク) を収集します

  • オペレーター: Prometheus とアラートマネージャーのカスタムリソースを管理します

この設定ではアラートマネージャーが無効になっています。

Grafana にアクセスする

インターネット向け AWS Application Load Balancer (ALB) を介して Grafana にアクセスします。ここでは作成しません。kube-prometheus-stack チャートは、Set up load balancingalb IngressClass を使用して、値ファイルgrafana.ingress 設定からプロビジョニングします。Grafana Helm チャートには組み込みの Ingress サポートがあるため、個別のマニフェストは必要ありません。ALB は grafana-ai-eks-docs という名前で、ラベル guide: ai-eks-docs を持ち、インストール時に MY_CIDR で設定した IP アドレスに制限されます。

Grafana ALB ターゲットグループにはヘルスチェックパスが必要です

値ファイルの alb.ingress.kubernetes.io/healthcheck-path 注釈は、ロードバランサーのヘルスチェックを Grafana の /api/health エンドポイントに向け、200 を返します。これがないと、ALB ヘルスチェックはデフォルトで / になり、Grafana は /login への 302 リダイレクトで応答し、ターゲットグループはエンドポイントを異常としてレポートします。

ロードバランサー URL を指します。ロードバランサーは非同期で作成されるため、1~2 分かかります。

echo "http://$(kubectl get ingress kube-prometheus-stack-grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')"

ブラウザで URL を開きます。以下のコマンドからユーザー名 admin とパスワードを使用してログインします。

kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo

メトリクスパイプラインがエンドツーエンドで機能していることを確認するには:

  1. [接続] > [データソース] に移動し、Amazon-Managed-Prometheus がデフォルトのデータソースとしてリストされていることを確認します。

    Grafana で AMP データソースを検証する

    Amazon-Managed-Prometheus がデフォルトのデータソースとしてリストされている Grafana Connections ページ
  2. [ドリルダウン] > [メトリクス] に移動し、up メトリクスを検索します。クラスターのスクレイプターゲットの結果が表示されます。

    Grafana で up メトリクスを検証する

    アクティブなスクレイプターゲットを示す緑色のステータスバーが付いたアップメトリクスが表示された Grafana ドリルダウンメトリクスページ

up が結果を表示する場合、パイプライン (クラスター → Prometheus → AMP → Grafana) は機能しています。

GPU メトリクス用の DCGM Exporter をデプロイする

kube-prometheus-stack はノードレベルの CPU メトリクスとメモリメトリクスを収集しますが、GPU メトリクスは収集しません。NVIDIA DCGM Exporter は、GPU 使用率、メモリ使用量、温度、消費電力、NVLink 帯域幅、テンソルアクティビティを追加します。

helm repo add gpu-helm-charts https://nvidia.github.io/dcgm-exporter/helm-charts helm repo update

パスの GPU ノードセレクタキーを設定します。EKS Auto Mode とセルフマネージド Karpenter は、GPU 製造元に異なるラベルキーを使用します。

EKS Auto Mode
GPU_NODE_SELECTOR_KEY="eks.amazonaws.com/instance-gpu-manufacturer"
Self-managed Karpenter
GPU_NODE_SELECTOR_KEY="karpenter.k8s.aws/instance-gpu-manufacturer"

DCGM Exporter 値ファイルを作成します。

例 dcgm-exporter 値ファイル
cat << EOF > /tmp/dcgm-exporter-values.yaml resources: requests: memory: "512Mi" cpu: "100m" limits: memory: "1Gi" cpu: "500m" serviceMonitor: enabled: true additionalLabels: release: kube-prometheus-stack nodeSelector: ${GPU_NODE_SELECTOR_KEY}: nvidia tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" customMetrics: | # Clocks DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency (in MHz). DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz). # Temperature DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature (in C). DCGM_FI_DEV_GPU_TEMP, gauge, GPU temperature (in C). # Power DCGM_FI_DEV_POWER_USAGE, gauge, Power draw (in W). DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION, counter, Total energy consumption since boot (in mJ). # PCIe DCGM_FI_PROF_PCIE_TX_BYTES, counter, Number of bytes transmitted through PCIe TX (in KB) via NVML. DCGM_FI_PROF_PCIE_RX_BYTES, counter, Number of bytes received through PCIe RX (in KB) via NVML. DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total number of PCIe retries. # Utilization (the sample period varies depending on the product) DCGM_FI_DEV_GPU_UTIL, gauge, GPU utilization (in %). DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory utilization (in %). DCGM_FI_DEV_ENC_UTIL, gauge, Encoder utilization (in %). DCGM_FI_DEV_DEC_UTIL, gauge, Decoder utilization (in %). # Errors and violations DCGM_FI_DEV_XID_ERRORS, gauge, Value of the last XID error encountered. DCGM_EXP_XID_ERRORS_COUNT, gauge, Value of count of XID errors encountered. DCGM_FI_DEV_POWER_VIOLATION, counter, Throttling duration due to power constraints (in us). DCGM_FI_DEV_THERMAL_VIOLATION, counter, Throttling duration due to thermal constraints (in us). DCGM_FI_DEV_SYNC_BOOST_VIOLATION, counter, Throttling duration due to sync-boost constraints (in us). DCGM_FI_DEV_BOARD_LIMIT_VIOLATION, counter, Throttling duration due to board limit constraints (in us). DCGM_FI_DEV_LOW_UTIL_VIOLATION, counter, Throttling duration due to low utilization (in us). DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Throttling duration due to reliability constraints (in us). # Memory usage DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free (in MiB). DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used (in MiB). # Retired pages DCGM_FI_DEV_RETIRED_SBE, counter, Total number of retired pages due to single-bit errors. DCGM_FI_DEV_RETIRED_DBE, counter, Total number of retired pages due to double-bit errors. DCGM_FI_DEV_RETIRED_PENDING, counter, Total number of pages pending retirement. # NVLink DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL, counter, Total number of NVLink bandwidth counters for all lanes. DCGM_FI_PROF_NVLINK_TX_BYTES, counter, The rate of data transmitted over NVLink not including protocol headers in bytes per second. DCGM_FI_PROF_NVLINK_RX_BYTES, counter, The rate of data received over NVLink not including protocol headers in bytes per second. # DCP metrics DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active (in %). DCGM_FI_PROF_SM_ACTIVE, gauge, The ratio of cycles an SM has at least 1 warp assigned (in %). DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident on an SM (in %). DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active (in %). DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of cycles the device memory interface is active sending or receiving data (in %). DCGM_FI_DEV_CLOCK_THROTTLE_REASONS, gauge, Current clock throttle reasons (bitmask of DCGM_CLOCKS_THROTTLE_REASON_*). DCGM_FI_DEV_GPU_NVLINK_ERRORS, gauge, Identifies a GPU NVLink error type returned by DCGM_FI_DEV_GPU_NVLINK_ERRORS. ## NVLink DCGM_FI_DEV_NVLINK_BANDWIDTH_L0, counter, The number of bytes of active NVLink rx or tx data including both header and payload. ## Remapped rows DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for uncorrectable errors. DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for correctable errors. DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, whether remapping of rows has failed. ## Profiling metrics DCGM_FI_PROF_PIPE_FP64_ACTIVE, gauge, Ratio of cycles the fp64 pipes are active (in %). DCGM_FI_PROF_PIPE_FP32_ACTIVE, gauge, Ratio of cycles the fp32 pipes are active (in %). DCGM_FI_PROF_PIPE_FP16_ACTIVE, gauge, Ratio of cycles the fp16 pipes are active (in %). # ECC DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Total number of single-bit volatile ECC errors. DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Total number of double-bit volatile ECC errors. EOF

customMetrics フィールドは、DCGM Exporter のデフォルトメトリクスセットを、NVLink 帯域幅、テンソルアクティビティ、PCIe スループット、ECC エラー、および熱スロットリングを含む拡張メトリクスセットで上書きします。推論ワークロードの場合、これらは GPU コンピューティングユニットが十分に使用されているかどうか、バッチサイズが低いためにリクエスト間で GPU がアイドル状態になっているかどうか、CPU と GPU 間のデータ転送がボトルネックになっているかどうか、熱スロットリングがレイテンシーの急増を引き起こしているかどうか、より大きなバッチを処理するための GPU メモリのヘッドルームがどれだけ残っているかを理解するのに役立ちます。

DCGM Exporter をインストールします。

helm install dcgm-exporter gpu-helm-charts/dcgm-exporter \ --namespace monitoring \ -f /tmp/dcgm-exporter-values.yaml

tolerations は、ステップ 2 でプロビジョニングした GPU テイントノードでエクスポーターを実行できるようにします。release: kube-prometheus-stack ラベル付きの serviceMonitor により、Prometheus はエクスポーターを自動的に検出してスクレイプします。

DCGM Exporter DaemonSet を確認します。

kubectl get daemonset dcgm-exporter -n monitoring

GPU ノードが実行されると、準備完了状態のポッドが 1 つ表示されます。DCGM メトリクスを検証するには、Grafana で [ドリルダウン] > [メトリクス] に移動し、DCGM_ を検索します。

Grafana で DCGM メトリクスを検証する

DCGM_FI_DEV_ECC_SBE_VOL_TOTAL、DCGM_FI_DEV_ENC_UTIL、DCGM_FI_DEV_FB_FREE、DCGM_FI_DEV_FB_USED などの GPU メトリクスを示す DCGM_ でフィルタリングされた Grafana ドリルダウンメトリクスページ

ダッシュボードを表示するには、[ダッシュボード] > [GPU モニタリング] > [NVIDIA DCGM Exporter ダッシュボード] に移動します。

Grafana の NVIDIA DCGM Exporter ダッシュボード

GPU 使用率、GPU 平均温度、GPU Framebuffer Mem Used、GPU Power Total パネルを示す Grafana NVIDIA DCGM Exporter ダッシュボード

モデルの重み S3 バケット

モデルの重みを保存するための Amazon S3 バケットを作成し、ワークロードポッドがそのバケットに対して読み書きできるように EKS Pod Identity の関連付けを設定します。

新しいターミナルを開いた場合は、クラスター名とリージョンを設定します。

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

S3 バケットの作成

名前の競合を避けるために、ランダムなサフィックスでバケットを作成します。

BUCKET_SUFFIX=$(head -c 4 /dev/urandom | od -An -tx1 | tr -d ' \n') MODEL_BUCKET="${CLUSTER_NAME}-models-${BUCKET_SUFFIX}" aws s3 mb s3://${MODEL_BUCKET} --region ${AWS_REGION}

2023 年 1 月以降に作成された S3 バケットでは、サーバー側の暗号化 (AES256) とパブリックアクセスのブロックがデフォルトで有効になっています。

S3 アクセス用の EKS Pod Identity を設定する

default 名前空間に model-storage-sa ServiceAccount、モデルバケットを対象とする IAM ポリシー、およびそれらをリンクする EKS Pod Identity の関連付けを作成します。serviceAccountName: model-storage-sa を設定したワークロードポッドは、バケットを読み書きできます。

kubectl create serviceaccount model-storage-sa

IAM ポリシーを作成します。

POLICY_ARN=$(aws iam create-policy \ --policy-name "${CLUSTER_NAME}-model-storage-policy" \ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"s3:GetObject\", \"s3:PutObject\", \"s3:ListBucket\", \"s3:DeleteObject\"], \"Resource\": [\"arn:aws:s3:::${MODEL_BUCKET}\", \"arn:aws:s3:::${MODEL_BUCKET}/*\"]}]}" \ --query 'Policy.Arn' \ --output text) echo "Policy ARN: ${POLICY_ARN}"
注記

このポリシーは、検証ステップに s3:DeleteObjects3:PutObject を付与します。モデルの重みのみを読み取る本番推論ポッドの場合は、s3:PutObjects3:DeleteObject を削除して最小特権に従います。

EKS Pod Identity の関連付けを作成します。eksctl は正しい信頼ポリシーを使用して IAM ロールを作成し、ServiceAccount にリンクします。

eksctl create podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace default \ --service-account-name model-storage-sa \ --role-name "${CLUSTER_NAME}-model-storage-role" \ --permission-policy-arns ${POLICY_ARN} \ --region ${AWS_REGION}

関連付けを確認します。

eksctl get podidentityassociation --cluster ${CLUSTER_NAME} --region ${AWS_REGION}

出力には、default 名前空間の model-storage-sa 関連付けを含める必要があります。

model-storage-sa ServiceAccount を使用して AWS CLI イメージで 1 回限りのポッドを実行し、EKS Pod Identity が正しく設定され、S3 アクセスが機能することを確認します。

cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: s3-test labels: guide: ai-eks-docs spec: serviceAccountName: model-storage-sa containers: - name: aws-cli image: public.ecr.aws/aws-cli/aws-cli:2.27.0 command: - sh - -c - | echo "=== Caller Identity ===" aws sts get-caller-identity echo "" echo "=== S3 Write Test ===" echo "pod identity works" | aws s3 cp - s3://${MODEL_BUCKET}/test.txt echo "" echo "=== S3 List Test ===" aws s3 ls s3://${MODEL_BUCKET}/ echo "" echo "=== S3 Delete Test ===" aws s3 rm s3://${MODEL_BUCKET}/test.txt restartPolicy: Never EOF

ポッドが完了するのを待ち、ログを確認します。

kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/s3-test --timeout=300s kubectl logs s3-test

正常な出力:

=== Caller Identity ===
{
    "UserId": "AROA...:eks-ai-eks-docs-model-s-...",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/ai-eks-docs-model-storage-role/eks-ai-eks-docs-model-s-..."
}

=== S3 Write Test ===
upload: - to s3://ai-eks-docs-models-01234567/test.txt

=== S3 List Test ===
2026-05-04 12:00:00         19 test.txt

=== S3 Delete Test ===
delete: s3://ai-eks-docs-models-01234567/test.txt

発信者 ID は、EKS Pod Identity を介してポッドが ${CLUSTER_NAME}-model-storage-role ロールを引き受けたことを確認します。S3 コマンドは読み取りおよび書き込みアクセスを確認します。

テストポッドをクリーンアップします。

kubectl delete pod s3-test

次のステップ

クラスターの準備ができたら、「モデルのロードと提供」に進み、大規模な言語モデルをデプロイし、推論エンドポイントとやり取りできます。

クリーンアップ

ヒント

このガイドの次のセクションに進む場合は、完全なクリーンアップをスキップします。完了時にのみ実行します。

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2
kubectl delete pod nvidia-smi --ignore-not-found kubectl delete deployment gpu-overflow-test --ignore-not-found

ODCR を作成した場合は、最初にキャンセルします。予約 ID を検索します。

INSTANCE_TYPE="g6e.4xlarge" CAPACITY_RESERVATION_ID=$(aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=instance-type,Values=${INSTANCE_TYPE}" \ --query 'CapacityReservations[0].CapacityReservationId' \ --output text \ --region ${AWS_REGION}) echo "Capacity reservation ID: ${CAPACITY_RESERVATION_ID}"

予約をキャンセルします。

aws ec2 cancel-capacity-reservation --capacity-reservation-id ${CAPACITY_RESERVATION_ID}
重要

予約をキャンセルしても、実行中のインスタンスは終了しません。これらは、終了するまで標準のオンデマンド料金で継続されます。キャンセルする前に、最初にデプロイを削除してリザーブドノードをドレインします。

IAM ポリシー ARN を検索します。

AMP_POLICY_ARN=$(aws iam list-policies \ --scope Local \ --query "Policies[?PolicyName=='${CLUSTER_NAME}-amp-grafana-policy'].Arn" \ --output text) echo "AMP Policy ARN: ${AMP_POLICY_ARN}"

AMP ワークスペース ID を検索します。

AMP_WORKSPACE_ID=$(aws amp list-workspaces \ --alias "amp-ws-${CLUSTER_NAME}" \ --query 'workspaces[0].workspaceId' \ --output text \ --region ${AWS_REGION}) echo "AMP Workspace ID: ${AMP_WORKSPACE_ID}"

DCGM Exporter Helm リリースをアンインストールします。

helm uninstall dcgm-exporter -n monitoring

kube-prometheus-stack Helm リリースをアンインストールします。

helm uninstall kube-prometheus-stack -n monitoring

Prometheus 取り込みサービスアカウントの EKS Pod Identity の関連付けを削除します。

eksctl delete podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name amp-iamproxy-ingest-service-account \ --region ${AWS_REGION}

Grafana サービスアカウントの EKS Pod Identity の関連付けを削除します。

eksctl delete podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace monitoring \ --service-account-name grafana-sa \ --region ${AWS_REGION}

Prometheus と Grafana で使用される IAM ポリシーを削除します。

aws iam delete-policy --policy-arn ${AMP_POLICY_ARN}

AMP ワークスペースを削除します。

aws amp delete-workspace --workspace-id ${AMP_WORKSPACE_ID} --region ${AWS_REGION}

モニタリング名前空間を削除します。

kubectl delete namespace monitoring

モデルバケット名を検索します。

MODEL_BUCKET=$(aws s3api list-buckets \ --query "Buckets[?starts_with(Name, '${CLUSTER_NAME}-models-')].Name | [0]" \ --output text) echo "Model bucket: ${MODEL_BUCKET}"

IAM ポリシー ARN を検索します。

POLICY_ARN=$(aws iam list-policies \ --scope Local \ --query "Policies[?PolicyName=='${CLUSTER_NAME}-model-storage-policy'].Arn" \ --output text) echo "Policy ARN: ${POLICY_ARN}"

S3 モデルバケットとそのすべてのオブジェクトを削除します。

aws s3 rb s3://${MODEL_BUCKET} --force

EKS Pod Identity の関連付けを削除します。

eksctl delete podidentityassociation \ --cluster ${CLUSTER_NAME} \ --namespace default \ --service-account-name model-storage-sa \ --region ${AWS_REGION}

IAM ポリシーを削除します。

aws iam delete-policy --policy-arn ${POLICY_ARN}

Kubernetes ServiceAccount を削除します。

kubectl delete serviceaccount model-storage-sa
kubectl delete nodepool gpu-inf --ignore-not-found kubectl delete nodeclass gpu-inf --ignore-not-found kubectl delete ec2nodeclass gpu-inf --ignore-not-found eksctl delete cluster --name=$CLUSTER_NAME --region=$AWS_REGION