[IT-방법] 디플로이먼트 YAML 설정 파일 작성법 – 실무 매니페스트 핵심 필드와 예제

디플로이먼트 관련 쿠버네티스 구조를 설명하는 대표 이미지

디플로이먼트 YAML 설정 파일, 왜 제대로 작성해야 할까요?

데이터 파이프라인을 운영하는 엔지니어라면 한 번쯤은 새벽에 알람을 듣고 일어나 CrashLoopBackOff 상태에 빠진 포드를 마주한 경험이 있을 거예요. 분명 로컬 환경에서는 잘 돌아가던 컨테이너였는데, 쿠버네티스에 배포만 하면 원인을 알 수 없는 오류가 반복되곤 하죠. 대개의 경우 문제는 컨테이너 코드 자체가 아니라, 그 컨테이너를 감싸고 있는 디플로이먼트 YAML 설정 파일의 사소한 실수에서 시작돼요.

잘못된 설정 하나가 서비스 전체의 가용성을 떨어뜨리고, 데이터 유실이라는 치명적인 결과로 이어질 수 있어요. 단순히 포드를 띄우는 것을 넘어, 어떻게 하면 무중단으로 업데이트를 수행하고 자원을 효율적으로 배분할 수 있을지 고민해야 하는 시점이에요. 이 글은 단순히 문법을 나열하는 것이 아니라, 실제 운영 환경에서 발생할 수 있는 변수들을 어떻게 매니페스트에 녹여낼지에 집중해요.

이 글을 끝까지 읽고 나면 다음과 같은 능력을 갖추게 될 거예요.

  • 디플로이먼트 매니페스트를 구성하는 필수 필드의 정확한 의미를 이해해요.
  • 실무에서 즉시 복사해서 사용할 수 있는 수준의 고품질 YAML 예제를 확보해요.
  • 배포 시 발생할 수 있는 흔한 실수들을 사전에 차단하는 검증 습관을 길러요.

안정적인 배포를 위한 사전 지식과 체크리스트

디플로이먼트를 작성하기 전에 우리가 무엇을 제어하려 하는지 명확히 알아야 해요. 쿠버네티스에서 디플로이먼트는 단순히 컨테이너를 실행하는 도구가 아니라, 원하는 상태(Desired State)를 유지하는 관리자예요. 우리가 YAML에 “복제본은 3개여야 해”라고 적으면, 디플로이먼트는 클러스터 전체를 감시하며 항상 3개의 포드가 돌아가도록 끊임없이 노력해요.

하지만 모든 워크로드가 디플로이먼트 방식에 적합한 것은 아니에요. 데이터 엔지니어라면 데이터의 상태를 유지해야 하는지, 아니면 단순 계산용 워커 노드인지에 따라 선택지가 달라져야 해요. 아래 표를 통해 상황에 맞는 컨트롤러를 선택하는 기준을 확인해 보세요.

컨트롤러 유형 주요 특징 추천 사용 사례
디플로이먼트(Deployment) 상태가 없는(Stateless) 앱 관리 웹 서버, API 서버, 데이터 처리 워커
스테이트풀셋(StatefulSet) 고유한 ID와 데이터 저장 유지 데이터베이스(DB), 분산 메시지 큐
데몬셋(DaemonSet) 모든 노드에 하나씩 실행 로그 수집기, 모니터링 에이전트
💡 알아두기
디플로이먼트는 내부적으로 레플리카셋(ReplicaSet)을 생성하여 포드의 개수를 관리해요. 우리가 설정을 변경하면 새로운 레플리카셋이 만들어지고, 기존의 것을 점진적으로 줄여나가는 방식으로 업데이트가 진행돼요.

작성을 시작하기 전에 다음 세 가지가 준비되었는지 확인해 주세요. 첫째, 사용할 컨테이너 이미지가 레지스트리에 등록되어 있어야 해요. 둘째, 서비스가 사용할 포트 번호가 명확해야 해요. 셋째, 애플리케이션이 종료될 때 안전하게 데이터를 저장할 수 있는 구조인지 검토해야 해요. 이 준비가 끝나야 비로소 견고한 디플로이먼트 설정 파일 작성이 가능해져요.

단계별 디플로이먼트 매니페스트 작성 가이드

이제 본격적으로 실무에서 바로 쓸 수 있는 디플로이먼트 YAML을 만들어볼게요. 단순히 필드를 채우는 것이 아니라, 각 설정이 실제 운영 환경에서 어떤 의미를 갖는지 파악하는 것이 중요해요.

STEP 1. API 버전과 종류 정의하기

모든 매니페스트의 시작은 이 파일이 무엇을 정의하는지 선언하는 거예요. 현재 가장 표준적으로 사용되는 버전은 apps/v1이에요. 여기에 kind: Deployment를 명시하면 쿠버네티스 컨트롤러가 이 파일을 읽고 디플로이먼트 객체를 생성할 준비를 마쳐요.

STEP 2. 메타데이터와 라벨링 전략 세우기

메타데이터는 이 객체의 이름과 네임스페이스를 지정하는 곳이에요. 여기서 가장 중요한 것은 라벨(Labels)이에요. 라벨은 포드와 디플로이먼트를 연결하는 유일한 끈과 같아요. 데이터 파이프라인을 운영한다면 app: pipeline, component: worker, env: production 처럼 계층적인 라벨링을 사용하는 것이 나중에 관리하기 훨씬 편해요.

STEP 3. 셀렉터를 통한 포드 연결 구조 설계

디플로이먼트의 spec.selector 부분은 이 디플로이먼트가 어떤 포드들을 관리할지 결정해요. 여기서 주의할 점은 spec.selector.matchLabels에 적힌 내용이 아래에 나올 spec.template.metadata.labels의 내용과 반드시 일치해야 한다는 점이에요. 이 둘이 다르면 쿠버네티스는 어떤 포드가 자기가 관리해야 할 포드인지 찾지 못해 무한 루프에 빠질 수 있어요.

STEP 4. 컨테이너 사양과 리소스 제한 설정

이제 실제 애플리케이션이 돌아갈 컨테이너의 상세 설정을 정의해요. 이미지 이름과 포트를 지정하는 것은 기본이고, 데이터 엔지니어로서 가장 신경 써야 할 부분은 바로 리소스 제한(Resources)이에요. requests는 포드가 실행되기 위해 최소한으로 필요한 자원이고, limits는 포드가 넘지 말아야 할 상한선이에요. 이 설정을 생략하면 특정 워커가 클러스터 전체의 메모리를 점유해버리는 대참사가 일어날 수 있어요.

STEP 5. 안정성을 위한 프로브와 업데이트 전략

애플리케이션이 실행 중이라고 해서 항상 정상은 아니에요. 그래서 livenessProbe(살아있는지 확인)와 readinessProbe(트래픽을 받을 준비가 되었는지 확인)를 반드시 설정해야 해요. 또한, 배포 중 서비스 중단을 막기 위해 RollingUpdate 전략을 사용하여 포드를 하나씩 교체하는 방식을 권장해요.

실무형 디플로이먼트 YAML 예제

위의 모든 내용을 반영한 완성형 예제예요. 이 코드를 참고해서 본인의 환경에 맞게 수정해 보세요.

# 디플로이먼트 매니페스트 예제
apiVersion: apps/v1
kind: Deployment
metadata:
  name: data-worker-deployment
  labels:
    app: data-pipeline
    component: worker
spec:
  replicas: 3
  selector:
    matchLabels:
      app: data-pipeline
      component: worker
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: data-pipeline
        component: worker
    spec:
      containers:
      - name: worker-container
        image: my-registry/data-worker:v1.2.3
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20
💡 알아두기
위 예제에서 maxSurge: 1은 업데이트 중에 기존 개수보다 최대 1개의 포드를 더 생성할 수 있다는 뜻이고, maxUnavailable: 0은 업데이트 중에도 가용 포드 수가 설정한 복제본 개수보다 적어지면 안 된다는 것을 의미해요.

자주 하는 실수와 해결법 및 자주 묻는 질문

설정 파일을 작성하다 보면 아주 사소한 실수로 인해 배포가 실패하는 경우가 많아요. 실무에서 자주 발생하는 문제들을 정리했으니, 문제가 생기면 가장 먼저 이 리스트를 체크해 보세요.

  • 들여쓰기(Indentation) 오류 → YAML은 들여쓰기에 매우 민감해요. 스페이스와 탭을 혼용하지 말고 반드시 일관된 스페이스를 사용하세요.
  • Selector와 Label 불일치spec.selector.matchLabelsspec.template.metadata.labels가 다르면 포드가 생성되지 않아요.
  • ImagePullBackOff 발생 → 컨테이너 이미지 경로가 틀렸거나, 프라이빗 레지스트리에 접근할 권한(imagePullSecrets)이 없는 경우예요.
  • 무한 재시작(CrashLoopBackOff) → 애플리케이션 실행 직후 에러가 나거나, livenessProbe 설정이 너무 엄격해서 정상적인 포드를 죽이고 있는 건 아닌지 확인하세요.
  • 리소스 부족으로 인한 OOMKilled → 메모리 제한(limits)을 너무 낮게 설정하면 프로세스가 강제로 종료돼요. 실제 사용량을 모니터링하고 적절히 늘려주세요.
⚠️ 주의
리소스 제한을 설정할 때는 반드시 실제 애플리케이션의 동작 패턴을 반영해야 해요. 갑작스러운 데이터 폭증이 예상되는 워커라면 메모리 한계치를 여유 있게 잡아야 해요.

자주 묻는 질문

Q. 디플로이먼트 업데이트를 어떻게 확인하나요?

kubectl rollout status deployment/[디플로이먼트명] 명령어를 사용하면 현재 업데이트가 진행 중인지, 완료되었는지 실시간으로 확인할 수 있어요.

Q. 배포한 내용이 잘못되었을 때 되돌릴 수 있나요?

네, 가능해요. kubectl rollout undo deployment/[디플로이먼트명]을 입력하면 바로 이전의 안정적인 상태로 즉시 롤백할 수 있어요.

Q. Readiness Probe와 Liveness Probe의 차이가 정확히 무엇인가요?

Readiness Probe는 포드가 트래픽을 받을 준비가 되었는지 확인하여 서비스 로드밸런서에 연결할지 결정하고, Liveness Probe는 포드가 살아있는지 확인하여 죽었다면 재시작할지를 결정해요.

Q. YAML 파일에서 버전 관리는 어떻게 하는 것이 좋은가요?

이미지 태그를 latest로 쓰지 마세요. 반드시 v1.2.3처럼 고유한 버전을 명시해야 어떤 버전의 코드가 배포되었는지 추적할 수 있고 롤백도 안전해요.

완벽한 디플로이먼트 관리를 위한 마무리

지금까지 쿠버네티스 디플로이먼트 YAML 설정 파일을 작성하는 핵심 방법과 실무 노하우를 살펴보았어요. 매니페스트는 한 번 쓰고 버리는 문서가 아니라, 우리 서비스의 상태를 정의하는 살아있는 설계도라는 점을 꼭 기억해 주세요.

✅ 핵심 요약

  • Selector와 Template Label은 반드시 일치시켜야 해요.
  • 리소스 제한(Requests/Limits)은 선택이 아닌 필수예요.
  • 무중단 배포를 위해 RollingUpdate 전략을 활용하세요.
  • 안정성을 위해 Readiness와 Liveness Probe를 꼭 포함하세요.
  • 이미지 태그는 항상 구체적인 버전을 명시하세요.

오늘 바로 여러분의 실습 환경이나 스테이징 클러스터에 위에서 배운 내용을 적용해 보세요. 처음에는 복잡해 보여도, 하나씩 필드를 채워가며 kubectl apply --dry-run=client -f [파일명] 명령어로 검증하는 습관을 들이면 금방 익숙해질 거예요.

실제로 적용해 보다가 설정이 꼬이거나 예상치 못한 에러가 발생한다면, 주저하지 말고 댓글로 질문을 남겨 주세요. 함께 고민하고 해결해 봐요!

관련해서 더 깊이 있는 내용을 공부하고 싶다면 아래 글들도 함께 읽어보시는 걸 추천해요.

  • 쿠버네티스 디플로이먼트 기본 개념 정리
  • 안정적인 클러스터 구축을 위한 입문 가이드

댓글 남기기