본문으로 건너뛰기

Kubernetes Engine 클러스터에 NVIDIA GPU 워크노드 사용

Kubernetes Engine을 이용해 생성한 쿠버네티스 클러스터에서 GPU 노드를 생성하고, 워크로드에 GPU를 사용하는 두 가지 방법을 설명합니다.

안내

시작하기 전에

Kubernetes 패키지 관리를 도와주는 패키지 매니저인 Helm을 설치합니다. Helm을 통해 Kubernetes용 소프트웨어를 검색하거나 공유하고 사용할 수 있습니다. 사용자의 로컬 머신에 아래와 같은 명령어를 입력하여 Helm 패키지를 설치합니다.

  1. Homebrew 패키지 매니저를 이용하여 설치합니다.

    brew install helm
  2. 설치가 정상적으로 되었는지 아래 명령어를 통해 확인합니다.

    helm version
    # version.BuildInfo{Version:"v3.14.0", GitCommit:"3fc9f4b2638e76f26739cd77c7017139be81d0ea", GitTreeState:"clean", GoVersion:"go1.21.6"}

시작하기

Kubernetes Engine을 이용해 생성한 쿠버네티스 클러스터에서 GPU 노드를 생성하는 방식과, 워크로드에 GPU를 사용하는 방식 두 방법을 설명합니다.

Type 1. Nvidia GPU 워크노드 구축

Type 1에서는 쿠버네티스 클러스터에 Nvidia GPU 워크노드 구축하는 방법을 설명합니다.

Step 1. 쿠버네티스 클러스터에 Nvidia GPU 노드 풀 생성

이 문서는 쿠버네티스 클러스터를 생성하는 방법을 다루지 않습니다. 새로운 클러스터를 생성하거나 기존에 존재하는 클러스터에 GPU 노드 풀을 생성합니다. 카카오클라우드 콘솔에서 쿠버네티스 노드 풀을 생성하는 방법은 다음과 같습니다.

  1. 카카오클라우드 콘솔에 접속합니다.

  2. Kubernetes Engine > 클러스터 목록에서 작업을 진행할 클러스터 혹은 [클러스터 생성] 버튼을 클릭합니다.

    • 노드 풀을 생성할 클러스터를 클릭한 경우, 클러스터의 상세 페이지의 노드 풀 탭에서 [노드 풀 생성] 버튼을 누른 후, 노드 풀 정보를 입력하고 노드 풀을 생성합니다.
    • [클러스터 생성] 버튼을 클릭한 경우, 클러스터 만들기의 단계별로 정보를 입력합니다. 2단계: 노드 풀 설정에서 다음을 참고해 노드 풀 정보를 입력하고 클러스터를 생성합니다.
    노드 풀 유형인스턴스 유형노드 수볼륨(GB)
    GPU     p2i.6xlarge   1    100
  3. GPU 노드를 생성할 시, 단일 GPU 인스턴스로 생성되도록 사용자 스크립트에 해당 코드를 작성합니다.

    sudo nvidia-smi -mig 0

Step 2. Nvidia GPU 워크노드 환경 구성

nvidia-k8se-device-plugin은 클러스터 내 GPU를 자동으로 노출하고 관리, 실행 등에 필요한 기능을 제공합니다. 노드 풀을 통해 GPU 워크노드를 생성하면, GPU 리소스를 사용하기 위해 필요한 Driver, Container Runtime 등의 환경 구축을 기본으로 제공합니다.

  1. 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
  2. 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
  3. 아래 명령어로 노드 리소스의 상세 정보를 출력해, 자원 용량에 GPU가 추가된 것을 확인합니다.

    kubectl describe nodes | grep nvidia
    # nvidia.com/gpu: 1
    # nvidia.com/gpu: 1
    # ...
  4. 쿠버네티스 클러스터에 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
  5. 아래 명령어로 작업이 수행되었는지 확인합니다.

    kubectl get pod/gpu-test
    # NAME READY STATUS RESTARTS AGE
    # gpu-test 0/1 Completed 0 2m
  6. 아래 명령어로 작업 수행 로그를 확인할 수 있습니다.

    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
  7. 생성된 테스트용 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 노드 풀을 생성합니다.

  1. 카카오클라우드 콘솔에 접속합니다.

  2. Kubernetes Engine > 클러스터 목록에서 작업을 진행할 클러스터 혹은 [클러스터 생성] 버튼을 클릭합니다.

    • 노드 풀을 생성할 클러스터를 클릭한 경우, 클러스터의 상세 페이지의 노드 풀 탭에서 [노드 풀 생성] 버튼을 누르고 노드 풀 정보를 입력합니다.
    • [클러스터 생성] 버튼을 클릭한 경우, 클러스터 만들기의 단계별로 정보를 입력합니다. 다음을 참고하여 클러스터 만들기의 2단계: 노드 풀 설정에서 노드 풀 정보를 입력합니다.
    노드 풀 유형인스턴스 유형노드 수볼륨(GB)
    GPU     p2i.6xlarge   1    100
  3. 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
  4. 노드 풀을 생성합니다.

Step 2. Nvidia GPU 워크노드 환경 구성

Step 1 작업을 통해 MIG가 설정된 GPU 노드가 클러스터에 생성되었습니다.

  1. GPU 노드를 K8s 클러스터에 노출하기 위해 Helm을 이용하여 nvidia-k8s-device-plugin을 k8s 구성 요소에 추가합니다.

    helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
    helm repo update
  2. 커맨드에서 설정 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
  3. 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
  4. 현재 작업을 수행 중인 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
  5. 생성된 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
  6. 작업이 완료되면 로그를 통해 해당 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)
  7. 생성한 예제 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