DigitalOceanKubernetesでFlaggerを使用してリリースを段階的に配信する方法
序章
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に追加する必要があります。
- helm repo add flagger https://flagger.app
出力は次のようになります。
Output"flagger" has been added to your repositories
Helmを更新して、Helmに何が含まれているかを知らせます。
- helm repo update
次に、次のコマンドを実行してFlaggerをインストールします。
- helm install flagger flagger/flagger \
- --set prometheus.install=true \
- --set meshProvider=nginx
このコマンドは、追加したチャートリポジトリからFlaggerをインストールし、Helmリリースに名前を付けます。 flagger
. Webアプリを監視するため、 flagger
リリースはNginxIngressコントローラーに関連付けられます。
出力は次のようになり、Flaggerがデプロイされていることを詳しく説明します。
OutputNAME: flagger
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Flagger installed
Nginx Ingress Controllerの指標を公開するには、すでに定義されている変数を保持したまま、Helmリリース内に追加の変数を設定する必要があります。 あなたは実行することによってそうすることができます helm upgrade
と渡す --reuse-values
新しい変数値とともに、パラメータ:
- helm upgrade nginx-ingress ingress-nginx/ingress-nginx \
- --reuse-values \
- --set controller.metrics.enabled=true \
- --set controller.podAnnotations."prometheus\.io/scrape"=true \
- --set controller.podAnnotations."prometheus\.io/port"=10254
このコマンドは、 nginx-ingress
Helmをリリースし、コントローラーとそのポッドでPrometheusメトリック収集を有効にします。
出力は次のようになります。
OutputRelease "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
. 次のコマンドを実行して作成します。
- kubectl create ns test
次に、デプロイします podinfo
実行することによって:
- kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main
このコマンドはプルします podinfo
公式のFlaggerGitHubリポジトリからマニフェストを取得し、クラスターに適用します。
kubectl
次の出力が表示されます。
Outputdeployment.apps/podinfo created
horizontalpodautoscaler.autoscaling/podinfo created
デプロイされていることを確認するには、次のコマンドを実行します。
- kubectl get pods -n test
次のような出力が表示されます。
OutputNAME READY STATUS RESTARTS AGE
podinfo-78fd6c49bf-jsjm5 1/1 Running 0 18s
podinfo-78fd6c49bf-k2nh4 0/1 Running 0 3s
ポッドが実行されたので、ドメインでアプリを公開するためのIngressを作成します。 というファイルを開きます podinfo-ingress.yaml
編集用:
- 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にイングレスを作成します。
- kubectl apply -f podinfo-ingress.yaml
カナリアを作成する前に、Flaggerのロードテスターをデプロイする必要があります。これにより、カナリアリソースはHTTPリクエストを送信してリリースをテストできます。 次のコマンドを実行して、 test
Helmを使用した名前空間:
- helm install flagger-loadtester flagger/loadtester -n test
Helmは次の出力を表示します。
OutputNAME: 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
. 次のコマンドを実行して、編集用に開きます。
- 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つのセクション、 metrics
と webhooks
、新しいリリースのテスト方法を定義します—以前にデプロイしたロードテスターを使用してトラフィックを作成し、リクエストの成功率を監視します。 成功したリクエストの割合が99% or高い場合、リリースはテストに合格します。
強調表示されたドメインを独自のドメインに置き換えてから、ファイルを保存して閉じることを忘れないでください。
でロールアウト kubectl
:
- kubectl apply -f podinfo-canary.yaml
カナリアが作成されているのがわかります。
Outputcanary.flagger.app/podinfo created
これで、に移動できます app.your_domain
. が表示されます podinfo
アプリ:
メインページには、のバージョンが表示されます podinfo
それはあなたとどのポッドから提供されました。 Ping ボタンを押すと、他のポッドのバージョン番号を更新できます。
カナリアで概説されている構成に従ってFlaggerがデプロイメントの更新プロセスを引き継ぐことを確認するには、次のコマンドを実行して、 podinfo
:
- kubectl set image deployment/podinfo podinfod=stefanprodan/podinfo:6.0.3 -n test
展開が更新されます。
Outputdeployment.apps/podinfo image updated
Flaggerは、展開リビジョン番号が変更されたことを検出します。これは、に関連付けられたイベントを一覧表示することで確認できます。 podinfo
カナリア:
- kubectl describe canary/podinfo -n test
しばらくすると、出力は次のようになります。
OutputEvents:
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
...
しばらくすると、カナリアの展開が成功し、バージョン番号が安定します。
カナリアの最終的なイベントログは次のようになります。
OutputEvents:
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リリースを更新する必要があります。
- helm upgrade flagger flagger/flagger \
- --reuse-values \
- --set slack.url=your_hook_URL \
- --set slack.channel=your_channel_name \
- --set slack.user=username
交換することを忘れないでください your_hook_URL
前にメモしたWebhookURLを使用して、 your_channel_name
目的のチャネルの名前を使用して、 username
Webhookを作成したユーザーのユーザー名を使用します。
なぜなら --reuse-values
渡されると、Helmは既存のFlaggerリリースに基づいて新しいFlaggerリリースを作成します。 これは、このチュートリアルの最初のステップでNginx Ingress Controllerを再構成したときと同じように、設定された変数の既存の値は変更されないままであることを意味します。
出力は次のようになります。
OutputRelease "flagger" has been upgraded. Happy Helming!
NAME: flagger
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
Flagger installed
これで、新しいリリースを試すことができます podinfo
実行による展開:
- 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
実行して再度バージョンを作成します。
- kubectl set image deployment/podinfo podinfod=stefanprodan/podinfo:6.0.3 -n test
FlaggerからのSlackに関する新しいメッセージが表示され、新しいリビジョンが検出されたことを示します。 障害をシミュレートするには、 status
のAPI podinfo
、これにより、指定したHTTPステータスレポートを生成できます。
次のコマンドを実行して、多数のHTTP500ステータスを作成します。
- watch curl http://app.your_domain/status/500
しばらくすると、HTTPリクエストの成功率が10回連続で許容できないほど低いため、Flaggerが新しいリリースを適用しないことを決定したことがわかります。
出る curl
、 押す CTRL+C
.
これで、FlaggerがSlackに新しいリビジョンを報告するたびに報告するようになりました。 podinfo
展開が検出されました。 また、新しいリリースの結果が通知されるので、あなたとあなたのチームは、アプリのリリースの成功に関して常にループになります。
デプロイしたリソースを破棄するには、次のコマンドを実行します。
- kubectl delete -f podinfo-ingress.yaml
- kubectl delete -f podinfo-canary.yaml
結論
これで、既存のデプロイに影響を与えることなく、Flaggerを使用してKubernetesクラスターにプッシュされた新しいリリースのテストを自動化する方法を学習しました。 また、Slackへのアラートを設定したので、どのデプロイメントがリアルタイムで行われているかを常に把握でき、新しいリリースに存在する問題について事前に通知されます。
カナリア分析プロセスは、高度なPrometheusクエリで拡張できます。たとえば、HTTPリクエストのレイテンシに応じて動作します。 これについて詳しくは、Flaggerの公式ドキュメントをご覧ください。