Automatyczne wdrożenia canary z Flagger i Istio

Automatyczne wdrożenia canary z Flagger i Istio

CD zostało uznane za praktykę korporacyjnego oprogramowania, będąc wynikiem naturalnej ewolucji ustalonych zasad CI. Niemniej jednak CD wciąż jest dość rzadkim zjawiskiem, być może z powodu trudności w zarządzaniu oraz strachu przed nieudanymi wdrożeniami, które wpływają na dostępność systemu.

Flagger jest operatorem Kubernetes o otwartym kodzie źródłowym, którego celem jest eliminacja skomplikowanych interakcji. Automatyzuje on promowanie wdrożeń canary, wykorzystując rozkład ruchu Istio oraz metryki Prometheus do analizy zachowania aplikacji podczas kontrolowanego wdrażania.

Poniżej znajduje się krok po kroku przewodnik po konfiguracji i używaniu Flagger w Google Kubernetes Engine (GKE).

Konfiguracja klastra Kubernetes

Zaczynasz od utworzenia klastra GKE z rozszerzeniem Istio (jeśli nie masz konta GCP, możesz się zarejestrować tutaj aby otrzymać darmowe kredyty).

Zaloguj się do Google Cloud, utwórz projekt i włącz dla niego fakturowanie. Zainstaluj narzędzie wiersza poleceń gcloud i skonfiguruj swój projekt używając gcloud init.

Ustaw projekt domyślny, region obliczeń i strefę (zastąp PROJECT_ID swoim projektem):

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

Włącz usługę GKE i utwórz klaster z HPA i rozszerzeniami 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

Podana powyżej komenda stworzy domyślny pul nadziwia, który zawiera dwie VM n1-standard-2 (vCPU: 2, RAM 7,5 GB, dysk: 30 GB). Idealnie byłoby izolować komponenty Istio od swoich obciążeń roboczych, jednak nie ma prostego sposobu na uruchomienie podów Istio w dedykowanym pul nadziwia. Manifesty Istio są traktowane jako dostępne tylko do odczytu, a GKE będzie anulować wszelkie zmiany, jak np. przywiązywanie do węzła czy odpinanie od podu.

Skonfiguruj dane uwierzytelniające dla kubectl:

gcloud container clusters get-credentials istio

Utwórz powiązanie roli administratora klastra:

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

Zainstaluj narzędzie wiersza poleceń Helm:

brew install kubernetes-helm

Homebrew 2.0 jest teraz również dostępny dla Linuxa.

Utwórz konto usługi i powiązanie roli klastra dla Tiller:

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

Wdróż Tiller w namespace kube-system:

helm init --service-account tiller

Powinieneś rozważyć użycie SSL między Helm a Tiller. Aby uzyskać więcej informacji na temat zabezpieczenia instalacji Helm, zobacz docs.helm.sh

Potwierdź ustawienia:

kubectl -n istio-system get svc

Po kilku sekundach GCP powinien przypisać zewnętrzny adres IP do usługi istio-ingressgateway.

Konfiguracja bramy wejściowej Istio

Utwórz statyczny adres IP o nazwie istio-gateway, używając adresu IP bramy 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

Teraz potrzebujesz domeny internetowej i dostępu do swojego rejestratora DNS. Dodaj dwie wpisy A (zastąp example.com swoją domeną):

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

Upewnij się, że wildcard DNS działa:

watch host test.istio.example.com

Utwórz ogólną bramę Istio, aby udostępniać usługi poza siecią usługową przez 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:
        - "*"

Zachowaj powyższy zasób jako public-gateway.yaml, a następnie zastosuj go:

kubectl apply -f ./public-gateway.yaml

Żaden system produkcyjny nie powinien udostępniać usług w Internecie bez SSL. Aby zabezpieczyć bramę wejściową Istio za pomocą cert-managera, CloudDNS i Let’s Encrypt, przeczytaj proszę dokumentację Flagger GKE.

Instalacja Flagger

Nakładka GKE Istio nie obejmuje instancji Prometheus, która zajmuje się zbieraniem telemetrii Istio. Ponieważ Flagger wykorzystuje metryki HTTP Istio do przeprowadzania analizy canary, musisz wdrożyć następującą konfigurację Prometheus, podobną do tej, która jest dostarczana z oficjalnym schematem Istio Helm.

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

Dodaj repozytorium Flagger Helm:

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

Wdróż Flagger w namespace istio-system, włączając powiadomienia 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

Możesz zainstalować Flagger w dowolnym namespace, o ile może wchodzić w interakcję z usługą Istio Prometheus przez port 9090.

Flagger ma pulpit nawigacyjny Grafana do analizy canary. Zainstaluj Grafana w 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

Otwórz Grafanę przez publiczny bramkę, tworząc usługi wirtualne (zastąp example.com twoją domeną):

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

Zapisz powyższy zasób jako grafana-virtual-service.yaml, a następnie go zastosuj:

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

Przechodząc do http://grafana.istio.example.com w przeglądarce powinieneś zostać przekierowany na stronę logowania do Grafany.

Rozpocznij wdrażanie aplikacji webowych z Flagger

Flagger wdraża Kubernetes i, w razie potrzeby, automatyczne skalowanie poziome (HPA), a następnie tworzy szereg obiektów (wdrożenia Kubernetes, usługi ClusterIP i wirtualne usługi Istio). Te obiekty odsłaniają aplikację w service mesh i zarządzają analizą i promowaniem canary.

Automatyczne wdrożenia canary z Flagger i Istio

Utwórz testową przestrzeń nazw z włączonym wprowadzeniem Istio Sidecar:

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

Utwórz wdrożenie i narzędzie automatyzujące poziome skalowanie podów:

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

Rozpocznij usługę testową do generowania ruchu podczas analizy canary:

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

Utwórz zasób canary dla użytkownika (zastąp example.com swoją domeną):

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

Zapisz powyższy zasób jako podinfo-canary.yaml, a następnie go zastosuj:

kubectl apply -f ./podinfo-canary.yaml

Powyższa analiza, w przypadku sukcesu, będzie trwała przez pięć minut z kontrolą metryk HTTP co pół minuty. Możesz określić minimalny czas potrzebny do sprawdzenia i promowania wdrożenia canary, stosując następujący wzór: interval * (maxWeight / stepWeight). Pola CRD canary są dokumentowane tutaj.

Po kilku sekundach Flagger utworzy obiekty 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

Otwórz przeglądarkę i przejdź do app.istio.example.com, powinieneś zobaczyć numer wersji aplikacji demonstracyjnej.

Automatyczna analiza canary i wdrażanie

Flagger realizuje cykl zarządzania, który stopniowo przenosi ruch na canary, jednocześnie mierząc kluczowe wskaźniki wydajności, takie jak wskaźnik udanych żądań HTTP, średni czas trwania żądań i dostępność poda. Na podstawie analizy KPI canary jest promowany lub przerwany, a wyniki analizy publikowane są w Slack.

Automatyczne wdrożenia canary z Flagger i Istio

Wdrażanie canary zaczyna się po zmianie jednego z poniższych obiektów:

  • Wdrażanie PodSpec (obraz kontenera, polecenie, porty, env itd.)
  • ConfigMaps montowane jako wolumeny lub przekształcane w zmienne środowiskowe
  • Sekrety montowane jako wolumeny lub przekształcane w zmienne środowiskowe

Rozpoczęcie wdrażania canary po aktualizacji obrazu kontenera:

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

Flagger wykrywa, że wersja wdrożenia się zmieniła i zaczyna ją analizować:

kubectl -n test describe canary/podinfo

Zdarzenia:

Nowa wersja wykryta podinfo.test
Skalowanie w górę podinfo.test
Czekam na zakończenie wdrażania podinfo.test: 0 z 1 zaktualizowanych replik dostępnych
Rozwój wagi canary podinfo.test 5
Rozwój wagi canary podinfo.test 10
Rozwój wagi canary podinfo.test 15
Rozwój wagi canary podinfo.test 20
Rozwój wagi canary podinfo.test 25
Rozwój wagi canary podinfo.test 30
Rozwój wagi canary podinfo.test 35
Rozwój wagi canary podinfo.test 40
Rozwój wagi canary podinfo.test 45
Rozwój wagi canary podinfo.test 50
Kopiowanie specyfikacji szablonu podinfo.test do podinfo-primary.test
Czekam na zakończenie wdrażania podinfo-primary.test: 1 z 2 zaktualizowanych replik dostępnych
Promocja zakończona! Skalowanie w dół podinfo.test

Podczas analizy wyniki canary można śledzić za pomocą Grafana:

Automatyczne wdrożenia canary z Flagger i Istio

Uwaga: jeśli nowe zmiany zostaną zastosowane do wdrożenia podczas analizy canary, Flagger zrestartuje fazę analizy.

Sporządź listę wszystkich "canary" w swoim klastrze:

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

Jeśli włączyłeś powiadomienia Slack, otrzymasz następujące wiadomości:

Automatyczne wdrożenia canary z Flagger i Istio

Automatyczny rollback

Podczas analizy canary można generować syntetyczne błędy HTTP 500 i wysoką latencję, aby sprawdzić, czy Flagger nie zatrzyma wdrożenia.

Utwórz testowy pod i wykonaj w nim następujące działanie:

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

Generowanie błędów HTTP 500:

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

Generowanie latencji:

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

Gdy liczba nieudanych kontroli osiągnie próg, ruch jest kierowany z powrotem do głównego kanału, canary jest skalowane do zera, a wdrożenie oznaczane jest jako nieudane.

Błędy canary i szczyty opóźnień są rejestrowane jako zdarzenia Kubernetes i zapisywane przez Flagger w formacie JSON:

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

Rozpoczęcie wdrożenia canary dla podinfo.test
Zwiększanie wagi canary podinfo.test do 5
Zwiększanie wagi canary podinfo.test do 10
Zwiększanie wagi canary podinfo.test do 15
Zatrzymanie postępu podinfo.test wskaźnik sukcesu 69,17% < 99%
Zatrzymanie postępu podinfo.test wskaźnik sukcesu 61,39% < 99%
Zatrzymanie postępu podinfo.test wskaźnik sukcesu 55,06% < 99%
Zatrzymanie postępu podinfo.test wskaźnik sukcesu 47,00% < 99%
Zatrzymanie postępu podinfo.test wskaźnik sukcesu 37,00%  500ms
Zatrzymanie postępu podinfo.test czas realizacji żądania 1,600s > 500ms
Zatrzymanie postępu podinfo.test czas realizacji żądania 1,915s > 500ms
Zatrzymanie postępu podinfo.test czas realizacji żądania 2,050s > 500ms
Zatrzymanie postępu podinfo.test czas realizacji żądania 2,515s > 500ms
Wycofanie podinfo.test osiągnięto próg nieudanych kontroli 10
Canary nie powiodło się! Zmniejszenie skali podinfo.test

Jeśli włączyłeś powiadomienia Slack, otrzymasz wiadomość, gdy zostanie przekroczony limit czasu lub osiągnięta maksymalna liczba nieudanych kontroli podczas analizy:

Automatyczne wdrożenia canary z Flagger i Istio

Na zakończenie

Uruchomienie service mesh, takiego jak Istio, oprócz Kubernetes, zapewni automatyczne metryki, logi i protokoły, ale wdrożenie obciążeń roboczych nadal zależy od zewnętrznych narzędzi. Flagger dąży do zmiany tej sytuacji, dodając możliwości Istio progresywnej dostawy.

Flagger jest kompatybilny z dowolnymi rozwiązaniami CI/CD dla Kubernetes, a analizę canary można łatwo rozszerzyć za pomocą webhooków do wykonywania testów integracyjnych/akceptacyjnych, testów obciążeniowych lub innych niestandardowych kontroli. Ponieważ Flagger jest deklaratywny i reaguje na zdarzenia Kubernetes, można go używać w potokach GitOps razem z Weave Flux lub JenkinsX. Jeśli używasz JenkinsX, możesz zainstalować Flagger jako rozszerzenia jx.

Flagger jest wspierany przez Weaveworks i zapewnia wdrożenia canary w Weave Cloud. Projekt jest testowany na GKE, EKS i „gołym metalu” z kubeadm.

Jeśli masz propozycje dotyczące ulepszenia Flaggera, prosimy o przesłanie pytania lub PR na GitHubie pod adresem stefanprodan/flagger. Wkłady są mile widziane!

Dziękuję Rey Chan.

Źródło: habr.com

Kup niezawodny hosting stron z ochroną DDoS, serwery VPS VDS 🔥 Kup niezawodny hosting stron z ochroną DDoS, serwery VPS VDS - ProHoster