본문 바로가기

AI ML

Kubernetes GPU Operator와 Time Slicing 간단히 알아보기

반응형

EKS에서 MLOps를 할 수 있도록 공부중인데 그 과정들을 하나씩 정리해보려 한다.

 

그 첫 번째로 GPU Operator와 Time Slicing에 대해서 정리해본다.

 

 

 

 

GPU Operator란?

NVIDIA GPU Operator는 k8s 클러스터 내에서 NVIDIA 계열의 GPU 노드로 파드를 편하게 관리할 수 있도록 도와주는 툴이다.

 

 

Operator 패턴이란?

Operator 패턴이란 CR(Custom Resource) 파일을 우리가 k8s에게 제공하면 k8s에 파드 형태로 떠있는 Operator가 이를 지속적으로 확인하면서 Custom Resource에 정의된 spec 대로 원하는 리소스들(ex. NVIDIA Device Plugin과 관련된 파드 및 Service Account, Role, ..)을 설치 및 관리해주는 패턴을 의미한다.

 

Operator 패턴의 대표적인 예는 ElasticSearch를 편하게 관리할 수 있게 해주는 ECK Operator, 시계열 메트릭을 편하게 스크래핑 및 관리를 할 수 있도록 해주는 Prometheus Operator 등이 있겠다.

 


GPU Operator가 관리하는 컴포넌트들은?

https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/index.html

 

About the NVIDIA GPU Operator — NVIDIA GPU Operator 23.9.2 documentation

Kubernetes provides access to special hardware resources such as NVIDIA GPUs, NICs, Infiniband adapters and other devices through the device plugin framework. However, configuring and managing nodes with these hardware resources requires configuration of m

docs.nvidia.com

 

 

[1] NFD(Node-feature-discovery)

NFD(node-feature-discovery)는 Kubernetes 클러스터 내 Node의 하드웨어 스펙을 감지하고 이를 노드 레이블 및 어노테이션 등을 사용하여 해당 기능들을 광고(advertising)하는 역할을 수행한다.

 

- NFD Master (Deployment로 배포) : NFD Worker로부터 노드에 대한 정보를 수집한 뒤 각 노드에 Label로 추가한다.

- NFD Worker (DaemonSet으로 배포) : 각 노드로부터 정보를 취합한 뒤 Master에게 전송해주는 역할을 한다. 이 때문에 DaemonSet으로 배포된다.

 

 

[2] GFD(GPU-feature-discovery)

해당 노드가 사용할 수 있는 GPU 관련 정보를 추출 및 취합하여 NFD Master에게 전달하는 역할을 한다.

NFD Worker의 역할과 유사한데 GPU 관련 정보만 뽑는다.

 

당연히 DaemonSet으로 배포된다.

 

 

[3] NVIDIA Driver Installer

노드에서 GPU를 감지할 수 있게 NVIDIA 그래픽 카드 드라이버를 설치해주는 인스톨러이다.

당연히 Node에 이미 Driver가 설치되어 있다면 따로 구성하지 않아도 되며 DaemonSet으로 구성된다. 사전에 설치되어 있다면 비활성화해도 된다.

 

 

[4] NVIDIA Device Plugin

Kubernetes YAML을 작성하다보면 pod resource spec을 작성하게 된다. 주로 CPU와 Memory spec을 작성할텐데 GPU Node에서는 nvidia.com/gpu를 주로 사용하게 된다.

 

NVIDIA Device Plugin은 nvidia.com/gpu 리소스를 감지하고 처리할 수 있도록 도와주는 컴포넌트이며 DaemonSet으로 배포된다.

 

 

[5] NVIDIA Container Toolkit

NVIDIA Driver가 설치가 되었다면 이를 기반으로 컨테이너를 GPU 환경에서 구동할 수 있도록 도와준다.

 

DaemonSet으로 구성되며 사전에 설치되어 있다면 비활성화해도 된다.

 

 

[6] GPU Operator Validator

GPU를 사용하는 컨테이너를 실행하여 GPU 환경이 잘 세팅되어 있는지 체크할 수 있도록 도와준다.

 

 

[7] DCGM Exporter

GPU 관련 메트릭을 수집하여 GPU 사용량, GPU 온도, Power 등을 확인할 수 있도록 도와준다.

 

DaemonSet으로 설치되며 GPU Workload를 운영한다면 필수 모니터링으로 꼽힌다.

 

 

 

 


GPU 리소스들을 쪼개 사용하는 방법

필자는 AWS EKS 환경에서 대부분의 서비스들을 운영중이다.

 

왜 GPU를 쪼개 써야 하는지 궁금해할 수 있는데 GPU 노드들은 비용이 매우 비싸다.

 

따라서 최대한 효율적이고 저렴한 가격으로 GPU 노드들을 사용하는게 중요한데 이를 도와주는 기술이 NVIDIA Device Plugin의 Time Slicing이다.

 

물론 MIG(Multi Instance GPU), MPS(Multi Process Service)등의 방법 또한 존재하지만 MIG의 경우 A100 같은 고성능 GPU 노드에서만 사용 가능하며 MPS는 NVIDIA Device Plugin에서 정식으로 지원되지 않아 별도 NVIDIA Device Plugin을 사용해야 한다는 단점이 있다.

 

따라서 가장 간단하게 사용할 수 있는 Time Sliciing에 대해 간단히 알아보자.

 

Time Slicing ?

Time Slicing은 temporal sharing(임시 공유)를 통해 여러 CUDA 프로세스를 동시에 실행하는 GPU 시간 분할 스케줄러를 활용한다.

Time Slicing이 활성화되면 GPU는 일정한 시간 간격으로 Process 간 전환하여 공정한 공유 방식으로 여러 프로세스 간에 컴퓨팅 리소스를 공유한다.

이는 CUDA 프로세스 간 Context Switching이 지속적으로 발생하기 때문에 오버헤드가 발생하며 jitter와 더 높은 latency를 유발한다.

또한 GPU를 공유하는 CUDA 프로세스 간 메모리 격리 수준을 제공하지 않으며 메모리 할당 제한도 제공되지 않아 OOM 오류가 자주 발생할 수 있다.

 

이런 단점이 있지만 가장 사용하기 쉬운 접근 방식이기 때문에 필자는 Time Slicing을 통해 GPU 노드 상에서 GPU 워크로드들을 운영하려고 한다.

 

다음은 NVIDIA Device Plugin의 ConfigMap 설정 예시이다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config-all
data:
  any: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu
          replicas: 4

 

 

이렇게 구성할 경우 해당 Kubernetes Node의 GPU 개수가 1개일 경우 총 4개의 GPU를 명시적으로 사용하는 것처럼 시분할하여 사용할 수 있게 해준다.

 

후에 Pod 생성 시 Pod resource spec 에서 nvidia.com/gpu를 1 혹은 2 등으로 설정함으로써 몇개의 gpu를 사용할 수 있는지 정의할 수 있게 된다.

 

물론 이것은 timeSlicing에 의해 나눠진것처럼 보일 뿐 실제 GPU 개수는 4개가 아닐것이다.

 

 

 


맺음말

필자는 EKS를 운영하기에 EKS 기준으로 설명해본다.

아직 개념을 접한지 얼마 안되었기에 추후 보강이 필요한 내용이 있다면 추가로 보강하겠음

 

 

- EKS에서 GPU 리소스를 사용하기 위해서는 g4dn.xlarge, g5.xlarge 등 GPU를 지원하는 인스턴스 타입을 골라야 한다.

- NVIDIA Driver가 설치되어 GPU 리소스를 사용할 수 있게끔 해줘야 한다.

- Container 환경에서 NVIDIA GPU를 구동하기 위해 NVIDIA Container Toolkit이 필요하다.

- time slicing을 활용하며 nvidia.com/gpu 리소스를 감지할 수 있도록 NVIDIA Device Plugin이 도와준다.

- NFD, GFD는 꼭 필요한지 아직까지 잘 모르겠다. label, annotation을 node에 달아주는 것 같은데 어디서 쓰일지 좀 더 확인해보자.

 

 

 

 

정리해야 할 내용들이 아직 더 많다.

아래는 필자가 추가로 확인 예정인 내용들이다.

 

 

1. Pytorch 기반 컨테이너 이미지는 사이즈가 기본적으로 크다. 이를 줄일 수 있는 방법이 무엇이 있을까? 단순히 .gitignore, .dockerignore, 불필요 requirements.txt 등을 줄이기가 아니라 실제 build 된 container에 접속하여 좀 더 어떤 부분에서 컨테이너 이미지가 매우 커졌을 지 조사해보자.

 

2. EKS 노드에서 좀 더 빠르게 Image를 Pulling 할 수 있는 방법은 무엇일까? 필자가 확인했을 때 약 8G 기준으로 4~5분이 소요되었다. 좀 더 빠르게 처리할 수 있는 방안에 대해 알아보자.

 

3. DCGM Exporter를 활용해 Grafana에서 모니터링하는 방법과 어떤 메트릭들을 봐야할까?

 

4. 비용 최적화를 위해 GPU 개발계 노드는 Spot + TimeSlicing으로 운영해야 할 것이라 생각한다. Spot의 경우 Light 한 컨테이너 이미지가 중요하고 Application에서 Graceful하게 요청을 처리하고 죽는 로직이 필요한데 이런 일련의 내용들을 정리해보자.

추가로 EKS Karpenter를 사용하기에 Karpenter에서 이를 활용하는 방법에 대해 알아보자.

 

5. 운영계는 CUDA 프로세스 간 Context Switching 문제로 인해 병목 현상이 발생할 수 있기에 1 GPU - 1 Process를 당분간 유지하려고 한다.

이 때 활용할 수 있는 비용 최적화 방안은 Spot과 On-Demand를 혼합하는 방식일 것이라 생각한다.

Helm Chart로 이를 구성하는 방안에 대해 알아보자.

 

 

 

 

 

Ref

https://heumsi.github.io/blog/posts/setup-gpu-env-in-k8s/

https://medium.com/@api.test9989/gpu-쪼개기-time-slicing-acbf5fffb16e

https://towardsdatascience.com/how-to-increase-gpu-utilization-in-kubernetes-with-nvidia-mps-e680d20c3181

반응형