Slide 1

Slide 1 text

  実践! Argo CD & Rollouts による canary release 
 2021.11.05


Slide 2

Slide 2 text

  2 ● profile
 ○ 福岡県宗像市出身。
 ● work
 ○ 2020.04 : freee に新卒入社
 ○ 2020.10 : インフラ基盤のEC2=>EKS移行
 ○ 2021.08 : CI/CD 周りの保守運用, 改善
 ● trend
 ○ ランニング, おうちk8s, 油そば(平太周)
 
 大隈 隼
 freee株式会社 / SRE
 Hayato Okuma - kumashun
 プロフィール画像の トリミング方法

Slide 3

Slide 3 text

  3 本登壇のメインターゲット
 ⚠ 資料製作時点では、Argo Rollouts の本番導入までには至りませんでしたm
 
 Kubernetes 環境において、
 ● 現在他の CD ツールを使っているが、Argo CD の導入を検討している方
 ● Canary や Bule/Green などのデプロイ戦略の導入を検討している方
 ● これから Argo Rollouts の導入 or Argo CD との併用を検討している方
 
 
 
 


Slide 4

Slide 4 text

4 01 freee の進化とプロダクトの成長
 02 freee の CD と Argo projects
 03 freee での Argo CD 導入過程
 04 freee会計と canary release
 05 Argo Rollouts 導入への道のり
 06 まとめ
 アジェンダ


Slide 5

Slide 5 text

  freee の進化と
 プロダクトの成長


Slide 6

Slide 6 text

  6 freee について
 ● 創立 : 2012年7月
 ● Mission : スモールビジネスを、世界の主役に。
 ● Vision : だれもが自由に経営できる統合型経営プラットフォーム。
 ○ 10以上のプロダクトで、創業から上場まであらゆるビジネスステージを網羅
 ● 【freee】ブランドムービー2021「スモールビジネスを、世界の主役に。」
 
 
 
 
 


Slide 7

Slide 7 text

  7 freee会計 freee開業 freee福利厚生 freeeアプリストア freee人事労務 freee会社設立 freeeスマート受発注 freeeプロジェクト管理 freee資金調達 freee申告 freeeカード プロダクトラインナップ


Slide 8

Slide 8 text

  8 2012 2013 2014 2015 2016 2017 200 100 150 50 2020 エンジニア数(人) プロダクトと開発組織の成長
 2019 2018 プロダクト リリース 会計freee freee 人事労務 freee 会社設立 マイナンバー 開業 freee申告 freeeカード アプリストア公 開 プロジェクト管 理freee freee finance lab株式会社 設立 API公開 サービス 分割開始 チーム制 導入 クラウドERP コンセプト発 表 マイクロサー ビス化 開始 基盤投資 加速 プラット フォーム 元年 新規 プロダクト加 速

Slide 9

Slide 9 text

  freee の CI/CD と
 Argo projects


Slide 10

Slide 10 text

  10 CI/CD の標準化を進めたい
 ● 既存のプロダクトのマイクロサービス化や新規プロダクトの爆速リリースによって、多く の Kubernetes cluster が生まれた。
 ○ freee ではシングルテナント戦略を採用。
 
 ● manifest の管理は SRE が行っているものの、image build やデプロイフローなどの CI/CD の仕組みはチームによってバラバラだった。
 
 ● それらを標準形に移行させ、保守運用していく = SRE の CLC チーム
 ○ CLC : Container Logistics Co. という造語の略称
 
 
 
 


Slide 11

Slide 11 text

  11 freee の cluster 運用
 ● computing : Amazon EKS
 ● routing : ELB -> envoy proxy -> service -> pod
 ● AWS リソース及び cluster 本体や node group の設定な どは Terraform による IaC
 
 
 
 


Slide 12

Slide 12 text

  12 freee の cluster 運用
 ● manifest 管理
 ○ Helm + Helmfile を使用。
 ○ サービス共通で使い回せる common chart を定義。
 
 ● common chart はアプリエンジニアとSREの責務を分ける目的で 2 種類に分類。
 ○ app 系 : ビジネスロジック (Rails, Go などのアプリケーション) が載る。
 ○ system 系 : Daemonset や APM など (fluentd, envoy-proxy, Datadog) が載る。
 
 
 
 
 
 


Slide 13

Slide 13 text

  13 freee の cluster 運用
 ● CI
 ○ GitHub Actions self hosted runner による image build
 ● CD
 ○ 内製 GitOps ツールによる helmfile sync の実行
 => Argo CD に移行中
 
 
 
 


Slide 14

Slide 14 text

  14 Argo projects
 ● intuit が開発した Kubernetes 向け OSS の総称
 ● プロダクトの種類
 ○ Argo CD
 ■ GitOps のための CD ツール
 ○ Argo Rollouts
 ■ デプロイ戦略を提供
 ○ Argo Workflow
 ■ データ処理パイプラインの Argo Workflows 移行を検討した話 
 ○ Argo Events
 ■ event source を受けて、workflow へのトリガーを管理する
 
 
 
 


Slide 15

Slide 15 text

  15 Argo CD
 ● GitOps のための Kubernetes 向け CDツール。
 ● manifest の PR merge をトリガーにデプロイ= sync で きる。
 ● 実体はすべて CRD であり、自身も Argo CD によるデ プロイが可能。
 
 
 
 https://argo-cd.readthedocs.io/en/stable/assets/argocd_architecture.png

Slide 16

Slide 16 text

  16 デプロイ対象ごとに必要なリソース
 ● kind: Application
 ○ Argo CD でのデプロイ対象となるKubernetes リ ソースのグループ
 
 ● kind: AppProject
 ○ 複数の kind: Application のグループ
 ○ デプロイ元となるソースコードやデプロイ先の cluster などを制限することが可能。
 
 
 
 


Slide 17

Slide 17 text

  17 Argo CD のアーキテクチャ
 dex-server
 Argo CD における SAML SP
 repo-server
 repogitory を clone して helmfile template を行う
 argocd-server
 web UI や API endpoint を提供する
 application-controller
 kind: Application を監視し、定義に従ってライフサイクルイベント (sync など) を実行する
 redis-ha
 argocd-repo-server が render した manifest をキャッシュする
 ref : Argo CD はどのように manifest をキャッシュしているのか? 
 redis-ha-haproxy
 redis-ha の proxy


Slide 18

Slide 18 text

  18 Argo Rollouts
 ● Canary や Blue/Green のようなデプロイ戦略を 導入するための Kubenertes controller 及び CRD の総称。
 ● Ingress controller や Service mesh への integration も用意されている。
 
 
 
 
 https://argoproj.github.io/argo-rollouts/architecture-assets/argo-rollout-architecture.png

Slide 19

Slide 19 text

  19 kind: Rollout
 ● kind: Deployment を拡張したイメージ。
 ● spec.strategy に応じて複数の replicasets を管理す る。
 ● spec.strategy.canary の場合
 ○ stable/canary の 2 つの replicasets 。
 ○ steps : canary のリリース段階
 ■ manifest をデプロイ直後、canary の pod 数は全体の 20 %
 ■ 1 step 進める = promote すると全体の 50%
 ■ さらに promote すると 100% = release 完了
 
 
 
 
 strategy: canary: stableMetadata: labels: role: stable canaryMetadata: labels: role: canary steps: - setWeight: 20 - pause: {} - setWeight: 50 - pause: {}

Slide 20

Slide 20 text

  freee での Argo CD 導 入過程


Slide 21

Slide 21 text

  21 Argo CD 導入前
 ● Circle CI を使った内製 GitOps ツールでデプロイ。
 ● manifest を管理している repository への PR 上のコメント経由で、helmfile コマ ンドを叩いていた。(例)
 ○ hoge deploy -c --dry-run=true ■ helmfile -f /path/to//helmfile.yaml diff ○ hoge deploy -c ■ helmfile -f /path/to//helmfile.yaml sync ○ 本番環境へのデプロイには dry-run が必須になる仕組み
 ● デプロイ時は基本的に image tag を書き換える PR を出して、そこでコマンド実 行していた。
 
 
 
 


Slide 22

Slide 22 text

  22 内製ツールのgood/bad
 ● good
 ○ アプリエンジニアでも簡単にデプロイできる。
 ○ cluster ごとのデプロイ手順が共通化する。
 ● bad
 ○ Circle CI に強力な権限を渡す必要があった。
 ○ 誰でも PR にコメント = デプロイできてしまう。
 ○ app 系と system 系の両方がデプロイ対象になるので、
 ■ デプロイ時間が遅い。
 ■ dry-run の結果にデプロイに関わりのない(system 系の) diff が出てしま う。
 
 
 
 


Slide 23

Slide 23 text

  23 そこで Argo CD !!
 ● tekton, FluxCD と合わせて比較を行った結果、Argo CD を採用。
 ○ 使い勝手の良さで判断。
 
 ● 内製ツールの bad への対応
 ○ Circle CI に強力な権限を渡す必要があった。
 => VPC 内でデプロイフローが完結する。
 
 ○ 誰でも PR にコメント = デプロイできてしまう。
 => appProject ごとに実行権限を分けて管理できる。
 
 ○ app 系と system 系の両方がデプロイ対象になる
 => app 系と system 系で application を分けることで回避。
 
 
 
 


Slide 24

Slide 24 text

  24 Argo CD によるデプロイの手順
 1. image tag 変更の PR を作成する。
 2. 内製 Argo CD 連携アプリによって PR- 実リソース間の diff を取得。
 a. 想定通りの diff であれば、PR をマージする。
 b. 意図しない diff があれば、問題ないか確認する。
 3. Argo CD の UI 上から master ブランチ- 実リソース間の diff を確認。
 a. 想定通りの diff であれば、sync を実行する。
 b. 意図しない diff があれば、問題ないか確認する。
 
 
 
 


Slide 25

Slide 25 text

  25 内製 Argo CD 連携アプリ
 ● UI 上から確認できる diff は、target revision として指定した branch と実リソースとの 間にあるもの。
 ○ master マージするまで、valid な manifest かどうかが不明。
 
 
 
 


Slide 26

Slide 26 text

  26 内製 Argo CD 連携アプリ
 ● GitHub Actions をトリガーとして、連携アプリが処理を行う。
 ○ 変更のあったファイルのディレクトリ構成などから PR に label を付与。
 ■ application の名前を特定できるような labeling
 ○ label が貼られたのをトリガーに、連携アプリが Argo CD の API を叩く。
 ■ argocd app diff ${ application_name } \ --revision ${ PR の commit hash } --grpc-web
 ○ 取得した diff を PR にコメントする。
 ■ diff の内容を含めてPRレビューが可能に!
 
 
 
 


Slide 27

Slide 27 text

  27 Argo CD の導入手順 
 Argo CD 本体のデプロイしたうえで、各 cluster ごとに以下を行う。
 1. helmfile を app 系/system系の 2 つに分離
 2. 権限周りの設定追加
 3. Application, AppProject の作成
 4. 内製 GitOps ツールからのデプロイ禁止設定
 
 
 


Slide 28

Slide 28 text

  freee会計と
 canary release


Slide 29

Slide 29 text

  29 freee 会計
 ● 有料課金ユーザー企業数※1 293K 以上のクラウド会計ソフト。
 ● freee のサービス群の中で最も規模の大きなサービス。
 
 
 
 
 ※1 2021年6月末時点。有料課金ユーザー企業数に 䛿個人事業主を含む https://contents.xj-storage.jp/xcontents/AS08692/330086ca/ca2e/48ce/a618/7936926a5dff/20210813130156762s.pdf

Slide 30

Slide 30 text

  30 EKS 移行
 ● 直近の2年間で ほぼ全てのサービスのインフラ基盤 を EC2 から EKS に移行。
 ○ 規模や与える影響的に freee 会計は終盤に。
 ● やったこと
 ○ アプリケーションのコンテナ化
 ○ common chart の整備 & helmfile 作成
 ○ 環境変数の移行
 ○ Argo CD 周りの設定
 ○ ALB target group による weigthed traffic の切り 替え
 
 
 


Slide 31

Slide 31 text

  31 EKS 移行 ( + Argo CD 導入) による影響
 ● デプロイ/ロールバックの時間及び作業コストの大幅な削減
 ● Argo CD の Web UI による Kubernetes リソースの可視化
 
 一方で、EC2 時代にあった canary release がデグレした状態。
 
 
 


Slide 32

Slide 32 text

  32 freee 会計の canary release
 ● freee のサービスは、ユーザーの売上や経営状況に関わるようなセンシティブな データを扱う。
 ● freee 会計は大規模ゆえ他サービスとの連携機能が多数あり、障害の影響も伝播 しやすい。
 
 ● canary release を導入して、新機能のリリースに伴うサービス障害の影響範囲を小 さくすることで、
 ○ ロールバックを容易にする。
 ○ 新機能のリリースの心理的ハードルを下げる。
 
 
 


Slide 33

Slide 33 text

  33 sticky session
 ● 影響範囲 = ユーザー数を少数に固定するために、sticky session を導入していた。
 ○ front が canary release で処理した場合、 canary release された server にのみリクエスト が飛ぶようにする。
 ○ sticky session がなければ、結局アクセスした全ユーザーが対象になってしまう。
 
 ● L7 (ALB listener rule) での cookie によるトラフィック管理で実現。
 
 
 


Slide 34

Slide 34 text

  34 canary release 再導入への期待
 ● EKS移行後初の確定申告期間中(アクセス急増)も安心してデプロイするために、や はり canary release は必要。
 
 ● sticky session 含め、仕組みは Kubernetes 内で完結させたい。
 ○ AWS Ingress controller のような Kubernetes 外のリソースを manifest で管理する のは freee の cluster 戦略に合わない。
 
 ● Argo CD に次ぐ Argo project として Argo Rollouts での実装を検討。
 
 


Slide 35

Slide 35 text

  Argo Rollouts 導入への道のり


Slide 36

Slide 36 text

  36 cluster 構成の before/after


Slide 37

Slide 37 text

  37 canary release の手順
 1. image tag 変更の PR をマージする。
 2. Argo CD の sync を実行する。
 3. canary の 1st step に入って、定義に従った台数分 canary pod が立ち上 がる。
 4. metrics や bug など canary の状態を 一定時間 watch して、問題がない か確認
 a. 問題がなければ、canary を promote して次の step へ、または promote-full で一気にデプロイを進める。
 b. 問題があれば canary を abort して、canary pod が 0 台の状態に戻 す。
 
 
 
 


Slide 38

Slide 38 text

  38 導入作業
 ● kind: Rollout をコードベースで利用可能にする
 ● RBAC の追加
 ● stable/canary ごとの bug や metrics の出し分け設定
 
 
 
 


Slide 39

Slide 39 text

  39 kind: Rollout をコードベースで利用可能にする
 ● Deployment => Rollout への変更
 ● CRD のインストール
 
 
 
 


Slide 40

Slide 40 text

  40 Deployment => Rollout への変更
 ● app 系の common chart に対して
 ○ kind: Rollout を入れる。
 ○ spec.strategy の内容を kind: Rollout 用に変える。
 
 ● 書き換える方針として
 ○ 既存の chart の version を上げる。
 ○ -canary のような別 chart として作成する。
 
 
 
 


Slide 41

Slide 41 text

  41 (方針1) 既存の chart の version を上げる
 ● freee では common chart の version 管理を行っている。
 ○ version を切ると、GitHub Actions によって chart を S3 に upload。
 ○ semantic versioning により、chart の新機能を特定の cluster 内に先行して導入でき る。
 
 


Slide 42

Slide 42 text

  42 (方針1) 既存の chart の version を上げる
 ● chart 内の template で、Argo Rollouts を 使うかどうかに応じて kind を書き換える。 (spec.strategy も同様)
 
 
 
 # /templates/deployment.yaml {{- if .Values.argoRollouts.canary.enabled }} apiVersion: argoproj.io/v1alpha1 kind: Rollout {{- else -}} apiVersion: apps/v1 kind: Deployment {{- end }} # /values.yaml argoRollouts: canary: enabled: false # defaultでは無効 v1.2.2
 v1.2.3
 v1.3.0
 common chart A


Slide 43

Slide 43 text

  43 (方針2) 別 chart として作成する
 
 
 ● kind: Rollout 用に書き換え済みの -canary として新規に chart を作成する。
 
 
 
 v1.2.2
 v1.2.3
 common chart A
 v1.0.0
 common chart A-canary
 # -canary/templates/deployment.yaml apiVersion: argoproj.io/v1alpha1 kind: Rollout

Slide 44

Slide 44 text

  44 方針の比較
 ● 既存の chart の version を上げる。
 ○ pros
 ■ 従来の chart version 管理に沿っている。
 ■ chart の修正が deployment, rollout どちらに対しても反映される。
 ○ cons
 ■ chart の中身が rollout を知らない開発者にとって混乱を招く。
 ● -canary のような別 chart として作成する。
 ○ pros
 ■ 用途によって chart を使い分ければ良いことが明確になる。
 ○ cons
 ■ 双方の chart に共通した修正を入れる場合に面倒。
 ● どちらかに修正を入れ忘れる、ということがありそう。
 
 


Slide 45

Slide 45 text

  45 方針の比較
 ● 既存の chart の version を上げる。
 ○ pros
 ■ 従来の chart version 管理に沿っている。
 ■ chart の修正が deployment, rollout どちらに対しても反映される。
 ○ cons
 ■ chart の中身が rollout を知らない開発者にとって混乱を招く。
 ● -canary のような別 chart として作成する。
 ○ pros
 ■ 用途によって chart を使い分ければ良いことが明確になる。
 ○ cons
 ■ 双方の chart に共通した修正を入れる場合に面倒。
 ● どちらかに修正を入れ忘れる、ということがありそう。
 
 


Slide 46

Slide 46 text

  46 CRD のインストール
 
 
 ● kind: Rollout 用に書き換えた common chart を使 う前に、CRD のインストールが必要。
 ● 公式 Helm Chart 経由で、common chart 外でイ ンストールしておく。
 ○ system 系 の helmfile の一部として管理。
 
 
 
 
 # argo-rollouts/helmfile.yaml repositories: - name: argo url: https://argoproj.github.io/argo-helm releases: - name: argo-rollouts namespace: argo-rollouts forceNamespace: argo-rollouts chart: argo/argo-rollouts version: 2.3.0 wait: true timeout: 7200

Slide 47

Slide 47 text

  47 導入作業
 ● kind: Rollout をコードベースで利用可能にする
 ● RBAC の追加
 ● stable/canary ごとの bug や metrics の出し分け設定
 
 
 
 


Slide 48

Slide 48 text

  48 RBAC 追加
 ● Argo CD の UI から canary を進めるため。
 ● argo-cd-config に Argo Rollouts 向けの policy を追加する。
 ○ ※ 検証中なので一旦 * 指定
 
 
 
 
 apiVersion: v1 kind: ConfigMap metadata: name: argocd-rbac-cm namespace: argocd data: policy.default: role:readonly policy.csv: | p, role:org-admin, applications, *, */*, allow p, role:org-admin, applications, action/argoproj.io/Rollout/*, */*, allow p, role:org-admin, clusters, get, *, allow p, role:org-admin, repositories, get, *, allow p, role:org-admin, repositories, create, *, allow p, role:org-admin, repositories, update, *, allow p, role:org-admin, repositories, delete, *, allow g, your-github-org:your-team, role:org-admin

Slide 49

Slide 49 text

  49 stable/canary ごとの bug や metrics の出し分け
 ● Ephemeral Metadata をもとに出し分けが可能。
 ○ pod の metadata に (stable|canary)Metadata の値が入る。
 ○ canary release の進行に合わせて、 canary => stable に書き換わる。
 
 
 
 # kind: Pod labels: app: helm-guestbook release: helm-argo-rollouts-example role: canary rollouts-pod-template-hash: cb5c9b94b labels: app: helm-guestbook release: helm-argo-rollouts-example role: stable rollouts-pod-template-hash: cb5c9b94b # kind: Rollout strategy: canary: stableMetadata: labels: role: stable canaryMetadata: labels: role: canary

Slide 50

Slide 50 text

  50 metrics, log への対応
 ● Datadog を利用。
 ○ 公式 Helm Chart を使って設定を管理。
 ● Helm Chart の podLabelsAsTags に role label を設定する。
 ○ Datadog で canary デプロイメントの状態を監視する 
 
 
 
 
 podLabelsAsTags: role: kube_role

Slide 51

Slide 51 text

  51 error monitoring への対応
 ● bugsnag を利用。
 ● role label を環境変数に渡して、bugsnag 上の stage として canary を識 別させる。
 ○ canary release 完了後に restart する必要あり。
 
 
 
 
 # kind: Rollout containers - env: - name: RELEASE_STAGE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.labels['role'] # ruby config.release_stage = ENV['RELEASE_STAGE'] == 'canary' ? 'canary' : ENV['RAILS_ENV']

Slide 52

Slide 52 text

  52 要検証な課題
 ● sticky session の実装
 ● envoy proxy の設定変更
 ● kind: AppProject レベルで canary を進められるか
 ● canary をスキップしてデプロイしたい場合の対応
 
 
 
 


Slide 53

Slide 53 text

  53 (不要) sticky session の実装
 ● Nginx Ingress controller や Istio 上での実現方法を検討していたが、実装が不要と なった。
 ● 影響範囲を狭くするため という sticky session 導入の目的が、高速でロールバック が行えることで達成できると判断したから。
 ○ Argo Rollouts のロールバック ( canary abort) は即座に canary pod が terminating になる = ユーザー影響を与えなくなるため十分早い。
 
 
 


Slide 54

Slide 54 text

  54 envoy proxy の設定変更
 ● sticky session が必須でなくなったため、traffic 管理の設定を追加する必要ない認識 ではあるが、要検証。
 
 
 


Slide 55

Slide 55 text

  55 kind: AppProject レベルで canary を進められるか
 ● kind: AppProject 内にある全ての rollout の操作を一括で進めたい
 ○ 特定の rollout だけタイミングをずらす事はまずない。
 ● 用意されている UI 的に rollout の数ぶんポチポチは避けられない...?
 ○ Argo CD 2.1 で可能性を探る!
 
 
 
 
 まとめて promote させたい まとめて promote させたい

Slide 56

Slide 56 text

  56 kind: AppProject レベルで canary を進められるか
 ● staragety.canary.steps.pause を指定すれば、promte は自動で進むから楽かも。
 ○ abort する場合だけ UI 操作が発生する。
 
 
 strategy: steps: - setWeight: 10 - pause: { duration: 30m } - setWeight: 50 - pause: { duration: 10m }

Slide 57

Slide 57 text

  57 canary をスキップしてデプロイしたい場合の対応
 ● 急ぎの場合、hotfix など。
 ● strategy.canary.steps が 1 段階 ( 1:9 => 10:0 ) なら watch せずに即 promote-full すれば良さそう。
 ○ 多段に設定する必要が出てきた場合を想定して、sync 後に自動で promote-full す る仕組みを用意しておきたい。
 
 
 
 


Slide 58

Slide 58 text

  58 canary をスキップしてデプロイしたい場合の対応
 ● staragety.canary.steps.pause をとても短く設定すれば、一気にリ リースできそう。
 ○ common chart に skipCanary=true を指定すると こう書き換えてくれる オプションを付ける。
 
 
 
 strategy: steps: - setWeight: 10 - pause: { duration: 1s } - setWeight: 50 - pause: { duration: 1s } strategy: steps: - setWeight: 10 - pause: { duration: 30m } - setWeight: 50 - pause: { duration: 10m }

Slide 59

Slide 59 text

  まとめ


Slide 60

Slide 60 text

  60 まとめ
 ● 内製ツールから Argo CD への移行により、Kuberentes 環境のデプロイがより簡単 & 高速 & セキュアになった。
 ● 繁忙期でも安心してデプロイできるように canary release 導入に向けて、Argo Rollouts を検証中。
 ● 本番環境での運用の前にクリアすべき課題は少なくないが、徹底したコード管理を行 いつつ手法を探る。
 
 
 
 


Slide 61

Slide 61 text

  61 失敗して攻めよう
 学びのある失敗をして最速で成長しよう。学 びのある失敗とはチームやプロダクトの成長 につながる失敗。学びのある失敗をしていな いのは挑戦が足りない。


Slide 62

Slide 62 text

  Job Board 載せてます!!


Slide 63

Slide 63 text

スモールビジネスを、世界の主役に。