배포 전략
배포 전략 (Deployment Strategies)
Flagger는 다음 배포 전략들에 대해 자동화된 애플리케이션 분석, 승격, 롤백을 수행할 수 있습니다. 어떤 전략을 쓸지, 각각 어떻게 구성하는지 이 문서에서 정리해 드릴게요.
출처: 문서
본문
Flagger는 다음 배포 전략들에 대해 자동화된 애플리케이션 분석, 승격, 롤백을 실행할 수 있습니다:
- 카나리아 릴리스 (점진적 트래픽 전환)
- Istio, Linkerd, App Mesh, NGINX, Skipper, Contour, Gloo Edge, Traefik, Kuma, Gateway API, Apache APISIX, Knative
- A/B 테스트 (HTTP 헤더와 쿠키 트래픽 라우팅)
- Istio, App Mesh, NGINX, Contour, Gloo Edge, Gateway API
- 블루/그린 (트래픽 전환)
- Kubernetes CNI, Istio, Linkerd, App Mesh, NGINX, Contour, Gloo Edge, Gateway API
- 블루/그린 미러링 (트래픽 섀도잉)
- Istio, Gateway API
- 세션 어피니티 카나리아 릴리스 (쿠키 기반 라우팅과 결합된 점진적 트래픽 전환)
- Istio, Gateway API
카나리아 릴리스와 A/B 테스트에는 서비스 메시나 인그레스 컨트롤러 같은 Layer 7 트래픽 관리 솔루션이 필요합니다. 블루/그린 배포에는 서비스 메시나 인그레스 컨트롤러가 필요하지 않습니다.
canary 분석은 다음 오브젝트 중 하나의 변경으로 트리거됩니다:
- Deployment PodSpec (컨테이너 이미지, 명령, 포트, env, 리소스 등)
- 볼륨으로 마운트되거나 환경 변수로 매핑된 ConfigMaps
- 볼륨으로 마운트되거나 환경 변수로 매핑된 Secrets
카나리아 릴리스 (Canary Release)
Flagger는 HTTP 요청 성공률, 요청 평균 지속 시간, 파드 상태 같은 핵심 성과 지표를 측정하면서 점진적으로 canary로 트래픽을 옮기는 제어 루프를 구현합니다. KPI 분석에 따라 canary는 승격되거나 중단됩니다.

카나리아 분석은 최대 트래픽 가중치 또는 실패 검사 임계값에 도달할 때까지 주기적으로 실행됩니다.
스펙:
analysis:
# schedule interval (default 60s)
interval: 1m
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 2
# promotion increment step (default 100)
# percentage (0-100)
stepWeightPromotion: 100
# deploy straight to production without
# the metrics and webhook checks
skipAnalysis: false
위 분석은 성공할 경우 매분 HTTP 메트릭과 웹훅을 검증하면서 25분 동안 실행됩니다. canary 배포를 검증하고 승격하는 데 걸리는 최소 시간은 다음 공식으로 구할 수 있습니다:
interval * (maxWeight / stepWeight)
메트릭이나 웹훅 검사가 실패할 때 canary가 롤백되는 데 걸리는 시간:
interval * threshold
stepWeightPromotion이 지정되면 승격 단계가 단계별로 진행됩니다. 트래픽이 점진적으로 primary 파드로 다시 라우팅되며 primary 가중치가 100%에 도달할 때까지 증가합니다.
긴급 상황에서는 분석 단계를 건너뛰고 변경 사항을 바로 프로덕션으로 보내고 싶을 수 있습니다. 언제든 spec.skipAnalysis: true를 설정할 수 있습니다. skip analysis가 활성화되면 Flagger는 canary 배포가 정상인지 확인하고 분석 없이 승격합니다. 분석이 진행 중이라면 Flagger는 이를 취소하고 승격을 실행합니다.
게이트(gated) 카나리아 승격 단계:
- canary 배포 스캔
- primary와 canary 배포 상태 확인
- 롤링 업데이트가 진행 중이면 진행 중지
- 파드가 비정상이면 진행 중지
- confirm-rollout 웹훅 호출 및 결과 확인
- 어떤 훅이라도 HTTP 2xx가 아닌 결과를 반환하면 진행 중지
- pre-rollout 웹훅 호출 및 결과 확인
- 어떤 훅이라도 HTTP 2xx가 아닌 결과를 반환하면 진행 중지
- 실패 검사 카운터 증가
- canary 트래픽 가중치 비율을 0%에서 2%(step weight)로 증가
- rollout 웹훅 호출 및 결과 확인
- canary HTTP 요청 성공률과 지연 시간 확인
- 지정된 임계값 아래로 떨어지면 진행 중지
- 실패 검사 카운터 증가
- 실패 검사 횟수가 임계값에 도달했는지 확인
- 모든 트래픽을 primary로 라우팅
- canary 배포를 0으로 스케일하고 실패로 표시
- post-rollout 웹훅 호출
- 분석 결과를 Slack에 게시
- canary 배포가 업데이트될 때까지 대기 후 다시 시작
- canary 트래픽 가중치를 50%(max weight)에 도달할 때까지 2%(step weight)씩 증가
- 어떤 웹훅 호출이라도 실패하면 진행 중지
- canary 요청 성공률이 임계값 아래인 동안 진행 중지
- canary 요청 지속 시간 P99가 임계값 위인 동안 진행 중지
- 어떤 커스텀 메트릭 검사라도 실패하면 진행 중지
- primary 또는 canary 배포가 비정상이 되면 진행 중지
- HPA가 canary 배포를 스케일 업/다운하는 동안 진행 중지
- confirm-promotion 웹훅 호출 및 결과 확인
- 어떤 훅이라도 HTTP 2xx가 아닌 결과를 반환하면 진행 중지
- canary를 primary로 승격
- ConfigMaps와 Secrets를 canary에서 primary로 복사
- canary 배포 spec 템플릿을 primary에 복사
- primary 롤링 업데이트가 끝날 때까지 대기
- 파드가 비정상이면 진행 중지
- 모든 트래픽을 primary로 라우팅
- canary 배포를 0으로 스케일
- 롤아웃 완료로 표시
- post-rollout 웹훅 호출
- canary 분석 결과로 알림 전송
- canary 배포가 업데이트될 때까지 대기 후 다시 시작
롤아웃 가중치 (Rollout Weights)
기본적으로 Flagger는 승격에 선형 가중치 값을 사용하며, 시작 값, 단계, 최대 가중치 값은 0에서 100 범위입니다.
예시:
# canary.yaml
spec:
analysis:
maxWeight: 50
stepWeight: 20
이 구성은 20에서 시작해 가중치가 50을 넘을 때까지 20씩 증가하며 분석을 수행합니다.\\ 단계는 다음과 같습니다 (canary 가중치 : primary 가중치):
- 20 (20 : 80)
- 40 (40 : 60)
- 60 (60 : 40)
- 승격
비선형 승격을 활성화하기 위해 새 파라미터가 도입되었습니다:
stepWeights- canary 승격 중 사용될 가중치의 순서 있는 배열을 결정합니다.
예시:
# canary.yaml
spec:
analysis:
stepWeights: [1, 2, 10, 80]
이 구성은 1에서 시작해 stepWeights 값을 따라 80까지 진행하며 분석을 수행합니다.\\
단계는 다음과 같습니다 (canary 가중치 : primary 가중치):
- 1 (1 : 99)
- 2 (2 : 98)
- 10 (10 : 90)
- 80 (20 : 60)
- 승격
A/B 테스트
세션 어피니티가 필요한 프론트엔드 애플리케이션의 경우, HTTP 헤더나 쿠키 매치 조건을 사용해 특정 사용자 집합이 카나리아 분석 전체 기간 동안 같은 버전에 머물도록 해야 합니다.

HTTP 매치 조건과 반복 횟수를 지정해 A/B 테스트를 활성화할 수 있습니다. Flagger가 HTTP 매치 조건을 찾으면 maxWeight와 stepWeight 설정을 무시합니다.
Istio 예시:
analysis:
# schedule interval (default 60s)
interval: 1m
# total number of iterations
iterations: 10
# max number of failed iterations before rollback
threshold: 2
# canary match condition
match:
- headers:
x-canary:
regex: ".*insider.*"
- headers:
cookie:
regex: "^(.*?;)?(canary=always)(;.*)?$"
위 구성은 Safari 사용자와 테스트 쿠키가 있는 사용자를 대상으로 10분 동안 분석을 실행합니다. canary 배포를 검증하고 승격하는 데 걸리는 최소 시간은 다음 공식으로 구할 수 있습니다:
interval * iterations
메트릭이나 웹훅 검사가 실패할 때 canary가 롤백되는 데 걸리는 시간:
interval * threshold
Istio 예시:
analysis:
interval: 1m
threshold: 10
iterations: 2
match:
- headers:
x-canary:
exact: "insider"
- headers:
cookie:
regex: "^(.*?;)?(canary=always)(;.*)?$"
- sourceLabels:
app.kubernetes.io/name: "scheduler"
헤더 키는 소문자여야 하고 구분자로 하이픈을 사용해야 합니다. 헤더 값은 대소문자를 구분하며 다음과 같이 형식화됩니다:
exact: "value"정확한 문자열 매치용prefix: "value"접두사 기반 매치용suffix: "value"접미사 기반 매치용regex: "value"RE2 스타일 정규식 매치용
sourceLabels 매치 조건은 canary.service.gateways 목록에 mesh 게이트웨이가 포함된 경우에만 적용됩니다.
App Mesh 예시:
analysis:
interval: 1m
threshold: 10
iterations: 2
match:
- headers:
user-agent:
regex: ".*Chrome.*"
App Mesh는 단일 조건을 지원한다는 점에 유의하세요.
Contour 예시:
analysis:
interval: 1m
threshold: 10
iterations: 2
match:
- headers:
user-agent:
prefix: "Chrome"
Contour는 regex를 지원하지 않으므로 prefix, suffix 또는 exact를 사용할 수 있습니다.
NGINX 예시:
analysis:
interval: 1m
threshold: 10
iterations: 2
match:
- headers:
x-canary:
exact: "insider"
- headers:
cookie:
exact: "canary"
NGINX 인그레스 컨트롤러는 쿠키 이름에 대해 값이 always로 설정되어야 하는 정확한 매치만 지원합니다. NGINX ingress v0.31부터 헤더 값에 대한 regex 매칭이 지원됩니다.
위 구성들은 분석 중에 x-canary 헤더나 canary 쿠키를 가진 사용자를 canary 인스턴스로 라우팅합니다:
curl -H 'X-Canary: insider' http://app.example.com
curl -b 'canary=always' http://app.example.com
블루/그린 배포 (Blue/Green Deployments)
서비스 메시에 배포되지 않는 애플리케이션의 경우, Flagger는 Kubernetes L4 네트워킹으로 블루/그린 방식의 배포를 오케스트레이션할 수 있습니다. Istio를 사용할 때는 블루와 그린 사이에 트래픽을 미러링하는 옵션도 있습니다.

analysis 스펙에서 stepWeight/maxWeight를 iterations로 바꿔 블루/그린 배포 전략을 사용할 수 있습니다:
analysis:
# schedule interval (default 60s)
interval: 1m
# total number of iterations
iterations: 10
# max number of failed iterations before rollback
threshold: 2
위 구성으로 Flagger는 10분 동안 canary 파드에 대해 합성 테스트와 부하 테스트를 실행합니다. 메트릭 분석이 성공하면 canary가 승격될 때 라이브 트래픽이 이전 버전에서 새 버전으로 전환됩니다.
블루/그린 배포 전략은 모든 서비스 메시 프로바이더에서 지원됩니다.
서비스 메시의 블루/그린 롤아웃 단계:
- 새 리비전 감지 (deployment spec, secrets 또는 configmaps 변경)
- canary(그린) 스케일 업
- canary 파드에 대한 합성 테스트 실행
- 매분 canary 파드에 대한 부하 테스트와 메트릭 검사 실행
- 실패 임계값에 도달하면 canary 릴리스 중단
- canary로 트래픽 라우팅 (Kubernetes 프로바이더를 사용할 때는 발생하지 않음)
- canary spec을 primary(블루) 위로 승격
- primary 롤아웃 대기
- primary로 트래픽 라우팅
- canary 스케일 다운
분석이 끝나면 primary(블루) 롤링 업데이트를 트리거하기 전에 트래픽이 canary(그린)로 라우팅됩니다. 이는 Kubernetes 배포 롤아웃 중 진행 중인 요청이 끊기는 것을 피하면서 새 버전으로의 부드러운 전환을 보장합니다.
트래픽 미러링이 있는 블루/그린 (Blue/Green with Traffic Mirroring)
트래픽 미러링은 Canary(점진적 트래픽 전환) 또는 블루/그린 배포 전략의 사전 단계입니다. 트래픽 미러링은 들어오는 각 요청을 복사해 primary 서비스와 canary 서비스에 각각 하나씩 보냅니다. primary의 응답은 사용자에게 돌려보내고 canary의 응답은 버립니다. 두 요청 모두에서 메트릭이 수집되므로 canary 메트릭이 정상일 때만 배포가 진행됩니다.
미러링은 멱등적(idempotent) 이거나 두 번 처리될 수 있는(primary에서 한 번, canary에서 한 번) 요청에 사용해야 합니다. 읽기(read)는 멱등적입니다. 쓰기일 수 있는 요청에 미러링을 사용하기 전에는, 쓰기가 중복되어 primary와 canary 모두에서 처리되면 어떻게 될지 고려해야 합니다.
미러링을 사용하려면 spec.analysis.mirror를 true로 설정합니다.
analysis:
# schedule interval (default 60s)
interval: 1m
# total number of iterations
iterations: 10
# max number of failed iterations before rollback
threshold: 2
# Traffic shadowing
mirror: true
# Weight of the traffic mirrored to your canary (defaults to 100%)
# Only applicable for Istio.
mirrorWeight: 100
서비스 메시의 미러링 롤아웃 단계:
- 새 리비전 감지 (deployment spec, secrets 또는 configmaps 변경)
- canary 배포를 0에서 스케일 업
- HPA가 canary 최소 복제본을 설정할 때까지 대기
- canary 파드 상태 확인
- 승인 테스트 실행
- 테스트가 실패하면 canary 릴리스 중단
- 부하 테스트 시작
- primary에서 canary로 트래픽 100% 미러링
- 매분 요청 성공률과 요청 지속 시간 확인
- 실패 임계값에 도달하면 canary 릴리스 중단
- 반복 횟수에 도달하면 트래픽 미러링 중지
- 라이브 트래픽을 canary 파드로 라우팅
- canary 승격 (primary secrets, configmaps, deployment spec 업데이트)
- primary 배포 롤아웃이 끝날 때까지 대기
- HPA가 primary 최소 복제본을 설정할 때까지 대기
- primary 파드 상태 확인
- 라이브 트래픽을 primary로 다시 전환
- canary를 0으로 스케일
- canary 분석 결과로 알림 전송
분석이 끝나면 primary(블루) 롤링 업데이트를 트리거하기 전에 트래픽이 canary(그린)로 라우팅됩니다. 이는 Kubernetes 배포 롤아웃 중 진행 중인 요청이 끊기는 것을 피하면서 새 버전으로의 부드러운 전환을 보장합니다.
세션 어피니티 카나리아 릴리스 (Canary Release with Session Affinity)
이 배포 전략은 카나리아 릴리스와 A/B 테스트를 혼합합니다. 카나리아 릴리스는 새 기능을 사용자에게 점진적으로 노출하려 할 때 유용하지만, 그 라우팅(가중치 기반)의 특성상 사용자가 이전에 새 버전으로 라우팅된 후에도 앱의 이전 버전에 도달할 수 있습니다. 이는 짜증날 수 있고, 더 심하면 다른 서비스가 우리 애플리케이션과 상호작용하는 방식을 망가뜨릴 수 있습니다. 이 문제를 해결하기 위해 A/B 테스트에서 몇 가지를 차용합니다.
A/B 테스트는 세션 어피니티가 필요한 애플리케이션에 특히 유용하므로, 쿠키 기반 라우팅을 일반 가중치 기반 라우팅과 통합합니다. 즉, 사용자가 (트래픽 가중치에 따라) 앱의 새 버전에 한 번 노출되면 항상 그 버전으로 라우팅됩니다. 즉, 앱의 이전 버전으로 다시 라우팅되지 않습니다.
Canary에서 .spec.analysis.sessionAffinity를 지정해 이를 활성화할 수 있습니다:
analysis:
# schedule interval (default 60s)
interval: 1m
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 2
# session affinity config
sessionAffinity:
# name of the cookie used
cookieName: flagger-cookie
# max age of the cookie (in seconds)
# optional; defaults to 86400
maxAge: 21600
.spec.analysis.sessionAffinity.cookieName은 저장되는 Cookie의 이름입니다. 쿠키의 값은 고유 식별자 역할을 하는 무작위로 생성된 문자열입니다. 위 구성에서 Canary 실행 중 canary 배포로 라우팅된 요청의 응답 헤더는 다음과 같습니다:
Set-Cookie: flagger-cookie=LpsIaLdoNZ; Max-Age=21600
Canary 실행이 끝나고 모든 트래픽이 primary 배포로 다시 이동하면, 모든 응답은 다음 헤더를 갖습니다:
Set-Cookie: flagger-cookie=LpsIaLdoNZ; Max-Age=-1
이는 클라이언트에게 쿠키를 삭제하라고 알려 사용자의 시스템에 정크 쿠키가 남지 않게 합니다.
새 Canary 실행이 트리거되면 응답 헤더는 Canary 배포로 라우팅된 모든 요청에 새 쿠키를 설정합니다:
Set-Cookie: flagger-cookie=McxKdLQoIN; Max-Age=21600
Primary 배포에 고정성 구성 (Configuring stickiness for Primary deployment)
위 전략은 Canary 배포로 한 번 라우팅된 사용자가 항상 그 배포로 라우팅되도록 보장하므로 유용합니다. 하지만 시간이 지나면서 대부분의 트래픽이 Canary 배포로 흐르게 되어 트래픽 전환에 불균형이 생길 수 있습니다. 공정한 트래픽 분배를 보장하기 위해 Primary 배포에도 고정성(stickiness)을 구성할 수 있습니다. primaryCookieName 필드를 지정해 구성합니다:
analysis:
# schedule interval (default 60s)
interval: 1m
sessionAffinity:
# name of the cookie used
cookieName: flagger-cookie
# max age of the cookie (in seconds)
# optional; defaults to 86400
maxAge: 21600
# name of the cookie to use for the primary backend
# optional; unset means no primary stickiness
primaryCookieName: primary-flagger-cookie
참고: 이는 현재 Gateway API 프로바이더에서만 지원됩니다.
위 구성이 무엇을 하는지 이해해 봅시다. 위 섹션의 모든 세션 어피니티 동작이 여전히 발생하지만, 이제 primary 배포로 라우팅된 요청의 응답 헤더에도 Set-Cookie 헤더가 포함됩니다:
Set-Cookie: primary-flagger-cookie=ApvLdqCoMF; Max-Age=60
쿠키의 수명은 Canary 분석의 interval과 같다는 점에 유의하세요. 즉, 분석의 새 단계가 시작되면 쿠키가 만료되고 다음과 같이 새 쿠키가 생성됩니다:
Set-Cookie: primary-flagger-cookie=BRtlVaQoPC; Max-Age=60
이는 특정 단계에서 사용자의 첫 요청이 primary 배포로 라우팅되면, 다음 단계가 시작될 때까지 모든 후속 요청이 같은 곳으로 라우팅되도록 보장합니다. 새 단계가 시작되면 primary 워크로드의 응답 헤더에 포함되는 새 쿠키 값이 생성됩니다. 이렇게 하면 가중치 트래픽 라우팅이 이루어지면서도 Canary 분석 중 사용자가 canary 배포에서 primary 배포로 다시 전환되는 일이 없도록 보장합니다.
추가 쿠키 속성 구성 (Configuring additional cookie attributes)
사용 사례에 따라 애플리케이션이 요청을 올바르게 라우팅하도록 추가 쿠키 속성을 설정해야 할 수 있습니다. 다음 속성들을 설정할 수 있습니다:
analysis:
# schedule interval (default 60s)
interval: 1m
sessionAffinity:
# name of the cookie used
cookieName: flagger-cookie
# max age of the cookie (in seconds)
# optional; defaults to 86400
maxAge: 21600
# defines the host to which the cookie will be sent.
# optional
domain: fluxcd.io
# forbids JavaScript from accessing the cookie, for example, through the Document.cookie property.
# optional
httpOnly: true
# indicates that the cookie should be stored using partitioned storage.
# optional
partitioned: true
# indicates the path that must exist in the requested URL for the browser to send the Cookie header.
# optional
path: /flagger
# controls whether or not a cookie is sent with cross-site requests.
# optional; valid values are Strict, Lax or None
sameSite: Strict
# indicates that the cookie is sent to the server only when a request is made with the https: scheme (except on localhost)
# optional
secure: true