こちらは Kubernetes3 Advent Calendar 2020 16日目の記事です。
前回の 記事 では PipeCD の疑問点と回答についてまとめましたが、今回はデプロイと分析周りについてです。
尚、PipeCD 自体については非常に良い記事が公開されていたので、そちらを参考にすると良いかと思います。
GitOps を実現する CD ツール、PipeCD が良さそうという話
概要
現在 PipeCD を使った Kubernetes の GitOps について試しているのですが、今回は以下のようなデプロイの仕組みを構築して、検証してみたのでそれについてまとめてみます。
- GitOps の Config Repository に変更がマージされたら、1 Pod だけ Canary Pod を Kubernetes 上にデプロイする
- Canary Pod から取得された Prometheus のメトリクスを使ってエラーレートの分析をする
- エラーレートが基準値を超えたら自動的にロールバックする
- デプロイが終了したら Slack に通知する
自分は ArgoCD を使って同じような仕組みを作ったことがあるのですが、その場合は ArgoCD, Argo Rollouts, ArgoCD Notifications を組み合わせて使う必要がありました。
しかし、PipeCD の場合は単体で簡単に実現することができました。
前提
検証時のバージョンは以下のものを使っています。
- PipeCD:
v0.9.0
- Kubernetes (GKE):
v1.16.15
- Prometheus:
v2.18.1
Kubernetes 上には、PipeCD、gRPC Server App、Prometheus がデプロイ済みとします。
また gRPC Server App 上では、gRPC のリクエストを処理した時に grpc_server_handled_total
というメトリクスを計測しています。
セットアップ
Piped の設定
Piped の設定ファイル (piped-values.yaml
) は以下のように設定します。
args: insecure: true config: data: | apiVersion: pipecd.dev/v1beta1 kind: Piped spec: projectID: YOUR_PROJECT_ID pipedID: YOUR_PIPED_ID pipedKeyFile: /etc/piped-secret/piped-key apiAddress: pipecd:8080 webAddress: http://pipecd:8080 syncInterval: 1m repositories: - repoId: config remote: CONFIG_REPO_URL branch: master analysisProviders: - name: prometheus type: PROMETHEUS config: address: http://your-prometheus-address notifications: routes: - name: dev-slack events: - DEPLOYMENT_SUCCEEDED - DEPLOYMENT_FAILED envs: - dev receiver: dev-slack-channel receivers: - name: dev-slack-channel slack: hookURL: https://your-slack-hook-url
analysisProviders
のセクションで、連携する Prometheus の設定を書いています。
https://pipecd.dev/docs/operator-manual/piped/adding-an-analysis-provider/
notifications
のセクションでは、Slack 通知の設定を書いています。ここでは dev environment でデプロイが成功・失敗した場合に、dev-slack-channel に通知する設定となっています。
https://pipecd.dev/docs/operator-manual/piped/configuring-notifications/
設定できたら、helm upgrade
で Piped の設定を更新します。
https://pipecd.dev/docs/operator-manual/piped/installation/
Analysis Templateの設定
PipeCD でデプロイ分析 (Automated deployment analysis (ADA)) をする際には、Analysis Template を書いて、これを Deploy Pipeline の設定から参照する形になります。
Analysis Template (analysis-template.yaml
) は以下のように設定します。
apiVersion: pipecd.dev/v1beta1 kind: AnalysisTemplate spec: metrics: grpc_error_rate: provider: prometheus # `>= 0` removes `NaN`. # `or on() vector(0)` returns `0` if the result is `no data`. query: | ( ( sum(rate(grpc_server_handled_total{pod=~"{{ .Args.serviceName }}-canary-[a-z0-9-]+",code="Internal"}[1m])) / sum(rate(grpc_server_handled_total{pod=~"{{ .Args.serviceName }}-canary-[a-z0-9-]+"}[1m])) ) >= 0 ) or on() vector(0) expected: max: 0.01 interval: 60s failureLimit: 0
この設定ファイルでは grpc_error_rate
を Prometheus Query で 60s
ごとに取得して、その値が 0.01
を上回ったら失敗とするように設定しています。
Canary Pod には PipeCD が自動で -canary
という名前を付与してくれるので、 pod=~"{{ .Args.serviceName }}-canary-[a-z0-9-]+"
のように正規表現でマッチするようにしています。
(Args には Deploy Pipeline の設定から任意の文字列を渡すことができます。)
analysis-template.yaml
は、Config Repository のルートに .pipe
というディレクトリを作り、その下に配置します。
https://pipecd.dev/docs/user-guide/automated-deployment-analysis/#analysis-template
App のデプロイの設定
App のデプロイの設定ファイル (.pipe.yaml
) は以下のように設定します。
apiVersion: pipecd.dev/v1beta1 kind: KubernetesApp spec: ... pipeline: stages: - name: K8S_CANARY_ROLLOUT with: replicas: 1 - name: WAIT with: duration: 10s - name: ANALYSIS with: duration: 130s metrics: - template: name: grpc_error_rate args: serviceName: grpc-server - name: K8S_PRIMARY_ROLLOUT - name: K8S_CANARY_CLEAN
今回設定した Deploy Pipeline は以下の Stage で構成されています。
K8S_CANARY_ROLLOUT
: Canary Pod を1つデプロイWAIT
: デプロイされた Pod が Running になるまで適当に待つANALYSIS
: Analysis Template で設定したgrpc_error_rate
の分析を、duration
で指定した期間実行K8S_PRIMARY_ROLLOUT
: 既存の Pod を新しいバージョンに更新K8S_CANARY_CLEAN
: Canary Pod を削除
ANALYSIS
Stage で失敗した場合、PipeCD が自動でロールバックしてくれます。
.pipe.yaml
は Config Repository に push し、PipeCD の WebUI から App の登録を行います。
動作確認
デプロイ成功したケース
Config Repository を更新して、デプロイを走らせてみます。 デプロイ成功したケースでは、Deploy Pipeline が最後まで実行され、終了後に Slack に通知がきました。
PipeCDのWebUI:
Slack:
※ 別の環境で撮った画像なので、今回設定した値とは異なっている部分があります。
デプロイ失敗したケース
ANALYSIS
Stage の Prometheus Query が失敗したケースでは、自動的にロールバックが行われ、終了後に Slack に通知がきました。
PipeCDのWebUI:
Slack:
※ 別の環境で撮った画像なので、今回設定した値とは異なっている部分があります。
まとめ
PipeCD で Prometheus と連携した Canary Release 分析と Slack 通知が動作していることを確認できました。
概要でも書きましたが、ArgoCD で同じことを実現するためには、いくつか周辺ツールを組み合わせる必要があるので、導入や管理の手間が増えてしまいます。
また、Argo Rollouts を導入するためには Deployment を Rollouts という独自の Resource に変更する必要があり、Deployment に依存していた部分 (例えば Prometheus の Query など) を修正する必要がありました。
PipeCD ではこのような問題を解決できているのが良いなと思いました。
備考
Prometheus の代わりに Thanos に対して Query を投げるように変更してみる
Thanos についてはこちらを参照: https://thanos.io/
Thanos も Prometheus の Query を受けて実行できるはずなので試してみました。
(使用している Thanos のバージョンは v0.13.0
です。)
設定ファイルの変更点は以下の部分です。
piped-values.yaml
:
... analysisProviders: - name: thanos type: PROMETHEUS config: address: http://your-thanos-address ...
analysis-template.yaml
:
apiVersion: pipecd.dev/v1beta1 kind: AnalysisTemplate spec: metrics: grpc_error_rate: provider: thanos ...
これで問題なく動作していました。
Automated deployment analysis (ADA) 周りの Issue について
この検証をしている際にバグっぽい挙動を見つけたので Issue を上げておきました。
- https://github.com/pipe-cd/pipe/issues/1244
analysis-template.yaml
で設定したtimeout
が、Prometheus の Query で使用されないという Issue
- https://github.com/pipe-cd/pipe/issues/1245
ANALYSIS
Stage の終了タイミングで、ちょうど動いている Prometheus の Query がエラーになることがあるという Issue
後者については ANALYSIS
Stage の duration
と Query の interval
をずらすという回避策がありますし、どちらもクリティカルな問題ではないと思います。