こんにちは、研究開発部 Architectグループの辻田です。今回はKubernetesアプリケーション基盤にArgo Rolloutsを導入し、カナリアリリースからメトリクスの自動解析、ロールバックの自動化を実現したので紹介していきたいと思います。
Kubernetes導入の経緯や導入後の取り組みについては以下の記事で紹介しています。
なお、本記事は【R&D DevOps通信】という連載記事のひとつです。
Argo Rolloutsについて
概要
RolloutsはKubernetes上でデプロイメントの管理と自動化を行うためのツールです。CI/CDパイプラインの自動化、ネイティブなKubernetesのリソースのデプロイメント戦略、プログレッシブデリバリなどの目的に使用されます。また、Argo CDやArgo Workflowと組み合わせることでより高度な自動化を実現することができます。
詳しくはドキュメントを参照ください。
https://argo-rollouts.readthedocs.io/en/stable/
導入の背景
アプリケーション基盤ではmainブランチにマージすればデプロイできますが、まだデフォルトのローリングアップデート戦略しか対応できていませんでした。研究開発部では大量のデータを利用することが多いため、
- staging環境で本番相当のデータを用意して検証するのに時間がかかる
- 実データを使用しないと検知できないメモリリークなどの問題がある
- リリース時のメトリクスやログのチェックは目視確認している
- ロールバックしたい場合はRevertプルリクを出す必要がある
という課題感がありました。
B/Gデプロイやシャドウデプロイなどデプロイ戦略はいくつもありますが、本番環境のトラフィックを流して実際のデータ量、使われ方で検証を行いたい、より迅速かつ安全で低コストなデプロイメントを実現したい、という要件を満たしているのがカナリアリリースであったため、カナリアリリースを導入することにしました。
カナリアリリースを実現する外部ツールは色々とありますが、Argo CDとArgo Workflowsを導入しており、それぞれの親和性の高さからRolloutsを採用しました。
構成
システム構成とカナリアリリースの挙動は以下の図のようになります。
現状の構成ではトラフィックをルーティングするためにIngressコントローラやService Meshプロバイダを利用していません。その代わりに通常のKubernetesサービスネットワーキング(kube-proxy)を使用して、新旧レプリカ数の最も近い比率に基づいておおよそのカナリアの重みを達成しています。
5つのポッドのうち1つを新しいバージョンで動作させることで、20%のトラフィックを達成することができます。IngressコントローラやService Meshを導入することで数%単位でのより細やかなトラフィック制御やヘッダーベースのルーティングなどが可能になるため、今後検討を進めたいところです。
AnalysisTemplateについて
概要
RolloutsのAnalysisTemplateを使用することで、プログレッシブデリバリを実現することができます。プログレッシブデリバリはアプリケーションのデプロイメントを少しずつ進めながら、その影響を測定することで、問題が発生した場合にはすぐにロールバックできるようにするデプロイメント戦略です。
フローチャートに表すと以下のようになります。
詳しくはドキュメントを参照ください。
https://argo-rollouts.readthedocs.io/en/stable/
Datadogでの使い方
監視ツールにはDatadogを使用しているため、AnalysisTemplateでもDatadogと連携させることにしました。 他にもPrometheusやNewRelicなど様々なツールをサポートしています。
以下はAnalysisTemplateでDatadogのメトリクスを解析しながらデプロイのステップを進行 or 中断させるマニフェストの例です。
apiVersion: argoproj.io/v1alpha1 kind: AnalysisTemplate metadata: namespace: samples name: success-rate spec: args: - name: lb-name # Rolloutリソースから受け取る引数 - name: env-name metrics: - name: success-rate interval: 5m # 5分間計測する successCondition: default(result, 0) < 5 # 成功と判定する条件。resultにはqueryの結果が入る。 failureLimit: 1 # 失敗回数の上限。この回数を超えたらロールバックする。 provider: datadog: interval: 5m # 5分間隔でメトリクスを集計 query: | sum:aws.applicationelb.httpcode_target_5xx{name:{{args.lb-name}},account:{{args.env-name}}}.as_count()
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: namespace: samples name: rollout-canary spec: replicas: 3 revisionHistoryLimit: 2 selector: matchLabels: app: rollout-canary template: metadata: labels: app: rollout-canary spec: serviceAccountName: rollout-canary containers: - name: rollouts-demo image: argoproj/rollouts-demo:blue imagePullPolicy: Always ports: - containerPort: 8080 resources: requests: memory: 32Mi cpu: 5m strategy: canary: stableMetadata: labels: role: stable canaryMetadata: labels: role: canary analysis: templates: - templateName: success-rate # どのAnalysisTemplateで解析するか指定 startingStep: 2 # ステップの2番目(重み40%)から解析を開始する args: - name: lb-name # AnalysisTemplateに渡す引数の変数名 value: sample # AnalysisTemplateに渡す引数の値 - name: env-name value: develop steps: - setWeight: 20 - pause: {} - setWeight: 40 - pause: {duration: 5m} - setWeight: 70 - pause: {duration: 5m}
AnalysisTemplateを定義しRolloutの任意のステップからAnalysisRunをトリガーします。AnalysisRunの結果を評価し、次のステップに進むかどうかを決定します。
この例ではALBの500エラーを5分間隔でチェックし、エラー数が5回未満だと成功と判断されカナリアリリースのステップを進行します。 500エラーが5回以上発生した場合は失敗と判断され自動でデプロイを中断し、前のリビジョンにロールバックされます。
ダッシュボード
Rolloutsではデプロイメントの進行状況などを可視化するためのダッシュボードが用意されてます。 カナリアリリースのステップの状況はもちろん、AnalysisTemplateで定義したメトリクスの成功/失敗の状況も確認できます。
ダッシュボードでは以下のような操作をUI上で行うことができます。
- イメージタグの更新
- カナリアステップの進行、中断、再開
- ロールバック
まとめ
このようにRolloutsを導入することによってカナリアリリースを手軽に実行できる仕組みが整いました。さらに、AnalysisTemplateを使用することでプログレッシブデリバリを簡単な方法で実現することができます。
成功、失敗条件のメトリクスに何を使用するかが重要なポイントになると思いますが、このあたりは色々試しながらより良いメトリクスを見つけていきたいと思います。
まだ導入したてのため効果や課題については見えない部分が多いですが、抱えていた課題感は改善されそうと期待しています。また導入後の効果についてもブログにできればと思います。
以上、カナリアリリースやプログレッシブデリバリを検討している方の参考になれば幸いです。最後まで読んでいただきありがとうございました。