АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

CD ΠΏΡ€ΠΈΠ·Π½Π°Π½ΠΎ Π² качСствС ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ ΠΊΠΎΡ€ΠΏΠΎΡ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния, это β€” Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ СстСствСнной ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΈ ΡƒΡΡ‚ΠΎΡΠ²ΡˆΠΈΡ…ΡΡ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΎΠ² CI. Однако CD ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ довольно Ρ€Π΅Π΄ΠΊΠΎΠ΅ явлСниС, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΈΠ·-Π·Π° слоТности управлСния ΠΈ страха ΠΏΠ΅Ρ€Π΅Π΄ Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹ΠΌΠΈ дСплоями, Π²Π»ΠΈΡΡŽΡ‰ΠΈΠΌΠΈ Π½Π° Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΠΎΡΡ‚ΡŒ систСмы.

Flagger β€” это ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ Kubernetes с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ, Ρ†Π΅Π»ΡŒ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ β€” ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π·Π°ΠΏΡƒΡ‚Π°Π½Π½Ρ‹Π΅ взаимосвязи. Он Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ canary Π΄Π΅ΠΏΠ»ΠΎΠ΅Π² с использованиСм смСщСния Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Istio ΠΈ ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊ Prometheus для Π°Π½Π°Π»ΠΈΠ·Π° повСдСния прилоТСния Π²ΠΎ врСмя управляСмого выкатывания.

НиТС ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΎ пошаговоС руководство ΠΏΠΎ настройкС ΠΈ использованию Flagger Π² Google Kubernetes Engine (GKE).

Настройка кластСра Kubernetes

Π’Ρ‹ Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚Π΅ с создания кластСра GKE с надстройкой Istio (Ссли Ρƒ вас Π½Π΅Ρ‚ ΡƒΡ‡Π΅Ρ‚Π½ΠΎΠΉ записи GCP, Π·Π°Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΌΠΎΠΆΠ½ΠΎ здСсь β€” для получСния бСсплатных ΠΊΡ€Π΅Π΄ΠΈΡ‚ΠΎΠ²).

Π’ΠΎΠΉΠ΄ΠΈΡ‚Π΅ Π² Google Cloud, создайтС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΠΈ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ для Π½Π΅Π³ΠΎ Π±ΠΈΠ»Π»ΠΈΠ½Π³. УстановитС ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρƒ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки gcloud ΠΈ настройтС свой ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ gcloud init.

УстановитС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, ΠΎΠ±Π»Π°ΡΡ‚ΡŒ вычислСний ΠΈ Π·ΠΎΠ½Ρƒ (Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ PROJECT_ID Π½Π° свой ΠΏΡ€ΠΎΠ΅ΠΊΡ‚):

gcloud config set project PROJECT_ID
gcloud config set compute/region us-central1
gcloud config set compute/zone us-central1-a

Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ сСрвис GKE ΠΈ создайтС кластСр с HPA ΠΈ надстройками Istio:

gcloud services enable container.googleapis.com
K8S_VERSION=$(gcloud beta container get-server-config --format=json | jq -r '.validMasterVersions[0]')
gcloud beta container clusters create istio 
--cluster-version=${K8S_VERSION} 
--zone=us-central1-a 
--num-nodes=2 
--machine-type=n1-standard-2 
--disk-size=30 
--enable-autorepair 
--no-enable-cloud-logging 
--no-enable-cloud-monitoring 
--addons=HorizontalPodAutoscaling,Istio 
--istio-config=auth=MTLS_PERMISSIVE

ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Π°Ρ Π²Ρ‹ΡˆΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Π° создаст ΠΏΡƒΠ» Π½ΠΎΠ΄ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ Π΄Π²Π΅ Π’Πœ n1-standard-2 (vCPU: 2, RAM 7,5 GB, диск: 30 GB). Π’ ΠΈΠ΄Π΅Π°Π»Π΅ стоит ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Istio ΠΎΡ‚ своих Ρ€Π°Π±ΠΎΡ‡ΠΈΡ… Π½Π°Π³Ρ€ΡƒΠ·ΠΎΠΊ, Π½ΠΎ простого способа запуска ΠΏΠΎΠ΄ΠΎΠ² Istio Π² Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ ΠΏΡƒΠ»Π΅ Π½ΠΎΠ΄ Π½Π΅ сущСствуСт. ΠœΠ°Π½ΠΈΡ„Π΅ΡΡ‚Ρ‹ Istio ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ доступными Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для чтСния, ΠΈ GKE Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ измСнСния, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, привязку ΠΊ Π½ΠΎΠ΄Π΅ ΠΈΠ»ΠΈ отсоСдинСниС ΠΎΡ‚ ΠΏΠΎΠ΄Π°.

НастройтС ΡƒΡ‡Π΅Ρ‚Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ для kubectl:

gcloud container clusters get-credentials istio

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ привязку Ρ€ΠΎΠ»ΠΈ администратора кластСра:

kubectl create clusterrolebinding "cluster-admin-$(whoami)" 
--clusterrole=cluster-admin 
--user="$(gcloud config get-value core/account)"

УстановитС инструмСнт ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки Helm:

brew install kubernetes-helm

Homebrew 2.0 Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ доступСн для Linux.

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΡƒΡ‡Π΅Ρ‚Π½ΡƒΡŽ запись слуТбы ΠΈ привязку Ρ€ΠΎΠ»ΠΈ кластСра для Tiller:

kubectl -n kube-system create sa tiller && 
kubectl create clusterrolebinding tiller-cluster-rule 
--clusterrole=cluster-admin 
--serviceaccount=kube-system:tiller

Π Π°Π·Π²Π΅Ρ€Π½ΠΈΡ‚Π΅ Tiller Π² нСймспСйс kube-system:

helm init --service-account tiller

Π’Π°ΠΌ слСдуСт Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ использования SSL ΠΌΠ΅ΠΆΠ΄Ρƒ Helm ΠΈ Tiller. Для получСния Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ Π·Π°Ρ‰ΠΈΡ‚Π΅ установки Helm см. docs.helm.sh

ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€Π΄ΠΈΡ‚Π΅ настройки:

kubectl -n istio-system get svc

Π§Π΅Ρ€Π΅Π· нСсколько сСкунд GCP Π΄ΠΎΠ»ΠΆΠ΅Π½ Π½Π°Π·Π½Π°Ρ‡ΠΈΡ‚ΡŒ внСшний IP-адрСс для сСрвиса istio-ingressgateway.

Настройка Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ шлюза Istio

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ статичСский IP-адрСс с ΠΈΠΌΠ΅Π½Π΅ΠΌ istio-gateway, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ IP-адрСс шлюза Istio:

export GATEWAY_IP=$(kubectl -n istio-system get svc/istio-ingressgateway -ojson | jq -r .status.loadBalancer.ingress[0].ip)
gcloud compute addresses create istio-gateway --addresses ${GATEWAY_IP} --region us-central1

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π²Π°ΠΌ Π½ΡƒΠΆΠ΅Π½ ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚-Π΄ΠΎΠΌΠ΅Π½ ΠΈ доступ ΠΊ своСму рСгистратору DNS. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π΄Π²Π΅ записи А (Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ example.com Π½Π° свой Π΄ΠΎΠΌΠ΅Π½):

istio.example.com   A ${GATEWAY_IP}
*.istio.example.com A ${GATEWAY_IP}

Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ подстановочный символ DNS Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚:

watch host test.istio.example.com

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΎΠ±Ρ‰ΠΈΠΉ шлюз Istio для прСдоставлСния услуг Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Π°ΠΌΠΈ service mesh ΠΏΠΎ HTTP:

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:
        - "*"

Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚Π΅ Π²Ρ‹ΡˆΠ΅ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ рСсурс ΠΊΠ°ΠΊ public-gateway.yaml, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ Π΅Π³ΠΎ:

kubectl apply -f ./public-gateway.yaml

Ни ΠΎΠ΄Π½Π° производствСнная систСма Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ услуги Π² Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π΅ Π±Π΅Π· SSL. Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ΡŒ Π²Ρ…ΠΎΠ΄Π½ΠΎΠΉ шлюз Istio с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ cert-manager, CloudDNS ΠΈ Let’s Encrypt, ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅, поТалуйста, Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ Flagger GKE.

Установка Flagger

Надстройка GKE Istio Π½Π΅ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ экзСмпляр Prometheus, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ занимаСтся очисткой слуТбы Ρ‚Π΅Π»Π΅ΠΌΠ΅Ρ‚Ρ€ΠΈΠΈ Istio. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Flagger ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ Istio HTTP для выполнСния canary Π°Π½Π°Π»ΠΈΠ·Π°, Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π·Π°Π΄Π΅ΠΏΠ»ΠΎΠΈΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ Prometheus, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΡƒΡŽ Ρ‚ΠΎΠΉ, которая поставляСтся с ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ схСмой Istio Helm.

REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
kubectl apply -f ${REPO}/artifacts/gke/istio-prometheus.yaml

Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ Flagger Helm:

helm repo add flagger [https://flagger.app](https://flagger.app/)

Π Π°Π·Π²Π΅Ρ€Π½ΠΈΡ‚Π΅ Flagger Π² нСймспСйс istio-system, Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ² увСдомлСния Slack:

helm upgrade -i flagger flagger/flagger 
--namespace=istio-system 
--set metricsServer=http://prometheus.istio-system:9090 
--set slack.url=https://hooks.slack.com/services/YOUR-WEBHOOK-ID 
--set slack.channel=general 
--set slack.user=flagger

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Flagger Π² любом нСймспСйсС, Ссли ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ с сСрвисом Istio Prometheus Ρ‡Π΅Ρ€Π΅Π· ΠΏΠΎΡ€Ρ‚ 9090.

Flagger ΠΈΠΌΠ΅Π΅Ρ‚ панСль ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³Π° Grafana для canary Π°Π½Π°Π»ΠΈΠ·Π°. УстановитС Grafana Π² нСймспСйс istio-system:

helm upgrade -i flagger-grafana flagger/grafana 
--namespace=istio-system 
--set url=http://prometheus.istio-system:9090 
--set user=admin 
--set password=change-me

РаскройтС Grafana Ρ‡Π΅Ρ€Π΅Π· ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΉ шлюз, создав Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ сСрвис (Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ example.com Π½Π° ваш Π΄ΠΎΠΌΠ΅Π½):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: grafana
  namespace: istio-system
spec:
  hosts:
    - "grafana.istio.example.com"
  gateways:
    - public-gateway.istio-system.svc.cluster.local
  http:
    - route:
        - destination:
            host: flagger-grafana

Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚Π΅ Π²Ρ‹ΡˆΠ΅ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ рСсурс ΠΊΠ°ΠΊ grafana-virtual-service.yaml, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ Π΅Π³ΠΎ:

kubectl apply -f ./grafana-virtual-service.yaml

ΠŸΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ ΠΊ http://grafana.istio.example.com Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅ вас Π΄ΠΎΠ»Π½ΠΆΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π½Π° страницу Π²Ρ…ΠΎΠ΄Π° Π² систСму Grafana.

Π”Π΅ΠΏΠ»ΠΎΠΉ Π²Π΅Π±-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ с Flagger

Flagger Π΄Π΅ΠΏΠ»ΠΎΠΈΡ‚ Kubernetes ΠΈ, ΠΏΡ€ΠΈ нСобходимости, Π³ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒΠ½ΠΎΠ΅ автоматичСскоС ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ (HPA), Π·Π°Ρ‚Π΅ΠΌ создаСт ΡΠ΅Ρ€ΠΈΡŽ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² (Π΄Π΅ΠΏΠ»ΠΎΠΈ Kubernetes, сСрвисы ClusterIP ΠΈ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ сСрвисы Istio). Π­Ρ‚ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Ρ€Π°ΡΠΊΡ€Ρ‹Π²Π°ΡŽΡ‚ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π² service mesh ΠΈ ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ canary Π°Π½Π°Π»ΠΈΠ·ΠΎΠΌ ΠΈ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ΠΌ.

АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ тСстовый нСймспСйс с Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹ΠΌ Π²Π½Π΅Π΄Ρ€Π΅Π½ΠΈΠ΅ΠΌ Istio Sidecar:

REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
kubectl apply -f ${REPO}/artifacts/namespaces/test.yaml

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Π΄Π΅ΠΏΠ»ΠΎΠΉ ΠΈ инструмСнт автоматичСского Π³ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ ΠΏΠΎΠ΄Π°:

kubectl apply -f ${REPO}/artifacts/canaries/deployment.yaml
kubectl apply -f ${REPO}/artifacts/canaries/hpa.yaml

Π Π°Π·Π²Π΅Ρ€Π½ΠΈΡ‚Π΅ сСрвис тСстовой Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Π²ΠΎ врСмя canary Π°Π½Π°Π»ΠΈΠ·Π°:

helm upgrade -i flagger-loadtester flagger/loadtester 
--namepace=test

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ canary рСсурс (Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ example.com Π½Π° свой Π΄ΠΎΠΌΠ΅Π½):

apiVersion: flagger.app/v1alpha3
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  progressDeadlineSeconds: 60
  autoscalerRef:
    apiVersion: autoscaling/v2beta1
    kind: HorizontalPodAutoscaler
    name: podinfo
  service:
    port: 9898
    gateways:
    - public-gateway.istio-system.svc.cluster.local
    hosts:
    - app.istio.example.com
  canaryAnalysis:
    interval: 30s
    threshold: 10
    maxWeight: 50
    stepWeight: 5
    metrics:
    - name: istio_requests_total
      threshold: 99
      interval: 30s
    - name: istio_request_duration_seconds_bucket
      threshold: 500
      interval: 30s
    webhooks:
      - name: load-test
        url: http://flagger-loadtester.test/
        timeout: 5s
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"

Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚Π΅ Π²Ρ‹ΡˆΠ΅ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ рСсурс ΠΊΠ°ΠΊ podinfo-canary.yaml, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ Π΅Π³ΠΎ:

kubectl apply -f ./podinfo-canary.yaml

ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π²Ρ‹ΡˆΠ΅ Π°Π½Π°Π»ΠΈΠ·, Π² случаС успСха, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ пяти ΠΌΠΈΠ½ΡƒΡ‚ с ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊ HTTP ΠΊΠ°ΠΆΠ΄Ρ‹Π΅ ΠΏΠΎΠ»ΠΌΠΈΠ½ΡƒΡ‚Ρ‹. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ минимальноС врСмя, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ продвиТСния canary дСплоя, ΠΏΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Ρ„ΠΎΡ€ΠΌΡƒΠ»Π΅: interval * (maxWeight / stepWeight). Поля Canary CRD Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ здСсь.

Π§Π΅Ρ€Π΅Π· ΠΏΠ°Ρ€Ρƒ сСкунд 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
virtualservice.networking.istio.io/podinfo

ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ ΠΈ ΠΏΠ΅Ρ€Π΅ΠΉΠ΄ΠΈΡ‚Π΅ ΠΊ app.istio.example.com, Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Π½ΠΎΠΌΠ΅Ρ€ вСрсии Π΄Π΅ΠΌΠΎ-прилоТСния.

АвтоматичСский canary Π°Π½Π°Π»ΠΈΠ· ΠΈ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅

Flagger Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ Ρ†ΠΈΠΊΠ» управлСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ постСпСнно ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Π΅Ρ‚ Ρ‚Ρ€Π°Ρ„ΠΈΠΊ Π½Π° canary, ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ измСряя ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΡΡ‚ΠΈ HTTP-запросов, ΡΡ€Π΅Π΄Π½ΡŽΡŽ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ запросов ΠΈ Ρ€Π°Π±ΠΎΡ‚ΠΎΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ ΠΏΠΎΠ΄Π°. На основС Π°Π½Π°Π»ΠΈΠ·Π° KPI canary продвигаСтся ΠΈΠ»ΠΈ прСрываСтся, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ Π² Slack.

АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

Canary Π΄Π΅ΠΏΠ»ΠΎΠΉ запускаСтся ΠΏΡ€ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²:

  • Π”Π΅ΠΏΠ»ΠΎΠΉ PodSpec (ΠΎΠ±Ρ€Π°Π· ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, ΠΊΠΎΠΌΠ°Π½Π΄Π°, ΠΏΠΎΡ€Ρ‚Ρ‹, env ΠΈ Ρ‚.Π΄.)
  • ConfigMaps ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Ρ‚ΠΎΠΌΠ° ΠΈΠ»ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°ΠΆΠ°ΡŽΡ‚ΡΡ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ срСды
  • Π‘Π΅ΠΊΡ€Π΅Ρ‚Ρ‹ ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Ρ‚ΠΎΠΌΠ° ΠΈΠ»ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°ΠΆΠ°ΡŽΡ‚ΡΡ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ срСды

Запуск canary дСплоя ΠΏΡ€ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ ΠΎΠ±Ρ€Π°Π·Π° ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°:

kubectl -n test set image deployment/podinfo 
podinfod=quay.io/stefanprodan/podinfo:1.4.1

Flagger ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ вСрсия дСплоя измСнилась, ΠΈ Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ Π΅Π΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ:

kubectl -n test describe canary/podinfo

Events:

New revision detected podinfo.test
Scaling up podinfo.test
Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
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
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

Π’ΠΎ врСмя Π°Π½Π°Π»ΠΈΠ·Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ canary ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Grafana:

АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: Ссли Π½ΠΎΠ²Ρ‹Π΅ измСнСния ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π² ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠΈ дСплоя Π²ΠΎ врСмя canary Π°Π½Π°Π»ΠΈΠ·Π°, Ρ‚ΠΎ Flagger пСрСзапустит Ρ„Π°Π·Ρƒ Π°Π½Π°Π»ΠΈΠ·Π°.

Π‘ΠΎΡΡ‚Π°Π²ΡŒΡ‚Π΅ список всСх «ΠΊΠ°Π½Π°Ρ€Π΅Π΅ΠΊ» Π² вашСм кластСрС:

watch kubectl get canaries --all-namespaces
NAMESPACE   NAME      STATUS        WEIGHT   LASTTRANSITIONTIME
test        podinfo   Progressing   15       2019-01-16T14:05:07Z
prod        frontend  Succeeded     0        2019-01-15T16:15:07Z
prod        backend   Failed        0        2019-01-14T17:05:07Z

Если Π²Ρ‹ Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ»ΠΈ увСдомлСния Slack, Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ сообщСния:

АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

АвтоматичСский ΠΎΡ‚ΠΊΠ°Ρ‚

Π’ΠΎ врСмя canary Π°Π½Π°Π»ΠΈΠ·Π° ΠΌΠΎΠΆΠ½ΠΎ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ синтСтичСскиС ошибки HTTP 500 ΠΈ Π²Ρ‹ΡΠΎΠΊΡƒΡŽ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ ΠΎΡ‚Π²Π΅Ρ‚Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, Π½Π΅ остановит Π»ΠΈ Flagger Π΄Π΅ΠΏΠ»ΠΎΠΉ.

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ тСстовый ΠΏΠΎΠ΄ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ Π² Π½Π΅ΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ дСйствиС:

kubectl -n test run tester 
--image=quay.io/stefanprodan/podinfo:1.2.1 
-- ./podinfo --port=9898
kubectl -n test exec -it tester-xx-xx sh

ГСнСрация ошибок HTTP 500:

watch curl http://podinfo-canary:9898/status/500

ГСнСрация Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΈ:

watch curl http://podinfo-canary:9898/delay/1

Когда число Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹Ρ… ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ достигаСт ΠΏΠΎΡ€ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ значСния, Ρ‚Ρ€Π°Ρ„ΠΈΠΊ направляСтся ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΊ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½ΠΎΠΌΡƒ ΠΊΠ°Π½Π°Π»Ρƒ, canary ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ Π΄ΠΎ нуля, Π° Π΄Π΅ΠΏΠ»ΠΎΠΉ помСчаСтся ΠΊΠ°ΠΊ Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹ΠΉ.

Ошибки canary ΠΈ ΠΏΠΈΠΊΠΈ Π·Π°Π΄Π΅Ρ€ΠΆΠ΅ΠΊ Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ события Kubernetes ΠΈ Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Flagger Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ JSON:

kubectl -n istio-system logs deployment/flagger -f | jq .msg

Starting canary deployment for podinfo.test
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 success rate 47.00% < 99%
Halt podinfo.test advancement success rate 37.00% < 99%
Halt podinfo.test advancement request duration 1.515s > 500ms
Halt podinfo.test advancement request duration 1.600s > 500ms
Halt podinfo.test advancement request duration 1.915s > 500ms
Halt podinfo.test advancement request duration 2.050s > 500ms
Halt podinfo.test advancement request duration 2.515s > 500ms
Rolling back podinfo.test failed checks threshold reached 10
Canary failed! Scaling down podinfo.test

Если Π²Ρ‹ Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ»ΠΈ увСдомлСния Slack, Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ сообщСниС, ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ ΠΊΡ€Π°ΠΉΠ½ΠΈΠΉ срок выполнСния ΠΈΠ»ΠΈ достиТСния максимального количСства Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹Ρ… ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ Π² Ρ…ΠΎΠ΄Π΅ Π°Π½Π°Π»ΠΈΠ·Π°:

АвтоматичСскиС canary Π΄Π΅ΠΏΠ»ΠΎΠΈ с Flagger ΠΈ Istio

Π’ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Запуск service mesh, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Istio, Π²Π΄ΠΎΠ±Π°Π²ΠΎΠΊ ΠΊ Kubernetes прСдоставит автоматичСскиС ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ, Π»ΠΎΠ³ΠΈ ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Ρ‹, Π½ΠΎ Π΄Π΅ΠΏΠ»ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‡ΠΈΡ… Π½Π°Π³Ρ€ΡƒΠ·ΠΎΠΊ всС Π΅Ρ‰Π΅ зависит ΠΎΡ‚ Π²Π½Π΅ΡˆΠ½ΠΈΡ… инструмСнтов. Flagger стрСмится ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ эту ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ, добавляя Istio возмоТности прогрСссивной поставки.

Flagger совмСстим с Π»ΡŽΠ±Ρ‹ΠΌΠΈ CI/CD-Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΠΌΠΈ для Kubernetes, ΠΈ ΠΊΠ°Π½Π°Ρ€Π΅Π΅Ρ‡Π½Ρ‹ΠΉ Π°Π½Π°Π»ΠΈΠ· ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² для выполнСния систСмных тСстов ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ/ΠΏΡ€ΠΈΠ΅ΠΌΠΊΠΈ, Π½Π°Π³Ρ€ΡƒΠ·ΠΎΡ‡Π½Ρ‹Ρ… тСстов ΠΈΠ»ΠΈ Π»ΡŽΠ±Ρ‹Ρ… Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Flagger являСтся Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌ ΠΈ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π° события Kubernetes, Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π°Ρ… GitOps вмСстС с Weave Flux ΠΈΠ»ΠΈ JenkinsX. Если Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ JenkinsX, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Flagger с надстройками jx.

Flagger поддСрТиваСтся Weaveworks ΠΈ обСспСчиваСт canary Π΄Π΅ΠΏΠ»ΠΎΠΈ Π² Weave Cloud. ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ тСстируСтся Π½Π° GKE, EKS ΠΈ «Π³ΠΎΠ»ΠΎΠΌ ΠΆΠ΅Π»Π΅Π·Π΅» с kubeadm.

Если Ρƒ вас Π΅ΡΡ‚ΡŒ прСдлоТСния ΠΏΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡŽ Flagger, поТалуйста, ΠΎΡ‚ΠΏΡ€Π°Π²ΡŒΡ‚Π΅ вопрос ΠΈΠ»ΠΈ PR Π½Π° GitHub ΠΏΠΎ адрСсу stefanprodan/flagger. Взносы Π±ΠΎΠ»Π΅Π΅ Ρ‡Π΅ΠΌ ΠΏΡ€ΠΈΠ²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ΡΡ!

Бпасибо Рэю Π¦Π°Π½Ρƒ.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com