使用 Flagger 和 Istio 進行自動金絲雀部署

使用 Flagger 和 Istio 進行自動金絲雀部署

CD 被認為是一種企業軟件實踐,是既定 CI 原則自然演變的結果。 然而,CD 仍然很少見,這可能是由於管理的複雜性以及擔心部署失敗會影響系統可用性。

旗手 是一個開源的 Kubernetes 操作符,旨在消除混淆關係。 它使用 Istio 流量偏移和 Prometheus 指標自動促進金絲雀部署,以分析託管部署期間的應用程序行為。

以下是在 Google Kubernetes Engine (GKE) 上設置和使用 Flagger 的分步指南。

設置 Kubernetes 集群

您首先使用 Istio 附加組件創建一個 GKE 集群(如果您沒有 GCP 帳戶,您可以註冊 這裡 - 獲得免費學分)。

登錄 Google Cloud,創建項目,並為其啟用計費。 安裝命令行實用程序 並設置您的項目 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 Pod。 Istio 清單被認為是只讀的,GKE 將撤消任何更改,例如鍊接到節點或從 pod 分離。

設置憑據 kubectl:

gcloud container clusters get-credentials istio

創建集群管理員角色綁定:

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

安裝命令行工具 :

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

您應該考慮在 Helm 和 Tiller 之間使用 SSL。 有關保護 Helm 安裝的更多信息,請參閱 文檔.helm.sh

確認設置:

kubectl -n istio-system get svc

幾秒鐘後,GCP 應該為該服務分配一個外部 IP 地址 istio-ingressgateway.

配置 Istio 入口網關

使用名稱創建靜態 IP 地址 istio-gateway使用 Istio 網關的 IP 地址:

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

現在您需要一個 Internet 域並訪問您的 DNS 註冊商。 添加兩條A記錄(替換 example.com 到您的域):

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

驗證 DNS 通配符是否正常工作:

watch host test.istio.example.com

創建一個通用 Istio 網關以通過 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 的情況下在 Internet 上提供服務。 要使用證書管理器、CloudDNS 和 Let's Encrypt 保護 Istio 入口網關,請閱讀 文件 弗拉格 G.K.E.

標記器安裝

GKE Istio 附加組件不包含清理 Istio 遙測服務的 Prometheus 實例。 因為 Flagger 使用 Istio HTTP 指標來執行金絲雀分析,所以您需要部署以下 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,只要它可以與端口 9090 上的 Istio Prometheus 服務通信即可。

Flagger 有一個用於金絲雀分析的 Grafana 儀表板。 在命名空間中安裝 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

通過創建虛擬服務(替換 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 部署 Web 應用程序

Flagger 部署 Kubernetes 並可選擇自動橫向擴展 (HPA),然後創建一系列對象(Kubernetes 部署、ClusterIP 服務和 Istio 虛擬服務)。 這些對象將應用程序暴露給服務網格並控制金絲雀分析和進度。

使用 Flagger 和 Istio 進行自動金絲雀部署

創建啟用 Istio Sidecar 注入的測試命名空間:

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

創建 deployment 和 pod 自動擴容工具:

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

部署測試負載服務以在金絲雀分析期間生成流量:

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

創建自定義金絲雀資源(替換 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 指標。 您可以使用以下公式確定驗證和推廣金絲雀部署所需的最短時間: interval * (maxWeight / stepWeight). 記錄了 Canary CRD 字段 這裡.

幾秒鐘後,Flagger 將創建金絲雀對象:

# 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, 你應該看到版本號 演示應用.

自動金絲雀分析和推廣

Flagger 實現了一個控制循環,逐漸將流量轉移到金絲雀,同時測量關鍵性能指標,例如 HTTP 請求成功率、平均請求持續時間和 pod 健康狀況。 根據KPI分析,推進或中斷金絲雀,並將分析結果發佈到Slack。

使用 Flagger 和 Istio 進行自動金絲雀部署

當以下對象之一發生更改時,會觸發金絲雀部署:

  • 部署 PodSpec(容器鏡像、命令、端口、環境等)
  • ConfigMap 掛載為卷或映射到環境變量
  • 秘密作為卷安裝或轉換為環境變量

更新容器鏡像時運行 canary deploy:

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

在分析期間,可以使用 Grafana 跟踪金絲雀結果:

使用 Flagger 和 Istio 進行自動金絲雀部署

請注意,如果在金絲雀分析期間將新更改應用於部署,則 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 通知,您將收到以下消息:

使用 Flagger 和 Istio 進行自動金絲雀部署

自動回滾

在 Canary 分析期間,您可以生成合成 HTTP 500 錯誤和高響應延遲,以查看 Flagger 是否會停止部署。

創建一個測試 pod 並在其中執行以下操作:

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 錯誤和延遲峰值被記錄為 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 通知,當超過截止日期或達到分析中失敗檢查的最大數量時,您將收到一條消息:

使用 Flagger 和 Istio 進行自動金絲雀部署

總之

除了 Kubernetes 之外,運行像 Istio 這樣的服務網格將提供自動指標、日誌和協議,但工作負載部署仍然依賴於外部工具。 Flagger 旨在通過添加 Istio 功能來改變這一點 漸進式交付.

Flagger 與任何 Kubernetes CI/CD 解決方案兼容,並且可以輕鬆擴展金絲雀分析 網絡鉤子 執行系統集成/驗收測試、負載測試或任何其他自定義檢查。 由於 Flagger 是聲明式的並且響應 Kubernetes 事件,它可以與 GitOps 管道一起使用 編織助焊劑詹金斯X. 如果您使用的是 JenkinsX,則可以使用 jx 插件安裝 Flagger。

支持旗手 編織作品 並提供金絲雀部署 織雲. 該項目正在使用 kubeadm 在 GKE、EKS 和裸機上進行測試。

如果您有改進 Flagger 的建議,請在 GitHub 上提交問題或 PR stefanprodan/舉報人. 我們非常歡迎您的貢獻!

謝謝 曾雷.

來源: www.habr.com

添加評論