このページの改善にご協力ください
このユーザーガイドに貢献するには、すべてのページの右側のペインにある「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 Mode と Karpenter
高レベルアーキテクチャとワークフロー
この図は、このセクションのセットアップの AWS 高レベルアーキテクチャを示しています。右側の番号付きステップは、以下のステップで設定を完了する順序を示しています。
前提条件
-
kubectl>= 1.35。セットアップ手順については、「kubectl および eksctl のセットアップ」を参照してください。 -
AWS CLI >= 2.27。セットアップ手順については、「AWS CLI の最新バージョンのインストールまたは更新」を参照してください。
-
Helm >= 3.14。セットアップの手順については、「Helm を使用して Amazon EKS にアプリケーションをデプロイする」を参照してください。
-
jq。セットアップ手順については、「Download jq」を参照してください。 -
eksctl>= 0.227.0。セットアップ手順については、eksctlドキュメントの「インストール」を参照してください。
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-az3、usw1-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
以下の各ステップで、パス (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 パスとセルフマネージド Karpenter パスの両方において、ノードの自動修復は NodePools によってプロビジョニングされたノードでも同じように動作します。EKS Auto Mode と Karpenter の自動ノード修復は、PodDisruptionBudgets、karpenter.sh/do-not-disrupt 注釈、および terminationGracePeriod をバイパスする強力な中断方法です。自動ノード修復は、AcceleratedHardwareReady 条件が False に設定されたノードについては置き換えまで 10 分待機し、他の修復条件については 30 分待機します。
ステップ 2: 動的 GPU NodePool を作成する
オンデマンドのスポットキャパシティをフォールバックとして使用して、生成が 4 を超える G ファミリー GPU インスタンスを動的にプロビジョニングする NodePool を定義します。EKS Auto Mode パスと Karpenter パスはどちらも同じ NodePool API を使用しますが、唯一の違いはそれが指す NodeClass です。EKS Auto Mode では、バンドルされた default NodeClass は既に適切な AMI を選択し、SOCI 並列プルを設定しているため、NodePool は作成する唯一のオブジェクトです。セルフマネージド Karpenter では、AMI を固定して SOCI を調整するカスタム EC2NodeClass も必要です。
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.126.09 Driver Version: 580.126.09 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 RTX PRO 6000 Blac... On | 00000000:2B:00.0 Off | 0 | | N/A 30C P0 81W / 600W | 0MiB / 97887MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+
出力には、GPU モデル、ドライバーバージョン、CUDA バージョン、利用可能なメモリが表示されます。この例では、Karpenter は 96 GB のメモリを持つ NVIDIA RTX PRO 6000 Blackwell GPU を持つ G7e インスタンスをプロビジョニングしました。30C は現在の GPU 温度であり、P0 は GPU が最高のパフォーマンス状態 (アイドル状態で準備完了) であることを意味します。81W/600W は現在の電力消費量と最大電力容量を示し、0MiB/97887MiB は現在の GPU メモリ使用量と利用可能な合計を示します。ポッドは nvidia-smi を実行して終了しただけなので、GPU を使用するワークロードはありません。そのため、メモリは 0 で、電力はアイドル状態です。NVIDIA GPU ドライバーバージョン (580.126.09) は Bottlerocket AMI から、CUDA バージョン (13.0) はコンテナイメージから取得されます。GPU モデルとメモリは、Karpenter が選択するインスタンスタイプによって異なります。G5 インスタンスには NVIDIA A10G GPU (24 GB)、G6e インスタンスには NVIDIA L40S GPU (48 GB)、G7e インスタンスには NVIDIA RTX PRO 6000 GPU (96 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-xxxxx g7e.2xlarge spot us-east-2a i-0xxxxxxxxxxxx True 2m
インスタンスタイプと AZ は異なります。第 4 世代より新しい 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 の変更を適用します。
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 g7e.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-account と grafana-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 ノードを含むすべてのノードで実行され、フリート全体でメトリクスを収集します。
値ファイルを作成します。
cat << EOF > /tmp/kube-prometheus-values.yaml prometheus: serviceAccount: create: false name: amp-iamproxy-ingest-service-account prometheusSpec: serviceAccountName: amp-iamproxy-ingest-service-account remoteWrite: - url: "${AMP_ENDPOINT}api/v1/remote_write" sigv4: region: "${AWS_REGION}" queueConfig: maxSamplesPerSend: 1000 maxShards: 200 capacity: 2500 retention: 5h scrapeInterval: 30s evaluationInterval: 30s podMonitorSelectorNilUsesHelmValues: false serviceMonitorSelectorNilUsesHelmValues: false alertmanager: enabled: false grafana: enabled: true serviceAccount: create: false name: grafana-sa 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 prometheus-node-exporter: tolerations: - operator: Exists EOF
変数が正しく入力されたことを確認します。
grep -E "url:|region:|tolerations:" /tmp/kube-prometheus-values.yaml
完全な AMP エンドポイント URL (https://aps-workspaces… で始まる)、リージョン、および node-exporter の tolerations: 行が表示されます。空の場合は、変数を再エクスポートしてファイルを再作成します。
チャートをインストールします。
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 にアクセスする
別のターミナルを開き、ポートフォワードして Grafana にアクセスします。
kubectl port-forward svc/kube-prometheus-stack-grafana 3000:80 -n monitoring
ブラウザで http://localhost:3000admin とパスワードを使用してログインします。
kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo
メトリクスパイプラインがエンドツーエンドで機能していることを確認するには:
-
[接続] > [データソース] に移動し、
Amazon-Managed-Prometheusがデフォルトのデータソースとしてリストされていることを確認します。Grafana で AMP データソースを検証する
-
[ドリルダウン] > [メトリクス] に移動し、
upメトリクスを検索します。クラスターのスクレイプターゲットの結果が表示されます。Grafana で
upメトリクスを検証する
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 製造元に異なるラベルキーを使用します。
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 メトリクスを検証する
ダッシュボードを表示するには、[ダッシュボード] > [GPU モニタリング] > [NVIDIA DCGM Exporter ダッシュボード] に移動します。
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:DeleteObject と s3:PutObject を付与します。モデルの重みのみを読み取る本番推論ポッドの場合は、s3:PutObject と s3: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 を作成した場合は、最初にキャンセルします。
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}) 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