본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout

내비게이션

  • Tech
  • Projects
  • Books
  • About
  • Tags

카테고리

  • AI / ML
  • 웹 개발
  • 프로그래밍
  • 개발 도구

연결

  • GitHub
  • Email
  • RSS
© 2026 Kreath Archive. All rights reserved.Built with Next.js + MDX
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 6장: Kubernetes 배포 실전 - GPU 노드와 모델 서빙 배포
2026년 1월 28일·AI / ML·

6장: Kubernetes 배포 실전 - GPU 노드와 모델 서빙 배포

Kubernetes에서 GPU 기반 AI 서비스를 배포하는 실전 과정을 다루며, 프로브 설정, 리소스 관리, 무중단 배포 전략을 구현합니다.

18분753자9개 섹션
mlopskubernetesinfrastructureperformance
공유
ai-deployment6 / 10
12345678910
이전5장: Kubernetes 기초 - AI 워크로드를 위한 클러스터 설계다음7장: 오토스케일링 - 트래픽 기반 GPU 워크로드 확장

프로덕션 배포의 요구사항

5장에서 Kubernetes의 기초 개념과 GPU 노드 구성을 다루었습니다. 이 장에서는 실제 프로덕션 환경에 AI 서비스를 배포하는 과정을 단계별로 진행합니다. 단순히 Pod를 실행하는 것을 넘어, 안정적이고 운영 가능한 서비스를 구축하는 데 필요한 모든 설정을 다룹니다.

프로덕션 배포에서 고려해야 할 핵심 요소는 다음과 같습니다.

  • 헬스 체크와 자동 복구
  • 리소스 요청과 제한의 정확한 설정
  • 무중단 배포(Rolling Update)
  • 환경 설정과 시크릿 관리
  • 모니터링과 로깅

완전한 Deployment 매니페스트

프로덕션 환경을 위한 완전한 vLLM Deployment 매니페스트를 먼저 제시하고, 각 부분을 상세히 설명하겠습니다.

vllm-deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-llama
  namespace: ai-serving
  labels:
    app: vllm
    model: llama-3-1-8b
    version: v1
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: vllm
      model: llama-3-1-8b
  template:
    metadata:
      labels:
        app: vllm
        model: llama-3-1-8b
        version: v1
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8000"
        prometheus.io/path: "/metrics"
    spec:
      terminationGracePeriodSeconds: 120
      tolerations:
        - key: nvidia.com/gpu
          operator: Equal
          value: present
          effect: NoSchedule
      nodeSelector:
        accelerator: nvidia-a100
      initContainers:
        - name: model-loader
          image: amazon/aws-cli:2.15
          command:
            - sh
            - -c
            - |
              if [ ! -f /models/Llama-3.1-8B-Instruct/config.json ]; then
                echo "Downloading model..."
                aws s3 sync \
                  s3://my-models/Llama-3.1-8B-Instruct \
                  /models/Llama-3.1-8B-Instruct \
                  --quiet
                echo "Download complete"
              else
                echo "Model already present, skipping download"
              fi
          volumeMounts:
            - name: model-cache
              mountPath: /models
          envFrom:
            - secretRef:
                name: aws-credentials
          resources:
            requests:
              cpu: "1"
              memory: "2Gi"
            limits:
              cpu: "2"
              memory: "4Gi"
      containers:
        - name: vllm
          image: vllm/vllm-openai:v0.6.0
          args:
            - "--model"
            - "/models/Llama-3.1-8B-Instruct"
            - "--host"
            - "0.0.0.0"
            - "--port"
            - "8000"
            - "--max-model-len"
            - "4096"
            - "--gpu-memory-utilization"
            - "0.90"
            - "--enable-prefix-caching"
            - "--disable-log-requests"
            - "--dtype"
            - "bfloat16"
          ports:
            - containerPort: 8000
              name: http
              protocol: TCP
          env:
            - name: CUDA_VISIBLE_DEVICES
              value: "0"
            - name: VLLM_ATTENTION_BACKEND
              value: "FLASH_ATTN"
          volumeMounts:
            - name: model-cache
              mountPath: /models
              readOnly: true
            - name: shm
              mountPath: /dev/shm
          resources:
            requests:
              nvidia.com/gpu: 1
              cpu: "4"
              memory: "24Gi"
            limits:
              nvidia.com/gpu: 1
              cpu: "8"
              memory: "32Gi"
          startupProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 30
            periodSeconds: 10
            failureThreshold: 30
            timeoutSeconds: 5
          readinessProbe:
            httpGet:
              path: /health
              port: 8000
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /health
              port: 8000
            periodSeconds: 30
            timeoutSeconds: 10
            failureThreshold: 3
      volumes:
        - name: model-cache
          emptyDir:
            sizeLimit: 50Gi
        - name: shm
          emptyDir:
            medium: Memory
            sizeLimit: 2Gi

프로브 설정 상세

세 가지 프로브의 역할

Kubernetes는 세 가지 종류의 헬스 체크 프로브를 제공하며, AI 서비스에서는 각각의 역할이 특히 중요합니다.

Startup Probe는 컨테이너가 시작된 후 애플리케이션이 준비될 때까지 기다립니다. AI 서비스는 모델 로딩에 수 분이 걸리므로, 이 프로브가 없으면 Liveness Probe가 모델 로딩 중에 컨테이너를 재시작시키는 문제가 발생합니다.

위 예시에서 initialDelaySeconds: 30 후부터 10초 간격으로 최대 30번(300초) 확인합니다. 즉 모델 로딩에 최대 약 5분 30초까지 허용합니다.

Readiness Probe는 Pod가 트래픽을 받을 준비가 되었는지 확인합니다. 이 프로브가 실패하면 Pod는 Service의 엔드포인트에서 제거되어 트래픽을 받지 않습니다. GPU 메모리 부족이나 과부하 상태에서 일시적으로 트래픽을 차단하는 데 유용합니다.

Liveness Probe는 컨테이너가 정상 동작 중인지 확인합니다. 이 프로브가 지속적으로 실패하면 Kubernetes가 컨테이너를 재시작합니다. 데드락이나 메모리 누수로 인해 서비스가 응답하지 않는 상황을 감지합니다.

text
프로브 동작 흐름:
 
Pod 시작
  |
  v
[Startup Probe] --> 실패 반복 가능 (모델 로딩 중)
  |
  v (성공)
[Readiness Probe 시작] --> Service 엔드포인트에 추가
[Liveness Probe 시작]  --> 이상 감지 시 컨테이너 재시작
  |
  v
서비스 제공 중
  |
  v (Readiness 실패)
Service 엔드포인트에서 제거 (트래픽 차단)
  |
  v (Readiness 회복)
Service 엔드포인트에 재추가
Warning

AI 서비스에서 Liveness Probe의 타임아웃을 너무 짧게 설정하면 위험합니다. GPU가 대규모 배치를 처리하는 동안 헬스 체크 응답이 지연될 수 있으며, 이로 인해 불필요한 재시작이 발생할 수 있습니다. timeoutSeconds를 10초 이상으로 설정하고, failureThreshold를 3 이상으로 유지하는 것을 권장합니다.

리소스 관리

GPU 리소스 설정

GPU 리소스는 nvidia.com/gpu로 요청합니다. CPU나 메모리와 달리 GPU는 분할 할당이 기본적으로 불가능합니다. 하나의 Pod에 GPU 1개 또는 여러 개를 할당할 수 있지만, 0.5개와 같은 부분 할당은 지원되지 않습니다.

멀티 GPU 서빙(텐서 병렬 처리)이 필요한 경우에는 다음과 같이 설정합니다.

멀티 GPU 설정 (70B 모델)
yaml
containers:
  - name: vllm
    args:
      - "--model"
      - "/models/Llama-3.1-70B-Instruct"
      - "--tensor-parallel-size"
      - "4"
    resources:
      limits:
        nvidia.com/gpu: 4
      requests:
        nvidia.com/gpu: 4
        cpu: "16"
        memory: "200Gi"

CPU와 메모리 설정

AI 서비스에서 CPU와 메모리 설정도 중요합니다. vLLM은 토큰화(Tokenization), 요청 스케줄링, API 처리에 CPU를 사용합니다. CPU가 부족하면 GPU가 유휴 상태로 대기하는 병목이 발생할 수 있습니다.

메모리는 모델 가중치의 CPU 메모리 복사본, 토큰화 데이터, 요청 버퍼 등에 사용됩니다. GPU 메모리와는 별도로 충분한 시스템 메모리를 확보해야 합니다.

text
리소스 설정 권장 사항:
 
모델 크기    GPU      CPU(requests)  메모리(requests)
---------  -------  ------------   ----------------
7-8B       1x A100  4 cores        24 Gi
13B        1x A100  4 cores        32 Gi
70B        4x A100  16 cores       200 Gi
70B(양자화) 1x A100  4 cores        48 Gi

환경 설정과 시크릿 관리

ConfigMap으로 설정 관리

모델 서빙 파라미터를 ConfigMap으로 분리하면 이미지를 재빌드하지 않고도 설정을 변경할 수 있습니다.

vllm-config.yaml
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: vllm-config
  namespace: ai-serving
data:
  MODEL_PATH: "/models/Llama-3.1-8B-Instruct"
  MAX_MODEL_LEN: "4096"
  GPU_MEMORY_UTILIZATION: "0.90"
  MAX_NUM_SEQS: "256"
  DTYPE: "bfloat16"
ConfigMap을 Pod에서 사용
yaml
containers:
  - name: vllm
    envFrom:
      - configMapRef:
          name: vllm-config

Secret으로 민감 정보 관리

Hugging Face 토큰, 클라우드 자격 증명 등의 민감 정보는 Kubernetes Secret으로 관리합니다.

시크릿 생성
bash
kubectl create secret generic hf-token \
  --from-literal=HF_TOKEN=hf_xxxxxxxxxxxxx \
  -n ai-serving
 
kubectl create secret generic aws-credentials \
  --from-literal=AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \
  --from-literal=AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
  -n ai-serving
시크릿을 Pod에서 사용
yaml
containers:
  - name: vllm
    env:
      - name: HF_TOKEN
        valueFrom:
          secretKeyRef:
            name: hf-token
            key: HF_TOKEN
Tip

프로덕션 환경에서는 Kubernetes Secret 대신 AWS Secrets Manager, HashiCorp Vault, 또는 External Secrets Operator를 사용하는 것이 더 안전합니다. Kubernetes Secret은 기본적으로 Base64 인코딩만 적용되며, etcd에 평문으로 저장됩니다.

무중단 배포 전략

Rolling Update 설정

AI 서비스의 무중단 배포에서 가장 중요한 점은 모델 로딩 시간입니다. 새 Pod가 모델을 로드하고 Readiness Probe를 통과할 때까지 기존 Pod를 유지해야 합니다.

안전한 Rolling Update 설정
yaml
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

maxSurge: 1은 업데이트 중 현재 복제본 수보다 1개 더 많은 Pod를 허용합니다. maxUnavailable: 0은 업데이트 중 사용 불가능한 Pod가 없어야 함을 의미합니다. 이 조합은 항상 원래 수 이상의 Pod가 서비스를 제공하도록 보장합니다.

text
Rolling Update 진행 과정 (replicas: 2):
 
단계 1: 새 Pod 생성 (총 3개)
  [기존 Pod 1: 서빙 중] [기존 Pod 2: 서빙 중] [새 Pod 3: 모델 로딩...]
 
단계 2: 새 Pod 준비 완료 (Readiness 통과)
  [기존 Pod 1: 서빙 중] [기존 Pod 2: 서빙 중] [새 Pod 3: 서빙 시작]
 
단계 3: 기존 Pod 1 종료
  [기존 Pod 1: 종료 중...] [기존 Pod 2: 서빙 중] [새 Pod 3: 서빙 중]
 
단계 4: 새 Pod 4 생성
  [새 Pod 4: 모델 로딩...] [기존 Pod 2: 서빙 중] [새 Pod 3: 서빙 중]
 
단계 5: 새 Pod 4 준비 완료, 기존 Pod 2 종료
  [새 Pod 4: 서빙 중] [새 Pod 3: 서빙 중]
 
=> 서비스 중단 없이 업데이트 완료

Graceful Shutdown

Pod가 종료될 때 진행 중인 요청을 완료할 시간을 주어야 합니다. terminationGracePeriodSeconds는 SIGTERM 신호를 받은 후 강제 종료(SIGKILL)까지의 대기 시간입니다.

LLM 추론 요청은 수십 초가 걸릴 수 있으므로, 이 값을 충분히 길게 설정해야 합니다. 120초 이상을 권장합니다.

Graceful Shutdown 설정
yaml
spec:
  terminationGracePeriodSeconds: 120
  containers:
    - name: vllm
      lifecycle:
        preStop:
          exec:
            command:
              - sh
              - -c
              - "sleep 10"

preStop 훅에서 10초 대기를 추가하는 것은, 엔드포인트에서 Pod가 제거되기 전에 새 요청이 유입되는 것을 방지하기 위한 안전 장치입니다.

블루-그린 배포

모델을 완전히 새로운 버전으로 교체하는 경우, 롤링 업데이트보다 블루-그린 배포가 더 안전할 수 있습니다. 기존 Deployment(블루)를 유지한 채 새 Deployment(그린)를 완전히 띄운 후, Service의 셀렉터를 변경하여 트래픽을 전환합니다.

블루-그린 배포: 그린 Deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-llama-green
  namespace: ai-serving
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vllm
      model: llama-3-1-8b
      color: green
  template:
    metadata:
      labels:
        app: vllm
        model: llama-3-1-8b
        color: green
    spec:
      # ... (새 모델/설정으로 구성)
트래픽 전환
bash
# 그린이 준비되면 Service 셀렉터를 변경
kubectl patch service vllm-service -n ai-serving \
  -p '{"spec":{"selector":{"color":"green"}}}'
 
# 확인 후 블루 삭제
kubectl delete deployment vllm-llama-blue -n ai-serving

모니터링 설정

Prometheus 메트릭 수집

vLLM은 /metrics 엔드포인트를 통해 Prometheus 형식의 메트릭을 제공합니다.

prometheus-config.yaml
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: monitoring
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    scrape_configs:
      - job_name: vllm
        kubernetes_sd_configs:
          - role: pod
            namespaces:
              names:
                - ai-serving
        relabel_configs:
          - source_labels:
              - __meta_kubernetes_pod_annotation_prometheus_io_scrape
            action: keep
            regex: "true"
          - source_labels:
              - __meta_kubernetes_pod_annotation_prometheus_io_port
            action: replace
            target_label: __address__
            regex: (.+)
            replacement: "$1"

핵심 모니터링 메트릭

AI 서비스에서 추적해야 할 핵심 메트릭은 다음과 같습니다.

text
vLLM 주요 메트릭:
 
요청 관련:
  vllm:num_requests_running     - 현재 처리 중인 요청 수
  vllm:num_requests_waiting     - 대기 큐의 요청 수
  vllm:request_success_total    - 성공한 요청 총 수
  vllm:request_failure_total    - 실패한 요청 총 수
 
성능 관련:
  vllm:e2e_request_latency      - 요청 전체 지연 시간
  vllm:time_to_first_token      - 첫 토큰까지의 시간
  vllm:time_per_output_token    - 토큰당 생성 시간
 
GPU 관련:
  vllm:gpu_cache_usage_perc     - GPU KV 캐시 사용률
  vllm:cpu_cache_usage_perc     - CPU KV 캐시 사용률
Info

대기 큐 요청 수(num_requests_waiting)가 지속적으로 증가하면, 현재 GPU 용량이 트래픽을 감당하지 못하고 있다는 신호입니다. 이 메트릭은 오토스케일링의 트리거로 활용할 수 있으며, 7장에서 자세히 다루겠습니다.

전체 배포 체크리스트

프로덕션 배포 전에 다음 항목을 확인합니다.

text
배포 전 체크리스트:
 
[인프라]
- GPU 노드 풀이 구성되어 있는가
- NVIDIA GPU Operator가 설치되어 있는가
- 모델이 접근 가능한 스토리지에 준비되어 있는가
- 네임스페이스와 RBAC가 설정되어 있는가
 
[Deployment]
- GPU 리소스 requests/limits가 올바른가
- Startup Probe 타임아웃이 모델 로딩 시간보다 긴가
- terminationGracePeriodSeconds가 충분한가
- 이미지 버전이 고정되어 있는가 (latest 사용 금지)
 
[네트워킹]
- Service가 올바른 셀렉터를 사용하는가
- Ingress 타임아웃이 충분히 긴가
- 스트리밍을 위한 프록시 버퍼링이 비활성화되어 있는가
 
[보안]
- 시크릿이 안전하게 관리되는가
- 컨테이너가 비루트 사용자로 실행되는가
- 네트워크 정책이 설정되어 있는가
 
[모니터링]
- Prometheus 메트릭 수집이 설정되어 있는가
- 핵심 대시보드가 준비되어 있는가
- 알림 규칙이 설정되어 있는가

정리

이 장에서는 Kubernetes에 AI 서비스를 배포하는 실전 과정을 다루었습니다. 프로브 설정, 리소스 관리, 무중단 배포 전략, 모니터링 설정까지 프로덕션 수준의 배포에 필요한 모든 요소를 살펴보았습니다.

다음 장에서는 트래픽 변화에 자동으로 대응하는 오토스케일링 전략을 다루겠습니다. GPU 워크로드의 특수한 확장 요구사항과 커스텀 메트릭 기반 스케일링을 구현합니다.

이 글이 도움이 되셨나요?

관련 주제 더 보기

#mlops#kubernetes#infrastructure#performance

관련 글

AI / ML

7장: 오토스케일링 - 트래픽 기반 GPU 워크로드 확장

Kubernetes에서 GPU 기반 AI 서비스의 자동 확장 전략을 구현하며, HPA 커스텀 메트릭과 Cluster Autoscaler를 활용한 효율적인 스케일링 방법을 다룹니다.

2026년 1월 30일·17분
AI / ML

5장: Kubernetes 기초 - AI 워크로드를 위한 클러스터 설계

Kubernetes의 핵심 개념을 AI 워크로드 관점에서 설명하고, GPU 노드 구성과 AI 서비스에 적합한 클러스터 아키텍처를 설계합니다.

2026년 1월 26일·14분
AI / ML

8장: 비용 최적화 - 스팟 인스턴스, 모델 공유, 리소스 관리

GPU 기반 AI 서비스의 운영 비용을 체계적으로 절감하는 전략을 다루며, 스팟 인스턴스 활용, 모델 공유 아키텍처, 리소스 관리 기법을 소개합니다.

2026년 2월 1일·18분
이전 글5장: Kubernetes 기초 - AI 워크로드를 위한 클러스터 설계
다음 글7장: 오토스케일링 - 트래픽 기반 GPU 워크로드 확장

댓글

목차

약 18분 남음
  • 프로덕션 배포의 요구사항
  • 완전한 Deployment 매니페스트
  • 프로브 설정 상세
    • 세 가지 프로브의 역할
  • 리소스 관리
    • GPU 리소스 설정
    • CPU와 메모리 설정
  • 환경 설정과 시크릿 관리
    • ConfigMap으로 설정 관리
    • Secret으로 민감 정보 관리
  • 무중단 배포 전략
    • Rolling Update 설정
    • Graceful Shutdown
    • 블루-그린 배포
  • 모니터링 설정
    • Prometheus 메트릭 수집
    • 핵심 모니터링 메트릭
  • 전체 배포 체크리스트
  • 정리