Kubernetes Engine 클러스터에 NVIDIA GPU 워크노드 사용
Kubernetes Engine을 이용해 생성한 쿠버네티스 클러스터에서 GPU 노드를 생성하고, 워크로드에 GPU를 사용하는 두 가지 방법을 설명합니다.
- 예상 소요 시간: 15분
- 사용자 환경
- 권장 운영 체제: MacOS, Ubuntu
- Region: kr-central-2
- 사전 준비 사항
시작하기 전에
Kubernetes 패키지 관리를 도와주는 패키지 매니저인 Helm을 설치합니다. Helm을 통해 Kubernetes용 소프트웨어를 검색하거나 공유하고 사용할 수 있습니다. 사용자의 로컬 머신에 아래와 같은 명령어를 입력하여 Helm 패키지를 설치합니다.
- Mac
- Linux(Ubuntu)
-
Homebrew 패키지 매니저를 이용하여 설치합니다.
brew install helm
-
설치가 정상적으로 되었는지 아래 명령어를 통해 확인합니다.
helm version
# version.BuildInfo{Version:"v3.14.0", GitCommit:"3fc9f4b2638e76f26739cd77c7017139be81d0ea", GitTreeState:"clean", GoVersion:"go1.21.6"}
-
curl
명령어를 이용하여 설치합니다.curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh -
설치가 정상적으로 되었는지 아래 명령어를 통해 확인합니다.
helm version
# version.BuildInfo{Version:"v3.14.0", GitCommit:"3fc9f4b2638e76f26739cd77c7017139be81d0ea", GitTreeState:"clean", GoVersion:"go1.21.6"}
Type 1. Nvidia GPU 워크노드 구축
Type 1에서는 쿠버네티스 클러스터에 Nvidia GPU 워크노드 구축하는 방법을 설명합니다.
Step 1. 쿠버네티스 클러스터에 Nvidia GPU 노드 풀 생성하기
이 문서는 쿠버네티스 클러스터를 생성하는 방법을 다루지 않습니다. 새로운 클러스터를 생성하거나 기존에 존재하는 클러스터에 GPU 노드 풀을 생성합니다. 카카오클라우드 콘솔에서 쿠버네티스 노드 풀을 생성하는 방법은 다음과 같습니다.
-
카카오클라우드 콘솔에 접속합니다.
-
Kubernetes Engine > 클러스터 목록에서 작업을 진행할 클러스터 혹은 [클러스터 생성] 버튼을 클릭합니다.
- 노드 풀을 생성할 클러스터를 클릭한 경우, 클러스터의 상세 페이지의 노드 풀 탭에서 [노드 풀 생성] 버튼을 누른 후, 노드 풀 정보를 입력하고 노드 풀을 생성합니다.
- [클러스터 생성] 버튼을 클릭한 경우, 클러스터 만들기의 단계별로 정보를 입력합니다. 2단계: 노드 풀 설정에서 다음을 참고해 노드 풀 정보를 입력하고 클러스터를 생성합니다.
노드 풀 유형 인스턴스 유형 노드 수 볼륨(GB) GPU p2i.6xlarge 1 100 -
GPU 노드를 생성할 시, 단일 GPU 인스턴스로 생성되도록 사용자 스크립트에 해당 코드를 작성합니다.
sudo nvidia-smi -mig 0
Step 2. Nvidia GPU 워크노드 환경 구성하기
nvidia-k8se-device-plugin은 클러스터 내 GPU를 자동으로 노출하고 관리, 실행 등에 필요한 기능을 제공합니다. 노드 풀을 통해 GPU 워크노드를 생성하면, GPU 리소스를 사용하기 위해 필요한 Driver, Container Runtime 등의 환경 구축을 기본으로 제공합니다.
-
GPU를 쿠버네티스 클러스터에 노출하기 위해 Helm을 이용하여 nvidia-k8s-device-plugin을 구성 요소에 추가합니다.
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
helm repo update
helm install \
--version=0.12.3 \
--namespace nvidia-device-plugin \
--create-namespace \
--generate-name \
nvdp/nvidia-device-plugin -
nvidia-k8s-device-plugin이 클러스터에 추가되었는지 확인합니다.
kubectl get all -A | grep nvidia
# kube-system pod/nvidia-device-plugin-daemonset-dpp4b 1/1 Running 0 64m
# kube-system pod/nvidia-device-plugin-daemonset-qprc7 1/1 Running 0 64m
# kube-system daemonset.apps/nvidia-device-plugin-daemonset 2 2 2 2 2 <none> 64m -
아래 명령어로 노드 리소스의 상세 정보를 출력해, 자원 용량에 GPU가 추가된 것을 확인합니다.
kubectl describe nodes | grep nvidia
# nvidia.com/gpu: 1
# nvidia.com/gpu: 1
# ... -
쿠버네티스 클러스터에 GPU 테스트용 파드를 추가합니다.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vector-add
image: "nvidia/samples:vectoradd-cuda10.2"
resources:
limits:
nvidia.com/gpu: 1
EOF -
아래 명령어로 작업이 수행되었는지 확인합니다.
kubectl get pod/gpu-test
# NAME READY STATUS RESTARTS AGE
# gpu-test 0/1 Completed 0 2m -
아래 명령어로 작업 수행 로그를 확인할 수 있습니다.
kubectl logs gpu-test
# GPU 0: NVIDIA A100 80GB PCIe ...
# [Vector addition of 50000 elements]
# Copy input data from the host memory to the CUDA device
# CUDA kernel launch with 196 blocks of 256 threads
# Copy output data from the CUDA device to the host memory
# Test PASSED
# Done -
생성된 테스트용 Pod를 제거합니다.
kubectl delete pod/gpu-test
# pod "gpu-test" deleted
Type 2. MIG 지원 Nvidia GPU 워크노드 구축
Type 2에서는 쿠버네티스 클러스터에 GPU 작업 노드를 생성하고 MIG를 사용하는 방법 중 하나를 설명합니다.
카카오클라우드에서 제공하는 일부 GPU(예. A100 등)는 MIG(Multi Instance GPU)를 지원합니다. 사용자는 쿠버네티스 클러스터 노드를 GPU 지원 유형으로 생성하고 MIG 전략을 이용하여 리소스를 더 효율적으로 사용할 수 있습니다.
해당 GPU가 제공되는 인스턴스는 인스턴스 유형별 사양에서 확인할 수 있습니다.
Step 1. 쿠버네티스 클러스터에 GPU 워크노드 추가하기
이 문서에서는 K8s 클러스터를 생성하는 방법을 다루지 않습니다. 새로운 클러스터를 생성하거나 기존에 존재하는 클러스터에 GPU 노드 풀을 생성합니다.
-
카카오클라우드 콘솔에 접속합니다.
-
Kubernetes Engine > 클러스터 목록에서 작업을 진행할 클러스터 혹은 [클러스터 생성] 버튼을 클릭합니다.
- 노드 풀을 생성할 클러스터를 클릭한 경우, 클러스터의 상세 페이지의 노드 풀 탭에서 [노드 풀 생성] 버튼을 누르고 노드 풀 정보를 입력합니다.
- [클러스터 생성] 버튼을 클릭한 경우, 클러스터 만들기의 단계별로 정보를 입력합니다. 다음을 참고하여 클러스터 만들기의 2단계: 노드 풀 설정에서 노드 풀 정보를 입력합니다.
노드 풀 유형 인스턴스 유형 노드 수 볼륨(GB) GPU p2i.6xlarge 1 100 -
GPU 노드를 생성할 시, 노드 프로비저닝 단계에서 MIG를 허용하고 GPU 리소스를 MIG로 분리하는 스크립트를 작성합니다. GPU를 7개의 인스턴스로 분리하고 GPU 컨테이너 런타임 설정을 진행합니다.
sudo nvidia-smi -mig 1
sudo nvidia-smi mig -cgi 19,19,19,19,19,19,19 -C -
노드 풀을 생성합니다.
Step 2. Nvidia GPU 워크노드 환경 구성하기
Step 1 작업을 통해 MIG가 설정된 GPU 노드가 클러스터에 생성되었습니다.
-
GPU 노드를 K8s 클러스터에 노출하기 위해 Helm을 이용하여 nvidia-k8s-device-plugin을 k8s 구성 요소에 추가합니다.
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
helm repo update -
커맨드에서 설정 flag로 migStrategy를 사용할 수 있습니다. MIG 리소스를 클러스터에서 사용할 수 있습니다. 더 많은 정보가 필요하다면 NVIDIA/k8s-device-plugin Github을 참고하시기 바랍니다.
helm install \
--version=0.12.3 \
--namespace nvidia-device-plugin \
--create-namespace \
--set compatWithCPUManager=true \
--set migStrategy=mixed \
--generate-name \
nvdp/nvidia-device-plugin -
Helm 커맨드를 실행하면 nvidia-k8se-device-plugin Pod가 gpu worknode에 올라가고 GPU를 클러스터에 노출합니다. 아래 명령어로 노드 리소스의 상세 정보를 출력해 자원 용량에 mig 7개가 추가된 것을 확인합니다.
kubectl describe nodes | grep nvidia
# nvidia.com/mig-1g.10gb: 7
# nvidia.com/mig-1g.10gb: 7 -
현재 작업을 수행 중인 GPU 정보를 출력하는 명령어로, 워크로드 여러 개를 클러스터에 올립니다. 클러스터 리소스의 스케줄링을 확인합니다.
for i in $(seq 7); do
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: mig-example-${i}
spec:
restartPolicy: Never
containers:
- name: cuda-container
image: nvidia/cuda:11.2.2-base-ubuntu20.04
command: ["nvidia-smi"]
args: ["-L"]
resources:
limits:
nvidia.com/mig-1g.10gb: 1
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
EOF
done
# pod/mig-example-1 created
# pod/mig-example-2 created
# pod/mig-example-3 created
# pod/mig-example-4 created
# pod/mig-example-5 created
# pod/mig-example-6 created
# pod/mig-example-7 created -
생성된 pod를 확인합니다. 명령어에 대한 결과와 같이 작업이 완료되었는지 확인합니다.
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# mig-example-1 0/1 Completed 0 29s
# mig-example-2 0/1 Completed 0 26s
# mig-example-3 0/1 Completed 0 22s
# mig-example-4 0/1 Completed 0 19s
# mig-example-5 0/1 Completed 0 15s
# mig-example-6 0/1 Completed 0 12s
# mig-example-7 0/1 Completed 0 9s -
작업이 완료되면 로그를 통해 해당 Pod를 실행한 MIG의 UUID를 확인할 수 있습니다. 아래 명령어를 입력해 결과를 확인합니다.
for i in $(seq 7); do
kubectl logs mig-example-${i} | grep MIG
done
# MIG 1g.10gb Device 0: (UUID: MIG-aaaaa)
# MIG 1g.10gb Device 0: (UUID: MIG-bbbbb)
# MIG 1g.10gb Device 0: (UUID: MIG-ccccc)
# MIG 1g.10gb Device 0: (UUID: MIG-aaaaa)
# MIG 1g.10gb Device 0: (UUID: MIG-bbbbb)
# MIG 1g.10gb Device 0: (UUID: MIG-ddddd)
# MIG 1g.10gb Device 0: (UUID: MIG-eeeee) -
생성한 예제 Pod를 제거합니다.
for i in $(seq 7); do
kubectl delete pod mig-example-${i}
done
# pod "mig-example-1" deleted
# pod "mig-example-2" deleted
# pod "mig-example-3" deleted
# pod "mig-example-4" deleted
# pod "mig-example-5" deleted
# pod "mig-example-6" deleted
# pod "mig-example-7" deleted