random_image

K3S에 GPU worker 노드를 추가해보자

tony | March 31, 2024, 10:25 a.m. | devops | kubernetes

홈네트워크로 사용중인 K3S 클러스터에 GPU 머신을 워커로 추가하는 방법

K3S에 GPU worker 노드 추가하는 방법

홈 네트워크에 구축한 K3S 에 GPU 서버 노드를 추가한후 사용할 수 있도록 셋팅해보자.

우선 알아둬야할 배경지식이 있다.

k3s 는 컨테이너엔진을 기반으로 동작하는데, 아래 세가지 중 하나의 컨테이너 엔진을 선택할 수 있다.

  • containerd
  • docker
  • cri-o

k3s의 default 엔진은 containerd를 사용하도록 되어있으므로 해당 엔진을 기반으로 설명하도록 하겠음.

GPU 사용을 위해서 nvidia에서 제공하는 containerd 엔진을 default로 사용하도록 셋팅하는 작업이 필요하다.
https://github.com/NVIDIA/k8s-device-plugin#prerequisites 에 자세한 내용이 설명되어있다.
간략하게 서두에서 요약해보면 GPU 노드에서 다음의 과정들이 필요하다.

nvidia driver 와 nvcc 설치

sudo ubuntu-drivers list
sudo ubuntu-drivers autoinstall  # reboot 하면 nvidia-smi 사용가능

sudo apt-get install nvidia-cuda-toolkit  # nvcc --version

nvidia-container-toolkit 설치

nvidia-container toolkit 을 gpu node에 설치하고, default로 사용하도록 셋팅하고 containerd 재시작

sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd (만약 containerd 관련 에러가 뜨면 아래 sub 불릿 참고)

만약, containerd 가 없다면 설치가 필요 (참고: https://github.com/containerd/containerd/blob/main/docs/getting-started.md)

containerd, runs, cni plugins 가 설치되어있어야한다.

k3s 에 worker로 gpu node 추가

https://docs.k3s.io/kr/quick-start 가이드를 따라 수행한다.

K3S_TOKEN은 k3s master 서버의 /var/lib/rancher/k3s/server/node-token에 저장되어있어서 확인 필요.

curl -sfL https://get.k3s.io | K3S_URL=https://$K3S_SERVER:6443 K3S_TOKEN=$K3S_TOKEN sh -

노드를 추가한 이후 다음과 같이 노드가 뜬다.

$ kubectl get nodes
NAME          STATUS     ROLES                  AGE   VERSION
mango         Ready      <none>                 16h   v1.28.8+k3s1
raspberrypi   Ready      control-plane,master   43d   v1.28.6+k3s2

gpu 노드에 label을 지정해준다.

 k label nodes mango machine=gpu

다음과 같이 role 지정을 해줘도 됨

$ kubectl label node mango kubernetes.io/role=worker
node/mango labeled

$ kubectl get nodes # --show-labels 붙혀주면 레이블도 볼 수 있음
NAME          STATUS     ROLES                  AGE   VERSION
raspberrypi   Ready      control-plane,master   43d   v1.28.6+k3s2
mango         NotReady   worker                 16h   v1.28.8+k3s1

nvidia-device-plugin 배포

k3s 재시작하고, nvidia-container-runtime 이 있으면 자동으로 감지하도록 설정

https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.5/nvidia-device-plugin.yml 를 배포

그대로 배포해서는 안되고, RuntimeClass를 생성하고 이를 참고하도록 DaemonSet를 생성한다.

# cat nvidia-runtime-class.yml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  # The name the RuntimeClass will be referenced by.
  # RuntimeClass is a non-namespaced resource.
  name: "nvidia"
# The name of the corresponding CRI configuration
handler: "nvidia"

spec.template.spec에 다음의 node selecter 혹은 affinity 를 통해 gpu 노드를 선택하도록 변경이 필요

# cat nvidia-device-plugin.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: nvidia-device-plugin-ds
    spec:
      runtimeClassName: nvidia
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                - key: machine
                  operator: In
                  values:
                  - "gpu"
      nodeSelector:
        machine: gpu
      tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      priorityClassName: "system-node-critical"
      containers:
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.14.5
        name: nvidia-device-plugin-ctr
        env:
          - name: FAIL_ON_INIT_ERROR
            value: "false"
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        volumeMounts:
        - name: device-plugin
          mountPath: /var/lib/kubelet/device-plugins
      volumes:
      - name: device-plugin
        hostPath:
          path: /var/lib/kubelet/device-plugins

Running GPU Jobs

RuntimeClass로 nvidia 를 갖는 pod이 gpu를 사용할 수있는지 테스트 해봄

# test-gpu-pod.yaml
apiVersion: v1
kind: Pod
metadata:
 name: gpu-pod
spec:
 restartPolicy: OnFailure
 runtimeClassName: nvidia
 containers:
   - name: cuda-container
     image: nvidia/cuda:12.3.2-base-ubuntu22.04
     command: ["nvidia-smi"]
     resources:
       limits:
         nvidia.com/gpu: 1 # requesting 1 GPU
(base) ➜  nvidia git:(dev) ✗ k logs gpu-pod
Sat Mar 30 09:32:22 2024
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.161.07             Driver Version: 535.161.07   CUDA Version: 12.3     |
|-----------------------------------------+----------------------+----------------------+
| 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 GeForce GTX 1060 6GB    Off | 00000000:01:00.0 Off |                  N/A |
| 34%   25C    P8               6W / 120W |    139MiB /  6144MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
+---------------------------------------------------------------------------------------+

주의사항

https://github.com/NVIDIA/k8s-device-plugin#quick-start 가이드를 따라 진행하는데 조심해야할 2가지 요소가 있었음

  • nvidia-device-plugin (DaemonSet) 배포시 RuntimeClass 지정과, gpu node를 선택하도록 해야함
  • pod 배포시 RuntimeClass 지정과 gpu 노드를 선택하도록 해야함

Last updated on March 31, 2024, 10:25 a.m.

LEAVE A COMMENT