著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

序章

Kubernetesでホストされているリソースの更新は、ほぼ即座に伝播されるようにスケジュールされています。 Kubernetesはクラスターの状態を監視し、必要に応じてコンテナーを再起動できますが、不良またはバグのあるコンテナーを処理するための戦略は含まれていません。 つまり、新しいコンテナリリースが適用されて予期しない動作が開始された場合、Kubernetesは、以前のバージョンへのロールバックを開始したり、伝播を完全に停止したりしても、状況を適切に解決できません。

Flagger は、Kubernetesのプログレッシブ配信オペレーターであり、構成されたメトリックを監視しながらトラフィックを新しいリリースに徐々にシフトすることで、概説された問題を解決します。 新しいリリースで自動分析とテストを実行し、クラスター全体に伝播するか、問題が見つかった場合に停止するかを決定できます。 Flaggerは、古いリリースを利用可能な状態に保ちながら、新しいリリースの負荷をゆっくりと増やし、ダウンタイムを最小限に抑えます。 Slack、Microsoft Teams、およびその他のプラットフォームに通知を送信して、発生したイベントをユーザーとチームに通知できます。

このチュートリアルでは、Flaggerをインストールし、それを使用して、DigitalOceanKubernetesクラスターへのpodinfoアプリのプログレッシブ配信を設定します。 podinfo は、実行中の環境に関する詳細を提供するWebアプリです。 デプロイされたリソースを監視し、新しいリリースを自動的にテストし、Webhookを使用してSlackで通知するようにFlaggerを設定します。 最終的に、クラスターデプロイメントを使用できない状態のままにすることなく、要求された変更に問題があるかどうかがすぐに通知されます。

前提条件

このチュートリアルを開始する前に、次のものが必要です。

  • DigitalOcean Kubernetesクラスター、バージョン1.19以降、接続構成が kubectl デフォルト。 設定方法の説明 kubectl は、クラスターの作成時に表示されるクラスターへの接続ステップの下に表示されます。 DigitalOceanでKubernetesクラスタを作成する方法については、 KubernetesQuickstartをご覧ください。

  • ローカルマシンにインストールされているHelmパッケージマネージャー。 これを行うには、Helm3パッケージマネージャーを使用してKubernetesクラスターにソフトウェアをインストールする方法チュートリアルのステップ1を完了します。

  • クラスターにインストールされているNginxIngressControllerとCert-Manager。 これを行う方法のガイドについては、Helmを使用してDigitalOceanKubernetesでNginxIngressを設定する方法を参照してください。

  • メンバーになっているSlackワークスペース。 ワークスペースの作成方法については、公式ドキュメントにアクセスしてください。

  • Ingressが使用するDigitalOceanロードバランサーを指すDNSAレコードを持つドメイン名。 DigitalOceanを使用してドメインのDNSレコードを管理している場合は、DNSレコードの管理方法を参照してAレコードを作成してください。 このチュートリアルでは、Aレコードを次のように参照します。 app.your_domain.

    注:このチュートリアルで使用するドメイン名は、 DigitalOceanKubernetes前提条件チュートリアルでNginxIngressを設定する方法で使用するドメイン名とは異なる必要があります。

ステップ1—FlaggerのインストールとNginxIngressControllerの構成

このセクションでは、Helmを使用してFlaggerをクラスターにインストールします。 また、Nginx Ingress Controllerを構成して、内部メトリックを他のアプリケーションからアクセスできるようにします。Flaggerは、パフォーマンスに応じて、新しいリリースを許可するか拒否するかを決定するために使用します。

まず、次のコマンドを実行して、Flaggerを含むリポジトリをHelmに追加する必要があります。

  1. helm repo add flagger https://flagger.app

出力は次のようになります。

Output
"flagger" has been added to your repositories

Helmを更新して、Helmに何が含まれているかを知らせます。

  1. helm repo update

次に、次のコマンドを実行してFlaggerをインストールします。

  1. helm install flagger flagger/flagger \
  2. --set prometheus.install=true \
  3. --set meshProvider=nginx

このコマンドは、追加したチャートリポジトリからFlaggerをインストールし、Helmリリースに名前を付けます。 flagger. Webアプリを監視するため、 flagger リリースはNginxIngressコントローラーに関連付けられます。

出力は次のようになり、Flaggerがデプロイされていることを詳しく説明します。

Output
NAME: flagger LAST DEPLOYED: ... NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Flagger installed

Nginx Ingress Controllerの指標を公開するには、すでに定義されている変数を保持したまま、Helmリリース内に追加の変数を設定する必要があります。 あなたは実行することによってそうすることができます helm upgrade と渡す --reuse-values 新しい変数値とともに、パラメータ:

  1. helm upgrade nginx-ingress ingress-nginx/ingress-nginx \
  2. --reuse-values \
  3. --set controller.metrics.enabled=true \
  4. --set controller.podAnnotations."prometheus\.io/scrape"=true \
  5. --set controller.podAnnotations."prometheus\.io/port"=10254

このコマンドは、 nginx-ingress Helmをリリースし、コントローラーとそのポッドでPrometheusメトリック収集を有効にします。

出力は次のようになります。

Output
Release "nginx-ingress" has been upgraded. Happy Helming! NAME: nginx-ingress LAST DEPLOYED: ... NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None NOTES: The ingress-nginx controller has been installed. ...

リビジョン番号は現在 2、アップグレードが行われたことを示します。

このセクションでは、Flaggerをインストールし、内部メトリックを公開するようにNginxIngressControllerを構成しました。 次のステップでは、アプリをデプロイし、そのリリースを制御するようにFlaggerを設定します。

ステップ2—アプリをデプロイする

次に、をデプロイします podinfo Webアプリを作成し、カナリアリソースを作成してリリースを制御します。 カナリアリソースはFlaggerから提供されており、新しいリリースを適用または拒否する前に、どのように、いつ、どのくらいの期間テストするかを示しています。 また、古いリリースから新しいリリースにトラフィックを徐々に迂回させるフローも制御します。

The podinfo アプリはという名前空間に保存されます test. 次のコマンドを実行して作成します。

  1. kubectl create ns test

次に、デプロイします podinfo 実行することによって:

  1. kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main

このコマンドはプルします podinfo 公式のFlaggerGitHubリポジトリからマニフェストを取得し、クラスターに適用します。

kubectl 次の出力が表示されます。

Output
deployment.apps/podinfo created horizontalpodautoscaler.autoscaling/podinfo created

デプロイされていることを確認するには、次のコマンドを実行します。

  1. kubectl get pods -n test

次のような出力が表示されます。

Output
NAME READY STATUS RESTARTS AGE podinfo-78fd6c49bf-jsjm5 1/1 Running 0 18s podinfo-78fd6c49bf-k2nh4 0/1 Running 0 3s

ポッドが実行されたので、ドメインでアプリを公開するためのIngressを作成します。 というファイルを開きます podinfo-ingress.yaml 編集用:

  1. nano podinfo-ingress.yaml

次の行を追加します。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: podinfo
  namespace: test
  labels:
    app: podinfo
spec:
  ingressClassName: nginx
  rules:
    - host: "app.your_domain"
      http:
        paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: podinfo
                port:
                  number: 80

このイングレスは、 podinfo でのサービス app.your_domain ドメイン。 忘れずに独自のドメインに置き換えてから、ファイルを保存して閉じてください。

に注意してください podinfo サービスはまだクラスターに存在しません。 後で、カナリアの一部としてFlaggerによって自動的に作成されます。 これにより、Ingressの展開が妨げられることはありません。

次のコマンドを実行して、Kubernetesにイングレスを作成します。

  1. kubectl apply -f podinfo-ingress.yaml

カナリアを作成する前に、Flaggerのロードテスターをデプロイする必要があります。これにより、カナリアリソースはHTTPリクエストを送信してリリースをテストできます。 次のコマンドを実行して、 test Helmを使用した名前空間:

  1. helm install flagger-loadtester flagger/loadtester -n test

Helmは次の出力を表示します。

Output
NAME: flagger-loadtester LAST DEPLOYED: Thu Jan 6 11:37:45 2022 NAMESPACE: test STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Flagger's load testing service is available at http://flagger-loadtester.test/

次に、カナリアを定義して、というファイルに保存します。 podinfo-canary.yaml. 次のコマンドを実行して、編集用に開きます。

  1. nano podinfo-canary.yaml

次の行を追加します。

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  provider: nginx
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  ingressRef:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    name: podinfo
  progressDeadlineSeconds: 60
  service:
    port: 80
    targetPort: 9898
  analysis:
    interval: 10s
    threshold: 10
    maxWeight: 50
    stepWeight: 5
    metrics:
    - name: request-success-rate
      thresholdRange:
        min: 99
      interval: 1m
    webhooks:
      - name: acceptance-test
        type: pre-rollout
        url: http://flagger-loadtester.test/
        timeout: 30s
        metadata:
          type: bash
          cmd: "curl -sd 'test' http://podinfo-canary/token | grep token"
      - name: load-test
        url: http://flagger-loadtester.test/
        timeout: 5s
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://app.your_domain/"

まず、カナリアが存在する名前と名前空間を設定します。 下 spec、最初に定義します targetRef、監視する展開を指定します。 podinfo. 同様に、作成したばかりの付随するIngressは、 ingressRef.

progressDeadlineSeconds、新しい変更が完全に元に戻される前に、カナリアをいつでも最大60秒間アイドル状態にすることができます。 これにより、ストールが防止され、実行の期限が設定されます。 次に、 podinfo Ingressが使用するサービス。 Flaggerは、カナリアの実行中に複数の一時的なサービスを作成する場合もありますが、メインのサービスはカナリアの存続期間中は常に利用可能です。

The analysis ブロックは、FlaggerがNginxIngressControllerから受信したメトリックをどのように確認するかを定義します。 interval 10秒ごとにそれらを見るように指示し、 threshold 新しいリリースがロールバックされる前に、メトリックチェックが失敗または使用できなくなる回数を制限します。 新しいリリースにルーティングできるトラフィックの最大パーセンテージは 50、で指定されているように maxWeight. stepWeight テストステップごとにカナリアへのトラフィックがどれだけ増加するかを制御します。

次の2つのセクション、 metricswebhooks、新しいリリースのテスト方法を定義します—以前にデプロイしたロードテスターを使用してトラフィックを作成し、リクエストの成功率を監視します。 成功したリクエストの割合が99% or高い場合、リリースはテストに合格します。

強調表示されたドメインを独自のドメインに置き換えてから、ファイルを保存して閉じることを忘れないでください。

でロールアウト kubectl:

  1. kubectl apply -f podinfo-canary.yaml

カナリアが作成されているのがわかります。

Output
canary.flagger.app/podinfo created

これで、に移動できます app.your_domain. が表示されます podinfo アプリ:

メインページには、のバージョンが表示されます podinfo それはあなたとどのポッドから提供されました。 Ping ボタンを押すと、他のポッドのバージョン番号を更新できます。

カナリアで概説されている構成に従ってFlaggerがデプロイメントの更新プロセスを引き継ぐことを確認するには、次のコマンドを実行して、 podinfo:

  1. kubectl set image deployment/podinfo podinfod=stefanprodan/podinfo:6.0.3 -n test

展開が更新されます。

Output
deployment.apps/podinfo image updated

Flaggerは、展開リビジョン番号が変更されたことを検出します。これは、に関連付けられたイベントを一覧表示することで確認できます。 podinfo カナリア:

  1. kubectl describe canary/podinfo -n test

しばらくすると、出力は次のようになります。

Output
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Synced 117s flagger New revision detected! Scaling up podinfo.test Warning Synced 107s flagger canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 2 (readyThreshold 100%) updated replicas are available Warning Synced 97s flagger canary deployment podinfo.test not ready: waiting for rollout to finish: 1 of 2 (readyThreshold 100%) updated replicas are available Normal Synced 87s flagger Starting canary analysis for podinfo.test Normal Synced 87s flagger Pre-rollout check acceptance-test passed Normal Synced 87s flagger Advance podinfo.test canary weight 5 Warning Synced 67s (x2 over 77s) flagger Halt advancement no values found for nginx metric request-success-rate probably podinfo.test is not receiving traffic: running query failed: no values found Normal Synced 57s flagger Advance podinfo.test canary weight 10 Normal Synced 47s flagger Advance podinfo.test canary weight 15 Normal Synced 37s flagger Advance podinfo.test canary weight 20 Normal Synced 27s flagger Advance podinfo.test canary weight 25 ...

Flaggerは、カナリアの定義に従って実行するすべてのアクションをログに記録します。 新しいリビジョンを検出すると、そこからテストポッドを起動し、カナリアウェイトを進めることで分析を開始します。これは、より多くのトラフィックが新しいポッドに転送されていることを意味します。

ブラウザに戻り、アプリが継続的に更新されるときにバージョン番号がちらつくのを確認します。 Flaggerがテスト中の新しいリリースにルーティングされるトラフィックの量を増やしているため、バージョンが変更されています。

Flaggerは、で始まるイベントでトラフィックシフトを示します Advance podinfo.test canary weight、続いて迂回されるトラフィックの割合:

Output
... Normal Synced 116s flagger Advance podinfo.test canary weight 10 Normal Synced 106s flagger Advance podinfo.test canary weight 15 ...

しばらくすると、カナリアの展開が成功し、バージョン番号が安定します。

カナリアの最終的なイベントログは次のようになります。

Output
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Synced 2m56s flagger New revision detected! Scaling up podinfo.test Warning Synced 2m46s flagger canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 2 (readyThreshold 100%) updated replicas are available Warning Synced 2m36s flagger canary deployment podinfo.test not ready: waiting for rollout to finish: 1 of 2 (readyThreshold 100%) updated replicas are available Normal Synced 2m26s flagger Starting canary analysis for podinfo.test Normal Synced 2m26s flagger Pre-rollout check acceptance-test passed Normal Synced 2m26s flagger Advance podinfo.test canary weight 5 Warning Synced 2m6s (x2 over 2m16s) flagger Halt advancement no values found for nginx metric request-success-rate probably podinfo.test is not receiving traffic: running query failed: no values found Normal Synced 116s flagger Advance podinfo.test canary weight 10 Normal Synced 106s flagger Advance podinfo.test canary weight 15 Normal Synced 96s flagger Advance podinfo.test canary weight 20 Normal Synced 86s flagger Advance podinfo.test canary weight 25 Normal Synced 76s flagger Advance podinfo.test canary weight 30 Warning Synced 16s flagger podinfo-primary.test not ready: waiting for rollout to finish: 1 old replicas are pending termination Normal Synced 6s (x6 over 66s) flagger (combined from similar events): Routing all traffic to primary

最後のイベントは、トラフィックがプライマリサービスにルーティングされることを示しています。これは、カナリアの展開が完了したことを意味します。

このステップでは、 podinfo アプリを作成し、ドメインで公開するためのIngressを作成しました。 また、新しいデプロイメントリビジョンを制御およびテストするためのカナリアリソースを作成しました。 次に、可視性を高めるためにカナリアイベントをSlackに報告するようにFlaggerを構成します。

ステップ3—Slackへのレポート

これで、ログをSlackワークスペースに送信するようにFlaggerを設定するので、あなたとあなたのチームはいつでもイベントの完全なログをいつでも見ることができます。

Slack統合を使用するには、ワークスペースのSlack着信Webhookが必要です。 着信Webhookは、アプリケーションが他のアプリケーションからのリアルタイム情報を提供するための簡単な方法です。 Webhookを作成したことがない場合は、最初にワークスペース用のアプリを作成する必要があります。

これを行うには、最初にSlackにログインし、アプリ作成ページに移動します。 わかりやすい名前を選び、目的のワークスペースを選択して、アプリの作成をクリックします。

新しいアプリの設定ページにリダイレクトされます。 左側のナビゲーションバーにあるIncomingWebhooksをクリックします。

タイトルActivateIncoming Webhooks の横にあるスイッチボタンを切り替えて、Webhookを有効にします。

ページのさらに下にある新しいセクションが明らかになります。 下にスクロールして、新しいWebhookをワークスペースに追加ボタンをクリックします。 次のページで、レポートの送信先のチャネルを選択し、[許可]をクリックします。

Webhookの設定ページにリダイレクトされ、新しいWebhookが表に表示されます。 コピーをクリックしてクリップボードにコピーし、後で使用できるようにメモしておきます。

ログをSlackに送信するようにFlaggerを構成するには、次のコマンドを実行してHelmリリースを更新する必要があります。

  1. helm upgrade flagger flagger/flagger \
  2. --reuse-values \
  3. --set slack.url=your_hook_URL \
  4. --set slack.channel=your_channel_name \
  5. --set slack.user=username

交換することを忘れないでください your_hook_URL 前にメモしたWebhookURLを使用して、 your_channel_name 目的のチャネルの名前を使用して、 username Webhookを作成したユーザーのユーザー名を使用します。

なぜなら --reuse-values 渡されると、Helmは既存のFlaggerリリースに基づいて新しいFlaggerリリースを作成します。 これは、このチュートリアルの最初のステップでNginx Ingress Controllerを再構成したときと同じように、設定された変数の既存の値は変更されないままであることを意味します。

出力は次のようになります。

Output
Release "flagger" has been upgraded. Happy Helming! NAME: flagger LAST DEPLOYED: ... NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None NOTES: Flagger installed

これで、新しいリリースを試すことができます podinfo 実行による展開:

  1. kubectl set image deployment/podinfo podinfod=stefanprodan/podinfo:3.1.1 -n test

間もなくSlackにメッセージが表示されます。

Slackメッセージは、期限や展開を中止する前にテストが失敗する可能性がある回数など、カナリア分析に関する基本的な情報を示しています。 トラフィックルーティングで、表示されている制限に達するまで、各反復中にルーティングされたトラフィックの割合がどの程度増加するかを確認できます。

このリリースがデプロイされると、成功メッセージが表示されます。

Flaggerがどのように失敗を報告するか見てみましょう。 カナリアはすべてのHTTPリクエスト(Nginx Ingress Controllerから読み取る)に対して99 % sの成功率を必要とするため、テスト中に新しいリリースを作成し、そこからHTTP500エラーを生成します。

新しいリリースの場合は、 6.0.3 実行して再度バージョンを作成します。

  1. kubectl set image deployment/podinfo podinfod=stefanprodan/podinfo:6.0.3 -n test

FlaggerからのSlackに関する新しいメッセージが表示され、新しいリビジョンが検出されたことを示します。 障害をシミュレートするには、 status のAPI podinfo、これにより、指定したHTTPステータスレポートを生成できます。

次のコマンドを実行して、多数のHTTP500ステータスを作成します。

  1. watch curl http://app.your_domain/status/500

しばらくすると、HTTPリクエストの成功率が10回連続で許容できないほど低いため、Flaggerが新しいリリースを適用しないことを決定したことがわかります。

出る curl、 押す CTRL+C.

これで、FlaggerがSlackに新しいリビジョンを報告するたびに報告するようになりました。 podinfo 展開が検出されました。 また、新しいリリースの結果が通知されるので、あなたとあなたのチームは、アプリのリリースの成功に関して常にループになります。

デプロイしたリソースを破棄するには、次のコマンドを実行します。

  1. kubectl delete -f podinfo-ingress.yaml
  2. kubectl delete -f podinfo-canary.yaml

結論

これで、既存のデプロイに影響を与えることなく、Flaggerを使用してKubernetesクラスターにプッシュされた新しいリリースのテストを自動化する方法を学習しました。 また、Slackへのアラートを設定したので、どのデプロイメントがリアルタイムで行われているかを常に把握でき、新しいリリースに存在する問題について事前に通知されます。

カナリア分析プロセスは、高度なPrometheusクエリで拡張できます。たとえば、HTTPリクエストのレイテンシに応じて動作します。 これについて詳しくは、Flaggerの公式ドキュメントをご覧ください。