Kuma 카나리아 배포
이 가이드에서는 Kuma와 Flagger를 사용해 카나리아 배포를 자동화하는 방법을 보여드립니다. Kuma 메시의 트래픽 라우팅(TrafficRoute)을 활용해 점진적으로 새 버전을 배포하고 검증하는 전체 과정을 살펴볼게요.
출처: 문서
본문
이 가이드에서는 Kuma와 Flagger를 사용해 카나리아 배포를 자동화하는 방법을 보여드립니다.

사전 요구사항 (Prerequisites)
Flagger는 Kubernetes 클러스터 v1.19 이상과 Kuma 1.7 이상이 필요합니다.
Kuma와 Prometheus(Kuma Metrics의 일부)를 설치합니다:
kumactl install control-plane | kubectl apply -f -
kumactl install observability --components "grafana,prometheus" | kubectl apply -f -
kong-mesh-system 네임스페이스에 Flagger를 설치합니다:
kubectl apply -k github.com/fluxcd/flagger//kustomize/kuma
부트스트랩 (Bootstrap)
Flagger는 Kubernetes deployment와 선택적으로 horizontal pod autoscaler(HPA)를 받아, 일련의 오브젝트(Kubernetes deployments, ClusterIP services, Kuma TrafficRoute)를 생성합니다. 이 오브젝트들은 메시 내부에서 애플리케이션을 노출하고 카나리아 분석과 승격을 구동합니다.
테스트 네임스페이스를 만들고 Kuma 사이드카 주입을 활성화합니다:
kubectl create ns test
kubectl annotate namespace test kuma.io/sidecar-injection=enabled
카나리아 분석 중 트래픽을 생성할 부하 테스트 서비스를 설치합니다:
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/tester?ref=main
deployment와 horizontal pod autoscaler를 만듭니다:
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main
podinfo 배포용 canary 커스텀 리소스를 만듭니다:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
namespace: test
annotations:
kuma.io/mesh: default
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
progressDeadlineSeconds: 60
service:
port: 9898
targetPort: 9898
apex:
annotations:
9898.service.kuma.io/protocol: "http"
canary:
annotations:
9898.service.kuma.io/protocol: "http"
primary:
annotations:
9898.service.kuma.io/protocol: "http"
analysis:
# schedule interval (default 60s)
interval: 30s
# max number of failed metric checks before rollback
threshold: 5
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 5
metrics:
- name: request-success-rate
threshold: 99
interval: 1m
- name: request-duration
threshold: 500
interval: 30s
webhooks:
- name: acceptance-test
type: pre-rollout
url: http://flagger-loadtester.test/
timeout: 30s
metadata:
type: bash
cmd: "curl -sd 'test' http://podinfo-canary.test:9898/token | grep token"
- name: load-test
type: rollout
url: http://flagger-loadtester.test/
metadata:
cmd: "hey -z 2m -q 10 -c 2 http://podinfo-canary.test:9898/"
위 리소스를 podinfo-canary.yaml로 저장한 뒤 적용합니다:
kubectl apply -f ./podinfo-canary.yaml
카나리아 분석이 시작되면 Flagger는 트래픽을 canary로 라우팅하기 전에 pre-rollout 웹훅을 호출합니다. 카나리아 분석은 매 30초마다 HTTP 메트릭과 롤아웃 훅을 검증하면서 5분 동안 실행됩니다.
몇 초 후 Flagger가 canary 오브젝트를 생성합니다:
# applied
deployment.apps/podinfo
horizontalpodautoscaler.autoscaling/podinfo
ingresses.extensions/podinfo
canary.flagger.app/podinfo
# generated
deployment.apps/podinfo-primary
horizontalpodautoscaler.autoscaling/podinfo-primary
service/podinfo
service/podinfo-canary
service/podinfo-primary
trafficroutes.kuma.io/podinfo
부트스트랩 후 podinfo 배포는 0으로 스케일되고 podinfo.test로 가는 트래픽은 primary 파드로 라우팅됩니다. 카나리아 분석 중에는 podinfo-canary.test 주소로 canary 파드를 직접 대상으로 삼을 수 있습니다.
자동 카나리아 승격 (Automated canary promotion)
Flagger는 HTTP 요청 성공률, 요청 평균 지속 시간, 파드 상태 같은 핵심 성과 지표(KPI)를 측정하면서 점진적으로 canary로 트래픽을 옮기는 제어 루프를 구현합니다. KPI 분석에 따라 canary는 승격되거나 중단(abort)되며, 분석 결과는 Slack에 게시됩니다.

컨테이너 이미지를 업데이트해 카나리아 배포를 트리거합니다:
kubectl -n test set image deployment/podinfo \
podinfod=ghcr.io/stefanprodan/podinfo:6.0.1
Flagger는 배포 리비전이 변경되었음을 감지하고 새 롤아웃을 시작합니다:
kubectl -n test describe canary/podinfo
Status:
Canary Weight: 0
Failed Checks: 0
Phase: Succeeded
Events:
New revision detected! Scaling up podinfo.test
Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
Pre-rollout check acceptance-test passed
Advance podinfo.test canary weight 5
Advance podinfo.test canary weight 10
Advance podinfo.test canary weight 15
Advance podinfo.test canary weight 20
Advance podinfo.test canary weight 25
Waiting for podinfo.test rollout to finish: 1 of 2 updated replicas are available
Advance podinfo.test canary weight 30
Advance podinfo.test canary weight 35
Advance podinfo.test canary weight 40
Advance podinfo.test canary weight 45
Advance podinfo.test canary weight 50
Copying podinfo.test template spec to podinfo-primary.test
Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available
Promotion completed! Scaling down podinfo.test
참고 카나리아 분석 중에 배포에 새 변경 사항을 적용하면 Flagger가 분석을 다시 시작합니다.
canary 배포는 다음 오브젝트 중 하나의 변경으로 트리거됩니다:
- Deployment PodSpec (컨테이너 이미지, 명령, 포트, env, 리소스 등)
- 볼륨으로 마운트되거나 환경 변수로 매핑된 ConfigMaps
- 볼륨으로 마운트되거나 환경 변수로 매핑된 Secrets
모든 canary는 다음과 같이 모니터링할 수 있습니다:
watch kubectl get canaries --all-namespaces
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
test podinfo Progressing 15 2019-06-30T14:05:07Z
prod frontend Succeeded 0 2019-06-30T16:15:07Z
prod backend Failed 0 2019-06-30T17:05:07Z
자동 롤백 (Automated rollback)
카나리아 분석 중에 HTTP 500 오류와 높은 지연 시간을 생성해 Flagger가 결함 있는 버전을 일시 중지하고 롤백하는지 테스트할 수 있습니다.
또 다른 카나리아 배포를 트리거합니다:
kubectl -n test set image deployment/podinfo \
podinfod=ghcr.io/stefanprodan/podinfo:6.0.2
로드 테스터 파드에 exec로 들어갑니다:
kubectl -n test exec -it flagger-loadtester-xx-xx sh
HTTP 500 오류를 생성합니다:
watch -n 1 curl http://podinfo-canary.test:9898/status/500
지연 시간을 생성합니다:
watch -n 1 curl http://podinfo-canary.test:9898/delay/1
실패한 검사 횟수가 카나리아 분석 임계값에 도달하면 트래픽은 primary로 다시 라우팅되고, canary는 0으로 스케일되며 롤아웃은 실패로 표시됩니다.
kubectl -n test describe canary/podinfo
Status:
Canary Weight: 0
Failed Checks: 10
Phase: Failed
Events:
Starting canary analysis for podinfo.test
Pre-rollout check acceptance-test passed
Advance podinfo.test canary weight 5
Advance podinfo.test canary weight 10
Advance podinfo.test canary weight 15
Halt podinfo.test advancement success rate 69.17% < 99%
Halt podinfo.test advancement success rate 61.39% < 99%
Halt podinfo.test advancement success rate 55.06% < 99%
Halt podinfo.test advancement request duration 1.20s > 0.5s
Halt podinfo.test advancement request duration 1.45s > 0.5s
Rolling back podinfo.test failed checks threshold reached 5
Canary failed! Scaling down podinfo.test
위 절차는 커스텀 메트릭 검사, 웹훅, 수동 승격 승인, Slack 또는 MS Teams 알림으로 확장할 수 있습니다.