CKAD — 쿠버네티스 애플리케이션 개발자 · 애플리케이션 배포 · 실습
롤링 업데이트, 되돌리기, 블루-그린, 카나리
목표
Deployment 의 롤아웃 파라미터를 조절하고, 리비전을 쌓아 원하는 지점으로 되돌리며, 블루-그린과 카나리를 라벨·셀렉터·레플리카만으로 구성할 수 있게 된다.
왜 중요한가
Deployment 가 ReplicaSet 을 여러 개 관리한다는 사실을 이해하면 나머지가 전부 따라온다. 이미지를 바꾸면 새 ReplicaSet 이 생기고 옛 것은 레플리카 0 으로 남는다. rollout undo 가 즉각적인 이유는 이미지를 다시 받는 게 아니라 이미 있는 ReplicaSet 을 다시 부풀리기 때문이다. revisionHistoryLimit 을 0 으로 두면 그 안전망이 사라진다.
maxSurge 와 maxUnavailable 은 "얼마나 빠르게"와 "얼마나 안전하게"의 트레이드오프다. maxUnavailable: 0 은 배포 중에도 가용 파드 수를 유지하지만 새 파드가 Ready 가 될 때까지 기다려야 하므로 느리다. 그리고 이 안전장치는 Readiness Probe 가 있어야만 의미가 있다 — 프로브가 없으면 컨테이너가 뜬 즉시 Ready 로 간주된다.
블루-그린과 카나리는 별도 CRD 없이 라벨만으로 만들 수 있다. 차이는 Service 셀렉터의 좁기다. 셀렉터에 버전 라벨까지 넣으면 한쪽만 받고(블루-그린), 공통 라벨만 넣으면 양쪽이 다 들어와 개수 비율대로 나뉜다(카나리).
단계
1. 네임스페이스 ckad-deploy 를 만들고 Deployment web 을 만든다. 이미지 nginx:1.25, 레플리카 4. (컨테이너 이름은 nginx 가 된다.)
2. web 의 전략을 RollingUpdate 로 두고 maxSurge: 1, maxUnavailable: 0 으로 설정한다.
3. web 의 이미지를 nginx:1.26 으로 올리고, Deployment 에 애너테이션 kubernetes.io/change-cause=nginx 1.26 으로 업데이트 를 붙인다.
4. web 의 이미지를 nginx:1.27 로 한 번 더 올리고, 애너테이션 kubernetes.io/change-cause=nginx 1.27 으로 업데이트 로 갱신한다. 이 시점에 ReplicaSet 이 3개 이상 존재해야 한다.
5. web 을 리비전 2 로 되돌린다. 되돌리기도 앞으로 나아가는 변경이므로 리비전 4 가 새로 생기고, 그 리비전의 이미지는 nginx:1.26 이어야 한다.
6. 블루-그린을 만든다. Deployment checkout-blue(레플리카 2, 라벨 app=checkout 과 version=blue, 이미지 nginx:1.26)와 checkout-green(레플리카 2, 라벨 app=checkout 과 version=green, 이미지 nginx:1.27)을 만들고, Service checkout(포트 80, targetPort 80)의 셀렉터를 app=checkout + version=green 으로 준다.
7. 카나리를 만든다. Deployment pay-stable(레플리카 9, 라벨 app=pay 와 track=stable, 이미지 nginx:1.26)와 pay-canary(레플리카 1, 라벨 app=pay 와 track=canary, 이미지 nginx:1.27)를 만들고, Service pay(포트 80, targetPort 80)의 셀렉터는 app=pay 하나만 준다.
8. web 에 kubectl rollout pause 를 먼저 건 뒤, 이미지를 nginx:1.28 로 바꾸고 revisionHistoryLimit 을 3 으로 설정한다. 일시 중지 상태이므로 새 ReplicaSet 은 만들어지지 않아야 한다. (재개하지 않는다. 레플리카 4는 그대로 둔다.)
참고
kubectl patch deployment web -n ckad-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'kubectl annotate deployment web -n ckad-deploy kubernetes.io/change-cause='...' --overwritekubectl rollout history deployment/web -n ckad-deploy와--revision=2로 리비전별 내용을 본다.- 흔한 실수 1:
kubectl set image에 컨테이너 이름 대신 Deployment 이름을 쓰는 것.deployment/web nginx=nginx:1.26처럼컨테이너=이미지다. - 흔한 실수 2: 카나리에서 Service 셀렉터에
track까지 넣는 것. 그러면 한쪽만 받으므로 카나리가 아니라 블루-그린이 된다. - 8단계는
pause를 먼저 걸어야 의미가 있다. 순서가 바뀌면 롤아웃이 이미 시작된다.
단계 8개
- 네임스페이스와 Deployment 만들기
- 롤링 업데이트 파라미터 조정
- 이미지 갱신과 change-cause 기록
- 한 번 더 올려 리비전 쌓기
- 특정 리비전으로 되돌리기
- 블루-그린 — Service 셀렉터 전환
- 카나리 — 레플리카 비율로 트래픽 나누기
- 일시 중지 상태로 변경 모으기 (종합)