Skip to content

필사 모드: [AWS] KarpenterでGPUノード管理:AI/MLワークロードの最適化

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

目次

1. KarpenterによるGPUノードプロビジョニング

GPUワークロードの特殊性

AI/MLワークロードは一般的なコンピューティングとは異なる固有の要件があります:

+---------------------------------------------------------------+

| GPUワークロードの特性 |

+---------------------------------------------------------------+

| - 高額なGPUインスタンス(1時間あたり数〜数十ドル) |

| - 長時間の学習ジョブ(数時間〜数日) |

| - 推論作業の低レイテンシ要件 |

| - GPUメモリ(VRAM)ベースのリソース制約 |

| - インスタンスタイプ別のGPU性能差が大きい |

| - Spot中断時の学習進捗損失リスク |

+---------------------------------------------------------------+

KarpenterがGPU管理に適している理由

+------------------------------------------+

| 従来方式(Cluster Autoscaler) |

| |

| GPU Node Group A: p3.2xlarge |

| GPU Node Group B: g5.xlarge |

| GPU Node Group C: g5.2xlarge |

| GPU Node Group D: p4d.24xlarge |

| ... |

| 各Node Groupを個別管理(非効率) |

+------------------------------------------+

+------------------------------------------+

| Karpenter方式 |

| |

| 単一のGPU NodePool: |

| - Pod要件の分析 |

| - 最適なGPUインスタンスを自動選択 |

| - Spot/On-Demandの自動切替 |

| - コストベースのインスタンス最適化 |

+------------------------------------------+

2. GPU NodePool設定

汎用GPU NodePool

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-general

spec:

template:

metadata:

labels:

node-type: gpu

workload: ai-ml

spec:

requirements:

GPUインスタンスのみ選択

- key: karpenter.k8s.aws/instance-gpu-count

operator: Gt

values: ['0']

GPUインスタンスファミリー

- key: karpenter.k8s.aws/instance-category

operator: In

values: ['g', 'p']

容量タイプ

- key: karpenter.sh/capacity-type

operator: In

values: ['on-demand', 'spot']

アベイラビリティゾーン

- key: topology.kubernetes.io/zone

operator: In

values: ['ap-northeast-1a', 'ap-northeast-1c', 'ap-northeast-1d']

x86アーキテクチャのみ

- key: kubernetes.io/arch

operator: In

values: ['amd64']

GPU専用taint

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-optimized

GPUノードは長い有効期限

expireAfter: 336h # 14日

limits:

cpu: '500'

memory: 2000Gi

nvidia.com/gpu: '100'

disruption:

consolidationPolicy: WhenEmpty

consolidateAfter: 5m

budgets:

- nodes: '1'

weight: 80

AWS GPUインスタンスタイプガイド

+------------------+----------+----------+------------------+---------------------+

| インスタンス | GPU | 数量 | GPUメモリ | 主な用途 |

+------------------+----------+----------+------------------+---------------------+

| g4dn.xlarge | T4 | 1 | 16 GB | 推論、軽量学習 |

| g4dn.12xlarge | T4 | 4 | 64 GB | マルチ推論 |

| g5.xlarge | A10G | 1 | 24 GB | 推論、微調整 |

| g5.12xlarge | A10G | 4 | 96 GB | 中型学習 |

| g5.48xlarge | A10G | 8 | 192 GB | 大型学習 |

| g6.xlarge | L4 | 1 | 24 GB | 推論最適化 |

| g6.12xlarge | L4 | 4 | 96 GB | マルチモーダル推論 |

| p3.2xlarge | V100 | 1 | 16 GB | 汎用学習 |

| p3.8xlarge | V100 | 4 | 64 GB | 大規模学習 |

| p4d.24xlarge | A100 | 8 | 320 GB (40GB x8) | 超大規模学習 |

| p5.48xlarge | H100 | 8 | 640 GB (80GB x8) | 最高性能学習 |

+------------------+----------+----------+------------------+---------------------+

推論専用NodePool

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-inference

spec:

template:

metadata:

labels:

node-type: gpu-inference

workload: inference

spec:

requirements:

推論に適したインスタンス

- key: karpenter.k8s.aws/instance-gpu-name

operator: In

values: ['t4', 'a10g', 'l4']

Spotインスタンス優先(推論はstateless)

- key: karpenter.sh/capacity-type

operator: In

values: ['spot', 'on-demand']

インスタンスサイズ制限

- key: karpenter.k8s.aws/instance-size

operator: In

values: ['xlarge', '2xlarge', '4xlarge']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-optimized

limits:

nvidia.com/gpu: '50'

disruption:

consolidationPolicy: WhenEmptyOrUnderutilized

consolidateAfter: 2m

weight: 60

学習専用NodePool

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-training

spec:

template:

metadata:

labels:

node-type: gpu-training

workload: training

spec:

requirements:

学習に適した高性能GPU

- key: karpenter.k8s.aws/instance-gpu-name

operator: In

values: ['a100', 'h100', 'a10g']

On-Demand専用(学習の中断コストが高い)

- key: karpenter.sh/capacity-type

operator: In

values: ['on-demand']

大型インスタンス

- key: karpenter.k8s.aws/instance-gpu-count

operator: Gt

values: ['0']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-training

学習用ノードは有効期限なし

expireAfter: 720h # 30日

limits:

nvidia.com/gpu: '32'

disruption:

学習中のConsolidation無効化

consolidationPolicy: WhenEmpty

consolidateAfter: 30m

budgets:

- nodes: '0'

weight: 90

3. GPU専用EC2NodeClass

apiVersion: karpenter.k8s.aws/v1

kind: EC2NodeClass

metadata:

name: gpu-optimized

spec:

GPUドライバ対応AMI

amiSelectorTerms:

- alias: al2023@latest

role: KarpenterNodeRole-my-cluster

subnetSelectorTerms:

- tags:

karpenter.sh/discovery: my-cluster

network-type: private

securityGroupSelectorTerms:

- tags:

karpenter.sh/discovery: my-cluster

GPUワークロード用大容量ディスク

blockDeviceMappings:

- deviceName: /dev/xvda

ebs:

volumeSize: 200Gi

volumeType: gp3

iops: 6000

throughput: 250

encrypted: true

deleteOnTermination: true

metadataOptions:

httpEndpoint: enabled

httpPutResponseHopLimit: 2

httpTokens: required

tags:

Environment: production

NodeType: gpu

ManagedBy: karpenter

GPUドライバインストール用ユーザーデータ

userData: |

#!/bin/bash

echo "GPU node bootstrap"

NVIDIAドライバはGPU Operatorが処理

学習専用EC2NodeClass(大容量ストレージ)

apiVersion: karpenter.k8s.aws/v1

kind: EC2NodeClass

metadata:

name: gpu-training

spec:

amiSelectorTerms:

- alias: al2023@latest

role: KarpenterNodeRole-my-cluster

subnetSelectorTerms:

- tags:

karpenter.sh/discovery: my-cluster

securityGroupSelectorTerms:

- tags:

karpenter.sh/discovery: my-cluster

学習データ用大容量・高性能ストレージ

blockDeviceMappings:

- deviceName: /dev/xvda

ebs:

volumeSize: 500Gi

volumeType: gp3

iops: 16000

throughput: 1000

encrypted: true

deleteOnTermination: true

tags:

Environment: production

NodeType: gpu-training

ManagedBy: karpenter

4. Spot GPUインスタンス戦略

Spot GPUのコスト削減効果

+------------------+-------------------+-------------------+---------+

| インスタンス | On-Demand (時間) | Spot予想 (時間) | 削減率 |

+------------------+-------------------+-------------------+---------+

| g4dn.xlarge | ~0.526 | ~0.158 | ~70% |

| g5.xlarge | ~1.006 | ~0.302 | ~70% |

| g5.2xlarge | ~1.212 | ~0.364 | ~70% |

| g5.12xlarge | ~5.672 | ~1.702 | ~70% |

| p3.2xlarge | ~3.060 | ~0.918 | ~70% |

+------------------+-------------------+-------------------+---------+

(価格はリージョンと時期により変動します)

Spot GPU NodePool - 推論用

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-spot-inference

spec:

template:

metadata:

labels:

node-type: gpu-spot

workload: inference

spec:

requirements:

- key: karpenter.sh/capacity-type

operator: In

values: ['spot']

推論に適した多様なGPUタイプ

- key: karpenter.k8s.aws/instance-gpu-name

operator: In

values: ['t4', 'a10g', 'l4']

多様なサイズでSpot可用性確保

- key: karpenter.k8s.aws/instance-size

operator: In

values: ['xlarge', '2xlarge', '4xlarge', '8xlarge', '12xlarge']

複数AZ活用

- key: topology.kubernetes.io/zone

operator: In

values: ['ap-northeast-1a', 'ap-northeast-1c', 'ap-northeast-1d']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-optimized

limits:

nvidia.com/gpu: '40'

disruption:

consolidationPolicy: WhenEmptyOrUnderutilized

consolidateAfter: 1m

weight: 70

Spot中断対策

長時間学習ジョブにdo-not-disruptアノテーションを適用

apiVersion: v1

kind: Pod

metadata:

name: training-job

annotations:

karpenter.sh/do-not-disrupt: 'true'

spec:

containers:

- name: training

image: my-training-image:latest

resources:

requests:

nvidia.com/gpu: '1'

cpu: '4'

memory: 16Gi

limits:

nvidia.com/gpu: '1'

tolerations:

- key: nvidia.com/gpu

operator: Exists

effect: NoSchedule

terminationGracePeriodSeconds: 120

5. NVIDIA GPU Operator連携

GPU Operatorの概要

+----------------------------------------------------------------+

| NVIDIA GPU Operator |

| |

| +------------------+ +-------------------+ +--------------+ |

| | NVIDIAドライバ | | Container Toolkit | | Device Plugin| |

| | (自動インストール)| | (自動設定) | | (自動デプロイ)| |

| +------------------+ +-------------------+ +--------------+ |

| |

| +------------------+ +-------------------+ +--------------+ |

| | GPU Feature | | DCGM Exporter | | MIG Manager | |

| | Discovery | | (メトリクス収集) | | (MIG管理) | |

| +------------------+ +-------------------+ +--------------+ |

+----------------------------------------------------------------+

GPU Operatorのインストール

NVIDIA GPU Operator Helmリポジトリ追加

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia

helm repo update

GPU Operatorインストール

helm install gpu-operator nvidia/gpu-operator \

--namespace gpu-operator \

--create-namespace \

--set driver.enabled=true \

--set toolkit.enabled=true \

--set devicePlugin.enabled=true \

--set dcgmExporter.enabled=true \

--set migManager.enabled=false \

--set gfd.enabled=true

GPU OperatorとKarpenterの連携確認

GPUノードのラベル確認

kubectl get nodes -l node-type=gpu -o json | \

jq '.items[].metadata.labels | with_entries(select(.key | startswith("nvidia")))'

GPUリソース確認

kubectl describe node gpu-node-name | grep -A 5 "nvidia.com/gpu"

DCGM Exporter Pod確認

kubectl get pods -n gpu-operator -l app=nvidia-dcgm-exporter

GPUワークロードデプロイ例

apiVersion: apps/v1

kind: Deployment

metadata:

name: gpu-inference-server

namespace: ml-serving

spec:

replicas: 3

selector:

matchLabels:

app: inference-server

template:

metadata:

labels:

app: inference-server

spec:

containers:

- name: inference

image: nvcr.io/nvidia/tritonserver:24.01-py3

ports:

- containerPort: 8000

name: http

- containerPort: 8001

name: grpc

- containerPort: 8002

name: metrics

resources:

requests:

cpu: '4'

memory: 16Gi

nvidia.com/gpu: '1'

limits:

nvidia.com/gpu: '1'

volumeMounts:

- name: model-store

mountPath: /models

tolerations:

- key: nvidia.com/gpu

operator: Exists

effect: NoSchedule

nodeSelector:

node-type: gpu-inference

volumes:

- name: model-store

persistentVolumeClaim:

claimName: model-store-pvc

6. マルチアーキテクチャサポート(x86 + ARM/Graviton)

マルチアーキテクチャNodePool

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: multi-arch

spec:

template:

spec:

requirements:

x86とARMの両方を許可

- key: kubernetes.io/arch

operator: In

values: ['amd64', 'arm64']

Gravitonインスタンスを含む

- key: karpenter.k8s.aws/instance-category

operator: In

values: ['c', 'm', 'r']

- key: karpenter.k8s.aws/instance-generation

operator: Gt

values: ['5']

- key: karpenter.sh/capacity-type

operator: In

values: ['on-demand', 'spot']

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: default

limits:

cpu: '1000'

memory: 2000Gi

disruption:

consolidationPolicy: WhenEmptyOrUnderutilized

consolidateAfter: 1m

GravitonのGPU代替:Inferentia/Trainium

AWS Inferentia推論専用NodePool

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: inferentia

spec:

template:

metadata:

labels:

accelerator: inferentia

spec:

requirements:

- key: node.kubernetes.io/instance-type

operator: In

values: ['inf2.xlarge', 'inf2.8xlarge', 'inf2.24xlarge', 'inf2.48xlarge']

- key: karpenter.sh/capacity-type

operator: In

values: ['on-demand']

taints:

- key: aws.amazon.com/neuron

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: inferentia-nodes

limits:

aws.amazon.com/neuron: '32'

disruption:

consolidationPolicy: WhenEmpty

consolidateAfter: 5m

7. コスト最適化戦略

SpotとOn-Demandの混合戦略

+-------------------------------------------------------------+

| コスト最適化の意思決定ツリー |

+-------------------------------------------------------------+

| |

| ワークロードタイプの確認 |

| | |

| +-- 推論 (Stateless) --> Spot優先 + On-Demand代替 |

| | |

| +-- 微調整 (短期) --> Spot + チェックポイント戦略 |

| | |

| +-- 大規模学習 (長期) --> On-Demand + リザーブド |

| | |

| +-- バッチ処理 --> Spot専用 |

| |

+-------------------------------------------------------------+

重み付き優先順位によるインスタンスファミリー戦略

第1優先:G5 Spot(最もコスト効率的な推論)

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-tier1-g5-spot

spec:

template:

spec:

requirements:

- key: karpenter.sh/capacity-type

operator: In

values: ['spot']

- key: karpenter.k8s.aws/instance-gpu-name

operator: In

values: ['a10g']

- key: karpenter.k8s.aws/instance-category

operator: In

values: ['g']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-optimized

weight: 100

limits:

nvidia.com/gpu: '20'

第2優先:G4dn Spot(フォールバック)

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-tier2-g4dn-spot

spec:

template:

spec:

requirements:

- key: karpenter.sh/capacity-type

operator: In

values: ['spot']

- key: karpenter.k8s.aws/instance-gpu-name

operator: In

values: ['t4']

- key: karpenter.k8s.aws/instance-category

operator: In

values: ['g']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-optimized

weight: 50

limits:

nvidia.com/gpu: '20'

第3優先:G5 On-Demand(最終手段)

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-tier3-g5-ondemand

spec:

template:

spec:

requirements:

- key: karpenter.sh/capacity-type

operator: In

values: ['on-demand']

- key: karpenter.k8s.aws/instance-gpu-name

operator: In

values: ['a10g']

- key: karpenter.k8s.aws/instance-category

operator: In

values: ['g']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-optimized

weight: 10

limits:

nvidia.com/gpu: '10'

Consolidationポリシーの最適化

GPUノードのConsolidation設定

disruption:

GPUノードはWhenEmptyのみ使用(実行中のGPUジョブを保護)

consolidationPolicy: WhenEmpty

空ノード検知後5分待機(一時的な非アクティブを考慮)

consolidateAfter: 5m

budgets:

同時に最大1ノードのみ中断

- nodes: '1'

業務時間中は中断をブロック

- nodes: '0'

schedule: '0 9 * * MON-FRI'

duration: 10h

8. ノード中断バジェット(Node Disruption Budgets)

GPUワークロード用Disruption Budget

apiVersion: karpenter.sh/v1

kind: NodePool

metadata:

name: gpu-training-protected

spec:

template:

spec:

requirements:

- key: karpenter.k8s.aws/instance-gpu-count

operator: Gt

values: ['0']

- key: karpenter.sh/capacity-type

operator: In

values: ['on-demand']

taints:

- key: nvidia.com/gpu

value: 'true'

effect: NoSchedule

nodeClassRef:

group: karpenter.k8s.aws

kind: EC2NodeClass

name: gpu-training

disruption:

consolidationPolicy: WhenEmpty

consolidateAfter: 30m

budgets:

学習時間中は中断を完全にブロック

- nodes: '0'

schedule: '0 0 * * *'

duration: 23h

メンテナンスウィンドウ(毎日1時間)

- nodes: '1'

schedule: '0 23 * * *'

duration: 1h

ドリフトによる中断は別途管理

- nodes: '1'

reasons:

- 'Drifted'

Podレベルの保護

長時間学習Pod:Karpenterの中断を防止

apiVersion: v1

kind: Pod

metadata:

name: long-training-job

annotations:

このアノテーションでKarpenterの自発的中断を防止

karpenter.sh/do-not-disrupt: 'true'

spec:

containers:

- name: trainer

image: my-training-image:v1

resources:

requests:

nvidia.com/gpu: '4'

cpu: '16'

memory: 64Gi

limits:

nvidia.com/gpu: '4'

tolerations:

- key: nvidia.com/gpu

operator: Exists

effect: NoSchedule

十分な終了猶予時間(チェックポイント保存)

terminationGracePeriodSeconds: 300

PDB(Pod Disruption Budget)設定

apiVersion: policy/v1

kind: PodDisruptionBudget

metadata:

name: inference-server-pdb

namespace: ml-serving

spec:

minAvailable: 2

selector:

matchLabels:

app: inference-server

9. Prometheus/Grafanaによるモニタリング

Karpenterメトリクス収集設定

Karpenter ServiceMonitor

apiVersion: monitoring.coreos.com/v1

kind: ServiceMonitor

metadata:

name: karpenter

namespace: karpenter

spec:

selector:

matchLabels:

app.kubernetes.io/name: karpenter

endpoints:

- port: http-metrics

interval: 15s

path: /metrics

主要なKarpenterメトリクス

+-----------------------------------------------+------------------------------------------+

| メトリクス | 説明 |

+-----------------------------------------------+------------------------------------------+

| karpenter_nodeclaims_launched_total | 起動されたNodeClaim総数 |

| karpenter_nodeclaims_registered_total | 登録されたNodeClaim総数 |

| karpenter_nodeclaims_terminated_total | 終了されたNodeClaim総数 |

| karpenter_pods_state | Pod状態(ノード、ネームスペース等) |

| karpenter_nodepool_usage | NodePool別リソース使用量 |

| karpenter_nodepool_limit | NodePool別リソース制限 |

| karpenter_voluntary_disruption_eligible_nodes | 自発的中断対象ノード数 |

| karpenter_disruption_actions_performed_total | 実行された中断アクション数 |

| karpenter_nodes_allocatable | ノード別割当可能リソース |

| karpenter_nodes_total_daemon_requests | DaemonSetリソース要求合計 |

+-----------------------------------------------+------------------------------------------+

GPU専用Grafanaダッシュボードクエリ

GPUノード数の追跡

count(karpenter_nodes_allocatable{resource_type="nvidia.com/gpu"} > 0)

GPU使用率(DCGM Exporter必要)

DCGM_FI_DEV_GPU_UTIL

NodePool別GPU使用量 vs 制限

karpenter_nodepool_usage{resource_type="nvidia.com/gpu"}

/

karpenter_nodepool_limit{resource_type="nvidia.com/gpu"}

プロビジョニングレイテンシ

histogram_quantile(0.99,

rate(karpenter_provisioner_scheduling_duration_seconds_bucket[5m])

)

DCGM Exporterメトリクス

DCGM Exporter ServiceMonitor

apiVersion: monitoring.coreos.com/v1

kind: ServiceMonitor

metadata:

name: dcgm-exporter

namespace: gpu-operator

spec:

selector:

matchLabels:

app: nvidia-dcgm-exporter

endpoints:

- port: metrics

interval: 15s

アラートルール例

apiVersion: monitoring.coreos.com/v1

kind: PrometheusRule

metadata:

name: karpenter-gpu-alerts

namespace: monitoring

spec:

groups:

- name: karpenter-gpu

rules:

GPU NodePoolが制限の90%に到達

- alert: GPUNodePoolNearLimit

expr: |

karpenter_nodepool_usage{nodepool="gpu-general", resource_type="nvidia.com/gpu"}

/

karpenter_nodepool_limit{nodepool="gpu-general", resource_type="nvidia.com/gpu"}

> 0.9

for: 5m

labels:

severity: warning

annotations:

summary: 'GPU NodePoolがリソース制限に近づいています'

GPU使用率が低いノードの検知

- alert: LowGPUUtilization

expr: |

avg_over_time(DCGM_FI_DEV_GPU_UTIL[30m]) < 10

for: 1h

labels:

severity: info

annotations:

summary: 'GPU使用率が1時間にわたり10%未満です'

Karpenterプロビジョニング失敗

- alert: KarpenterProvisioningFailed

expr: |

increase(karpenter_nodeclaims_terminated_total{reason="ProvisioningFailed"}[15m]) > 0

labels:

severity: critical

annotations:

summary: 'KarpenterがGPUノードのプロビジョニングに失敗しました'

10. 実践例:学習クラスタ

分散学習クラスタの構成

PyTorch分散学習Job

apiVersion: batch/v1

kind: Job

metadata:

name: distributed-training

namespace: ml-training

spec:

parallelism: 4

completions: 4

template:

metadata:

labels:

app: distributed-training

annotations:

karpenter.sh/do-not-disrupt: 'true'

spec:

containers:

- name: pytorch-trainer

image: my-pytorch-training:v1

command: ['torchrun']

args:

- '--nproc_per_node=1'

- '--nnodes=4'

- '--node_rank=$(JOB_COMPLETION_INDEX)'

- '--master_addr=training-master'

- '--master_port=29500'

- 'train.py'

env:

- name: JOB_COMPLETION_INDEX

valueFrom:

fieldRef:

fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index']

resources:

requests:

cpu: '8'

memory: 32Gi

nvidia.com/gpu: '1'

limits:

nvidia.com/gpu: '1'

volumeMounts:

- name: shared-data

mountPath: /data

- name: checkpoints

mountPath: /checkpoints

tolerations:

- key: nvidia.com/gpu

operator: Exists

effect: NoSchedule

nodeSelector:

node-type: gpu-training

restartPolicy: OnFailure

volumes:

- name: shared-data

persistentVolumeClaim:

claimName: training-data-pvc

- name: checkpoints

persistentVolumeClaim:

claimName: checkpoint-pvc

11. 実践例:推論クラスタ

オートスケーリング推論サービス

推論Deployment

apiVersion: apps/v1

kind: Deployment

metadata:

name: llm-inference

namespace: ml-serving

spec:

replicas: 2

selector:

matchLabels:

app: llm-inference

template:

metadata:

labels:

app: llm-inference

spec:

containers:

- name: vllm-server

image: vllm/vllm-openai:latest

args:

- '--model'

- 'meta-llama/Llama-3-8B'

- '--tensor-parallel-size'

- '1'

- '--gpu-memory-utilization'

- '0.9'

ports:

- containerPort: 8000

name: http

resources:

requests:

cpu: '4'

memory: 16Gi

nvidia.com/gpu: '1'

limits:

nvidia.com/gpu: '1'

readinessProbe:

httpGet:

path: /health

port: 8000

initialDelaySeconds: 60

periodSeconds: 10

tolerations:

- key: nvidia.com/gpu

operator: Exists

effect: NoSchedule

nodeSelector:

node-type: gpu-inference

HPA設定

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: llm-inference-hpa

namespace: ml-serving

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: llm-inference

minReplicas: 2

maxReplicas: 10

metrics:

- type: Pods

pods:

metric:

name: gpu_utilization

target:

type: AverageValue

averageValue: '70'

behavior:

scaleUp:

stabilizationWindowSeconds: 60

policies:

- type: Pods

value: 2

periodSeconds: 60

scaleDown:

stabilizationWindowSeconds: 300

policies:

- type: Pods

value: 1

periodSeconds: 120

12. トラブルシューティングガイド

一般的なGPUノードの問題

1. GPUリソースが表示されない場合

kubectl describe node gpu-node | grep -A 10 "Allocatable"

nvidia.com/gpuがない場合、GPU Operatorを確認

2. GPU Operator Podの状態確認

kubectl get pods -n gpu-operator

kubectl logs -n gpu-operator -l app=nvidia-driver-daemonset

3. Karpenterプロビジョニングログの確認

kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter \

| grep -i "gpu\|nvidia\|instance-type"

4. NodeClaimの状態確認

kubectl get nodeclaims -o wide

5. Pending Podの原因分析

kubectl describe pod gpu-pod-name | grep -A 20 "Events"

よくある問題と解決方法

+---------------------------------------------+------------------------------------------+

| 問題 | 解決方法 |

+---------------------------------------------+------------------------------------------+

| GPUリソースがノードに表示されない | GPU Operatorの再インストールまたは |

| | ドライバの確認 |

| Spot GPUインスタンスが見つからない | より多くのGPUインスタンスタイプとAZを追加|

| GPUノードプロビジョニングがタイムアウト | EC2NodeClassのサブネット/SGタグを確認 |

| 学習中にノードが中断された | do-not-disruptアノテーションを追加 |

| GPUメモリ不足(OOM) | より大きなGPUインスタンスタイプを許可 |

| 不要なGPUノードが維持されている | Consolidationポリシーと |

| | consolidateAfter値を確認 |

| 特定のGPUタイプのみプロビジョニングされる | NodePool requirements範囲を拡張 |

+---------------------------------------------+------------------------------------------+

GPUメモリデバッグ

ノード上で直接GPU状態を確認(デバッグPod使用)

kubectl run gpu-debug --rm -it \

--image=nvidia/cuda:12.0.0-base-ubuntu22.04 \

--overrides='{"spec":{"tolerations":[{"key":"nvidia.com/gpu","operator":"Exists","effect":"NoSchedule"}],"nodeSelector":{"node-type":"gpu"}}}' \

--restart=Never \

-- nvidia-smi

13. ベストプラクティスまとめ

GPUノード管理チェックリスト

+---+------------------------------------------------------------+

| # | ベストプラクティス |

+---+------------------------------------------------------------+

| 1 | 推論と学習ワークロードのNodePoolを分離 |

| 2 | GPU taintを設定して非GPUワークロードのスケジューリングを防止|

| 3 | 推論はSpot、学習はOn-Demandを使用 |

| 4 | 長時間学習にdo-not-disruptアノテーションを適用 |

| 5 | チェックポイント戦略で学習進捗を保護 |

| 6 | GPU Operatorでドライバ管理を自動化 |

| 7 | DCGM ExporterでGPUメトリクスを収集 |

| 8 | NodePool limitsでGPUコスト上限を設定 |

| 9 | 複数のGPUインスタンスタイプを許可して可用性を確保 |

| 10| PDBで推論サービスの最小可用性を保証 |

| 11| Disruption Budgetで学習時間中の中断をブロック |

| 12| HPAとKarpenterを連携して自動スケーリングを実現 |

+---+------------------------------------------------------------+

コスト最適化戦略まとめ

戦略1:階層型NodePool

- Spot GPU(高い重み) -> On-Demand GPU(低い重み)

- 推論ワークロードに最適

戦略2:インスタンス多角化

- 複数のGPUファミリー(g4dn、g5、g6)を許可

- 複数のインスタンスサイズを許可

- Spot可用性を最大化

戦略3:自動スケールダウン

- WhenEmpty consolidationで空のGPUノードを即座に削除

- consolidateAfterを短く設定(推論)

- 学習ノードはより長い待機時間を設定

戦略4:適切なリソース制限

- NodePool limitsで最大GPU数を制限

- 予期しないコスト暴走を防止

- チーム/プロジェクト別の割当量を管理

Karpenter + GPU最終アーキテクチャ図

+---------------------------------------------------------------------+

| EKS Cluster |

| |

| +-------------------+ +-------------------+ +-----------------+ |

| | NodePool: | | NodePool: | | NodePool: | |

| | gpu-inference | | gpu-training | | multi-arch | |

| | (Spot, weight:60) | | (OD, weight:90) | | (Mixed, w:50) | |

| +--------+----------+ +--------+----------+ +--------+--------+ |

| | | | |

| +--------v----------+ +--------v----------+ +--------v--------+ |

| | EC2NodeClass: | | EC2NodeClass: | | EC2NodeClass: | |

| | gpu-optimized | | gpu-training | | default | |

| | (200GB, gp3) | | (500GB, gp3) | | (100GB, gp3) | |

| +-------------------+ +-------------------+ +-----------------+ |

| |

| +-------------------+ +-------------------+ |

| | GPU Operator | | Prometheus + | |

| | (NVIDIAドライバ、 | | Grafana | |

| | Device Plugin、 | | (Karpenter + | |

| | DCGM Exporter) | | DCGMメトリクス) | |

| +-------------------+ +-------------------+ |

+---------------------------------------------------------------------+

현재 단락 (1/898)

AI/MLワークロードは一般的なコンピューティングとは異なる固有の要件があります:

작성 글자: 0원문 글자: 21,484작성 단락: 0/898