グレースケール リリース (カナリア デプロイメントとも呼ばれます) とは、トラフィック比率を制御して、古いバージョンを新しいバージョンに段階的に置き換えることを指します。たとえば、サービス A には 2 つのバージョン (青と緑) があります。現在、2つのバージョンが同時に導入されていますが、バージョン1が90%、バージョン2が10%を占めています。その後、バージョン 2 の実際の運用効果を観察できます。期待どおりであれば、トラフィックの割合を段階的に調整できます。たとえば、80:20 -> 70:30 -> 10:90 -> 0:100 に調整します。最後に、バージョン 1 はオフラインになり、バージョン 2 に置き換えられます。検証が失敗した場合は、トラフィックの 100% をバージョン 1 に戻します (ロールバック)。グレースケールリリースの特徴は次のとおりです。 フラガー Flagger、Argo Rollouts など、Istio でグレースケール リリースを実装するためのソリューションは多数あります。 フラガーFlagger は、Kubernetes 上で実行されているアプリケーションのリリース プロセスを自動化するプログレッシブ配信 Kubernetes Operator です。メトリックを測定し、適合性テストを実行しながら、トラフィックを徐々に新しいバージョンに移行することで、運用環境に新しいソフトウェア バージョンを導入するリスクを軽減します。 Flagger は、サービス メッシュ (App Mesh、Istio、Linkerd、Kuma、Open Service Mesh) または Ingress コントローラー (Contour、Gloo、NGINX、Skipper、Traefik、APISIX) を使用してトラフィック ルーティングを行うために使用されます。リリース分析の場合、Flagger は Prometheus、InfluxDB、Datadog、New Relic、CloudWatch、Stackdriver、または Graphite をクエリし、アラートに Slack、MS Teams、Discord、Rocket を使用できます。 フラガー Flagger は Kubernetes CRD を使用して構成でき、Kubernetes 用に作成されたあらゆる CI/CD ソリューションと互換性があります。 Flagger は Kubernetes イベントに宣言的に反応するため、Kubernetes などのツールと一緒に GitOps パイプラインで使用できます。 フラガーをインストールするFlagger を使用するには、まずサポートされているルーティング プロバイダー (ここでは Istio など) を選択し、次に Helm または Kustomize を使用して Flagger をインストールする必要があります。 Flagger には、Kubernetes クラスター v1.16 以上と Istio v1.5 以上が必要です。
まず、もちろん、Istio をインストールし、Prometheus プラグインを有効にする必要があります。 # demo 或者default 都可以istioctl manifest install --set profile=demo -y # istio 根目录kubectl apply -f samples/addons/prometheus.yaml 次に、istio-system 名前空間に Flagger をインストールします。 $ git clone https://github.com/fluxcd/flagger && cd flagger $ kubectl apply -k kustomize/istio $ kubectl get pods -n istio-system -l app=flagger NAME READY STATUS RESTARTS AGE flagger-ff76bfdff-kkcmz 1/1 Running 0 17m テストアプリケーション次に、test という名前空間を作成し、それに対して自動 Istio サイドカー インジェクションを有効にします。 kubectl create ns test kubectl label namespace test istio-injectinotallow=enabled 次に、flagger によって公式に提供されている podinfo アプリケーションを使用してテストします。 kubectl apply -k kustomize/podinfo このコマンドは、podinfo アプリケーションに対応するデプロイメントと HPA オブジェクトを作成します。 $ kubectl get deployment -n test NAME READY UP-TO-DATE AVAILABLE AGE podinfo 2/2 2 0 96s $ kubectl get hpa -n test NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE podinfo Deployment/podinfo <unknown>/99% 2 4 2 60s デプロイ後、podinfo アプリケーションのコンテナ数が 2 になり (istio サイドカーが自動的に挿入されます)、HPA も有効になっていることがわかります。 ```bash $ kubectl get pods -n test NAME READY STATUS RESTARTS AGE podinfo-584c4546df-fzw4d 0/2 PodInitializing 0 5m26s podinfo-584c4546df-n28cf 0/2 PodInitializing 0 5m11s 次に、カナリア分析中にトラフィックを生成するための負荷テスト サービスをデプロイします。 kubectl apply -k kustomize/tester カナリアの作成次に、カナリア リリースを実装するためのカナリア カスタム リソースを作成します。 Canary オブジェクトは Flagger の中核であり、カナリア リリースの目標を記述します。以下に示すように、podinfo アプリケーションの Canary オブジェクトを作成します。 # podinfo-canary.yaml apiVersion: flagger.app/v1beta1 kind: Canary metadata: name: podinfo namespace: test spec: targetRef: # deployment 引用apiVersion: apps/v1 kind: Deployment name: podinfo progressDeadlineSeconds: 60 # 金丝雀部署升级最大处理时间(以秒为单位)(默认600秒) autoscalerRef: # HPA 引用(可选) apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler name: podinfo service: port: 9898 targetPort: 9898 gateways: # Istio 网关(可选) - istio-system/public-gateway hosts: # VirtualService 主机名(optional) - podinfo.k8s.local trafficPolicy: # Istio 流量策略(可选) tls: # use ISTIO_MUTUAL when mTLS is enabled mode: DISABLE retries: # Istio 重试策略(可选) attempts: 3 perTryTimeout: 1s retryOn: "gateway-error,connect-failure,refused-stream" analysis: # 金丝雀分析interval: 1m # 金丝雀分析间隔时间(默认60s) threshold: 5 # 金丝雀分析失败阈值(默认5) maxWeight: 50 # 金丝雀最大流量权重(默认50) stepWeight: 10 # 金丝雀流量权重步长(默认10) metrics: - name: request-success-rate # minimum req success rate (non 5xx responses) # percentage (0-100) thresholdRange: min: 99 interval: 1m - name: request-duration # maximum req duration P99 # milliseconds thresholdRange: max: 500 interval: 30s # testing (optional) webhooks: - name: acceptance-test type: pre-rollout url: http://flagger-loadtester.test/ timeout: 30s metadata: type: bash cmd: "curl -sd 'test' http://podinfo-canary:9898/token | grep token" - name: load-test url: http://flagger-loadtester.test/ timeout: 5s metadata: # 使用hey 工具对podinfo-canary 进行为期1分钟的负载测试,每秒发送10个请求,且测试过程中会维持2个并发连接。 cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/" 上記の構成ファイルでは、podinfo アプリケーションのカナリア リリース戦略を定義します。 targetRef はカナリアリリースのデプロイメントオブジェクトを指定し、service はカナリアリリースのサービスを指定し、analysis はカナリア分析戦略を指定します。ここでは、request-success-rate と request-duration という 2 つの組み込みインジケーター チェックを指定します。 request-success-rate は HTTP リクエストの成功率を指定し、request-duration はリクエストの期間を指定します。各メトリックに対して、thresholdRange とウィンドウ サイズまたは時系列を使用して、許容可能な値の範囲と時間間隔を指定できます。組み込みチェックは各サービス メッシュ/Ingress コントローラーで使用でき、Prometheus クエリを介して実装されます。 サービスでは、VirtualService が使用する Istio Gateway (istio-system/public-gateway) とホスト名を指定します。まず、アプリケーションの Gateway オブジェクトを作成します。 # public-gateway.yaml 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: - "*" さらに、上記のオブジェクトの webhooks フィールドを通じて、カナリア分析中に実行されるテストを指定します。ここで、acceptance-test はカナリア分析の開始前に実行するために使用され、load-test はカナリア分析中に実行されるために使用されます。 カナリアデプロイメント 次に、Canary オブジェクトを直接作成します。 kubectl apply -f podinfo-canary.yaml Canary オブジェクトが作成されると、Flagger は pod-info-primary という名前の Deployment と 2 つのバージョンの Service オブジェクトを自動的に作成します。 $ kubectl get deploy -n test NAME READY UP-TO-DATE AVAILABLE AGE flagger-loadtester 1/1 1 1 42m podinfo 0/0 0 0 46m podinfo-primary 2/2 2 2 7m3s $ kubectl get svc -ntest NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE flagger-loadtester ClusterIP 10.106.172.190 <none> 80/TCP 35m podinfo-canary ClusterIP 10.101.184.213 <none> 9898/TCP 39s podinfo-primary ClusterIP 10.110.105.36 <none> 9898/TCP 39s 元の podinfo アプリケーションが podinfo デプロイメントから podinfo-primary デプロイメントに移行されていることがわかります。 さらに、Istio 関連のオブジェクトもあります。 $ kubectl get vs -ntest NAME GATEWAYS HOSTS AGE podinfo ["istio-system/public-gateway"] ["podinfo.k8s.local","podinfo"] 91s $ kubectl get dr -ntest NAME HOST AGE podinfo-canary podinfo-canary 95s podinfo-primary podinfo-primary 95s 自動的に生成された VirtualService オブジェクトを表示できます。 $ kubectl get vs -ntest podinfo -oyaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: podinfo namespace: test spec: gateways: - istio-system/public-gateway hosts: - podinfo.k8s.local - podinfo http: - retries: attempts: 3 perTryTimeout: 1s retryOn: gateway-error,connect-failure,refused-stream route: - destination: host: podinfo-primary weight: 100 - destination: host: podinfo-canary weight: 0 上記の構成から、現在の podinfo アプリケーションのすべてのトラフィックが podinfo-primary オブジェクトにルーティングされ、podinfo-canary オブジェクトのトラフィックの重みが 0 であることがわかります。もちろん、DestinationRule オブジェクトを表示することもできます。 $ kubectl get dr podinfo-primary -ntest -oyaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: podinfo-primary namespace: test spec: host: podinfo-primary trafficPolicy: tls: mode: DISABLE $ kubectl get dr podinfo-canary -ntest -oyaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: podinfo-canary namespace: test spec: host: podinfo-canary trafficPolicy: tls: mode: DISABLE したがって、デフォルトでは、現在のデフォルト バージョンである Deployment オブジェクト podinfo-primary にアクセスするようになりました。ブラウザで podinfo にアクセスすると、現在のバージョンを表示できます。 ポッドインフォ 自動カナリアリリース現在のバージョンは podinfo v6.0.0 であることがわかります。次に、アプリケーションをアップグレードして、カナリア リリースをトリガーします。カナリア リリースをトリガーするには、次のいずれかのオブジェクトに変更を加えることによってトリガーできます。 - デプロイメント PodSpec (コンテナ イメージ、コマンド、ポート、環境変数、リソースなど)
- ボリュームとしてマウントされた、または環境変数にマップされたConfigMap
- シークレットはボリュームとしてマウントされるか、環境変数にマップされます
たとえば、Deployment オブジェクトのイメージ バージョンを直接変更して、自動カナリア リリースをトリガーできます。 kubectl -n test set image deployment/podinfo podinfod=ghcr.io/stefanprodan/podinfo:6.0.1 Flagger がデプロイメントの変更を検出すると、新しいデプロイメントが開始されます。 $ kubectl describe canaries podinfo -ntest # ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Synced 15m flagger podinfo-primary.test not ready: waiting for rollout to finish: observed deployment generation less than desired generation Normal Synced 14m (x2 over 15m) flagger all the metrics providers are available! Normal Synced 14m flagger Initialization done! podinfo.test Normal Synced 56s flagger New revision detected! Scaling up podinfo.test カナリア分析中にデプロイメントに新しい変更を適用すると、Flagger によって分析が再開されることに注意してください。最初のステップは、podinfo アプリケーションを展開することです。 $ kubectl get pods -ntest NAME READY STATUS RESTARTS AGE flagger-loadtester-78dd9787d4-dq5fc 2/2 Running 0 67m podinfo-5d5dbc4d84-f2mp6 2/2 Running 0 31s podinfo-5d5dbc4d84-gd8ln 2/2 Running 0 31s podinfo-primary-64f865cf4-bhr79 2/2 Running 0 3m31s podinfo-primary-64f865cf4-tgsdj 2/2 Running 0 3m31s 次に、Canary オブジェクトで定義したカナリア分析戦略に従って分析し、段階的にカナリア バージョンの重みを増やしていきます。 Warning Synced 4m4s flagger podinfo-primary.test not ready: waiting for rollout to finish: observed deployment generation less than desired generation Normal Synced 3m4s (x2 over 4m4s) flagger all the metrics providers are available! Normal Synced 3m4s flagger Initialization done! podinfo.test Normal Synced 64s flagger New revision detected! Scaling up podinfo.test Normal Synced 4s flagger Starting canary analysis for podinfo.test Normal Synced 4s flagger Pre-rollout check acceptance-test passed Normal Synced 4s flagger Advance podinfo.test canary weight 10 最後に、すべてのトラフィックが自動的にカナリア バージョンに切り替わります。 カナリア版 全体のプロセスは、VirtualService の重みを制御することでカナリア リリースを実現することです。 自動ロールバックカナリア分析中に、HTTP 500 エラーと高レイテンシを生成して、Flagger が公開を一時停止するかどうかをテストできます。 たとえば、別のカナリアリリースをトリガーします。 kubectl -n test set image deployment/podinfo podinfod=ghcr.io/stefanprodan/podinfo:6.0.2 次に、ロードテスター コンテナーに入ります。 kubectl -n test exec -it flagger-loadtester-xx-xx sh HTTP 500 エラーを生成するには、次のコマンドを使用します。 watch curl http://podinfo-canary:9898/status/500 遅延を追加することも可能です: watch curl http://podinfo-canary:9898/delay/1 失敗したチェックの数がカナリア分析で設定されたしきい値に達すると、トラフィックはプライマリ ノードにルーティングされ、カナリアはゼロにスケーリングされ、デプロイメントは失敗としてマークされます。 Normal Synced 8m10s (x3 over 45m) flagger New revision detected! Scaling up podinfo.test Normal Synced 7m10s (x2 over 44m) flagger Pre-rollout check acceptance-test passed Normal Synced 7m10s (x2 over 44m) flagger Advance podinfo.test canary weight 10 Normal Synced 7m10s (x2 over 44m) flagger Starting canary analysis for podinfo.test Warning Synced 6m10s flagger Halt podinfo.test advancement success rate 55.86% < 99% Warning Synced 5m10s flagger Halt podinfo.test advancement success rate 97.61% < 99% Warning Synced 4m10s flagger Halt podinfo.test advancement success rate 8.00% < 99% Warning Synced 3m10s flagger Halt podinfo.test advancement success rate 98.13% < 99% Warning Synced 2m10s flagger Halt podinfo.test advancement success rate 7.69% < 99% Warning Synced 70s (x2 over 14m) flagger Canary failed! Scaling down podinfo.test Warning Synced 70s flagger Rolling back podinfo.test failed checks threshold reached 5 Flagger の詳細については、以降の記事を参照してください。 |