Distribuzioni canary automatiche con Flagger e Istio

Distribuzioni canary automatiche con Flagger e Istio

Il CD è riconosciuto come una pratica di software aziendale, risultato dell'evoluzione naturale dei principi consolidati del CI. Tuttavia, il CD è ancora un fenomeno piuttosto raro, forse a causa della complessità della gestione e della paura di distribuzioni fallite che influenzano la disponibilità del sistema.

Flagger è un operatore Kubernetes open source, il cui obiettivo è eliminare le interrelazioni complesse. Automatizza la promozione delle distribuzioni canary utilizzando il traffico di Istio e le metriche di Prometheus per analizzare il comportamento dell'applicazione durante il rilascio controllato.

Di seguito è riportata una guida passo passo per la configurazione e l'utilizzo di Flagger su Google Kubernetes Engine (GKE).

Configurazione del cluster Kubernetes

Iniziate creando un cluster GKE con Istio (se non avete un account GCP, potete registrarvi qui per ottenere crediti gratuiti).

Accedete a Google Cloud, create un progetto e attivate la fatturazione per esso. Installate la CLI gcloud e configurate il vostro progetto con gcloud init.

Impostate il progetto predefinito, la regione di calcolo e la zona (sostituite PROJECT_ID con il vostro progetto):

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

Attivate il servizio GKE e create un cluster con HPA e estensioni 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

Il comando sopra creerà un pool di nodi predefinito con due VM n1-standard-2 (vCPU: 2, RAM 7,5 GB, disco: 30 GB). Idealmente, è consigliabile isolare i componenti di Istio dai carichi di lavoro, ma non esiste un modo semplice per eseguire i pod di Istio in un pool di nodi dedicato. I manifest di Istio sono considerati disponibili solo in lettura, e GKE annullerà qualsiasi modifica, come il legame con un nodo o la dissociazione da un pod.

Configurate le credenziali per kubectl:

gcloud container clusters get-credentials istio

Create un binding di ruolo amministratore del cluster:

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

Installate lo strumento della riga di comando Helm:

brew install kubernetes-helm

Homebrew 2.0 è ora disponibile anche per Linux.

Crea un'account di servizio e un binding del ruolo del cluster per Tiller:

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

Distribuisci Tiller nello spazio dei nomi kube-system:

helm init --service-account tiller

Dovresti considerare l'uso di SSL tra Helm e Tiller. Per ulteriori informazioni sulla protezione dell'installazione di Helm, consulta docs.helm.sh

Conferma le impostazioni:

kubectl -n istio-system get svc

Dopo qualche secondo, GCP dovrebbe assegnare un IP pubblico al servizio istio-ingressgateway.

Configurazione del gateway di ingresso Istio

Crea un indirizzo IP statico con il nome istio-gateway, utilizzando l'indirizzo IP del gateway 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

Ora hai bisogno di un dominio internet e di accesso al tuo registrar DNS. Aggiungi due record A (sostituisci example.com con il tuo dominio):

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

Assicurati che il wildcard DNS funzioni:

watch host test.istio.example.com

Crea un gateway Istio pubblico per fornire servizi al di fuori del service mesh tramite 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:
        - "*"

Salva la risorsa sopra come public-gateway.yaml e poi applicala:

kubectl apply -f ./public-gateway.yaml

Nessun sistema di produzione dovrebbe fornire servizi online senza SSL. Per proteggere il gateway di ingresso Istio utilizzando cert-manager, CloudDNS e Let’s Encrypt, leggi per favore la documentazione Flagger GKE.

Installazione di Flagger

La configurazione di GKE Istio non include un'istanza di Prometheus che gestisce la pulizia del servizio di telemetria Istio. Poiché Flagger utilizza metriche Istio HTTP per eseguire analisi canary, è necessario distribuire la seguente configurazione Prometheus, simile a quella fornita con lo schema ufficiale di Istio Helm.

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

Aggiungi il repository Flagger Helm:

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

Distribuisci Flagger nello spazio dei nomi istio-system, abilitando le notifiche 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

Puoi installare Flagger in qualsiasi spazio dei nomi, se può interagire con il servizio Istio Prometheus tramite la porta 9090.

Flagger ha un pannello di controllo Grafana per l'analisi canary. Installa Grafana nel namespace 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

Espandi Grafana tramite un gateway aperto, creando un servizio virtuale (sostituisci example.com con il tuo dominio):

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

Salva la risorsa sopra menzionata come grafana-virtual-service.yaml e poi applicala:

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

Accedendo a http://grafana.istio.example.com nel browser dovresti essere reindirizzato alla pagina di accesso di Grafana.

Distribuzione di applicazioni web con Flagger

Flagger distribuisce Kubernetes e, se necessario, l'autoscaling orizzontale (HPA), quindi crea una serie di oggetti (distribuzioni Kubernetes, servizi ClusterIP e servizi virtuali Istio). Questi oggetti espongono l'applicazione nella service mesh e gestiscono l'analisi canary e la promozione.

Distribuzioni canary automatiche con Flagger e Istio

Crea un namespace di test con l'inserimento di Istio Sidecar attivato:

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

Crea una distribuzione e uno strumento di autoscaling orizzontale per i pod:

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

Distribuisci un servizio di carico di test per generare traffico durante l'analisi canary:

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

Crea una risorsa canary personalizzata (sostituisci example.com con il tuo dominio):

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/"

Salva la risorsa sopra menzionata come podinfo-canary.yaml e poi applicala:

kubectl apply -f ./podinfo-canary.yaml

L'analisi sopra riportata, in caso di successo, verrà eseguita per cinque minuti controllando le metriche HTTP ogni trenta secondi. Puoi determinare il tempo minimo necessario per verificare e promuovere la distribuzione canary secondo la seguente formula: interval * (maxWeight / stepWeight). I campi Canary CRD sono documentati qui.

Dopo un paio di secondi, Flagger creerà oggetti 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

Apri il browser e vai a app.istio.example.com, dovresti vedere il numero di versione dell'app demo.

Analisi e promozione canary automatica

Flagger implementa un ciclo di gestione che trasferisce gradualmente il traffico al canary, misurando simultaneamente indicatori chiave di prestazione come il tasso di successo delle richieste HTTP, la durata media delle richieste e la disponibilità del pod. Sulla base dell'analisi degli KPI, il canary viene promosso o interrotto, e i risultati dell'analisi vengono pubblicati su Slack.

Distribuzioni canary automatiche con Flagger e Istio

Il deployment canary viene avviato quando uno dei seguenti oggetti cambia:

  • PodSpec del deployment (immagine del contenitore, comando, porte, env, ecc.)
  • ConfigMap montati come volumi o trasformati in variabili d'ambiente
  • Segreti montati come volumi o trasformati in variabili d'ambiente

Avvio del deployment canary durante l'aggiornamento dell'immagine del contenitore:

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

Flagger rileva che la versione del deployment è cambiata e inizia ad analizzarla:

kubectl -n test describe canary/podinfo

Eventi:

Nuova revisione rilevata 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
Promozione completata! Scaling down podinfo.test

Durante l'analisi, i risultati canary possono essere monitorati utilizzando Grafana:

Distribuzioni canary automatiche con Flagger e Istio

Nota: se si applicano nuove modifiche al deployment durante l'analisi canary, Flagger riprenderà la fase di analisi.

Fai un elenco di tutti i "canary" nel tuo cluster:

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

Se hai abilitato le notifiche Slack, riceverai i seguenti messaggi:

Distribuzioni canary automatiche con Flagger e Istio

Rollback automatico

Durante l'analisi canary, puoi generare errori HTTP 500 sintetici e alta latenza nelle risposte per verificare se Flagger interromperà il deployment.

Crea un pod di test e esegui il seguente comando:

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

Generazione di errori HTTP 500:

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

Generazione di ritardi:

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

Quando il numero di verifiche fallite raggiunge la soglia, il traffico viene reindirizzato al canale primario, il canary viene scalato a zero e il deployment viene contrassegnato come fallito.

Gli errori del canary e i picchi di ritardi vengono registrati come eventi di Kubernetes e Flagger li registra in formato JSON:

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

Avvio del deployment canary per podinfo.test
Aumenta il peso del canary di podinfo.test 5
Aumenta il peso del canary di podinfo.test 10
Aumenta il peso del canary di podinfo.test 15
Interrompi l'avanzamento del podinfo.test tasso di successo 69,17% < 99%
Interrompi l'avanzamento del podinfo.test tasso di successo 61,39% < 99%
Interrompi l'avanzamento del podinfo.test tasso di successo 55,06% < 99%
Interrompi l'avanzamento del podinfo.test tasso di successo 47,00% < 99%
Interrompi l'avanzamento del podinfo.test tasso di successo 37,00%  500ms
Interrompi l'avanzamento della richiesta di podinfo.test durata 1,600s > 500ms
Interrompi l'avanzamento della richiesta di podinfo.test durata 1,915s > 500ms
Interrompi l'avanzamento della richiesta di podinfo.test durata 2,050s > 500ms
Interrompi l'avanzamento della richiesta di podinfo.test durata 2,515s > 500ms
Rollback podinfo.test soglia di controlli falliti raggiunta 10
Canary fallito! Riduzione della scala di podinfo.test

Se hai attivato le notifiche Slack, riceverai un messaggio quando verrà superato il termine di esecuzione o il numero massimo di verifiche fallite durante l'analisi:

Distribuzioni canary automatiche con Flagger e Istio

In conclusione

L'esecuzione di un service mesh, come Istio, oltre a Kubernetes fornirà metriche automatiche, log e protocolli, ma il deployment dei carichi di lavoro dipende ancora da strumenti esterni. Flagger cerca di cambiare questa situazione, aggiungendo capacità di Istio di consegna progressiva.

Flagger è compatibile con qualsiasi soluzione CI/CD per Kubernetes, e l'analisi canary può essere facilmente estesa con webhook per eseguire test di integrazione/accettazione, test di carico o qualsiasi altra verifica personalizzata. Poiché Flagger è dichiarativo e reagisce agli eventi di Kubernetes, può essere utilizzato in pipeline GitOps insieme a Weave Flux o JenkinsX. Se utilizzi JenkinsX, puoi installare Flagger con i plugin jx.

Flagger è supportato da Weaveworks e fornisce deployment canary in Weave Cloud. Il progetto viene testato su GKE, EKS e su hardware nudo con kubeadm.

Se hai suggerimenti per migliorare Flagger, ti preghiamo di inviare una domanda o un PR su GitHub all'indirizzo stefanprodan/flagger. I contributi sono più che benvenuti!

Grazie Ray Tsan.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster