メインコンテンツまでスキップ

コンピュートのプロビジョニング

このラボでは、Karpenterを使用して、加速された機械学習推論用に特別に設計されたAWS Trainiumノードをプロビジョニングします。TrainiumはAWSの専用ML高速化プロセッサーで、Mistral-7Bモデルのような推論ワークロードを実行する際の高性能とコスト効率性を提供します。

ヒント

Karpenterについて詳しく知りたい場合は、このワークショップのKarpenterモジュールをチェックしてください。

KarpenterはすでにEKSクラスタにインストールされており、Deploymentとして実行されています:

~$kubectl get deployment karpenter -n kube-system
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
karpenter   2/2     2            2           11m

Trainiumインスタンスをプロビジョニングするために使用するKarpenter NodePoolの設定を確認しましょう:

~/environment/eks-workshop/modules/aiml/chatbot/nodepool-trn1.yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: trainium-trn1
spec:
template:
metadata:
labels:
instanceType: trn1.2xlarge
provisionerType: Karpenter
neuron.amazonaws.com/neuron-device: "true"
vpc.amazonaws.com/has-trunk-attached: "true" # Required for Pod ENI
spec:
taints:
- key: aws.amazon.com/neuron
value: "true"
effect: "NoSchedule"
requirements:
- key: node.kubernetes.io/instance-type
operator: In
values: ["trn1.2xlarge"]
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
- key: "karpenter.sh/capacity-type"
operator: In
values: ["on-demand"]
expireAfter: 720h
terminationGracePeriod: 24h
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: trainium-trn1
limits:
aws.amazon.com/neuron: 2
cpu: 16
memory: 64Gi
disruption:
consolidateAfter: 300s
consolidationPolicy: WhenEmptyOrUnderutilized

---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: trainium-trn1
spec:
amiFamily: AL2023
amiSelectorTerms:
- alias: al2023@latest
instanceStorePolicy: RAID0
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
deleteOnTermination: true
encrypted: true
volumeSize: 256Gi
iops: 16000
throughput: 1000
volumeType: gp3
role: ${KARPENTER_NODE_ROLE}
userData: |
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="//"

--//
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
sed -i "s/^max_concurrent_downloads_per_image = .*$/max_concurrent_downloads_per_image = 10/" /etc/soci-snapshotter-grpc/config.toml
sed -i "s/^max_concurrent_unpacks_per_image = .*$/max_concurrent_unpacks_per_image = 10/" /etc/soci-snapshotter-grpc/config.toml

--//
Content-Type: application/node.eks.aws

apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
featureGates:
FastImagePull: true
--//

securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: ${EKS_CLUSTER_NAME}
- tags:
kubernetes.io/cluster/eks-workshop: owned
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: ${EKS_CLUSTER_NAME}
kubernetes.io/role/internal-elb: "1"
tags:
app.kubernetes.io/created-by: eks-workshop
karpenter.sh/discovery: ${EKS_CLUSTER_NAME}
aws-neuron: "true"
A

このNodePoolは、デモンストレーションの目的でPodを特定のターゲットにするために、すべての新しいノードにprovisionerType: KarpenterというKubernetesラベルを付けるよう設定されています。Karpenterによって複数のノードが自動スケーリングされるため、instanceType: trn1.2xlargeのような追加のラベルも追加され、このKarpenterノードがtrainium-trn1プールに割り当てられるべきことを示しています。

B

NodePool CRDはインスタンスタイプやゾーンなどのノードプロパティを定義することをサポートしています。この例では、karpenter.sh/capacity-typeを最初にKarpenterがオンデマンドインスタンスのみをプロビジョニングするように制限し、またkarpenter.k8s.aws/instance-typeで特定のインスタンスタイプのサブセットに限定しています。他にどのようなプロパティが利用可能かはこちらで確認できます。

C

Taintは、ノードが一連のPodを排除できるようにする特定のプロパティセットを定義します。このプロパティはマッチングするラベルであるTolerationと連携して機能します。TolerationとTaintは連携して、Podが適切なノードに正しくスケジュールされることを保証します。他のプロパティについては、このリソースで詳しく学べます。

D

NodePoolは、それによって管理されるCPUとメモリの量に制限を定義できます。この制限に達すると、Karpenterはその特定のNodePoolに関連する追加のキャパシティをプロビジョニングしなくなり、合計コンピュートに上限を設けます。

NodePoolを作成しましょう:

~$cat ~/environment/eks-workshop/modules/aiml/chatbot/nodepool-trn1.yaml \
| envsubst | kubectl apply -f-
ec2nodeclass.karpenter.k8s.aws/trainium-trn1 created
nodepool.karpenter.sh/trainium-trn1 created

正しく展開されたら、NodePoolsを確認します:

~$kubectl get nodepool
NAME                NODECLASS           NODES   READY   AGE
trainium-trn1       trainium-trn1       0       True    31s

上記のコマンドから、NodePoolが正しくプロビジョニングされていることがわかります。これにより、Karpenterは必要に応じて新しいノードをプロビジョニングできます。次のステップでMLワークロードをデプロイすると、Karpenterは指定したリソース要求と制限に基づいて必要なTrainiumインスタンスを自動的に作成します。