Istio A/B 테스트
이 가이드에서는 Istio와 Flagger를 사용해 A/B 테스트를 자동화하는 방법을 보여드립니다. HTTP 매치 조건에 따라 특정 사용자 세그먼트에게만 새 버전을 노출하는 A/B 테스트 시나리오를 설정해 볼게요.
출처: 문서
본문
이 가이드에서는 Istio와 Flagger를 사용해 A/B 테스트를 자동화하는 방법을 보여드립니다.
가중치 라우팅 외에도 Flagger는 HTTP 매치 조건을 기반으로 canary로 트래픽을 라우팅하도록 구성할 수 있습니다. A/B 테스트 시나리오에서는 HTTP 헤더나 쿠키를 사용해 특정 사용자 세그먼트를 대상으로 삼게 됩니다. 이는 세션 어피니티(session affinity)가 필요한 프론트엔드 애플리케이션에 특히 유용합니다.

사전 요구사항 (Prerequisites)
Flagger는 Kubernetes 클러스터 v1.16 이상과 Istio v1.0 이상이 필요합니다.
텔레메트리 지원과 Prometheus가 포함된 Istio를 설치합니다:
istioctl manifest install --set profile=default
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/addons/prometheus.yaml
istio-system 네임스페이스에 Flagger를 설치합니다:
kubectl apply -k github.com/fluxcd/flagger//kustomize/istio
데모 앱을 메시 외부로 노출할 인그레스 게이트웨이를 만듭니다:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: public-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
부트스트랩 (Bootstrap)
Istio 사이드카 주입이 활성화된 테스트 네임스페이스를 만듭니다:
kubectl create ns test
kubectl label namespace test istio-injection=enabled
deployment와 horizontal pod autoscaler를 만듭니다:
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main
카나리아 분석 중 트래픽을 생성할 부하 테스트 서비스를 배포합니다:
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/tester?ref=main
canary 커스텀 리소스를 만듭니다 (example.com을 자신의 도메인으로 바꾸세요):
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
# deployment reference
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
# the maximum time in seconds for the canary deployment
# to make progress before it is rollback (default 600s)
progressDeadlineSeconds: 60
# HPA reference (optional)
autoscalerRef:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
name: podinfo
service:
# container port
port: 9898
# Istio gateways (optional)
gateways:
- istio-system/public-gateway
# Istio virtual service host names (optional)
hosts:
- app.example.com
# Istio traffic policy (optional)
trafficPolicy:
tls:
# use ISTIO_MUTUAL when mTLS is enabled
mode: DISABLE
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:
user-agent:
regex: ".*Firefox.*"
- headers:
cookie:
regex: "^(.*?;)?(type=insider)(;.*)?$"
metrics:
- name: request-success-rate
# minimum req success rate (non 5xx responses)
# percentage (0-100)
thresholdRange:
min: 99
interval: 1m
- name: request-duration
# maximum req duration P99
# milliseconds
thresholdRange:
max: 500
interval: 30s
# generate traffic during analysis
webhooks:
- name: load-test
url: http://flagger-loadtester.test/
timeout: 15s
metadata:
cmd: "hey -z 1m -q 10 -c 2 -H 'Cookie: type=insider' http://podinfo.test:9898/"
참고 Istio 1.5를 사용할 때는 request-duration을 메트릭 템플릿으로 바꿔야 합니다.
위 구성은 Firefox 사용자와 insider 쿠키가 있는 사용자를 대상으로 10분 동안 분석을 실행합니다.
위 리소스를 podinfo-abtest.yaml로 저장한 뒤 적용합니다:
kubectl apply -f ./podinfo-abtest.yaml
몇 초 후 Flagger가 canary 오브젝트를 생성합니다:
# applied
deployment.apps/podinfo
horizontalpodautoscaler.autoscaling/podinfo
canary.flagger.app/podinfo
# generated
deployment.apps/podinfo-primary
horizontalpodautoscaler.autoscaling/podinfo-primary
service/podinfo
service/podinfo-canary
service/podinfo-primary
destinationrule.networking.istio.io/podinfo-canary
destinationrule.networking.istio.io/podinfo-primary
virtualservice.networking.istio.io/podinfo
자동 카나리아 승격 (Automated canary promotion)
컨테이너 이미지를 업데이트해 카나리아 배포를 트리거합니다:
kubectl -n test set image deployment/podinfo \
podinfod=ghcr.io/stefanprodan/podinfo:6.0.1
Flagger는 배포 리비전이 변경되었음을 감지하고 새 롤아웃을 시작합니다:
kubectl -n test describe canary/podinfo
Status:
Failed Checks: 0
Phase: Succeeded
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Synced 3m flagger New revision detected podinfo.test
Normal Synced 3m flagger Scaling up podinfo.test
Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
Normal Synced 3m flagger Advance podinfo.test canary iteration 1/10
Normal Synced 3m flagger Advance podinfo.test canary iteration 2/10
Normal Synced 3m flagger Advance podinfo.test canary iteration 3/10
Normal Synced 2m flagger Advance podinfo.test canary iteration 4/10
Normal Synced 2m flagger Advance podinfo.test canary iteration 5/10
Normal Synced 1m flagger Advance podinfo.test canary iteration 6/10
Normal Synced 1m flagger Advance podinfo.test canary iteration 7/10
Normal Synced 55s flagger Advance podinfo.test canary iteration 8/10
Normal Synced 45s flagger Advance podinfo.test canary iteration 9/10
Normal Synced 35s flagger Advance podinfo.test canary iteration 10/10
Normal Synced 25s flagger Copying podinfo.test template spec to podinfo-primary.test
Warning Synced 15s flagger Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available
Normal Synced 5s flagger Promotion completed! Scaling down podinfo.test
참고 카나리아 분석 중에 배포에 새 변경 사항을 적용하면 Flagger가 분석을 다시 시작합니다.
모든 canary는 다음과 같이 모니터링할 수 있습니다:
watch kubectl get canaries --all-namespaces
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
test podinfo Progressing 100 2019-03-16T14:05:07Z
prod frontend Succeeded 0 2019-03-15T16:15:07Z
prod backend Failed 0 2019-03-14T17:05:07Z
자동 롤백 (Automated rollback)
카나리아 분석 중에 HTTP 500 오류와 높은 지연 시간을 생성해 Flagger의 롤백을 테스트할 수 있습니다.
HTTP 500 오류를 생성합니다:
watch curl -b 'type=insider' http://app.example.com/status/500
지연 시간을 생성합니다:
watch curl -b 'type=insider' http://app.example.com/delay/1
실패한 검사 횟수가 카나리아 분석 임계값에 도달하면 트래픽은 primary로 다시 라우팅되고, canary는 0으로 스케일되며 롤아웃은 실패로 표시됩니다.
kubectl -n test describe canary/podinfo
Status:
Failed Checks: 2
Phase: Failed
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Synced 3m flagger Starting canary deployment for podinfo.test
Normal Synced 3m flagger Advance podinfo.test canary iteration 1/10
Normal Synced 3m flagger Advance podinfo.test canary iteration 2/10
Normal Synced 3m flagger Advance podinfo.test canary iteration 3/10
Normal Synced 3m flagger Halt podinfo.test advancement success rate 69.17% < 99%
Normal Synced 2m flagger Halt podinfo.test advancement success rate 61.39% < 99%
Warning Synced 2m flagger Rolling back podinfo.test failed checks threshold reached 2
Warning Synced 1m flagger Canary failed! Scaling down podinfo.test
위 절차는 커스텀 메트릭 검사, 웹훅, 수동 승격 승인, Slack 또는 MS Teams 알림으로 확장할 수 있습니다.