Fluxによるアプリケーションの継続的デプロイ
FluxのAutomated deployment of new container imagesを利用して、Kubernetes上でアプリケーションの継続的デプロイを構成する機会があったのでまとめます。
GitOpsの基本形
GitOpsを採用する場合は下図のデプロイフローが基本形になります。
具体的には以下の流れになります。
- 開発者がアプリケーションリポジトリを更新する。
- CIがアプリケーションをビルドし、新しいDockerイメージをプッシュする。
- 開発者がマニフェストリポジトリを更新する。
- GitOpsが新しいマニフェストをデプロイする。
これはWeaveworksのGuide To GitOpsで説明されている開発フローです。チームの大きさやアプリケーションの特性によっては、以下のような違いが出てくると思います。
- アプリケーションリポジトリのブランチ戦略
- アプリケーションリポジトリの更新を契機にビルドとデプロイを行うか、ビルドのみ行うか
- マニフェストリポジトリとクラスタを自動的に同期させるか、手動で同期するか
- 実行環境(dev/stg/prod)によって自動と手動を使い分ける
継続的デプロイに必要なもの
チームが小さい、あるいは、チームが自己完結している場合は、アプリケーションを更新した契機で開発環境にデプロイされる方が効率的に開発できることがあります。ビジネス上の受入テストまで自動化している場合は本番環境まで自動デプロイすることもあります。これを継続的デプロイ(Continuous Deployment)といいます。下記の記事が参考になります。
継続的デプロイを実現するにはアプリケーションのビルドとデプロイを連続して行う必要があります。Cloud FoundryのようなPaaSを利用するとこのような開発フローを簡単に実現できますが、KubernetesのようなCaaSでは仕組みを作る必要があります。具体的には、以下が自動的に流れる仕組みが必要になります。
- 開発者がアプリケーションリポジトリを更新する。
- CIがアプリケーションをビルドし、新しいDockerイメージをプッシュする。
- (何らかの仕組みで)マニフェストリポジトリにあるマニフェストのイメージタグを書き換える。
- GitOpsが新しいマニフェストをクラスタに適用する。
今のところ、GitOpsで継続的デプロイを実現するにはFluxを利用するか、上記3を自作する必要があります。Argo CDでは実現できません。
Flux automated deployment of new container images
FluxにはAutomated deployment of new container imagesという機能があります。この機能を有効にすると、Dockerレジストリに新しいイメージが存在したらマニフェストのイメージタグを新しいものに書き換えてくれます。ちょうど下図のようなデプロイフローになります。
具体的には以下の流れになります。
- Gitリポジトリからマニフェストを取得する。
- Dockerレジストリにあるイメージをスキャンする。
- 新しいタイムスタンプのイメージが存在する場合は以下を行う。
- 新しいマニフェストをクラスタに適用する。
公式ドキュメントには詳細が書かれていないので、Fluxのログを元に動作を推測しています。間違っていたら教えてください。
Automated deployment of new container imagesを有効にするには、Deploymentに以下のアノテーションを付加します。
metadata: annotations: fluxcd.io/automated: "true"
スキャン対象のイメージタグを正規表現やglobで絞り込むことも可能です。以下に例を示します。
metadata: annotations: fluxcd.io/automated: "true" # appコンテナについて、master-で始まるイメージタグのみ自動更新とする fluxcd.io/tag.app: glob:master-* spec: template: spec: containers: - name: app image: ...
スキャン対象のイメージ名やDockerレジストリを限定することも可能です。詳しくはfluxdの引数リストを参照してください。
下記のリポジトリにデモを置いているので、よかったらご覧ください。
FlaggerによるCanary Release
参考までに、FluxとFlaggerを併用するとCanary Releaseが可能です。アプリケーションリポジトリを更新した契機でデプロイを開始し、一定の基準(例:10%のトラフィックに新しいバージョンを適用して99%が成功ステータスだった場合)を満たしたら全トラフィックを新しいバージョンに切り替える、といったことも可能です。
Flaggerを使うにはIstioなどのサービスメッシュが必要です。また、Kialiなどの可視化ツールがあるとトラフィックの切り替えがよく分かります。詳しくは下記の記事が参考になります。
Fluxによる継続的デプロイの課題
Fluxには以下の制約があるため、実際に運用してみると辛いところがあります。
- デプロイが成功した場合やエラーが発生した場合の通知がない。
- WeaveworksとしてはWeave Cloudを使ってほしいみたいです。
- fluxdのログをelastalertなどで監視してSlackに通知する仕組みを作れば可能です。
- デプロイが成功すると
flux-sync
タグが更新されるので、GitHubでタグの更新をSlackに通知するという方法もあります。 - FlaggerにはSlack通知の機能があります。
- GUIがないので、クラスタで何が起きているのか分かりにくい。
- 同期状態を管理するためにマニフェストリポジトリに
flux-sync
というタグが作成される。flux-sync
タグ契機でCIが実行されないように設定するとよいです。
参考までに、fluxctlコマンドを利用すると以下のようなステータスを表示できます。
% fluxctl --k8s-fwd-ns flux -n develop list-images WORKLOAD CONTAINER IMAGE CREATED develop:deployment/echoserver echoserver gcr.io/google_containers/echoserver '-> 1.10 22 Mar 18 17:30 UTC 1.9 14 Feb 18 22:35 UTC 1.8 27 Jul 17 18:50 UTC 1.7 18 Jul 17 19:23 UTC 1.6 16 Jun 17 22:41 UTC 1.5 06 Jun 17 23:28 UTC 1.4 29 May 16 05:03 UTC 1.3 08 Mar 16 19:10 UTC 1.2 23 Feb 16 02:18 UTC 1.1 26 Jan 16 18:13 UTC
デプロイの前後で自動テストなどの処理を入れたい場合は今のところ方法がありません。Tekton CDでは柔軟なデプロイメントパイプラインを構成できるので、今後Tekton CDのエコシステムが発達してきたら有力候補になるかもしれませんね。