k8s のCDツールがいくつかあるので、それらの特徴についてまとめる。
一応CDツールの定義は"k8sにWebアプリケーションをデプロイするツール"を想定しているが、 k8sにおけるデプロイはマニフェストファイルを apply することなので、 そういったものはすべてCDツールとみなして調べた。 すべてのツールをちゃんと調べたわけではないので、ものによってはサラッとした紹介になっている。
- Flux
- Tekton(Tekton Pipeline)
- Jenkins-X
- PipeCD
- GCP Cloud Deploy
- AWS Code Pipeline
- Spinnaker
- ArgoCD
- 改めて各ツールに言及する
- 複数ツールの組み合わせ
- ちゃんと調べて、触ってみないと分からない部分が多い
- まとめ
- 宣伝
Flux
他のツールと比べると “GitHub上のリポジトリをk8sに適用する(GitOps)”という機能を提供するシンプルなCDツールという印象である。 シンプルと言っても以下のように最低限必要になる機能は備わっている。
- Helmを扱える
- kustomizeを扱える
- ImageOps(コンテナイメージをコンテナレジストリにプッシュすると自動的にデプロイが走るやつ)を利用できる
- slackなどへの通知ができる
単に "k8sのマニフェストファイルをapplyしたい" のであれば、このツールで十分な気がする。 小規模組織の場合もCDに投資する余力もないと思うので、これで良さそう。
ただ、パイプライン機能を持ってないので、Flux単体で複雑なCDパイプラインを構築することはできない。 パイプライン機能が必要な場合は他のツールを組み合わせる必要がある。
Tekton(Tekton Pipeline)
k8s Native な CI/CD Pipeline である。
CDツールというよりは "CI/CD Pipeline" なので、以下のように実行したいコマンドをyamlに指定する感じになる。
https://tekton.dev/docs/getting-started/#your-first-ci-cd-workflow-with-tekton
一応ダッシュボードもあるらしい。
https://tekton.dev/docs/dashboard/
雑に言うとCircleCIみたいなものをk8sで動かしているイメージに近いと思う。
CI/CD Pipelineということでパイプライン機能(複数の処理を任意の順番に実行できる機能)を持っており、 Flux よりも柔軟なデプロイを実現することができる。 例えば "デプロイ前のxxxをする" とか "デプロイ後にxxxをする" ということができる。 CDだけでなく、CIを作ることもできるので、1つのツールで一貫したCI/CDパイプラインを構築することができる。
ただ、言ってしまえば単なるコマンド実行ツールなのでアプリケーション用のリッチなCDを実現しようとした場合(例えばBlue/Green Deployとか)はそれなりに作り込む必要があると思う。
一応 Tekton Hub というパイプラインを共有するサービスはあるが、どこまで揃っているのかは不明である。
https://hub.tekton.dev/
Jenkins-X
Jenkinsという名のとおり、Jenkinsみたいなやつなんだろーなと思っている。
Fluxと同じようにGitOpsをベースとしたCDツールである。 Tektonを利用したパイプライン機能と簡易的なUIが存在するので、”Flux + Tekton + 簡易UI” みたいなツールである。 ChatOps機能を持っているのも面白い。
ただ、Tektonと同じように、リッチなCDを実現しようとした場合作り込みが発生しそうではある。
PipeCD
コンセプトとしては後述するSpinnakerやArgoCDに似ているかなと思っている。
実際にSpinnaker, ArgoCDを参考に生まれたらしい。
https://pipecd.dev/ja/blog/2020/10/06/announcing-pipecd/#thanks
Spinnakerとの違いはTerraform, ECS, Lambda, Cloud Runなどのクラウド関連のツールやサービスのデプロイを網羅的にサポートしている点かな? ちゃんと調べられていない。
後発なツールということもあって、pospome個人としては今回紹介する中で一番良さそうなツールだと思った。 ただ、利用実績が乏しそうなので、このタイミングで使って良いものか・・・という気持ちはある。
開発元(?)のCAでは使われているようだけど、実際どーなんでしょうね。
https://developers.cyberagent.co.jp/blog/archives/30573/
GCP Cloud Deploy
https://cloud.google.com/deploy/docs/overview
GCPが提供するCDサービスである。 リッチな機能があるわけではなさそうだが、どーなんでしょうね。 GKEにアプリケーションをデプロイするだけなら Cloud Deploy でサクッとやるのもありかなーと思う。
AWS Code Pipeline
EKSの場合は Code Pipeline を使うのだろうか? ちょっと調べたが GCP Cloud Deploy みたいなものが見当たらないので諦めた。
Spinnaker
Spinnakerの特徴は "複雑なCDパイプラインを構築することができる" という点である。
Pipeline & Stage
個人的にSpinnakerが扱うリソースの中でも最も強力なのがPipelineとStageだと思っている。 StageというのはCDパイプラインにおける1つの処理を表すリソースである。 Stageは単に直列につなぐだけでなく、並列に並べることができたり、特定の条件分岐を入れたり、Manual Judgementで人間の判断に委ねたり、 以下のようにとにかく自由に構成することができる。
そして、Spinnaker ではパイプライン(Stage同士の依存関係)を以下のようにUIで直感的に設定できるので、 Stageが複雑になってもPipeline全体を簡単に認識することができるし、 Stageの構成を変更することも簡単である。 SREでなくとも、開発チームは自分たちで最適なCDパイプラインを作成することができる。
Stageの種類も豊富である。 Manual Judgementで人間の判断を求めたり、 Rollout Strategy & Traffic Management によってBlue/Green DeployやCanary Releaseができたり、 Webhook の実行やスクリプトの実行も可能である。 要件に合うStageがない場合はk8sのJobという形で自作もできる。
動的なパイプライン
Spinnakerは任意のStageを組み合わせることによって複雑なCDパイプラインを構築できるだけではなく、 マニフェストファイルの値とパイプラインの挙動を動的に変更することができる。 Stageの組み合わせだけでも十分複雑なCDパイプラインを構築することができるが、以下の機能によってより柔軟な挙動を実現することができる。 例えば、"パイプラインの途中でマニフェストファイルの値を変更する", "デプロイが失敗したあとにxxxする" などが可能である。
- https://spinnaker.io/docs/guides/user/kubernetes-v2/parameterize-manifests/
- https://spinnaker.io/docs/guides/user/pipeline/expressions
- https://spinnaker.io/docs/guides/user/kubernetes-v2/patch-manifest/
Managed Delivery
Managed Delivery は(直訳したけだけどだけど) "管理されたCD" という思想である。
- https://spinnaker.io/docs/concepts/#managed-delivery
- https://blog.spinnaker.io/managed-delivery-evolving-continuous-delivery-at-netflix-eb74877fb33c
Spinnaker はパイプラインの構成をUIによって自由に変更することができるが、 自由度の高さ故に、"利用者側が自分たちに最適なパイプラインを構築しなければいけない" というある種のCDリテラシーのようなものが求められる。 組織が大きくなればなるほど、チームごとのCDに対する知見に差が出てくるので、 組織として "この設定は絶対に入れてください", "最新のStageを利用してください" みたいな統一的なCD戦略を実現するのが難しくなる。 実際に Netflix でもこういった問題が発生していたらしい。
この問題を解決するのが "Managed Delivery(管理されたCD)" である。
Managed Delivery はアプリケーションのパイプラインをUI上で作成するのではなく、 Githubリポジトリ上の(k8s likeな)yamlとSpinnaker APIによって管理する仕組みである。 ざっくり言うと、CDパイプラインのIaC化である。
なんかすごそうだが、Manged Delivery を実現するための sig がなくなっていたので、これを実現するのは無理だと思っている。
https://github.com/spinnaker/governance/pull/281
Spinnaker を使いこなせるか?
Spinnaker は複雑なCDパイプラインをUIによって簡単に構築することができる。 しかし、利用者側が複雑なCD戦略を考えられない(CDの知識がない) or 必要としない場合は "マニフェストファイルをk8sにapplyするだけのツール" で終わってしまう。 これではSpinnakerを利用する意味がない。
Spinnakerは多機能で自由度が高いので、意外とSREの運用コストや開発者の学習コストが高くなってしまうし、 "Spinnaker の用意したレールに乗らなければいけない" という部分があるので変にロックインされることになったり、 実際に使ってみると「微妙な機能だな・・・」と思うこともある。
良くも悪くも利用者のニーズとスキルに大きく依存するツールなので、 Spinnakerを使いこなせるか? は事前に考えておいたほうが良い。 リッチなCD戦略が不要な場合は、FluxやArgoCDを使った方がいいと思う。
ArgoCD
ArgoCDの特徴は "必要最低限な機能でシンプルなCDパイプラインを構築することができる" という点である。 Spinnakerに比べると機能として劣ってしまうので、地味な印象を受けるが、逆に良い感じにまとまっているツールだと思う。 "リッチなCD戦略を必要としないけど、Fluxよりはリッチなものが欲しい" のであれば、十分使い勝手の良いツールである。
Single Source of Truth(SSOT)
ArgoCDはGitHubリポジトリ上に存在するマニフェストファイルを "Single Source of Truth" として扱い、それをk8sに同期する(Syncする)ツールである。
アプリケーションのデプロイ方法としては、"GitHub上のマニフェストファイルにデプロイ対象のコンテナイメージのタグを指定し、commitする" というGitOpsが基本となるが、
GitHub上のマニフェストファイルとk8s上のリソースを同期する機能もある。
https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/
一応ArgoCD本体とは別で ImageOps ができるツールが存在するので、ImageOpsも可能である。
https://github.com/argoproj-labs/argocd-image-updater
デプロイ中に任意の処理ができるような仕組みもある。
- https://argo-cd.readthedocs.io/en/stable/user-guide/parameters/
- https://argo-cd.readthedocs.io/en/stable/operator-manual/resource_actions/
- https://argo-cd.readthedocs.io/en/stable/user-guide/resource_hooks/
しかし、ArgoCDにはSSOTという思想があるので、デプロイの前後でマニフェストファイルを変更することはオススメできない。
開発者の利便性を向上させるために、開発環境などに限り許容するような考えらしい。
https://argo-cd.readthedocs.io/en/stable/user-guide/parameters/
SpinnakerはCDパイプライン上でマニフェストファイルやクラスター上のリソースに変更を加えることを前提としているので、思想としては正反対である。
複雑なCDパイプラインは作れない
ArgoCDにはSpinnakerのPipelineのような概念が存在しない。 前述したように以下の機能によってデプロイ前後に任意の処理を差し込むことはできるが、Spinnakerほど柔軟ではないだろう。
Managed Delivery
Spinnaker で説明した Managed Delivery だが、実は ArgoCD は標準で可能だったりする。 ArgoCD のコンセプトが "Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes." であることからも、 この機能がArgoCDの特徴的なものであることが分かる。
具体的には以下のように yaml で管理することができる。 GitOpsとSSOTを徹底している感がある。
https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/
Argoシリーズ
ArgoCDは以下のArgo系のツールと組み合わせることができる。
- https://argoproj.github.io/argo-rollouts/
- https://argoproj.github.io/argo-workflows/
- https://argoproj.github.io/argo-events/
Argo RolloutsはBlue/Greenデプロイやカナリーリリースなどのリッチなロールアウト戦略を実行するためのツールである。 Argo Workflowsはワークフローエンジンである。 Argo Eventsはイベント駆動のワークフローを実現するためのツールである。
これらを組み合わせることで、Spinnaker 相当の柔軟なCD戦略を実現できる可能性がある。 ただ、管理するものが増えてしまうので「だったらオールインワンなSpinnakerの方がよくない?」というのはあるかもしれない。
ちなみに、これらのツールは単体でも利用できるようになっているので、 例えば "Spinnaker と Argo Rollouts を利用する" みたいなことも可能である。
シンプルなUI
(Spinnaker を使ったことある人にしか伝わらないと思うけど)個人的にArgoCDの方がUIがシンプルでわかりやすいと思う。 以下で実際に確認できるので、触ってみると良い。
https://cd.apps.argoproj.io/applications
改めて各ツールに言及する
Spinnaker, ArgoCD はアプリケーションをデプロイするためのツールという側面が強く、それに必要な機能がデフォルトで用意されている。 アプリケーションのCDツールの選定というのであれば、どちらかを利用するのがいいかなと思っている。 複雑なデプロイ戦略が不要であればSpinnakerよりもシンプルなArgoCDがいいかもしれない。
CI/CDパイプラインが欲しいのであれば、Tekton, Jnekins-X が候補になってくる。 CDだけでなく、CIを含めた一貫したデプロイパイプラインを1つのツールで構築できるのは嬉しいかもしれない(Jenkins-XはTekton利用するから実質2つのツールになるけど・・・)。
Fluxは機能としては少ない印象を受けるが、単にマニフェストファイルをクラスターに適用したい場合にサクッと使えそうなイメージがあるので、要件がシンプルな場合に採用するのがよさそうな気がする。
PipeCDは結構良さそうな雰囲気を感じるので、採用している企業の事例とかあったら嬉しいなーと思う。
複数ツールの組み合わせ
Spinnaker と ArgoCD がオールインワン気味なツールだと思うけど、いくつかのツールを組み合わせるという選択肢もある。 ここではパッと思いつくものを挙げる。
Flux + Tekton + Flagger
"GitOps/ImageOpsを実現するFlux" + "CI/CDを提供するTekon" + "Progressive Deliveryを実現する Flagger" というシンプルツールを組み合わせる構成である。 Flagger は Flux と同じプロジェクトなので Argo Rollout ではなく、Flagger を選んだけど、要件次第だと思う。
Tektonから Flux, Flagger を叩くことで、FluxによるGitOpsの前後に任意の処理を実行したり、Progressive Delivery を実現することができそう。 Tektonを採用したことでCI/CDに柔軟性が生まれるので、良さそうな組み合わせだなーと思ったが、 それぞれのツールをつなぎこむ必要があるので、結局 Spinnaker を頑張って自作する感じになってしまうかもしれない。
ArgoCD + ArgoWorkflows + Argo Rollout
ArgoシリーズでCDパイプラインを作る感じである。 ArgoCD単体でも最低限のCDパイプラインを構成することができるので、"ArgoCDで辛くなったら必要なものを追加する" という戦略が取れる。 もしかしたらCI部分もある程度ArgoWorkflowsに任せることができるかもしれない。 ただし、あとからツールを追加すると開発チームのデプロイ方法やArgoCDで完結していたパイプラインを変更する必要があるので、 意外と大変そう・・・。
ちゃんと調べて、触ってみないと分からない部分が多い
ここまで各ツールについて軽く説明してきたが、ちゃんとドキュメントを読んで、触ってみないと本当の良し悪しは分からない部分が多い。
例えばArgoCDにはGitHub上のマニフェストファイルとk8s上のリソースを同期する機能があるが、 これを有効にするとArgoCDのロールバック機能が利用できなくなってしまう。 デプロイ後に問題が発生した場合にUIなどから素早くロールバックできる機能は、 それはそれで重要だったりするので、 この機能を有効にするかどうかは悩ましいところかもしれない。
Spinnakerはパイプライン上でマニフェストファイルの値を任意の値に変更することができるが、 以下のようにプレースホルダーにしないといけないので、 Spinnakerに依存したマニフェストファイルになってしまう。
# ... other keys metadata: namespace: '${ parameters.namespace }' # other keys ...
ArgoCD, Spinnakerに限らず、こーゆー細かい機能や挙動を確認しないと本当の良し悪しは分からない。 開発組織の規模が大きくなればなるほど、後からCDツールやCD戦略を変更するのは難しくなってしまうと思うので、 選定する段階で可能な限り工数をかけて検証することをおすすめする(まあ、それができれば苦労しないんだけど・・・)。
まとめ
特にないです。 (´・ω・`)
宣伝
DMMプラットフォームのマイクロサービスアーキテクトチームではSREを募集しています。 選考なしのカジュアル面談が可能なので、このブログを読んで「なんか面白そうだなー」と感じたら、連絡ください。
DMMのマイクロサービスアーキテクトチームではサーバサイドエンジニアとSREを募集中です。マイクロサービスやプラットフォームエンジニアリングに興味のある人であれば楽しめる環境だと思います。選考なしのカジュアル面談をしているので興味のある方はぜひ。https://t.co/EndrfjFRHj
— pospome (@pospome) August 17, 2021