본문 바로가기
WIKI 기술 지식 베이스

Istio A/B 테스트

원문 보기 위키 갱신

이 가이드에서는 Istio와 Flagger를 사용해 A/B 테스트를 자동화하는 방법을 보여드립니다. HTTP 매치 조건에 따라 특정 사용자 세그먼트에게만 새 버전을 노출하는 A/B 테스트 시나리오를 설정해 볼게요.

출처: 문서

본문

이 가이드에서는 Istio와 Flagger를 사용해 A/B 테스트를 자동화하는 방법을 보여드립니다.

가중치 라우팅 외에도 Flagger는 HTTP 매치 조건을 기반으로 canary로 트래픽을 라우팅하도록 구성할 수 있습니다. A/B 테스트 시나리오에서는 HTTP 헤더나 쿠키를 사용해 특정 사용자 세그먼트를 대상으로 삼게 됩니다. 이는 세션 어피니티(session affinity)가 필요한 프론트엔드 애플리케이션에 특히 유용합니다.

Flagger A/B Testing Stages

사전 요구사항 (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 알림으로 확장할 수 있습니다.

더 알아보기 (Learn more)