쿠버네티스는 장치 플러그인 프레임워크를 통해 NVIDIA GPU와 같은 특수 하드웨어 자원에 대한 액세스를 제공하지만, 이러한 하드웨어 자원이 탑재된 노드를 구성하고 관리하는 것은 다수의 소프트웨어 구성 요소(드라이버, 컨테이너 런타임, 라이브러리 등)의 설정이 필요하며 오류가 발생하기 쉽다.
수동 설치 (Manual Install)
왼쪽의 "Manual Install" 부분은 개별 구성 요소들을 수동으로 설치해야 하는 과정을 보여준다.
이 방식에서는 리눅스 배포판 위에 NVIDIA 드라이버를 먼저 설치하고, 그 위에 NVIDIA 런타임을 설치한다. 이후에 쿠버네티스를 설치하고, 마지막으로 NVIDIA 디바이스 플러그인과 모니터링 도구를 설치한다. 일부 구성 요소는 베어 메탈 서버에 직접 설치해야 하며, 이 과정은 오류가 발생하기 쉽다. 각각의 구성 요소들은 버전 호환성을 고려하여 정확히 맞추어 설치해야 하고, 업데이트나 유지보수 시에도 이러한 과정을 반복해야 한다.
GPU Operator를 통한 자동화 (Automated by GPU Operator)
오른쪽의 "Automated by GPU Operator" 부분은 GPU Operator를 사용하여 이러한 과정을 자동화하는 방식을 보여준다. 이 경우에는 모든 NVIDIA 구성 요소들이 컨테이너화되어 있고, GPU Operator가 쿠버네티스 API를 통해 자동으로 관리한다. 사용자는 GPU Operator를 설치하기만 하면 되며, 나머지 NVIDIA 드라이버, 런타임, 디바이스 플러그인, 모니터링 도구들은 GPU Operator에 의해 자동으로 배포 및 관리된다. 이러한 자동화는 설치 과정을 간소화할 뿐만 아니라, 구성 요소들의 버전 관리와 업그레이드를 용이하게 한다.
요약하자면, GPU Operator는 쿠버네티스 내에서 NVIDIA GPU를 쉽게 배포하고 관리할 수 있게 하는 도구로서, 수동으로 여러 단계에 걸쳐 설정해야 하는 복잡한 과정을 자동화하여 효율성을 크게 향상시킨다.
구조적으로 차이가 있는 부분들이 보인다.
k8s를 운영하며 GPU를 사용할때 Helm을 받아 gpu operator를 설치하고 각 서버에서 nvidia를 볼 수 있도록 NVIDIA Driver는 각 서버에 설치관리를 진행하고, gpu operator를 받아 설치 시 False로 설정을 해주면 된다.
# Add to helm list
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
# Download helm chart
helm pull nvidia/gpu-operator --untar
gpu operator를 설치할 수 있고 해당 폴더에 들어가 values.yaml을 수정하면 된다.
# values.yaml
driver:
enabled: false
...
migManager:
enabled: false
다음과 같이 수정하고 싶은 컴포넌트에서 enabled를 false로 수정 후 배포하면 된다.
kubectl get pods -n gpu-operator
그러면 다음과같이 설치가 되는것을 확인할 수 있다.
CUDA_VISIBLE_DEVICES: "0"
이렇게 되면 CUDA_VISIBLE_DEVICES: "0" 다음과같이 yaml파일 작성시에 gpu를 선택해서 배포할 수 있다.
nvidia.com/gpu 옵션을 사용해서 배포하게되면 gpu memory를 선점하여 한 서버내 여러 GPU Graphic card를 가지고 있거나, 메모리가 충분히 여유가 있어도 그래픽 카드의 개수 이상 배포할 수 없는 상황이 발생하게 된다.
다만 이렇게 진행하는것또한 문제점이 존재한다.
바로 Kubernetes에서는 GPU를 인식하지 못한다.. GPU Memory가 꽉차게 되면 배포되었던 Pod들이 죽는 모습을 경험할 수 있다. 물론 배포했던 Pod만 죽으면 다행이지만 해당 그래픽카드에 있는 다른 Pod 역시 죽게 된다.
하여 첫번째로 생각할 수 있는것이 Nvidia에서 제공하는 MIG 이다.
Nvidia MIG
만일 mig를 false로 안주고 위에서 설치했다면 다음을 참고하면 된다.(유의 A30, A100, H100과 같은 한정된 지원)
kubectl label nodes $NODE nvidia.com/mig.config=all-1g.6gb
다음과 같이 노드에 라벨을 추가하고 배포함으로써 각 분리된 GPU 에서 서버들이 뜰 수 있게 된다.
그렇지만 이또한 제한적인 부분이 있다.
첫째로 GPU 메모리가 6gb로 잘랐다 생각하면 그것보다 적게 GPU Memory를 사용하는 서버가 존재한다면 리소스 낭비가 된다.
둘째로 아래와 같이 어떻게 자르냐에 따라 mig를 진행한 후 남는 메모리가 생기는 부분도 있다.
아? 그러면 어떻게 GPU를 더 효율적으로 쓸 수 있을까?
다음으로 생각해볼 수 있는것이 그러면 기존에 여러 Pod들이 죽는 부분을 막아주면 되지 않을까? 싶어 생긴 방식이 Extended Resource를 정의하는것이다.
방법부터 알아보자
kubectl proxy
proxy를 먼저 열어준다.
이후
curl --header "Content-Type: application/json-patch+json" --request PATCH --data '[{"op": "add", "path": "/status/capacity/gputaeng0.com~1vram", "value":"48"}]' http://localhost:8001/api/v1/nodes/k8s-worker-ex/status
다음과 같이 적용할 노드 그리고 value값과 path를 변경해주면 된다.
이후 kubectl describe node [node name]을 통해 확인할 수 있다.
kubectl describe node [node name]
...
Capacity:
...
gputaeng0.com/vram: 48
...
이는 여전히 GPU는 Kubernetes에서 알지 못한다. 하지만 우리가 배포시에 해당 옵션의 값을 조정해가며 GPU Pod를 배포하면 잘 운영할 수 있을것이다.
...
resources:
...
gputaeng0.com/vram: 4
...
limits:
...
gputaeng0.com/vram: 4
...
...
A30을 예로 들면 24GB의 그래픽카드가 있고 위에서 value가 48이였기에 500Mib처럼 생각을 하면 된다. 그러면 4는 2GB정도 준것으로 생각을 하면 되고 이처럼 여러 Pod들을 배포하면 된다.
이를 잘 적용하기 위해서는 Test시 Max GPU Memory를 어느정도로 점유할 것인가에 대한 부분이 잘 이루어져야 된다.
행운을 빈다~
위의 제시된 방법보다 좋은 Dynamic mig 방법이 있으면 귀담아 듣고 싶습니다 ,,,
'클라우드' 카테고리의 다른 글
EBS 볼륨 확장 및 축소 (0) | 2024.04.02 |
---|---|
kubernetes Role-based Access Control(RBAC) 역할 기반 정의(1) (0) | 2024.03.27 |
Terraform tfstate 상태 파일 관리 (0) | 2024.03.20 |
Kubernetes liveness, readness, startup probe (0) | 2024.03.13 |
AWS IP당 추가 비용, EBS SSD 스토리지 마이그레이션 (2) | 2024.02.28 |
댓글