:bulb: K8s 업데이트 전략은 두 추상화 층위로 나눠서 본다. 하나는 K8s API의 update strategy인 RollingUpdate·Recreate·OnDelete이고, 다른 하나는 배포 패턴인 Rolling·Blue-Green·Canary다. NVIDIA Driver Operator 같은 host kernel 결합 워크로드까지 함께 정리한다.


[01] Rolling Update 개요

K8s의 기본 무중단 배포 전략. Deployment의 Pod를 점진적으로 교체하여 두 버전이 일시적으로 공존하다가 최종적으로 새 버전으로 완전히 전환된다.

1-1. 동작 방식

새 ReplicaSet을 생성하고, 기존 ReplicaSet의 Pod를 줄이면서 새 Pod를 늘려가는 방식이다.

graph LR
    OLD["ReplicaSet v1
(10 Pods)"] -->|점진 감소| MID["v1: 8 / v2: 4
(공존)"] MID -->|점진 교체| NEW["ReplicaSet v2
(10 Pods)"] style OLD fill:#ffcccc,stroke:#c62828 style MID fill:#fff3e0,stroke:#e65100 style NEW fill:#e8f5e9,stroke:#2e7d32

1-2. 핵심 파라미터

spec.strategy.rollingUpdate 하위:

파라미터 의미 기본값
maxUnavailable 동시에 사용 불가능할 수 있는 최대 Pod 수 25%
maxSurge desired replica를 초과해 추가로 띄울 수 있는 최대 Pod 수 25%

예: replicas=10, maxUnavailable=2, maxSurge=2 → 항상 최소 8개가 동작하고, 최대 12개까지 띄우며 교체한다.

1-3. 주요 명령어

1
2
3
4
kubectl set image deployment/myapp container=myapp:v2  # 트리거
kubectl rollout status deployment/myapp                # 진행 상황
kubectl rollout history deployment/myapp               # 이력
kubectl rollout undo deployment/myapp                  # 롤백

1-4. 전제 조건

  • Pod에 적절한 readinessProbe 설정: 새 Pod가 트래픽을 받을 준비가 됐는지 판단한다
  • Stateful 워크로드는 StatefulSet 순차 업데이트 또는 Recreate 전략이 더 적합한 경우 있음

[02] 배포 패턴 비교: Rolling / Blue-Green / Canary

2-1. Blue/Green Deployment

동일한 환경 두 개를 완전히 분리해서 운영하다가 트래픽을 한 번에 스위치한다. Blue가 현재 버전, Green이 신규 버전이다.

1
2
3
4
5
6
7
[Service] ──► Blue (v1)  ✅ 현재 트래픽
              Green (v2) 🟢 대기 (검증 중)

       ↓ 스위치

[Service] ──► Blue (v1)  ⚪ 대기 (롤백용)
              Green (v2) ✅ 현재 트래픽
항목 내용
장점 즉시 롤백, 두 버전이 트래픽에 동시 노출 안 됨
단점 리소스 2배, DB 스키마 호환성 이슈

2-2. Canary Deployment

신규 버전에 소수 트래픽을 먼저 흘려보내 검증한 뒤 비율을 점진적으로 증가시킨다.

1
2
3
4
5
6
v1 (95%) ──┐
v2 (5%)  ──┴──► 메트릭 관찰 (에러율, 레이턴시)
                ↓ 정상이면 비율 ↑
                v1 (50%) / v2 (50%)
                ↓
                v1 (0%)  / v2 (100%)
항목 내용
장점 실 트래픽 검증, 영향 범위 최소화
단점 구현 복잡, observability 인프라 필수

2-3. 비교표

항목 Rolling Update Blue/Green Canary
리소스 부담 낮음 (maxSurge만큼) 높음 (2배) 중간
롤백 속도 느림 (재배포) 즉시 (스위치) 즉시 (라우팅 변경)
트래픽 분리 불가 (혼재) 완전 분리 비율 제어
구현 난이도 매우 낮음, K8s 기본 제공 중간 높음
검증 방식 readinessProbe 위주 사전 스모크 테스트 실 트래픽 메트릭
적합 케이스 대부분 stateless 워크로드 DB/캐시 호환성 검증 필요 리스크 큰 변경, A/B 테스트

[03] K8s API 차원의 Update Strategy

K8s API spec이 직접 정의한 update enum 값.

Workload 사용 가능한 strategy
Deployment RollingUpdate, Recreate
StatefulSet RollingUpdate, OnDelete
DaemonSet RollingUpdate, OnDelete

3-1. 각 전략의 동작

전략 동작 K8s 컨트롤러가 자동 처리?
RollingUpdate 점진 교체, maxUnavailable/maxSurge 준수 O
Recreate 모든 구버전 Pod 종료 후 신버전 생성 (다운타임 발생) O
OnDelete Pod가 명시적으로 삭제될 때만 새 버전으로 교체 X, 사람 또는 Operator가 직접

3-2. DaemonSet에는 Recreate가 없다

DaemonSet은 노드당 1개 Pod 모델이라 Recreate가 의미상 부적합하다. 대신 OnDelete가 그 역할을 일부 대체하며, 보통 Operator가 노드별 교체 로직을 추가로 구현한다.


[04] 두 추상화 층위의 구분 (핵심 개념)

4-1. 흔한 오해

“K8s resource의 update는 Rolling Update / Blue-Green / Canary 3개로 분류된다”

부정확하다. 두 다른 추상화 층위가 섞여 있다.

4-2. 두 층위의 정의

층위 정체 항목
A: K8s 리소스 update 방법 = K8s API strategy K8s가 리소스 spec을 어떻게 변경하는가 RollingUpdate, Recreate, OnDelete
B: 배포 패턴 애플리케이션의 새 버전을 사용자에게 어떻게 노출하는가 Rolling Update, Blue/Green, Canary

:warning: “K8s API의 update strategy”와 “K8s resource의 업데이트 방법”은 둘 다 A층위를 가리키는 같은 말이다. 표현만 다를 뿐 동일한 대상이다. 실제 구분선은 A층위와 B층위 사이에 있다.

4-3. 두 층위의 관계

graph TD
    subgraph B["B층위: 배포 패턴 (애플리케이션 버전 전환 방식)"]
        B1["Rolling Update"]
        B2["Blue/Green"]
        B3["Canary"]
    end

    subgraph A["A층위: K8s 리소스 update 방법 = API strategy"]
        A1["RollingUpdate"]
        A2["Recreate"]
        A3["OnDelete"]
    end

    B1 -.->|uses| A1
    B2 -.->|uses| A1
    B3 -.->|uses| A1

    style B fill:#e3f2fd,stroke:#1565c0
    style A fill:#fff3e0,stroke:#e65100
  • A는 K8s가 직접 제공하는 primitive다.
  • B는 그 primitive를 조합해서 만드는 상위 패턴이다.

4-4. 이름 충돌

  • “Rolling Update”는 A층위와 B층위에 모두 있다. 이름은 같지만 추상화 층위가 다르다.
  • “Recreate”도 A층위의 Deployment strategy와 B층위의 개념적 패턴으로 각각 등장한다.

그래서 “K8s 업데이트 분류 = Rolling/Recreate/Blue-Green/Canary”처럼 한 줄로 묶어 부르지만, 실제로는 두 층위가 섞여 있다.

4-5. B층위를 strategy 한 줄로 표현할 수 없는 이유

A층위 strategy는 단일 워크로드 리소스의 update 동작을 정의한다. Blue/Green과 Canary는 여러 리소스를 조합하는 패턴이라 strategy 한 줄로 표현할 수 없다.

패턴 K8s 표현 A층위 단독 표현?
Rolling Update Deployment 하나의 .spec.strategy 필드 O
Blue/Green Deployment(blue) + Deployment(green) + Service(selector swap) X
Canary Deployment 둘 + Ingress/VirtualService(weight) + 메트릭 로직 X

4-6. Blue/Green의 K8s 구현 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-blue
spec:
  strategy:
    type: RollingUpdate    # ← A층위: 이 Deployment의 update strategy
  selector:
    matchLabels:
      app: myapp
      color: blue
  template:
    metadata:
      labels:
        app: myapp
        color: blue
---
# green-deployment.yaml (동일 구조, color: green)
---
# service.yaml — selector를 blue ↔ green으로 스위치
apiVersion: v1
kind: Service
spec:
  selector:
    app: myapp
    color: blue            # ← B층위: 이 selector swap이 Blue/Green 패턴 자체

위 예시에서:

  • 각 Deployment가 내부적으로 update될 때의 방식은 A층위이며 RollingUpdate다.
  • 전체적으로 사용자에게 v1 → v2를 노출하는 패턴은 B층위이며 Blue/Green이다.

Blue/Green 패턴을 만들 때 사용하는 K8s strategy는 여전히 RollingUpdate다. B층위는 A층위를 조합해서 만든 상위 개념이다.

4-7. 패턴 → K8s 구현 매핑

배포 패턴 K8s에서의 구현 A층위 strategy
Rolling Update Deployment 단독, strategy=RollingUpdate RollingUpdate
Recreate Deployment 단독, strategy=Recreate Recreate
Blue/Green 두 Deployment + Service selector swap, 또는 Rollout CRD 각 Deployment는 RollingUpdate
Canary 두 Deployment + Ingress weight / 서비스 메시, 또는 Rollout CRD 각 Deployment는 RollingUpdate

[05] 외부 솔루션

도구 Blue/Green Canary 특징
Argo Rollouts O O Rollout CRD가 Deployment 대체. AnalysisRun으로 메트릭 기반 자동 promote/rollback
Flagger O O 기존 Deployment 유지. Prometheus 메트릭 기반 progressive delivery 자동화
Istio / Linkerd O O 트래픽 분산 primitive 제공. Argo/Flagger와 조합이 일반적
ingress-nginx 제한적 O nginx.ingress.kubernetes.io/canary 어노테이션. 메트릭 분석은 별도
수동 배포, vanilla K8s 가능 사실상 불가 두 Deployment + Service patch로 Blue/Green은 그럭저럭 가능, Canary는 트래픽 가중치 제어 불가

[06] NVIDIA Driver Operator 케이스 분석

6-1. 왜 노드 안에서 Rolling Update가 불가능한가

NVIDIA driver는 본질이 host kernel module 적재(nvidia.ko, nvidia-uvm.ko, nvidia-modeset.ko)이며, 이로 인한 제약이 있다.

# 제약 설명
1 커널 모듈 싱글톤 동일 모듈의 두 버전을 host kernel에 동시 로드 불가. 같은 노드에서 v1·v2 driver pod 공존이 OS 레벨에서 거부됨
2 모듈 unload의 ref count 조건 rmmod은 reference count가 0이어야 성공. GPU 사용 중인 컨테이너, nvidia-persistenced, X server 등이 붙어 있으면 EBUSY → 재부팅 필요
3 container-toolkit 의존성 nvidia-container-toolkit, libnvidia-container, device plugin이 모두 현재 driver를 참조. driver만 교체하면 의존 관계가 깨진다
4 재부팅 강제 케이스 secure boot + signed module 변경, persistent mode, driver-firmware coupling

이 모든 제약이 “두 버전 일시 공존”을 전제하는 Rolling Update와 정면 충돌한다.

6-2. 그래도 클러스터 단위 무중단 롤아웃은 가능

1
2
3
4
5
6
7
8
9
for each node (보통 maxUnavailable=1):
  cordon                           # 새 GPU pod 스케줄 차단
  drain GPU workloads              # PDB 준수
  wait module ref_count == 0
  unload old module                # 실패 → reboot 분기
  delete old driver pod (OnDelete)
  reconcile new driver pod
  wait Ready + module loaded + smoke test
  uncordon

6-3. K8s와 Operator의 책임 구분

요소 누가 정의 / 구현
OnDelete enum 값 K8s API
DaemonSet 매니페스트의 updateStrategy.type: OnDelete K8s API spec 위에 사용자가 선언
노드별 cordon/drain/unload/replace 상태머신 Operator
클러스터 전체 노드 순차 롤아웃 정책 (maxUnavailable, drainTimeout, rebootStrategy) Operator
검증 게이트: nvidia-smi, device plugin 상태 점검 Operator

OnDelete는 K8s가 제공하는 enum 값까지만 정의한다. 노드별로 driver를 안전하게 교체하는 순서와 조건은 Operator가 직접 구현한다.

6-4. 행위적 분류

관점 실제 모습
A층위, K8s API 레벨 OnDelete 전략
노드 안에서의 동작 “Recreate처럼 보임”, 두 버전 공존 불가
클러스터 전체에서의 동작 “Rolling Update처럼 보임”, 노드별 순차 처리

6-5. 설계 의사결정 순서

  1. A층위 결정: DaemonSet의 updateStrategy.typeRollingUpdate로 둘지 OnDelete로 둘지 정한다. driver는 OnDelete를 쓴다.
  2. B층위 결정: 그 위에서 어떤 배포 패턴을 구현할지 정한다. driver는 host kernel과 결합돼 Blue/Green과 Canary가 사실상 불가능하므로, 노드별 Recreate를 순차 진행하는 방식이 유일한 선택지다.

[07] 핵심 요약

# 요약
1 추상화 층위가 둘로 나뉜다. A층위는 K8s API strategy, B층위는 배포 패턴이다
2 A층위 항목: RollingUpdate, Recreate, OnDelete (워크로드 종류별로 사용 가능 값 상이)
3 B층위 항목: Rolling Update, Blue/Green, Canary. 여기에 Recreate, A/B, Shadow 등이 더해진다
4 K8s native로 직접 제공되는 패턴은 Rolling Update와 Recreate뿐. Blue/Green·Canary는 외부 CRD(Argo Rollouts, Flagger) 또는 multi-resource 조합으로 구현
5 OnDelete는 A층위의 enum 값이고, 그것이 활성화됐을 때의 오케스트레이션 로직은 Operator가 직접 구현해야 함
6 NVIDIA driver처럼 host kernel과 결합된 워크로드는 Rolling Update가 노드 안에서 물리적으로 불가능. “노드 안은 Recreate, 노드 간은 통제된 Rolling” 패턴이 사실상 유일한 정답

:bulb: 두 층위를 구분하면 워크로드마다 어떤 strategy를 고르고 그 위에 어떤 배포 패턴을 올릴지 따로 결정할 수 있다. host kernel과 결합된 워크로드처럼 B층위 선택지가 좁은 경우를 먼저 판별하는 것이 이 구분의 실용적 쓸모다.