Skip to main content

클러스터 선택은 기술 문제가 아니라 운영 문제다

쿠버네티스를 처음 배울 때 우리는 보통 이런 질문을 한다. "어떤 배포판을 써야 하지?", "kind가 좋아, minikube가 좋아?", "EKS와 GKE 중 무엇이 더 낫지?" 모두 필요한 질문이다. 하지만 AI 워크로드를 운영하려는 팀이라면 질문의 순서를 조금 바꿔야 한다.

"우리 팀은 어떤 실패를 감당할 수 있는가?"

웹 API 서버 하나가 재시작되는 것과 70B 모델을 올린 GPU 파드가 재시작되는 것은 무게가 다르다. 웹 서버는 몇 초 안에 다시 뜰 수 있지만, LLM 추론 서버는 컨테이너 이미지를 받고, 모델 가중치를 내려받고, GPU 메모리에 올리고, KV 캐시를 예열하는 데 몇 분이 걸릴 수 있다. 학습 작업이라면 더 심각하다. 체크포인트를 제대로 남기지 않았다면 몇 시간짜리 GPU 비용이 그대로 증발한다.

그래서 AI 시대의 클러스터 선택은 "쿠버네티스를 어디에 설치할 것인가"가 아니라 "GPU, 모델, 팀, 비용, 장애 대응을 어떤 방식으로 운영할 것인가"에 가깝다.

특히 2026년의 AI 인프라는 비용 압박이 크다. 한 보고서는 최적화되지 않은 쿠버네티스 클러스터에서 GPU 평균 활용률이 5%에 불과하다고 지적했다. CPU가 놀면 아깝지만, GPU가 놀면 청구서가 눈에 띄게 커진다.1 이 장의 목표는 쿠버네티스 배포판 이름을 외우는 것이 아니다. 여러분의 팀 규모와 GPU 요구사항, 비용 구조에 맞는 클러스터 운영 방식을 판단하는 눈을 갖는 것이다.

이 장에서는 세 가지 선택지를 비교한다. 로컬 실습 환경, 클라우드 매니지드 쿠버네티스, 그리고 GPU 서버가 포함된 베어메탈 클러스터다. 이어서 어떤 선택을 하든 반드시 알아야 할 기본 운영 단위인 kubeconfig, context, namespace, RBAC, ServiceAccount, ResourceQuota를 AI 팀의 관점에서 다시 정리한다.

AI 팀을 위한 클러스터 선택과 기본 운영

로컬 클러스터: 쿠버네티스 문법을 익히는 실험실

로컬 클러스터는 노트북이나 개발용 서버 한 대에서 쿠버네티스를 띄우는 방식이다. 대표적으로 kind, minikube, k3d가 있다. 이 도구들은 프로덕션을 대체하기 위한 것이 아니라, 쿠버네티스 리소스의 동작을 빠르게 확인하기 위한 실험실이다.

AI 팀에서 로컬 클러스터가 특히 유용한 순간은 모델 성능을 측정할 때가 아니라 배포 구조를 검증할 때다. 예를 들어 vLLM을 실제 H100에 올리기 전에 Namespace, Deployment, Service, ConfigMap, Secret, PVC, Helm 차트 구조가 맞는지 확인할 수 있다. KServe나 KEDA 같은 도구를 설치해 CRD가 어떻게 생겼는지 살펴보는 것도 로컬에서 충분히 가능하다. GPU가 없는 노트북에서도 "운영 문법"은 배울 수 있다.

다만 로컬 클러스터에 너무 큰 기대를 걸면 안 된다. LLM 추론에서 중요한 GPU 메모리, PCIe 대역폭, NVLink, 모델 로딩 시간, 노드 오토스케일링, 클라우드 스토리지 성능은 로컬 환경에서 제대로 재현하기 어렵다. 작은 모델을 CPU로 띄워 API 모양을 확인할 수는 있지만, 프로덕션 지연시간이나 처리량을 예측할 수는 없다.

로컬 도구의 성격은 다음처럼 나눠 볼 수 있다.

도구적합한 용도AI 워크로드 관점의 한계
kind쿠버네티스 API, 컨트롤러, CI 테스트컨테이너 안의 노드 구조라 실제 GPU 노드 재현이 까다롭다
minikube입문 실습, 단일 노드 애드온 테스트실제 다중 노드·GPU 운영 구조와는 거리가 있다
k3d가벼운 로컬 클러스터, 빠른 생성·삭제프로덕션급 스토리지·네트워크·GPU 토폴로지 검증에는 부족하다

kind는 "Kubernetes in Docker"라는 이름처럼 도커 컨테이너를 쿠버네티스 노드처럼 사용한다. 테스트 자동화에 특히 좋다. GitHub Actions 같은 CI 환경에서 Helm 차트를 렌더링하고, kubectl apply가 성공하는지 검증하기 좋다. AI 플랫폼 팀이라면 모델 서버 자체보다 주변 리소스, 예를 들어 InferenceService CRD나 Gateway 설정, RBAC 매니페스트 테스트에 kind를 사용할 수 있다.

minikube는 입문자에게 친절하다. 단일 노드 클러스터를 빠르게 만들고, 대시보드나 metrics-server 같은 애드온을 쉽게 켤 수 있다. 쿠버네티스 개념을 손으로 익히는 데 좋다. 다만 "내 노트북에서 minikube로 vLLM이 떴다"는 사실은 "프로덕션에서도 안정적으로 운영된다"는 뜻이 아니다. 특히 모델 크기가 커지고 GPU가 들어오면 완전히 다른 문제가 시작된다.

k3d는 Rancher의 경량 쿠버네티스 배포판인 k3s를 도커 안에서 실행한다. 빠르고 가볍다. 소규모 팀이 로컬에서 여러 클러스터를 만들고 지우며 GitOps 흐름을 연습하기 좋다. 예를 들어 dev, stage, prod-like 클러스터를 각각 띄워 Argo CD 애플리케이션 구조를 실험할 수 있다.

로컬 클러스터를 쓸 때는 목적을 좁게 잡아야 한다. "LLM이 빠른가?"를 묻지 말고 "YAML이 맞는가?", "Service 이름으로 통신되는가?", "Secret이 주입되는가?", "readinessProbe가 실패하면 트래픽이 빠지는가?"를 확인해야 한다. AI 인프라에서 로컬 클러스터는 비행 시뮬레이터다. 이륙 절차를 연습할 수는 있지만, 실제 난기류와 연료비는 하늘에 올라가야 알 수 있다.

간단한 kind 클러스터는 다음처럼 만들 수 있다.

kind create cluster --name ai-dev
kubectl cluster-info --context kind-ai-dev
kubectl get nodes

실습이 끝났다면 과감하게 지운다.

kind delete cluster --name ai-dev

이 삭제의 가벼움이 로컬 클러스터의 장점이다. 프로덕션 클러스터에서는 절대 해서는 안 되는 실험을 로컬에서는 마음껏 해볼 수 있다. ResourceQuota를 잘못 걸어 파드가 생성되지 않게 만들고, RBAC를 너무 좁게 잡아 컨트롤러가 403 에러를 내게 만들고, PVC 이름을 틀려 Pending에 빠뜨려 보자. 이런 실패를 노트북에서 먼저 겪은 사람은 프로덕션에서 덜 당황한다.

매니지드 쿠버네티스: 대부분의 팀이 먼저 선택해야 할 출발점

EKS, GKE, AKS 같은 매니지드 쿠버네티스는 클라우드 제공자가 컨트롤 플레인을 관리해 주는 방식이다. etcd 백업, API 서버 고가용성, 마스터 노드 패치 같은 무거운 일을 클라우드가 맡는다. 사용자는 워커 노드, 네트워크, 스토리지, 권한, 배포 파이프라인, 비용 최적화에 집중한다.

AI 팀에게 매니지드 쿠버네티스는 대부분의 경우 가장 현실적인 출발점이다. 특히 팀에 전담 플랫폼 엔지니어가 많지 않다면 더욱 그렇다. GPU 인스턴스 노드 풀을 만들고, NVIDIA GPU Operator나 디바이스 플러그인을 설치하고, vLLM이나 KServe를 올리는 것만으로도 이미 할 일이 많다. 여기에 컨트롤 플레인 운영까지 직접 떠안는 것은 초반 팀에게 과하다.

NVIDIA GPU Operator는 GPU 노드 운영을 단순화하는 대표적인 도구다. 드라이버, 컨테이너 런타임 설정, 디바이스 플러그인, GPU Feature Discovery, DCGM 기반 모니터링 구성요소를 클러스터 단위로 관리한다.2 과거에는 GPU 노드마다 드라이버 버전과 CUDA 런타임을 사람이 맞춰야 했다. 지금은 적어도 그 상당 부분을 오퍼레이터가 맡을 수 있다.

매니지드 클러스터가 잘 맞는 경우는 분명하다. 첫째, GPU 수요가 아직 들쭉날쭉하다. 어떤 날은 데모 때문에 트래픽이 몰리고, 어떤 날은 거의 없다. 둘째, 서비스 출시 속도가 중요하다. 인프라를 직접 조립하느라 몇 달을 보내는 것보다 클라우드 비용을 조금 더 내고 빠르게 검증하는 편이 낫다. 셋째, 팀이 이미 AWS, Google Cloud, Azure 중 하나의 데이터베이스, 오브젝트 스토리지, IAM, 로깅 서비스를 사용하고 있다. 이 경우 쿠버네티스도 같은 클라우드 안에 두면 네트워크와 권한 설계가 단순해진다.

하지만 매니지드라고 해서 운영이 사라지는 것은 아니다. 단지 운영의 위치가 바뀐다. 컨트롤 플레인은 클라우드가 봐주지만, 다음 문제는 여전히 여러분의 몫이다.

  • GPU 노드 풀을 어떤 인스턴스 타입으로 구성할 것인가

  • 추론용 노드와 학습용 노드를 분리할 것인가

  • 노드가 0개로 줄었다가 다시 늘어날 때 모델 콜드 스타트를 어떻게 감당할 것인가

  • 클라우드 GPU 할당량 부족을 어떻게 모니터링할 것인가

  • 모델 가중치를 어떤 스토리지에 캐시할 것인가

  • 장애 시 어느 팀이 어느 대시보드를 보고 대응할 것인가

vLLM의 프로덕션 스택 문서도 쿠버네티스 위에서 LLM을 배포할 때 GPU가 있는 실행 환경과 Helm 기반 배포, 관찰 가능성 구성을 전제로 설명한다.3 즉, 매니지드 쿠버네티스를 선택해도 "모델 서버를 띄우는 일"은 여전히 플랫폼 설계 문제다.

매니지드 클러스터에서는 노드 풀을 처음부터 나누는 습관이 중요하다. CPU 워크로드, 실시간 추론, 배치 학습을 한 노드 풀에 섞으면 나중에 거의 반드시 후회한다. 학습 작업이 GPU를 오래 붙잡아 실시간 추론 파드가 Pending에 빠질 수 있고, 반대로 추론 서비스의 최소 상시 노드 때문에 배치 작업 비용이 불필요하게 올라갈 수 있다.

초기 구조는 단순하게 시작해도 된다.

system-pool        : CoreDNS, metrics-server, ingress/gateway, 관찰 도구
cpu-app-pool       : 일반 API 서버, 백엔드 워커, RAG 오케스트레이터
gpu-inference-pool : vLLM, SGLang, KServe 추론 파드
gpu-batch-pool     : 학습, 임베딩 배치, 평가 Job

여기서 핵심은 GPU 노드를 "비싼 특수 자원"으로 취급하는 것이다. 아무 파드나 GPU 노드에 올라가면 안 된다. 일반 웹 서버가 우연히 GPU 노드에 스케줄링되어 CPU와 메모리를 잡아먹는 일은 생각보다 자주 일어난다. 그래서 GPU 노드에는 taint를 걸고, GPU 워크로드에만 toleration을 부여한다.

kubectl taint nodes gpu-node-1 nvidia.com/gpu=true:NoSchedule

그리고 GPU를 쓰는 파드에는 다음처럼 toleration과 리소스 요청을 넣는다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-server
  namespace: ai-serving
spec:
  replicas: 1
  selector:
    matchLabels:
      app: llm-server
  template:
    metadata:
      labels:
        app: llm-server
    spec:
      tolerations:
        - key: nvidia.com/gpu
          operator: Equal
          value: "true"
          effect: NoSchedule
      nodeSelector:
        workload-class: inference
      containers:
        - name: server
          image: vllm/vllm-openai:latest
          resources:
            limits:
              nvidia.com/gpu: 1
              cpu: "8"
              memory: 32Gi

이 YAML은 뒤 장에서 더 깊게 다룰 GPU 스케줄링의 출발점이다. 지금은 한 가지만 기억하면 된다. 매니지드 쿠버네티스에서도 GPU는 자동으로 잘 관리되지 않는다. 노드 풀, taint, label, quota, 모니터링을 함께 설계해야 한다.

베어메탈 클러스터: GPU를 직접 소유할 때 얻는 것과 잃는 것

베어메탈 쿠버네티스는 물리 서버 위에 직접 쿠버네티스를 구성하는 방식이다. 클라우드 VM이나 매니지드 노드가 아니라, 팀이 소유하거나 임대한 GPU 서버가 곧 쿠버네티스 노드가 된다. H100이 8장 꽂힌 서버, NVLink가 구성된 장비, 사내 데이터센터의 GPU 랙, 또는 전문 GPU 호스팅 업체의 베어메탈 서버가 여기에 해당한다.

베어메탈의 매력은 명확하다. GPU에 직접 접근할 수 있고, 가상화 계층의 제약이 줄어들며, 네트워크와 스토리지 토폴로지를 더 세밀하게 제어할 수 있다. 대규모 학습이나 지연시간에 민감한 추론에서는 이 차이가 중요해질 수 있다. 또한 장기적으로 GPU 사용률이 높다면 클라우드 온디맨드 비용보다 직접 운영이 경제적일 수 있다.

국내에서도 AI 서비스를 운영하던 팀이 기존 GPU 서버 인프라를 쿠버네티스 클러스터로 이전하며 운영 개선을 시도한 사례가 공유된 바 있다. 이처럼 GPU 서버가 이미 있고, 여러 서비스가 같은 자원을 나누어 써야 한다면 쿠버네티스는 자연스러운 통합 계층이 된다.4

하지만 베어메탈은 낭만적인 선택지가 아니다. 클라우드 콘솔에서 노드 풀을 하나 추가하는 대신, 서버 구매, 랙 장착, 전원, 냉각, 네트워크, OS 설치, 커널 버전, 드라이버, 컨테이너 런타임, CNI, CSI, 로드밸런서, 장애 부품 교체까지 모두 현실이 된다. 쿠버네티스 자체도 직접 업그레이드해야 한다. etcd 백업과 복구 절차도 있어야 한다.

베어메탈을 선택해야 하는 경우는 대체로 다음과 같다.

  • GPU를 장기간 높은 사용률로 돌릴 만큼 수요가 안정적이다.

  • 데이터 반출, 보안, 규정 준수 때문에 퍼블릭 클라우드 사용이 어렵다.

  • NVLink, RDMA, GPUDirect, 특정 스토리지 구성처럼 하드웨어 토폴로지 제어가 중요하다.

  • 클라우드 GPU 수급이나 비용 변동성이 사업 리스크가 되고 있다.

  • 이미 사내 GPU 서버가 있고, 이를 팀별 셀프서비스 플랫폼으로 바꾸고 싶다.

반대로 이런 팀은 베어메탈을 서두르지 않는 편이 좋다. 아직 모델도 자주 바뀌고, 트래픽도 예측하기 어렵고, 전담 인프라 엔지니어도 없고, 장애 대응 체계도 없다면 베어메탈은 절약이 아니라 부채가 될 수 있다. GPU 서버 한 대를 샀다고 끝이 아니다. 그 서버가 금요일 밤에 드라이버 문제로 GPU를 잃어버렸을 때 누가 볼 것인지가 진짜 비용이다.

베어메탈 클러스터를 운영한다면 최소한 다음 구성요소를 표준화해야 한다.

OS 이미지        : Ubuntu/RHEL 계열 버전 고정
컨테이너 런타임  : containerd 설정 표준화
GPU 드라이버     : 검증된 NVIDIA 드라이버 버전
GPU Operator     : 드라이버, 디바이스 플러그인, DCGM Exporter 관리
CNI              : Cilium, Calico 등 네트워크 플러그인
CSI              : Ceph, Longhorn, NFS, 로컬 SSD 등 스토리지 플러그인
로드밸런서       : MetalLB 또는 외부 L4 장비
관찰 가능성      : Prometheus, Grafana, Loki, Alertmanager
백업             : etcd 백업, 매니페스트 Git 저장소, 스토리지 스냅샷

베어메탈의 성공 여부는 "설치했는가"가 아니라 "재현 가능한가"로 갈린다. 첫 번째 GPU 노드를 손으로 겨우 붙였다면 아직 운영이 아니다. 같은 방식으로 열 번째 노드를 붙일 수 있어야 하고, 장애 난 노드를 제거하고 새 노드를 넣을 수 있어야 한다. 가능하면 OS 이미지, 드라이버, Helm values, 노드 라벨, taint 정책을 모두 코드로 남겨야 한다.

선택 기준: 작게 시작하되, 나중에 옮길 수 있게 설계하라

클러스터 선택에는 정답이 없다. 그러나 오답에 가까운 선택은 있다. 작은 팀이 처음부터 베어메탈 HA 클러스터를 직접 만들겠다고 3개월을 쓰는 것, 반대로 매달 수천만 원어치 GPU를 꾸준히 쓰면서도 아무런 비용 최적화 없이 온디맨드 클라우드에만 의존하는 것 모두 위험하다.

다음 표는 현실적인 판단 기준이다.

상황추천 출발점이유
쿠버네티스와 YAML을 배우는 단계kind, minikube, k3d빠르게 만들고 지우며 실패를 학습할 수 있다
GPU 없이 배포 구조만 검증로컬 클러스터 + CIHelm, RBAC, Namespace, Service 구조 검증에 충분하다
첫 LLM API를 제품에 붙이는 단계EKS/GKE/AKS컨트롤 플레인 부담 없이 GPU 노드 풀로 시작할 수 있다
트래픽 변동이 큰 추론 서비스매니지드 클러스터오토스케일링과 클라우드 연동이 쉽다
매일 장시간 학습을 수행베어메탈 또는 GPU 전문 클라우드장기 비용과 토폴로지 제어가 중요하다
민감 데이터로 사내 추론 운영베어메탈 또는 프라이빗 클라우드데이터 위치와 네트워크 통제를 강화할 수 있다
전담 플랫폼 팀이 없음매니지드 우선직접 운영 범위를 줄여야 한다

중요한 원칙은 이식성이다. 오늘은 GKE에서 시작하더라도 내년에 일부 워크로드를 베어메탈로 옮길 수 있어야 한다. 그러려면 특정 클라우드의 기능을 쓰지 말라는 뜻이 아니다. Secret, PVC, Ingress 또는 Gateway, IAM 연동처럼 클라우드별 차이가 생기는 부분을 의식적으로 분리하라는 뜻이다.

예를 들어 애플리케이션 매니페스트와 인프라 매니페스트를 섞지 않는다. Deployment와 Service는 공통 Helm 차트로 관리하고, StorageClass 이름이나 노드 라벨, 로드밸런서 애노테이션은 환경별 values로 분리한다. 이렇게 해두면 values-gke.yaml, values-eks.yaml, values-baremetal.yaml만 바꿔 같은 모델 서버를 여러 환경에 배포할 수 있다.

AI 팀의 좋은 출발 전략은 다음과 같다. 로컬 클러스터에서 쿠버네티스 문법을 익힌다. 매니지드 클러스터에서 첫 프로덕션 추론 서비스를 운영한다. GPU 사용량이 충분히 커지고 패턴이 안정되면 베어메탈이나 GPU 전문 클라우드로 일부 워크로드를 옮긴다. 처음부터 완벽한 최종 구조를 만들려고 하지 말고, 나중에 옮길 수 있는 구조로 작게 시작한다.

kubeconfig와 context: 클러스터를 헷갈리지 않는 기술

쿠버네티스를 운영하면서 가장 무서운 실수 중 하나는 "dev에 적용하려던 YAML을 prod에 적용하는 것"이다. AI 워크로드에서는 이 실수가 더 비싸다. 잘못된 네임스페이스에서 vLLM Deployment를 지웠는데, 그 파드가 고객 요청을 처리하던 프로덕션 모델 서버라면 몇 분의 장애가 발생할 수 있다. 학습 클러스터에서 잘못된 Job을 실행해 H100 8장을 밤새 점유할 수도 있다.

이런 실수를 줄이는 첫 번째 도구가 kubeconfig와 context다.

kubeconfig는 kubectl이 어느 클러스터에, 어떤 사용자 자격으로, 어떤 기본 네임스페이스를 대상으로 접속할지 담은 설정 파일이다. 기본 위치는 보통 ~/.kube/config다. context는 kubeconfig 안에서 "클러스터 + 사용자 + 네임스페이스" 조합에 붙인 이름이다.

현재 context는 다음 명령으로 확인한다.

kubectl config current-context

등록된 context 목록은 다음처럼 본다.

kubectl config get-contexts

context를 바꾸려면 다음 명령을 쓴다.

kubectl config use-context gke-tilnote-ai-dev

AI 팀에서는 context 이름을 대충 짓지 않는 것이 좋다. cluster1, test, new-prod 같은 이름은 사고를 부른다. 이름만 봐도 클라우드, 지역, 환경, 용도를 알 수 있게 만든다.

gke-asia-dev-ai
gke-asia-staging-ai
gke-asia-prod-serving
eks-us-prod-training
baremetal-seoul-gpu-lab

프롬프트에 현재 context와 namespace를 표시하는 도구를 쓰는 것도 추천한다. kubectx, kubens, starship, kube-ps1 같은 도구를 사용하면 터미널에서 현재 위치를 계속 확인할 수 있다. 운영자는 기억력이 아니라 도구로 안전을 확보해야 한다.

더 중요한 원칙은 프로덕션 클러스터 접근을 불편하게 만드는 것이다. 개발 클러스터는 빠르게 접근해도 되지만, 프로덕션은 의도적으로 마찰이 있어야 한다. SSO 로그인, MFA, 짧은 세션, 승인된 그룹만 접근, 읽기 전용 기본 권한 같은 장치가 실수를 줄인다. 편한 운영은 자주 위험한 운영이 된다.

namespace: 팀과 환경을 나누는 첫 번째 벽

Namespace는 하나의 클러스터 안에서 리소스를 논리적으로 나누는 경계다. Pod, Deployment, Service, ConfigMap, Secret, Role, RoleBinding, ResourceQuota 같은 많은 리소스가 Namespace 안에 속한다. 물리적인 격리는 아니지만, 운영 단위를 나누는 첫 번째 벽이다.

AI 팀에서는 Namespace를 단순히 dev, prod로만 나누면 금방 부족해진다. 워크로드 성격이 다르기 때문이다. 추론 서비스는 낮은 지연시간과 높은 가용성이 중요하다. 학습 작업은 긴 실행 시간과 GPU 대량 점유가 중요하다. 임베딩 배치 작업은 큐와 재시도가 중요하다. 관찰 도구는 클러스터 전체를 봐야 한다.

작은 팀이라면 다음 정도로 시작할 수 있다.

kubectl create namespace ai-dev
kubectl create namespace ai-staging
kubectl create namespace ai-serving
kubectl create namespace ai-training
kubectl create namespace observability

각 Namespace의 의미를 명확히 정한다. ai-dev는 실험용이다. 실패해도 된다. ai-staging은 프로덕션과 비슷한 설정을 검증하는 곳이다. ai-serving은 사용자 트래픽을 받는 추론 서비스가 있는 곳이다. ai-training은 학습 Job과 평가 Job이 실행되는 곳이다. observability에는 Prometheus, Grafana, Loki 같은 관찰 도구가 들어간다.

조금 더 큰 조직에서는 팀과 환경을 함께 반영한다.

search-ai-dev
search-ai-prod
vision-ai-dev
vision-ai-prod
platform-gpu-system
platform-observability

여기서 주의할 점이 있다. Namespace는 보안 경계의 일부일 뿐, 완전한 격리 장치가 아니다. 네트워크 정책이 없으면 다른 Namespace의 Service로 접근할 수 있고, RBAC가 넓으면 다른 Namespace 리소스를 볼 수 있다. ResourceQuota가 없으면 한 Namespace의 실험 Job이 클러스터 전체 GPU를 가져갈 수 있다. Namespace는 벽이라기보다 방 이름표에 가깝다. 진짜 통제는 RBAC, NetworkPolicy, ResourceQuota, Pod Security Standards와 함께 만들어진다.

그래도 Namespace는 운영의 언어를 바꾼다. "그 vLLM 파드 어디 있어요?"라는 질문보다 "ai-serving 네임스페이스의 llama-3-8b Deployment 상태를 봐주세요"가 훨씬 정확하다.

kubectl get pods -n ai-serving
kubectl describe deploy llama-3-8b -n ai-serving
kubectl logs -n ai-serving deploy/llama-3-8b

운영은 정확한 이름에서 시작한다.

RBAC와 ServiceAccount: 사람과 파드의 권한을 분리하라

쿠버네티스에는 두 종류의 사용자가 있다. 하나는 사람이다. 플랫폼 엔지니어, 백엔드 개발자, ML 엔지니어, SRE가 여기에 해당한다. 다른 하나는 파드 안에서 실행되는 프로그램이다. KServe 컨트롤러, Argo CD, Prometheus, 모델 배포 자동화 봇, 내부 오토스케일러가 여기에 해당한다.

사람은 보통 클라우드 IAM, SSO, 인증서 등을 통해 쿠버네티스 API 서버에 접근한다. 파드는 ServiceAccount를 통해 API 서버에 접근한다. Kubernetes 공식 문서에 따르면 ServiceAccount는 파드 안에서 실행되는 프로세스의 신원을 제공하며, 모든 Namespace에는 기본적으로 default ServiceAccount가 존재한다.5

문제는 이 default ServiceAccount다. 아무 생각 없이 모든 파드가 default ServiceAccount를 쓰게 두고, 나중에 여기에 권한을 붙이면 같은 Namespace의 많은 파드가 불필요한 권한을 갖게 된다. AI 워크로드에서는 특히 위험하다. 모델 서버는 보통 Kubernetes API를 호출할 필요가 없다. 그런데 default ServiceAccount에 Secret 조회 권한이 있다면, 모델 서버 취약점 하나가 클러스터 정보 유출로 이어질 수 있다.

기본 원칙은 간단하다. 파드마다 필요한 신원을 따로 만든다. 그리고 필요한 권한만 준다.

다음은 ai-serving Namespace에서 파드 목록만 읽을 수 있는 ServiceAccount와 RoleBinding 예시다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: serving-reader
  namespace: ai-serving
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: ai-serving
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: serving-reader-pod-reader
  namespace: ai-serving
subjects:
  - kind: ServiceAccount
    name: serving-reader
    namespace: ai-serving
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

여기서 automountServiceAccountToken: false가 중요하다. API 서버에 접근할 필요가 없는 파드는 토큰을 자동 마운트하지 않는 편이 안전하다. 정말 API 접근이 필요한 컨트롤러나 에이전트에만 토큰을 허용한다.

사람에 대한 권한도 역할별로 나눈다. 플랫폼 엔지니어는 클러스터 전체 노드와 스토리지, GPU Operator를 봐야 할 수 있다. ML 엔지니어는 ai-training Namespace에서 Job을 만들고 로그를 볼 수 있으면 충분할 수 있다. 백엔드 개발자는 ai-serving의 Deployment 상태를 조회하고 재시작할 권한만 있으면 될 수 있다.

예를 들어 조직의 SSO 그룹을 기준으로 다음과 같이 나눌 수 있다.

그룹권한 범위설명
platform-admins클러스터 관리자노드, 네트워크, 스토리지, 시스템 애드온 관리
ml-engineersai-dev, ai-training 편집학습 Job, 실험 Deployment, PVC 관리
backend-developersai-serving 조회 중심추론 서비스 상태 확인, 로그 조회
oncall-readers주요 Namespace 읽기장애 대응 시 관찰과 진단

처음부터 완벽한 RBAC를 만들 필요는 없다. 하지만 처음부터 cluster-admin을 남발하지는 말아야 한다. 작은 팀에서 흔한 변명은 "우리는 서로 믿으니까 괜찮다"다. 그러나 RBAC는 동료를 의심하기 위한 장치가 아니라 실수의 폭발 반경을 줄이기 위한 장치다. 누구나 피곤한 금요일 밤에는 잘못된 터미널에서 명령을 실행할 수 있다.

ResourceQuota: GPU 예산을 네임스페이스에 묶어라

ResourceQuota는 Namespace 단위로 사용할 수 있는 리소스 총량을 제한한다. CPU, 메모리, PVC 용량, 오브젝트 수뿐 아니라 GPU 같은 확장 리소스에도 사용할 수 있다. Kubernetes 공식 문서는 ResourceQuota를 Namespace의 전체 리소스 소비를 제한하는 정책 도구로 설명한다.6

AI 클러스터에서 ResourceQuota는 선택이 아니라 안전장치다. GPU는 비싸고 희소하다. 한 명의 실험 Job이 실수로 replica를 20개 만들었는데 각 파드가 GPU 1개를 요청한다면, 순식간에 클러스터 GPU가 사라질 수 있다. ResourceQuota는 이런 사고를 Namespace 경계에서 막는다.

예를 들어 ai-dev Namespace에는 GPU 2개까지만 허용하고 싶다고 하자.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: ai-dev-quota
  namespace: ai-dev
spec:
  hard:
    requests.cpu: "32"
    requests.memory: 128Gi
    requests.nvidia.com/gpu: "2"
    persistentvolumeclaims: "10"
    requests.storage: 500Gi

반면 프로덕션 추론 Namespace에는 GPU를 더 많이 허용하되, 파드 수와 스토리지도 함께 제한한다.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: ai-serving-quota
  namespace: ai-serving
spec:
  hard:
    requests.cpu: "128"
    requests.memory: 512Gi
    requests.nvidia.com/gpu: "8"
    pods: "80"
    services: "20"
    persistentvolumeclaims: "20"
    requests.storage: 2Ti

여기서 requests.nvidia.com/gpu 형식에 주목하자. GPU 같은 확장 리소스는 CPU처럼 requests와 limits를 자유롭게 오버커밋하는 자원이 아니다. 기본적으로 정수 단위로 할당되며, 파드가 GPU 1개를 요청하면 그 GPU는 해당 파드에 독점적으로 배정된다. MIG나 time-slicing 같은 공유 전략은 7장에서 자세히 다룬다.

ResourceQuota와 함께 LimitRange도 자주 쓴다. LimitRange는 Namespace 안에서 파드나 컨테이너의 기본 requests/limits를 정하거나 최소·최대 범위를 제한한다. 개발자가 CPU와 메모리 requests를 빼먹으면 스케줄러가 정확한 판단을 하기 어렵다. 특히 GPU 파드는 GPU만 요청하고 CPU·메모리를 적지 않는 경우가 많은데, 그러면 노드 메모리 압박으로 OOMKilled가 발생할 수 있다.

apiVersion: v1
kind: LimitRange
metadata:
  name: default-compute
  namespace: ai-dev
spec:
  limits:
    - type: Container
      defaultRequest:
        cpu: "500m"
        memory: 1Gi
      default:
        cpu: "2"
        memory: 4Gi

ResourceQuota는 비용 통제 도구이기도 하지만 대화 도구이기도 하다. "왜 우리 팀은 GPU 2개밖에 못 쓰나요?"라는 질문이 나오면, 그때부터 우선순위와 예산에 대한 대화가 시작된다. 쿠버네티스는 조직의 갈등을 없애주지 않는다. 다만 그 갈등을 YAML로 명시하게 해준다.

개발·스테이징·프로덕션을 어떻게 나눌 것인가

환경 분리는 모든 팀의 고민이다. 쿠버네티스에서는 크게 두 가지 방식이 있다. 하나의 클러스터 안에서 Namespace로 나누는 방식, 그리고 환경마다 클러스터를 분리하는 방식이다.

개발과 실험은 하나의 클러스터 안에서 Namespace로 나눠도 충분한 경우가 많다. ai-dev, team-a-dev, team-b-dev처럼 나누고 ResourceQuota를 걸면 된다. 비용도 절약되고 운영도 단순하다. 로컬 클러스터나 작은 매니지드 클러스터에서 실험용 환경을 운영하기 좋다.

스테이징은 프로덕션과 최대한 비슷해야 한다. 같은 Helm 차트, 같은 Secret 구조, 같은 Gateway 경로, 같은 모델 서버 옵션을 사용하되 replica 수와 GPU 수만 줄이는 방식이 좋다. 스테이징이 너무 가짜이면 장애도 가짜로만 잡힌다. 예를 들어 프로덕션에서는 모델 가중치를 PVC에 캐시하는데 스테이징에서는 컨테이너 이미지 안에 넣어둔다면, 모델 로딩 장애를 미리 발견할 수 없다.

프로덕션은 가능하면 별도 클러스터로 분리하는 편이 안전하다. Namespace만으로도 논리적 분리는 가능하지만, 클러스터 수준 장애를 막을 수는 없다. 잘못 설치한 CNI, GPU Operator 업그레이드 실패, API 서버 과부하, 노드 전체 장애는 같은 클러스터의 모든 Namespace에 영향을 준다. 특히 고객 트래픽을 받는 추론 서비스라면 개발 실험과 같은 클러스터에 두는 것이 장기적으로 위험할 수 있다.

현실적인 구조는 다음과 같다.

로컬 클러스터       : 개인 실습, 매니페스트 테스트
공유 dev 클러스터   : 팀 실험, 기능 개발, 작은 모델 검증
staging 클러스터    : 배포 전 검증, 부하 테스트, 장애 리허설
prod-serving 클러스터: 사용자 트래픽을 받는 추론 서비스
prod-training 클러스터: 대규모 학습과 배치 작업

물론 모든 팀이 처음부터 이렇게 나눌 필요는 없다. 작은 팀은 dev와 prod 두 개로 시작해도 된다. 중요한 것은 "지금은 합쳐 쓰지만, 나중에 분리할 수 있게" 만드는 것이다. Namespace 이름, Helm values, Secret 관리, DNS, 이미지 태그 전략을 처음부터 환경 분리를 염두에 두고 설계하면 나중에 덜 아프다.

AI 클러스터의 기본 애드온 세트

쿠버네티스 클러스터를 만들었다고 AI 플랫폼이 완성되는 것은 아니다. AI 워크로드를 운영하려면 기본 애드온 세트가 필요하다. 클라우드마다 기본 제공 범위는 다르지만, 개념적으로는 다음 구성을 갖추는 것이 좋다.

영역대표 구성요소역할
네트워크CNI, Gateway API, Ingress Controller파드 간 통신과 외부 트래픽 진입
스토리지CSI Driver, StorageClass모델 가중치, 체크포인트, 캐시 저장
GPUNVIDIA GPU Operator, Device Plugin, GPU Feature DiscoveryGPU 발견, 할당, 모니터링
관찰 가능성Prometheus, Grafana, Loki, Alertmanager메트릭, 로그, 알림
인증서cert-managerTLS 인증서 자동 발급과 갱신
시크릿External Secrets, Vault 연동API 키와 토큰 관리
배포Helm, Argo CD 또는 Flux선언적 배포와 GitOps
오토스케일링metrics-server, KEDA, Cluster Autoscaler/Karpenter파드와 노드 확장

AI 팀이 자주 저지르는 실수는 모델 서버부터 띄우는 것이다. 물론 빠른 데모에는 그게 맞다. 하지만 프로덕션에서는 모델 서버보다 먼저 로그와 메트릭, 권한, 시크릿, 스토리지, 배포 롤백이 있어야 한다. 관찰 도구 없이 GPU 추론 서버를 운영하는 것은 계기판 없이 야간 운전하는 것과 비슷하다.

특히 GPU 모니터링은 별도로 챙겨야 한다. CPU와 메모리만 봐서는 AI 워크로드의 상태를 알 수 없다. GPU 사용률, GPU 메모리, 온도, 전력, ECC 에러, 모델별 요청 수, 토큰 처리량, TTFT 같은 지표가 필요하다. 이 책의 뒤 장에서 Prometheus, DCGM Exporter, 추론 메트릭을 연결해 자세히 다룬다.

작은 팀을 위한 현실적인 시작 순서

이 책의 독자 중 상당수는 대기업 플랫폼 팀이 아닐 것이다. 한두 명이 백엔드, 인프라, AI 기능 개발을 같이 맡고 있을 수 있다. 그런 팀에게 "처음부터 멀티 클러스터 GitOps와 베어메탈 GPU 풀을 구성하라"고 말하는 것은 도움이 되지 않는다.

작은 팀이라면 다음 순서가 현실적이다.

첫째, 로컬에서 쿠버네티스 문법을 익힌다. kind나 minikube로 Namespace, Deployment, Service, Secret, ConfigMap, PVC, RBAC를 손으로 만들어 본다. GPU 없이도 충분하다. 이 단계의 목표는 모델 성능이 아니라 운영 문법이다.

둘째, 매니지드 클러스터 하나를 만든다. 처음에는 CPU 노드 풀만 있어도 된다. API 서버, RAG 백엔드, Redis, 작은 워커를 올려본다. 배포는 Helm으로 묶고, 가능하면 Argo CD 같은 GitOps 도구를 붙인다.

셋째, GPU 노드 풀을 추가한다. GPU 노드에는 taint와 label을 붙인다. NVIDIA GPU Operator 또는 클라우드가 권장하는 GPU 플러그인을 설치한다. 작은 vLLM 서버 하나를 올려 OpenAI 호환 API가 동작하는지 확인한다.

넷째, ResourceQuota와 RBAC를 적용한다. 이 시점이 중요하다. 서비스가 커진 뒤 권한과 quota를 조이려면 반발과 장애가 생긴다. 작을 때부터 "기본은 제한, 필요하면 확장"이라는 문화를 만든다.

다섯째, 비용과 사용률을 본다. GPU가 하루에 몇 시간 실제로 바쁘게 일하는지 확인한다. 트래픽이 거의 없는데 GPU가 계속 켜져 있다면 scale-to-zero나 예약 기반 배치 실행을 고려한다. 반대로 GPU가 항상 바쁘고 클라우드 비용이 예측 가능하게 커진다면 베어메탈이나 장기 약정, GPU 전문 클라우드를 검토한다.

이 순서는 기술적으로 가장 화려하지 않다. 하지만 실패 비용이 낮다. AI 인프라는 한 번에 완성되는 건축물이 아니라, 사용량과 장애 경험을 먹고 자라는 운영 체계다.

클러스터 선택 체크리스트

마지막으로 팀에서 클러스터 선택 회의를 할 때 사용할 수 있는 질문을 정리해 보자. 이 질문에 답하지 못한 상태에서 "일단 H100 서버부터 사자" 또는 "일단 EKS에 다 올리자"라고 결정하면 나중에 비용으로 배운다.

  • 우리 워크로드는 추론 중심인가, 학습 중심인가, 배치 처리 중심인가?

  • GPU가 필요한 시간이 하루 중 몇 시간인가?

  • 트래픽은 예측 가능한가, 이벤트성으로 튀는가?

  • 모델 가중치는 어디에 저장하고, 파드 재시작 시 얼마나 빨리 로딩해야 하는가?

  • GPU 노드가 0개로 줄었다가 다시 늘어나는 콜드 스타트를 허용할 수 있는가?

  • 팀에 쿠버네티스 컨트롤 플레인을 직접 운영할 사람이 있는가?

  • 장애가 났을 때 24시간 대응할 수 있는가?

  • 데이터가 퍼블릭 클라우드로 나가도 되는가?

  • 클라우드 GPU quota 부족이 사업에 영향을 줄 수 있는가?

  • 6개월 뒤 베어메탈이나 다른 클라우드로 옮길 가능성이 있는가?

이 질문의 답이 "아직 모르겠다"라면 매니지드 쿠버네티스에서 작게 시작하는 편이 좋다. 답이 "우리는 GPU를 매일 80% 이상 쓸 것이고, 전담 운영자가 있으며, 데이터센터 운영도 가능하다"라면 베어메탈을 검토할 만하다. 답이 "쿠버네티스도 아직 익숙하지 않다"라면 로컬 클러스터와 작은 dev 클러스터부터 시작하자.

쿠버네티스는 선택지가 많은 도구다. 그래서 처음에는 복잡해 보인다. 하지만 AI 팀의 관점에서 보면 기준은 단순해진다. 실험은 로컬에서, 첫 제품은 매니지드에서, 높은 사용률과 강한 통제가 필요할 때 베어메탈로 간다. 그리고 어떤 환경을 선택하든 kubeconfig, namespace, RBAC, ServiceAccount, ResourceQuota로 운영의 경계를 먼저 세운다.

다음 장에서는 이 경계 안에서 실제 워크로드가 어떻게 실행되는지 살펴본다. Pod, Deployment, StatefulSet, DaemonSet, Job, CronJob을 AI 관점에서 다시 읽어볼 것이다. 학습은 왜 Job에 가깝고, 추론은 왜 Deployment에 가까우며, 모델 캐시와 상태를 가진 에이전트는 왜 단순한 웹 서버와 다른지 하나씩 풀어보자.

참고

1Cast AI 2026 State of Kubernetes Optimization Report

2NVIDIA AI Enterprise Bare Metal Deployment Guide: GPU Operator Overview

3vLLM Production Stack Documentation

4NAVER D2: 대규모 AI 서비스 운영을 위한 Kubernetes GPU 클러스터 도입기

5Kubernetes Documentation: Configure Service Accounts for Pods

6Kubernetes Documentation: Resource Quotas

책 목록

AI 시대의 쿠버네티스: LLM 추론과 에이전트를 운영하는 인프라 전략

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기