KEDA ScaledObjects로 카나리아 분석
이 가이드에서는 Flagger를 KEDA ScaledObjects와 함께 사용해 Canary 분석 실행 중 워크로드를 자동 스케일링하는 방법을 보여드립니다. 이 튜토리얼에서는 Kubernetes 프로바이더와 블루/그린 배포 전략을 사용하지만, 어떤 배포 전략이든 지원되는 프로바이더와 조합해 사용할 수 있습니다.
출처: 문서
본문
이 가이드에서는 Flagger를 KEDA ScaledObjects와 함께 사용해 Canary 분석 실행 중 워크로드를 자동 스케일링하는 방법을 보여드립니다. 이 튜토리얼에서는 블루/그린 배포 전략과 Kubernetes 프로바이더를 사용하겠지만, 어떤 배포 전략이든 지원되는 프로바이더와 조합해 사용할 수 있습니다.
사전 요구사항 (Prerequisites)
Flagger는 Kubernetes 클러스터 v1.16 이상이 필요합니다. 이 튜토리얼에서는 KEDA 2.7.1 이상이 필요합니다.
KEDA를 설치합니다:
helm repo add kedacore https://kedacore.github.io/charts
kubectl create namespace keda
helm install keda kedacore/keda --namespace keda
Flagger를 설치합니다:
helm repo add flagger https://flagger.app
kubectl create namespace flagger
helm upgrade -i flagger flagger/flagger \
--namespace flagger \
--set prometheus.install=true \
--set meshProvider=kubernetes
부트스트랩 (Bootstrap)
Flagger는 Kubernetes deployment와 그 deployment를 대상으로 하는 KEDA ScaledObject를 받습니다. 그런 다음 일련의 오브젝트(Kubernetes deployments, ClusterIP services, 그리고 생성된 Deployment를 대상으로 하는 또 다른 KEDA ScaledObject)를 만듭니다. 이 오브젝트들은 메시 내부에서 애플리케이션을 노출하고 Canary 분석과 블루/그린 승격을 구동합니다.
테스트 네임스페이스를 만듭니다:
kubectl create ns test
podinfo라는 이름의 deployment를 만듭니다:
kubectl apply -n test -f https://raw.githubusercontent.com/fluxcd/flagger/main/kustomize/podinfo/deployment.yaml
분석 중 트래픽을 생성할 부하 테스트 서비스를 배포합니다:
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/tester?ref=main
podinfo 배포를 대상으로 하고 Prometheus를 트리거로 사용하는 ScaledObject를 만듭니다:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: podinfo-so
namespace: test
spec:
scaleTargetRef:
name: podinfo
pollingInterval: 10
cooldownPeriod: 20
minReplicaCount: 1
maxReplicaCount: 3
triggers:
- type: prometheus
metadata:
name: prom-trigger
serverAddress: http://flagger-prometheus.flagger:9090
metricName: http_requests_total
query: sum(rate(http_requests_total{ app="podinfo" }[30s]))
threshold: '5'
podinfo 배포용 canary 커스텀 리소스를 만듭니다:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
provider: kubernetes
# deployment reference
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
# Scaler reference
autoscalerRef:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
# ScaledObject targeting the canary deployment
name: podinfo-so
# Mapping between trigger names and the related query to use for the generated
# ScaledObject targeting the primary deployment. (Optional)
primaryScalerQueries:
prom-trigger: sum(rate(http_requests_total{ app="podinfo-primary" }[30s]))
# Overriding replica scaling configuration for the generated ScaledObject
# targeting the primary deployment. (Optional)
primaryScalerReplicas:
minReplicas: 2
maxReplicas: 5
# the maximum time in seconds for the canary deployment
# to make progress before rollback (default 600s)
progressDeadlineSeconds: 60
service:
port: 80
targetPort: 9898
name: podinfo-svc
portDiscovery: true
analysis:
# schedule interval (default 60s)
interval: 15s
# max number of failed checks before rollback
threshold: 5
# number of checks to run before promotion
iterations: 5
# Prometheus checks based on
# http_request_duration_seconds histogram
metrics:
- name: request-success-rate
interval: 1m
thresholdRange:
min: 99
- name: request-duration
interval: 30s
thresholdRange:
max: 500
# load testing hooks
webhooks:
- name: load-test
url: http://flagger-loadtester.test/
timeout: 5s
metadata:
type: cmd
cmd: "hey -z 2m -q 20 -c 2 http://podinfo-svc-canary.test/"
위 리소스를 podinfo-canary.yaml로 저장한 뒤 적용합니다:
kubectl apply -f ./podinfo-canary.yaml
몇 초 후 Flagger가 canary 오브젝트를 생성합니다:
# applied
deployment.apps/podinfo
scaledobject.keda.sh/podinfo-so
canary.flagger.app/podinfo
# generated
deployment.apps/podinfo-primary
horizontalpodautoscaler.autoscaling/podinfo-primary
service/podinfo
service/podinfo-canary
service/podinfo-primary
scaledobject.keda.sh/podinfo-so-primary
canary 배포용 ScaledObject는 .spec.autoscalerRef로 참조합니다. Flagger는 이를 사용해 primary 배포를 스케일링할 ScaledObject를 생성합니다. 기본적으로 Flagger는 모든 트리거에 대해 .spec.targetRef.Name과 {.spec.targetRef.Name}-canary의 모든 언급을 {.spec.targetRef.Name}-primary로 바꿔 primary ScaledObject에 사용할 쿼리를 추측하려 시도합니다. 예를 들어 ScaledObject의 트리거 쿼리가 sum(rate(http_requests_total{ app="podinfo" }[30s])) 또는 sum(rate(http_requests_total{ app="podinfo-primary" }[30s]))로 정의되어 있다면, primary ScaledObject는 sum(rate(http_requests_total{ app="podinfo-primary" }[30s]))로 정의된 쿼리를 가진 동일한 트리거를 갖게 됩니다.
생성된 쿼리가 요구 사항을 충족하지 않는다면 .spec.autoscalerRef.primaryScalerQueries로 primary 배포 자동 스케일링용 쿼리를 명시적으로 지정할 수 있으며, 이를 통해 각 트리거별 쿼리를 정의할 수 있습니다. ScaledObject의 .spec.triggers[@].name은 비어 있으면 안 됩니다. Flagger가 각 트리거를 고유하게 식별하는 데 필요하기 때문입니다.
canary와 primary 배포 ScaledObject 사이에 다른 스케일링 복제본 구성을 원할 경우 .spec.autoscalerRef.primaryScalerReplicas를 사용해 생성되는 primary ScaledObject의 값을 재정의할 수 있습니다.
부트스트랩 후 podinfo 배포는 0으로 스케일되고 podinfo.test로 가는 트래픽은 primary 파드로 라우팅됩니다. podinfo 배포를 0 복제본으로 유지하고 자동 스케일링을 일시 중지하기 위해 Flagger는 ScaledObject에 autoscaling.keda.sh/paused-replicas: 0 애노테이션을 추가합니다. 카나리아 분석 중에는 이 애노테이션이 제거되어 podinfo 배포의 자동 스케일링이 활성화됩니다. podinfo-canary.test 주소로 canary 파드를 직접 대상으로 삼을 수 있습니다. 카나리아 분석이 시작되면 Flagger는 트래픽을 canary로 라우팅하기 전에 pre-rollout 웹훅을 호출합니다. 블루/그린 배포는 매 15초마다 HTTP 메트릭과 롤아웃 훅을 검증하면서 5회 반복으로 실행됩니다.
자동 블루/그린 승격 (Automated Blue/Green promotion)
컨테이너 이미지를 업데이트해 배포를 트리거합니다:
kubectl -n test set image deployment/podinfo \
podinfod=ghcr.io/stefanprodan/podinfo:6.0.1
Flagger는 배포 리비전이 변경되었음을 감지하고 새 롤아웃을 시작합니다:
kubectl -n test describe canary/podinfo
Events:
New revision detected 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 iteration 1/10
Advance podinfo.test canary iteration 2/10
Advance podinfo.test canary iteration 3/10
Advance podinfo.test canary iteration 4/10
Advance podinfo.test canary iteration 5/10
Advance podinfo.test canary iteration 6/10
Advance podinfo.test canary iteration 7/10
Advance podinfo.test canary iteration 8/10
Advance podinfo.test canary iteration 9/10
Advance podinfo.test canary iteration 10/10
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는 다음과 같이 모니터링할 수 있습니다:
watch kubectl get canaries --all-namespaces
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
test podinfo Progressing 100 2019-06-16T14:05:07Z
배포의 스케일링은 다음과 같이 모니터링할 수 있습니다:
watch kubectl -n test get deploy podinfo
NAME READY UP-TO-DATE AVAILABLE AGE
flagger-loadtester 1/1 1 1 4m21s
podinfo 3/3 3 3 4m28s
podinfo-primary 3/3 3 3 3m14s
Flagger가 ScaledObject의 애노테이션을 편집하는 모습은 다음과 같이 모니터링할 수 있습니다:
watch "kubectl get -n test scaledobjects podinfo-so -o=jsonpath='{.metadata.annotations}'"