SRE兼スクラムマスターのブログ

チーム開発が好きなエンジニアブログです。検証した技術やチームの取り組みを書いていきます。

Flux v2 を使った GitOps チュートリアル Flux v1 との比較

Weaveworks社が提唱する kubernetes のベストプラクティスで , Single Source of Truth として Git を採用し,Kubernetes リソースなどを継続的にデリバリーしていく GitOps がある。 今回はそんな GitOpsを実現するツールである Flux のv2が出てきたのでチュートリアルを試し、 v1との比較を行っていく。

なお、 GitOps の説明や過去にv1を検証した内容は以下の記事等に紹介がある。

Get started

今回は Flux v2の動作を確認するために「Get started」の内容に沿って実施していく。 toolkit.fluxcd.io

事前準備

localに kubernetes 環境を構築する。 今回は minikube を使って cluster の構築を行う。 kubernetes.io

$ kubectl version --short
Client Version: v1.19.3
Server Version: v1.19.2

次に Flux を操作するためのクライアントをインストールする。 v1の時は fluxctl だったが、v2からは flux に変更されている。

$curl -s https://toolkit.fluxcd.io/install.sh | sudo bash
$flux --version
flux version 0.2.3

最後にチュートリアルで使う GitHub リポジトリをフォークしておく。 github.com

セットアップ

flux を使って, Flux に対応した環境か確認する。

$ flux check --pre
► checking prerequisites
✔ kubectl 1.19.4 >=1.18.0
✔ Kubernetes 1.19.2 >=1.16.0
✔ prerequisites checks passed

環境の問題はなさそうなので,環境変数GITHUB_TOKEN GITHUB_USER GITHUB_REPOを設定して flux bootstrapコマンドを実行する。

$ export GITHUB_TOKEN=<your-token>
$ export GITHUB_USER=<your-username>
$ export GITHUB_REPO=<repository-name>

$ flux bootstrap github \
    --owner=${GITHUB_USER} \
    --repository=${GITHUB_REPO} \
    --branch=main \
    --personal \
    --path=clusters/staging
► connecting to github.com
✔ repository cloned
✚ generating manifests
✔ components are up to date
► installing components in flux-system namespace

namespace/flux-system created
networkpolicy.networking.k8s.io/allow-scraping created
networkpolicy.networking.k8s.io/allow-webhooks created
networkpolicy.networking.k8s.io/deny-ingress created
role.rbac.authorization.k8s.io/crd-controller-flux-system created
rolebinding.rbac.authorization.k8s.io/crd-controller-flux-system created
clusterrolebinding.rbac.authorization.k8s.io/cluster-reconciler-flux-system created
customresourcedefinition.apiextensions.k8s.io/buckets.source.toolkit.fluxcd.io created
customresourcedefinition.apiextensions.k8s.io/gitrepositories.source.toolkit.fluxcd.io created
customresourcedefinition.apiextensions.k8s.io/helmcharts.source.toolkit.fluxcd.io created
customresourcedefinition.apiextensions.k8s.io/helmrepositories.source.toolkit.fluxcd.io created
service/source-controller created
deployment.apps/source-controller created
customresourcedefinition.apiextensions.k8s.io/kustomizations.kustomize.toolkit.fluxcd.io created
deployment.apps/kustomize-controller created
customresourcedefinition.apiextensions.k8s.io/helmreleases.helm.toolkit.fluxcd.io created
deployment.apps/helm-controller created
customresourcedefinition.apiextensions.k8s.io/alerts.notification.toolkit.fluxcd.io created
customresourcedefinition.apiextensions.k8s.io/providers.notification.toolkit.fluxcd.io created
customresourcedefinition.apiextensions.k8s.io/receivers.notification.toolkit.fluxcd.io created
service/notification-controller created
service/webhook-receiver created
deployment.apps/notification-controller created
Waiting for deployment "source-controller" rollout to finish: 0 of 1 updated replicas are available...
deployment "source-controller" successfully rolled out
Waiting for deployment "kustomize-controller" rollout to finish: 0 of 1 updated replicas are available...
deployment "kustomize-controller" successfully rolled out
deployment "helm-controller" successfully rolled out
Waiting for deployment "notification-controller" rollout to finish: 0 of 1 updated replicas are available...
deployment "notification-controller" successfully rolled out
✔ install completed
► configuring deploy key
✔ deploy key configured
► generating sync manifests
✔ sync manifests pushed
► applying sync manifests
◎ waiting for cluster sync
✔ bootstrap finished

$ kubectl get all -n flux-system

NAME                                           READY   STATUS    RESTARTS   AGE
pod/helm-controller-7fc55767cc-bfzck           1/1     Running   0          4m51s
pod/kustomize-controller-6b85bf79f9-t6qs4      1/1     Running   0          4m51s
pod/notification-controller-7bb8667967-6xqdb   1/1     Running   0          4m48s
pod/source-controller-6cdb6c8889-hpsxx         1/1     Running   0          4m53s

NAME                              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/notification-controller   ClusterIP   10.108.140.72    <none>        80/TCP    4m50s
service/source-controller         ClusterIP   10.104.224.8     <none>        80/TCP    4m53s
service/webhook-receiver          ClusterIP   10.103.160.216   <none>        80/TCP    4m48s

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/helm-controller           1/1     1            1           4m51s
deployment.apps/kustomize-controller      1/1     1            1           4m53s
deployment.apps/notification-controller   1/1     1            1           4m48s
deployment.apps/source-controller         1/1     1            1           4m53s

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/helm-controller-7fc55767cc           1         1         1       4m51s
replicaset.apps/kustomize-controller-6b85bf79f9      1         1         1       4m52s
replicaset.apps/notification-controller-7bb8667967   1         1         1       4m48s
replicaset.apps/source-controller-6cdb6c8889         1         1         1       4m53s

bootstrap コマンドで flux-system のnamespaceが作成されて, GitOpsを実施するための kustomize , helm のcontrollerが作成されている。 この他にもv2では監視機能が強化されたこともあって notificationのcontrollerが作成されている。 Flux v1flux-agentmemcacheのみだったのに対して役割に応じてcontrollerが増えているようだ。 Flux v2 の全体構成は公式に掲載されている図が非常に分かりやすい。

           Flux v2 構成図 https://toolkit.fluxcd.io/diagrams/gitops-toolkit.png

           Flux v2より引用

なお、bootstrapで対象にしたrepository で管理されているmanifestがclusterに展開されていることが分かる。

$ flux get kustomizations --all-namespaces
NAMESPACE       NAME            REVISION                                        SUSPENDED       READY   MESSAGE
flux-system     apps            main/32112c9d1a3f89fdd35f91fe3ae5d0b8096923b1   False           True    Applied revision: main/32112c9d1a3f89fdd35f91fe3ae5d0b8096923b1
flux-system     flux-system     main/32112c9d1a3f89fdd35f91fe3ae5d0b8096923b1   False           True    Applied revision: main/32112c9d1a3f89fdd35f91fe3ae5d0b8096923b1
flux-system     infrastructure  main/32112c9d1a3f89fdd35f91fe3ae5d0b8096923b1   False           True    Applied revision: main/32112c9d1a3f89fdd35f91fe3ae5d0b8096923b1


$ flux get helmreleases --all-namespaces
NAMESPACE       NAME    REVISION        SUSPENDED       READY   MESSAGE
nginx           nginx   5.6.14          False           True    release reconciliation succeeded
podinfo         podinfo 5.0.3           False           True    release reconciliation succeeded
redis           redis   11.3.4          False           True    release reconciliation succeeded

GitOps実践

初期状態の確認

まず, bootstrapでデプロイされた初期のappにアクセスするためにport-forwardする。

$ kubectl -n podinfo port-forward svc/podinfo 9898:9898

Forwarding from 127.0.0.1:9898 -> 9898
Forwarding from [::1]:9898 -> 9898
Handling connection for 9898
Handling connection for 9898

ブラウザからlocalhost:9898にアクセスすると、下記のようなサンプルアプリケーション画面が表示される。なお、初期状態ではv5.0.3と表示される。

サンプルアプリケーション画面初期状態
flux v2 gitops before

マニフェストの修正

GitOps対象のリポジトリ flux2-kustomize-helm-example の中にあるマニフェスト flux2-kustomize-helm-example/workloads/apps/staging/podinfo-values.yamlを修正する。chart.spec.version: ">=1.0.0-alpha"chart.spec.version: "5.0.0"に変更し、repositoryにpushしておく。

podinfoを確認すると変更されたことが確認できる

$ flux get helmreleases --all-namespaces
NAMESPACE       NAME    REVISION        SUSPENDED       READY   MESSAGE
nginx           nginx   5.6.14          False           True    release reconciliation succeeded  
podinfo         podinfo 5.0.0           False           True    release reconciliation succeeded  
redis           redis   11.3.4          False           True    release reconciliation succeeded

再度、ブラウザから確認する

$ kubectl -n podinfo port-forward svc/podinfo 9898:9898
Forwarding from 127.0.0.1:9898 -> 9898
Forwarding from [::1]:9898 -> 9898

versionが 5.0.0に変更していることが分かる これによりgitの結果を正とした GitOpsが実現できている

f:id:JunichiMitsunaga:20201118094212p:plain
flux v2 gitops after

モニタリングを設定

Flux v1では flux agentの監視が困難であり、同期の失敗を検知/修正するまでに時間がかかっていたが、 Flux v2 になってからは Prometheusによる監視と Grafanaダッシュボードが提供された。チュートリアルでは扱っていないが、有用な仕組みなので試してみる。

flux2リポジトリにあるmanifestから作成する

$ flux create source git monitoring \
>   --interval=30m \
>   --url=https://github.com/fluxcd/flux2 \
>   --branch=main
✚ generating GitRepository source
► applying GitRepository source
✔ GitRepository source created
◎ waiting for GitRepository source reconciliation
✔ GitRepository source reconciliation completed
✔ fetched revision: main/37fb0f632b7acd192a314388c8f6bab5a6376764

$ flux create kustomization monitoring \
  --interval=1h \
  --prune=true \
  --source=monitoring \
  --path="./manifests/monitoring" \
  --health-check="Deployment/prometheus.flux-system" \
  --health-check="Deployment/grafana.flux-system"

✚ generating Kustomization
► applying Kustomization
✔ Kustomization created
◎ waiting for Kustomization reconciliation
✔ Kustomization monitoring is ready
✔ applied revision main/37fb0f632b7acd192a314388c8f6bab5a6376764

kubectl -n flux-system port-forward svc/grafana 3000:3000

ブラウザでダッシュボードにアクセスすると GitOps 状態が確認できる。

Control planeのダッシュボード

http://localhost:3000/d/gitops-toolkit-control-plane/gitops-toolkit-control-plane

f:id:JunichiMitsunaga:20201118100432p:plain
control

Cluster reconciliationのダッシュボード

http://localhost:3000/d/flux-cluster/flux-cluster-stats

f:id:JunichiMitsunaga:20201118100354p:plain
cluster

v1との比較

導入のしやすさ

v2になってbootstrap コマンドが追加されたことによって、コマンド1つで設定できるため、v1と比較してnamespaceの準備等がなくなり、簡単に設定できるようになった。

監視

Flux v1 のlogを監視して、errorが発生した場合にトラブルシューティングするなど、泥臭いことをやっていた(少なくとも自分の環境では)。 Flux v2PrometheusGrafanaが提供されたので、metricsの取得やダッシュボードによる可視化が可能になり、保守性が高まった。 また、slackへの通知などの機能も提供されたので、障害発生から検知までの時間短縮に繋がる。

構成

Flux v1はflux agentが1つだったことに対して、Flux v2では役割毎にcontrol planeが分かれた。個人的には役割が明確になったため、トラブルシューティングが簡単になり、かつ自分たちの環境にマッチした最小構成を構築するのが容易になったと感じた。

まとめ

Flux v2チュートリアルを実施してみたが、Flux v1の時よりも導入は容易になったと感じる。 CLIに関しての変更はv1ユーザーにとっては破壊的変更なため、v2へ移行するには時間がかかりそうだ。しかし、移行した場合は、監視や通知といったこれまで苦戦していた部分が提供されているので、時間をかけてしっかり移行していきたいと思う。

移行の手順は用意されているのでcluserの移行だけなら簡単そう。 pipelineやその他の仕組みでFlux CLIを使っている場合は、考慮が必要そう。

toolkit.fluxcd.io