こんにちは、SRE で主に CI/CD 周りを担当している kumashun です。
この記事は freee Developers Advent Calendar 2021 20日目の記事になります。
私は今年11月に開催された、クラウドネイティブに関する国内でも大規模なテックカンファレンスである CloudNative Days Tokyo 2021 にオンライン登壇をしました。(人生初の社外登壇でもありました。)
登壇内容はタイトルの通りで、freee の中でも最大規模のサービスである freee会計に、Argo CD 及び Argo Rollouts を使って canary release を導入するまでの過程を述べています。コメントやアフタートークなどで反響を頂いたものの、登壇時点では Argo Rollouts の本番導入には至らなかったため、TBD な内容が多かったのが心残りでした。
しかし、一ヶ月後の12月中旬に満を辞して Argo Rollouts が本番環境に導入され、freee では初となる Kubernetes 環境での canary release が実装されました。
この記事では、登壇時点の導入方針から本番運用に載せるまでの過程で変更/追加された項目について説明します。なお、Argo Projects の概要や freee の Kubernetes cluster 戦略などは登壇スライドをご参照くださいm
Argo Rollouts の導入手順
導入手順の詳細はスライドにもあるので簡単におさらいすると、
kind: Deployment
からkind: Rollout
への移行kind: Rollout
向けRBAC の追加- stable/canary ごとの bug や metrics の出し分け設定
となっています。
kind: Deployment
から kind: Rollout
への移行
freee では Helm/Helmfile を使った manifest 管理を行っており、サービス共通で利用できる common chart を運用しています。その common chart の values にオプションを渡すことで、Deployment の代わりに Rollout を使えるようにしました。
本番環境では以下の手順を踏むことで、ダウンタイムを発生させることなく移行を完了させています。(Deployment と Rollout が共存する間は、Service に紐付く Endpoints の中には両方の Pod が追加されていたので、常に Pod がリクエストを受けられる状態になっていることが確認できました。)
- chart version をあげて Deployment => Rollout にする PR をマージ &
prune: false
で Sync - Rollout が作成されるが、Deployment もそのまま残る。
- Rollout の Pod が全て Running になったことを確認後
prune: true
で Sync し、Deployment を削除する。
prune は、manifest 上からは削除したが、実態が残っているリソースを削除するかどうかを選択できる Argo CD の Sync オプションです。
kind: Rollout
向けRBAC の追加
登壇時は Argo CD の GUI 上から Rollout に対する操作を行うための RBAC 追加の説明をしましたが、後述する CLI での操作のために以下のような RBAC も追加しました。
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: argo-rollouts-clusterrole rules: - apiGroups: - argoproj.io resources: - rollouts/status verbs: - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: argo-rollouts-crb roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argo-rollouts-clusterrole subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: hoge-group
stable/canary ごとの bug や metrics の出し分け設定
DataDog での metrics や log の出し分けには、スライド通り Ephemeral Metadata を使用しました。加えて、Deployment で watch していた metrics は、Argo Rollouts controller が提供している metrics を Datadog openmetrics integrationで取得しています。
Deployment で取得できていた全ての metrics が Rollout でも取得できるわけではないですが、従来の monitoring の観点から大きなデグレは今のところありません。
Bugsnag での bug の出し分けについては、登壇時点では Downward API で環境変数 = Bugsnag 上の stage を書き換える手法を考えていました。しかしこの手順ではcanary release 終了後に再度デプロイを行う必要があり、デプロイ時間が増えてしまうのは避けたいということで、Bugsnag の version を利用する方法にシフトしました。
以下の仕組みによって、canary/stable の Pod ごとに version が分かれるようにしています。
- Docker image build の際に、commit hash をファイルに吐き出す。
- initializer の中で 1. で作ったファイルの中身を
app_version
としてセットする。
この仕組みは canary release を導入していないサービスでも、bug とリリースの対応付けが可能になる良い機能追加となりました。
要検証な課題について
TBD となっていた以下の課題についても進捗を共有します。
- envoy proxy の設定変更
kind: Application
レベルで canary を進められるか- canary をスキップしてデプロイしたい場合の対応
envoy proxy の設定変更
freee の Cluster が外部からのリクエストを受ける routing は ELB -> envoy proxy -> Service -> Pod となっています。service 以下の構成を変更するだけなので、現状の envoy proxy の設定変更は必要ない認識でしたが、要検証となっていました。
実際これは杞憂で、検証環境で問題なくリクエストを受けられることが確認できました。
kind: Application
レベルで canary を進められるか
Argo CD の GUI から Rollout の promote (canary step を進める) や abort (canary step を全て rollback する) の操作を行うことは可能ですが、それを一つずつの Rollout に対してポチポチするのは楽ではありません。ましてや abort する際は canary に何か問題があった場合なので、極力少ない工数でできる必要があります。そのため、何らかの方法で、1つの Application が持つ Rollout に対して一括で操作できる方法を考えました。
promote については現状 canary step を2段階 (5% -> 30min経過 -> 自動的に 100%) にしているので、操作自体行う機会は無くなりました。
一方 abort については、kubectl からワンライナーで一括 abort する方針にしています。
canary をスキップしてデプロイしたい場合の対応
登壇時点では common chart に values として渡している canary step を上書きすれば ok としていました。しかしabort 同様、こちらも hotifx など緊急時のオペレーションになることが想定されるので、同一の方針によりワンライナーを用意しました。
ちなみに Argo CD の GUI を、 Custom Resouce を作ることで拡張できる Argo CD extensions という Custom Controller があります。
これを利用した GUI 拡張のサンプル を参考に、押すと一括 abort や promote-full してくれるボタンを自作することも頑張ればできそう! ...なのですが、現時点ではドキュメントなどがあまり充実していないので、実装はしばらく先になりそうです。
おわりに
今年中にやりきるぞ!! とチーム内でも高いモチベーションで挑み続けた結果、無事大きな障害を出すことなく canary release を本番運用に載せることができました。既にアプリエンジニアからの反響も多く、Datadog から canary release の進行具合を眺めていると達成感が得られました。
Argo CD に続いて Argo Rollouts の導入に成功したとはいえ、どちらもまだまだ使いこなせていない部分も多いです。ユーザーであるアプリエンジニアにとってより良い CI/CD となるように、改善を続けていきます。同時に、Argo Workflow など他の Argo projects 導入も今後のプロジェクトに盛り込んでいきたいです!
今回の canary release 導入のような Kubernetes 環境での CI/CD 開発に興味のある方を含め、freee ではエンジニア採用を実施中です!!
明日の Advent Calender 担当は @_kemuridama san です!!
freee会計の React 17 化についての記事になるそうです!! お楽しみに〜