k3s·GPU 준비
k3s 설치, RuntimeClass nvidia, NVIDIA device plugin(시분할 포함), 레지스트리 pull 설정
학습·이미지 빌드·서빙은 k3s 의 파드로 돕니다. 이 페이지에서는 k3s 를 올리고, 파드가 GPU 를 쓸 수 있게 하고, 앱이 GPU 를 "슬롯" 으로 셀 수 있게 만듭니다. 명령은 모두 서버에서 실행하며, 소스는 /opt/geo-mlops 에 있다고 가정합니다.
1. NVIDIA 드라이버와 Container Toolkit
k3s 는 시작할 때 nvidia-container-runtime 이 있는지 보고 containerd 에 nvidia 런타임을 등록합니다. 그래서 드라이버와 NVIDIA Container Toolkit 을 k3s 보다 먼저 설치합니다(설치 방법은 NVIDIA 공식 문서를 따릅니다). 이미 k3s 가 떠 있다면 Toolkit 설치 뒤 sudo systemctl restart k3s 로 다시 읽게 합니다.
nvidia-smi # 드라이버 확인
which nvidia-container-runtime # Toolkit 확인
2. k3s 설치
-
k3s 를 설치합니다(공식 설치 스크립트).
curl -sfL https://get.k3s.io | sh - -
노드가
Ready인지, kubeconfig 가 생겼는지 확인합니다. 앱 컨테이너는 이 파일을 그대로 읽습니다.sudo k3s kubectl get nodes ls -l /etc/rancher/k3s/k3s.yaml -
RuntimeClass
nvidia가 있는지 봅니다. 없으면 만듭니다.sudo k3s kubectl get runtimeclass nvidia || \ cat <<'EOF' | sudo k3s kubectl apply -f - apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: nvidia handler: nvidia EOF
3. NVIDIA device plugin
RuntimeClass 만으로도 파드에 GPU 를 넣을 수는 있지만, 그러면 클러스터가 GPU 점유를 모릅니다. GPU 한 장에 두 파드가 올라가 서로 메모리 부족으로 죽습니다. device plugin 은 노드가 GPU 를 nvidia.com/gpu 자원으로 광고(클러스터에 몇 개 있는지 알림)하게 합니다. 그러면 자리가 없을 때 파드가 Pending 으로 기다립니다. 앱의 GPU 슬롯 화면도 이 광고값을 셉니다.
설치 파일은 두 가지입니다. 둘 중 하나만 적용합니다(같은 DaemonSet 이름을 씁니다).
| 파일 | 언제 |
|---|---|
scripts/serving/nvidia-device-plugin.yml | GPU 한 장 = 슬롯 하나. GPU 가 여러 장이고 파드마다 한 장씩 주면 될 때 |
scripts/serving/nvidia-device-plugin-timeSlicing.yml | GPU 한 장을 여러 슬롯(기본 8) 으로 나눠 광고. GPU 가 한두 장인데 학습·서빙을 여럿 함께 올려야 할 때 |
-
하나를 적용합니다. kubeconfig 만 있으면 됩니다.
sudo k3s kubectl apply -f /opt/geo-mlops/scripts/serving/nvidia-device-plugin-timeSlicing.yml -
노드마다 광고되는 GPU 수를 확인합니다(시분할이면 GPU 수 × 8).
sudo k3s kubectl get nodes -o custom-columns='NAME:.metadata.name,ALLOC:.status.allocatable.nvidia\.com/gpu' -
앱에 전역 관리자로 로그인해 시스템 콘솔의 GPU 슬롯 화면을 엽니다. device plugin 이
Ready이고 총 슬롯이 위 숫자와 같으면 됩니다.GPU 슬롯: 노드가 광고하는 GPU 와 device plugin 상태
replicas(기본 8)를 바꾸려면 ConfigMap 을 고쳐 다시 적용한 뒤 반드시 롤아웃합니다. 그러지 않으면 반영되지 않습니다.
sudo k3s kubectl apply -f /opt/geo-mlops/scripts/serving/nvidia-device-plugin-timeSlicing.yml
sudo k3s kubectl -n kube-system rollout restart ds/nvidia-device-plugin-daemonset
4. 컨테이너 레지스트리를 k3s 가 받을 수 있게
앱의 내장 레지스트리(/v2)는 평문 HTTP 입니다. 이미지가 오가는 길은 둘입니다.
| 방향 | 누가 | 기본 주소 | 설정 |
|---|---|---|---|
| push | 빌드 파드 안의 BuildKit | 10.42.0.1:10000 | BuildKit 에 insecure 가 이미 켜져 있음(GEO_MLOPS_SERVING_REGISTRY_INSECURE=true) |
| pull | 노드의 containerd | localhost:10000 | containerd 는 localhost 를 insecure 로 취급하므로 단일 노드면 할 일 없음 |
그래서 서버 한 대 구성에서는 registries.yaml 이 필요 없습니다. pull 주소를 localhost 가 아닌 값으로 바꾼 경우(노드가 여럿이라 GEO_MLOPS_SERVING_REGISTRY_PULL 을 호스트:포트 로 지정한 경우)에만, 각 노드의 /etc/rancher/k3s/registries.yaml 에 그 주소를 insecure 로 등록합니다.
# /etc/rancher/k3s/registries.yaml: <registry-host>:10000 을 실제 pull 주소로
mirrors:
"<registry-host>:10000":
endpoint: ["http://<registry-host>:10000"]
configs:
"<registry-host>:10000":
tls:
insecure_skip_verify: true
sudo systemctl restart k3s # registries.yaml 은 k3s 가 시작할 때 읽는다
다음: 필수 보안 설정