이 챕터의 범위: Deployment와 배포 전략

  • 컨테이너화된 애플리케이션을 운영하다 보면 새 버전 배포가 반복적으로 발생한다
  • Kubernetes는 Deployment 리소스를 통해 이 과정을 선언적으로, 자동으로 처리한다
  • 이 챕터는 Deployment의 동작 원리와 네 가지 배포/릴리즈 전략을 다룬다

0. Contents


선언적 배포의 핵심

  • Kubernetes에서 애플리케이션을 배포한다는 것은 YAML 파일을 작성하고 kubectl apply를 실행하는 것이다
  • 그 뒤의 모든 과정은 Kubernetes가 처리한다
    • Pod 생성
    • 헬스체크
    • 순차 교체
    • 실패 시 롤백
  • 이것이 선언적 배포의 핵심이다

1. Problem & Solution

1.1 Problem

마이크로서비스 환경의 업데이트

  • 마이크로서비스 환경에서는 서비스 수가 많다
  • 각 서비스가 독립적으로 업데이트된다

한 서비스를 새 버전으로 교체하는 단계

  • 새 버전 Pod 실행
  • 기존 Pod 안전하게 종료 (graceful shutdown)
  • 새 Pod 정상 실행 여부 확인
  • 실패 시 이전 버전으로 롤백

문제: 수동 배포와 스크립트의 한계

  • 이 과정을 수동으로 하면 → 사람 실수가 생긴다
  • 스크립트로 자동화하면 → 유지 비용이 크다
  • 서비스가 많아질수록 배포 자체가 병목이 된다

업데이트 방식 두 가지

방식설명단점
다운타임 허용기존 전부 종료 후 새 버전 실행서비스 중단
다운타임 없음구버전과 신버전 동시 실행리소스 2배 사용

1.2 Solution

해법: Deployment 리소스

  • Kubernetes의 Deployment 리소스가 이 문제를 해결한다
  • Deployment는 “이런 상태여야 해"라고 선언해두면 나머지를 자동으로 처리하는 주문서다
누가할 일
개발자YAML 파일 작성 + kubectl apply
KubernetesPod 생성, 교체, 헬스체크, 롤백 전부

자동화의 효과

  • 릴리즈 사이클마다 수십 번 배포가 반복되는 환경에서, 이 자동화는 운영 비용을 크게 줄인다

2. How Deployment Works

2.1 Deployment → ReplicaSet → Pod

Deployment와 ReplicaSet의 관계

  • Deployment는 직접 Pod를 만들지 않는다
  • 내부적으로 ReplicaSet을 생성하고, ReplicaSet이 Pod를 관리한다

업데이트 시 ReplicaSet 동작

  • 새 ReplicaSet이 추가로 생성된다
  • 기존 ReplicaSet의 Pod를 하나씩 줄이면서 새 ReplicaSet의 Pod를 늘린다
  • 업데이트가 완료된 후에도 기존 ReplicaSet은 삭제되지 않고 replicas=0 상태로 남는다
    • 롤백 시 재사용하기 위해서다
Deployment주문서 · 설계도원하는 상태를 선언한다생성ReplicaSet v1 · Pod 개수 관리자replicas=0 · 롤백 대기생성빈 자리빈 자리빈 자리ReplicaSet v2 · Pod 개수 관리자replicas=3생성Pod실제 앱v2 · 준비됨Pod실제 앱v2 · 준비됨Pod실제 앱v2 · 준비됨업데이트가 끝나도 v1 ReplicaSet은 지우지 않는다. 롤백할 때 다시 늘려 쓴다
Deployment는 ReplicaSet을 만들고, ReplicaSet이 Pod를 만든다. 옛 ReplicaSet은 0개로 남는다

2.2 Prerequisites for Deployment

컨테이너의 두 가지 전제 조건

  • Deployment가 Pod를 예측 가능하게 시작하고 종료하려면 컨테이너가 두 가지를 갖춰야 한다
조건설명관련 챕터
Lifecycle 이벤트 처리SIGTERM 수신 시 작업을 마무리하고 종료Chapter 5, Managed Lifecycle
Health-check endpointreadinessProbe로 준비 완료 여부를 알림Chapter 4, Health Probe

전제 조건이 없을 때

  • 이 두 가지가 없으면 Kubernetes는 알 수 없다
    • Pod가 언제 준비됐는지
    • 언제 안전하게 종료할 수 있는지

2.3 kubectl rollout

YAML 수정과 rollout 명령어

  • Deployment는 YAML 파일 수정만으로도 관리할 수 있다
  • 일상적인 작업에는 kubectl rollout 명령어가 편리하다

참고: 명령형에서 선언형으로

  • Kubernetes 1.18 이전에는 kubectl rolling-update 명령어가 있었다
    • 클라이언트(kubectl)가 각 업데이트 단계를 직접 서버에 지시하는 명령형 방식이었다
  • 현재의 kubectl rollout은 선언형 방식이다
    • 서버 측에서 Deployment 선언을 기반으로 Kubernetes가 알아서 처리한다
명령어역할
kubectl rollout status현재 배포 진행 상태 확인
kubectl rollout pause롤아웃 일시 중지
kubectl rollout resume일시 중지된 롤아웃 재개
kubectl rollout undo이전 버전으로 롤백
kubectl rollout history배포 히스토리 확인
kubectl rollout restart현재 Pod 재시작 (업데이트 없이)

3. Rolling Deployment

Deployment의 기본 전략

  • RollingUpdate는 Deployment의 기본 전략이다
  • Pod를 하나씩 교체하면서 항상 일정 수 이상의 Pod가 살아있도록 보장한다
  • → 서비스 중단 없이 업데이트할 수 있다

3.1 Example YAML

# Example 3-1. Deployment for a rolling update
apiVersion: apps/v1
kind: Deployment
metadata:
  name: random-generator
spec:
  replicas: 3              # Pod 3개 유지 (롤링 업데이트는 2개 이상 필요)
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # 업데이트 중 추가로 띄울 수 있는 Pod 수 → 최대 4개
      maxUnavailable: 1    # 동시에 꺼져도 되는 Pod 수 → 최소 2개 유지
  minReadySeconds: 60      # 새 Pod readinessProbe 성공 후 60초 대기
  selector:
    matchLabels:
      app: random-generator
  template:
    metadata:
      labels:
        app: random-generator
    spec:
      containers:
      - image: k8spatterns/random-generator:1.0
        name: random-generator
        readinessProbe:            # 롤링 배포에서 핵심. 절대 빠뜨리면 안 됨
          exec:
            command: [ "stat", "/tmp/random-generator-ready" ]

3.2 maxSurge & maxUnavailable

설정 단위와 기본값

  • 두 필드 모두 절댓값 또는 퍼센트(%)로 설정할 수 있다
  • 퍼센트일 때 replicas 수를 기준으로 계산한다
    • maxSurge는 올림
    • maxUnavailable은 내림으로 처리한다
  • 기본값은 둘 다 25%다

replicas: 3, maxSurge: 1, maxUnavailable: 1 기준

  • 최대 Pod 수 = 3 + 1 = 4개 (maxSurge)
  • 최소 Pod 수 = 3 - 1 = 2개 (maxUnavailable)
  • → 업데이트 중 항상 2~4개 사이에서 유지

값 크기에 따른 차이

  • 숫자를 키우면 → 교체 속도가 빨라진다
  • 줄이면 → 느리지만 안정적이다

3.3 minReadySeconds

준비 완료 인정 기준

  • 새 Pod의 readinessProbe가 이 시간(초) 동안 연속으로 성공해야 “준비 완료"로 인정한다
  • 그 뒤에 다음 Pod 교체를 시작한다
1새 Pod 시작2readinessProbe통과 ✓3minReadySeconds: 6060초 동안이상 없어야 함4"준비 완료" 인정다음 Pod 교체 시작
readinessProbe 통과만으로는 부족하고, 60초를 더 버텨야 다음 교체로 넘어간다

큰 값의 장점

  • 값을 크게 설정할수록 안전하다
  • 교체 사이사이에 여유가 생겨 kubectl rollout pause로 일시 중지하기도 쉽다

3.4 Rolling Update Step-by-Step

ServiceReplicaSetv 1.0ReplicaSetv 1.1v 1.0✓v 1.0✓v 1.0✓

전체 흐름 요약

  • 아래는 전체 흐름을 한 장으로 정리한 그림이다
ReplicaSet v1ReplicaSet v2Pod 수✓ 준비 완료↻ 기동 중0단계v1 ✓v1 ✓v1 ✓3개1단계v1 ✓v2 ↻v1 ✓v1 ✓4개, maxSurge 허용2단계v1 ✓v2 ✓v1 ✓3개, v1 하나 종료3단계v1 ✓v2 ✓v1 ✓v2 ↻4개4단계v1 ✓v2 ✓v2 ✓3개, v1 하나 더 종료5단계v1 ✓v2 ✓v2 ✓v2 ↻4개6단계v2 ✓v2 ✓v2 ✓3개, 마지막 v1 종료완료replicas=0 대기v2 ✓v2 ✓v2 ✓3개
Pod 하나를 띄우고 하나를 끄는 일을 세 번 반복한다. Pod 수는 3개와 4개를 오간다

업데이트 중 Pod 수

  • 업데이트 내내 Pod 수는 2개(최소)와 4개(최대) 사이에서 유지된다
  • 사용자는 서비스 중단을 느끼지 못한다

3.5 How to Trigger an Update

업데이트 시작 방법 세 가지

# 1. 새 YAML 파일로 통째로 교체
kubectl replace -f new-deployment.yaml

# 2. 특정 부분만 수정
kubectl patch deployment random-generator \
  -p '{"spec":{"template":{"spec":{"containers":[{"name":"random-generator","image":"k8spatterns/random-generator:2.0"}]}}}}'

# 또는 에디터로 직접 수정
kubectl edit deployment random-generator

# 3. 이미지만 바꿀 때 (가장 간단)
kubectl set image deployment/random-generator \
  random-generator=k8spatterns/random-generator:2.0
방법언제 쓰나
kubectl replace변경사항이 많을 때
kubectl patch / edit일부 필드만 수정할 때
kubectl set image이미지 버전만 바꿀 때

3.6 Benefits of Deployment

네 가지 구조적 장점

  • 명령형 방식의 단점을 해결하는 것 외에 Deployment는 네 가지 구조적 장점을 가진다

서버 측 자동 관리

  • 업데이트 전 과정이 서버에서 처리된다
  • 클라이언트(개발자)의 개입 없이 Kubernetes가 상태를 유지한다

선언적 목표 지향

  • “어떻게 해라"가 아니라 “이런 상태여야 해"를 선언한다
  • 도달 방법은 Kubernetes가 결정한다

환경 간 재사용

  • YAML 파일은 단순 문서가 아니라 실행 가능한 객체다
  • 개발 → 스테이징 → 운영 환경에서 같은 파일을 그대로 사용할 수 있다

버전 관리와 롤백

  • 업데이트 과정이 전부 기록되고 버전이 매겨진다
  • kubectl rollout history로 확인한다
  • kubectl rollout undo로 언제든 롤백할 수 있다

4. Fixed Deployment (Recreate)

RollingUpdate의 단점: 두 버전 동시 실행

  • RollingUpdate의 단점은 업데이트 중 두 버전이 동시에 실행된다는 것이다
  • API가 하위 호환이 되지 않는 변경이 있을 때 문제가 생긴다

예: 응답 필드명 변경

  • 응답 필드명이 price에서 amount로 바뀌었다면
    • v1 Pod와 v2 Pod가 공존하는 시간 동안 클라이언트는 어떤 응답이 올지 예측할 수 없다
  • 이 경우 Recreate 전략을 사용한다
spec:
  strategy:
    type: Recreate    # maxUnavailable = replicas 전체로 설정하는 것과 같음

Recreate의 동작

  • Recreate는 maxUnavailable을 replicas 수 전체로 설정한 것과 동일하게 동작한다
  • 기존 Pod를 전부 종료한 뒤 새 Pod를 전부 동시에 시작한다
  • 중간에 다운타임이 발생한다
  • 대신 두 버전이 절대 공존하지 않는다는 것이 보장된다
RollingUpdate (기본 전략)v1 · v2 공존v1v1v1시작v1v1v2교체 중v1v2v2교체 중v2v2v2완료다운타임 없음. 대신 price 응답과 amount 응답이 섞여 나갈 수 있다Recreatev1v1v1Pod 0개 · 다운타임v2v2v2시작v1 전부 종료v2 전부 동시 시작두 버전이 절대 함께 뜨지 않는다. 대신 그 사이에 서비스가 멈춘다
RollingUpdate는 다운타임 대신 두 버전 공존을, Recreate는 공존 대신 다운타임을 택한다
RollingUpdateRecreate
다운타임없음있음
v1/v2 공존있음없음
API 호환성 문제발생 가능없음
언제 사용일반적인 업데이트API 크게 변경 시

5. Blue-Green Release

기본 리소스 조합으로 만드는 전략

  • Blue-Green은 Kubernetes 기본 제공 전략이 아니다
  • Deployment와 Service 같은 기본 리소스를 조합해서 구현하는 고급 릴리즈 전략이다
Serviceselector: version=v1.0Blue (v1.0)v 1.0✓v 1.0✓v 1.0✓Green (v1.1)v 1.1↻v 1.1↻v 1.1↻

구현 방식

# Blue Deployment (기존 v1.0)
metadata:
  name: app-blue
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: random-generator
        version: v1.0       # Blue 식별 라벨

# Green Deployment (새 v1.1)
metadata:
  name: app-green
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: random-generator
        version: v1.1       # Green 식별 라벨
# Service - selector 변경으로 트래픽 전환
spec:
  selector:
    app: random-generator
    version: v1.0    # → v1.1로 바꾸면 즉시 Green으로 전환

전환 흐름

1단계Green Deployment 생성별도 주문서 제출2단계Green Pod 전부 준비 완료 확인3단계Service selector: v1.0 → v1.1트래픽 즉시 전환4단계문제 없으면Blue Deployment 삭제문제 있으면selector를 v1.0으로 되돌리면 즉시 롤백
트래픽 전환과 롤백은 모두 Service selector 한 줄로 끝난다
내용
장점한 버전만 서비스 → 클라이언트 단순, 즉시 롤백 가능
단점 1두 환경이 동시에 뜨는 동안 리소스 2배 필요
단점 2오래 실행 중인 프로세스나 DB 스키마 변경 시 복잡성 증가

6. Canary Release

전략 개요: 일부 Pod 먼저 교체

  • Canary는 전체 Pod 중 일부만 새 버전으로 교체해서 소수의 사용자가 먼저 경험하게 하는 전략이다
  • 새 버전에 문제가 없다고 확인되면 나머지를 교체한다

이름의 유래

  • 광산에서 유독가스 감지를 위해 카나리아 새를 먼저 들여보내던 데서 이름이 유래했다

구현: 두 개의 Deployment

# 기존 Deployment (v1) - replicas 많음
metadata:
  name: app-v1
spec:
  replicas: 4

# Canary Deployment (v2) - replicas 적음
metadata:
  name: app-v2
spec:
  replicas: 1    # 전체의 20%만

트래픽 분산 방식

  • 두 Deployment가 같은 라벨을 공유하면 Service가 자동으로 트래픽을 분산한다

전체 5개 Pod 중

  • v1 Pod 4개 → 트래픽 80%
  • v2 Pod 1개 → 트래픽 20%

확인 후 전환 과정

# v2 문제없으면 점진적 전환
kubectl scale deployment app-v2 --replicas=5
kubectl scale deployment app-v1 --replicas=0

# v2 문제 있으면 즉시 롤백
kubectl delete deployment app-v2
svcService같은 라벨 Pod에 분산app-v1 · replicas: 4Pod v1Pod v1Pod v1Pod v1app-v2 (Canary) · replicas: 1Pod v280%20%v2를 지켜보며 확인사람이 판단scale문제 없음 → 점진적 전환app-v2 --replicas=5app-v1 --replicas=0delete문제 있음 → 즉시 롤백deployment app-v2v1 Pod 4개만 남는다
Pod 수로 트래픽을 나누고, 전환과 롤백은 사람이 판단한다

Canary와 RollingUpdate의 목적 차이

  • 겉보기에 비슷하지만 목적이 다르다
RollingUpdateCanary
목적빠른 전체 교체안전한 검증 후 교체
전환 주체Kubernetes 자동사람이 판단
모니터링없음각 단계마다 확인
트래픽 조절불가가능

7. Strategy Comparison

전략다운타임두 버전 공존자동화리소스K8s 기본RollingUpdate기본 전략없음 ✓있음완전 자동 ✓보통✓RecreateFixed Deployment있음없음 ✓완전 자동 ✓보통✓Blue-Green고급 릴리즈 전략없음 ✓없음 ✓사람 개입2배✕Canary고급 릴리즈 전략없음 ✓있음 (의도적)사람 개입보통✕

기본 전략과 고급 전략

  • 기본 전략(RollingUpdate, Recreate)은 Kubernetes가 완전 자동으로 처리한다
  • 고급 전략(Blue-Green, Canary)은 전환 시점을 사람이 판단해야 한다
    • Kubernetes가 직접 지원하지 않는다

8. Higher-Level Deployments

별도 플랫폼이 필요한 이유

  • Deployment는 RollingUpdate와 Recreate만 기본 제공한다
  • Blue-Green과 Canary를 선언적으로 자동화하려면 별도 플랫폼이 필요하다

공통 기반: Operator 패턴

  • 이 플랫폼들은 모두 Operator 패턴(Chapter 28)을 기반으로 동작한다
  • 새로운 커스텀 리소스 타입을 도입해 롤아웃 동작을 선언하면, Operator가 서버 측에서 필요한 작업을 처리한다
  • 일부는 업데이트 오류 시 자동 롤백도 지원한다

Flagger

  • Flux CD GitOps 도구의 일부다
  • 카나리와 Blue-Green 배포를 지원한다
  • 인그레스 컨트롤러와 서비스 메시와 통합해 트래픽 분할을 처리한다
  • 커스텀 메트릭으로 롤아웃 상태를 모니터링하고 실패 시 자동 롤백한다

Argo Rollouts

  • Argo CD GitOps 생태계의 일부로, Kubernetes를 위한 CD 솔루션이다
  • Flagger와 기능이 유사하며, 인그레스 컨트롤러와 서비스 메시를 지원한다
  • Flagger와 Argo Rollouts 중 선택은 어떤 GitOps 플랫폼을 사용하는지에 따라 결정하면 된다

Knative

  • Kubernetes 위의 서버리스 플랫폼이다
  • 트래픽 기반 오토스케일링이 핵심 기능이다(Chapter 29)
  • 트래픽 분할을 통한 간단한 배포 지원도 제공한다
  • Flagger나 Argo Rollouts만큼 고급 롤아웃 기능을 제공하지는 않는다
    • 이미 Knative를 사용하는 환경이라면 별도 도구 없이 활용할 수 있다

소속 재단

  • 세 프로젝트 모두 CNCF(Cloud Native Computing Foundation) 소속이다

9. Q & A

Q1. Deployment와 Pod를 직접 만드는 것의 차이

Pod 직접 생성과 Deployment의 차이

  • Pod를 직접 생성하면 해당 Pod가 종료될 때 아무도 살려주지 않는다
  • Deployment를 사용하면 Pod가 죽어도 Kubernetes가 자동으로 새 Pod를 만들어 선언된 수를 유지한다

결론: 운영 환경은 Deployment

  • Deployment 없이 Pod를 직접 운영하는 것은 구성 파일 없이 서버를 수동으로 관리하는 것과 같다
  • 운영 환경에서는 반드시 Deployment를 사용해야 한다

Q2. Rolling Update 중 두 버전이 공존하면 문제가 없나

문제없는 경우: 하위 호환 변경

  • API 응답 구조가 동일하게 유지되는 경우라면 문제없다
  • 하위 호환성이 보장되는 변경이 이에 해당한다
    • 예: 기존 필드를 유지하면서 새 필드를 추가하는 경우

문제가 되는 경우: 하위 호환이 깨지는 변경

  • 기존 필드를 삭제하거나 이름을 변경하는 등 하위 호환이 깨지는 변경
    • → 두 버전 공존이 클라이언트 오류를 유발한다
  • 이 경우 Recreate 또는 Blue-Green 전략을 선택해야 한다

Q3. Blue-Green과 Canary의 선택 기준

같은 문제, 다른 방식

  • 두 전략 모두 두 버전 공존 문제를 해결하지만 방식이 다르다

Blue-Green: 순간 전환

  • Blue-Green은 전환이 순간적으로 이루어진다
  • 신버전이 완전히 준비된 후 트래픽을 한꺼번에 전환한다
    • → 전환 중 두 버전이 동시에 트래픽을 받는 시간이 없다
  • 대신 리소스가 일시적으로 2배 필요하다

Canary: 점진적 전환

  • Canary는 소수 사용자에게 먼저 노출해서 실제 트래픽으로 검증한 뒤 점진적으로 전환한다
  • 리소스 효율은 좋다
  • 대신 검증 기간 동안 두 버전이 공존한다

선택 기준

  • API가 크게 바뀌었다면 → Blue-Green이 맞다
  • 새 버전의 안정성을 실사용자로 검증하면서 위험을 최소화하고 싶다면 → Canary가 맞다