FlaggerおよびIstioを使用したカナリアの自動展開







CDはエンタープライズソフトウェア開発プラクティスとして認識されており、確立されたCI原則の自然な進化の結果です。 ただし、おそらく管理の難しさと、システムの可用性に影響を与える展開の失敗の恐れがあるため、CDは依然としてかなりまれにしか発生しません。







Flaggerは、混乱を招く関係を排除することを目的としたオープンソースのKubernetesオペレーターです。 IstioのトラフィックバイアスとPrometheusメトリックを使用してカナリア展開のプロモーションを自動化し、管理されたロールアウト中のアプリケーションの動作を分析します。







以下は、Google Kubernetes Engine(GKE)でFlaggerを構成および使用する方法のステップバイステップガイドです。







Kubernetesクラスターを構成する



Istioアドインを使用してGKEクラスターを作成することから始めます(GCPアカウントを持っていない場合は、 ここで登録て無料のクレジットを受け取ることができます)。







Google Cloudにログインしてプロジェクトを作成し、その請求を有効にします。 gcloudコマンドラインユーティリティをインストールし、 gcloud gcloud init



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
      
      





上記のコマンドは、2つのn1-standard-2



VM(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
      
      





kube-system



Tillerを展開しkube-system









 helm init --service-account tiller
      
      





HelmとTillerの間でSSLの使用を検討する必要があります。 Helmインストールの保護の詳細については、 docs.helm.shを参照してください







設定を確認します。







 kubectl -n istio-system get svc
      
      





数秒後、GCPはistio-ingressgateway



外部IPアドレスを割り当てる必要がありistio-ingressgateway









Istio入力ゲートウェイのセットアップ



istio-gateway



のIPアドレスを使用して、 istio-gateway



という静的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
      
      





ここで、インターネットドメインとDNSレジストラへのアクセスが必要です。 2つのAエントリを追加します( example.com



をドメインに置き換え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なしでインターネット上でサービスを提供するべきではありません。 Istioゲートウェイをcert-manager、CloudDNS、およびLet's Encryptで保護するには、Flagger GKEのドキュメントをご覧ください。







フラッガーのインストール



GKE Istioアドインには、IstioテレメトリサービスをクリーンアップするPrometheusインスタンスは含まれていません。 FlaggerはIstio HTTPメトリックを使用してカナリア分析を実行するため、公式のIstio Helmスキームで提供されるものと同様の次のPrometheus構成を展開する必要があります。







 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
      
      





Slack通知を有効にして、istio istio-system



Flaggerを展開しistio-system









 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ダッシュボードがあります。 istio-system



をインストールし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



をドメインに置き換え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仮想サービス)を作成します。 これらのオブジェクトは、アプリケーションをサービスメッシュで開き、カナリア分析とプロモーションを管理します。













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
      
      





カナリア分析中にトラフィックを生成するテストロードサービスを展開します。







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





カスタムカナリアリソースを作成します( example.com



をドメインに置き換え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
      
      





上記の分析が成功した場合、5分以内に実行され、30分ごとにHTTPメトリックがチェックされます。 interval * (maxWeight / stepWeight)



式を使用して、カナリアデプロイメントの検証と昇格に必要な最小時間を決定できます。 カナリア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リクエストの成功率、リクエストの平均期間、囲炉裏のパフォーマンスなどの主要なパフォーマンスインジケータを測定しながら、トラフィックを徐々にカナリアに移動する制御ループを実装します。 分析に基づいて、KPIカナリアが進行または中断され、分析結果がSlackに公開されます。













次のオブジェクトのいずれかが変更されると、カナリアの展開が開始されます。









コンテナイメージの更新時にカナリアデプロイメントを起動する:







 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は分析フェーズを再開します。







クラスター内のすべての「カナリア」のリストを作成します。







 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通知を有効にしている場合、次のメッセージが表示されます。













自動ロールバック



カナリア分析中に、合成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
      
      





失敗したチェックの数がしきい値に達すると、トラフィックはプライマリチャネルにルーティングされ、カナリアはゼロにスケーリングされ、展開は失敗としてマークされます。







カナリアエラーと遅延ピークは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通知を有効にしている場合は、期限に達したとき、または分析中に失敗したチェックの最大数に達したときにメッセージを受け取ります。













結論として



Kubernetesに加えてIstioなどのサービスメッシュを起動すると、自動メトリックス、ログ、およびプロトコルが提供されますが、ワークロードの展開は依然として外部ツールに依存しています。 Flaggerは、Istioのプログレッシブ配信機能を追加することでこれを変更しようとしています。







FlaggerはKubernetes CI / CDソリューションと互換性があり、 webhookを使用してカナリア分析を簡単に拡張して、システム統合/受け入れテスト、ストレステスト、またはその他のユーザーテストを実行できます。 Flaggerは宣言的でKubernetesイベントに応答するため、 Weave FluxまたはJenkinsXを備えたGitOpsパイプラインで使用できます。 JenkinsXを使用している場合、jxアドオンでFlaggerをインストールできます。







FlaggerはWeaveworksによってサポートされておりWeave Cloudへのカナリア展開を提供します。 このプロジェクトは、kubeadmを使用してGKE、EX、およびベアメタルでテストされています。







Flaggerを改善するための提案がある場合は、 stefanprodan / flaggerの GitHubに質問またはPRを送信してください。 寄付は大歓迎です!







Ray Tsangに感謝します。








All Articles