先日、GitLabがFluxとの統合を発表した。まだ具体的な機能は見当たっていないが、Flux(beta)というページもあり、近いうちにGitLabからいい感じでFluxが使えるようになるのだと思われる。
このメモはその来たるべき未来に備えて、Flux+GitLabを使ってGitOpsを試した時のもの。
なお、GitLabオフィシャルのチュートリアルはこちら。
Fluxとは
FluxはKubernetes向けのContinuos Deliveryツールで、CNCFのプロジェクトにもなっている。
CNCFのGraduated Projectであるため、ある程度成熟されていることはCNCFからもお墨付きである。
よく比較される対象としてArgoCDがあるが、ArgoCDはリッチなUIやOIDC連携など機能的には豊富であるが独自拡張している面が強く、Fluxはk8sの標準リソースを中心にGitOpsを実現しており、軽さやシンプルさではFluxが勝ると思われる。
なお、Tanzu Mission Control(TMC)のContinuosDelivery機能でもFluxを採用している(確認した際の記事はこちら)。TMCのCD機能とこのメモでやってることは大体同じだが、TMCの方がGUIで設定可能で導入の難度は低い。
Fluxのインストール
FluxCDのkubernetesクラスタへの導入はHelmでもyamlでもなく、fluxコマンドで行う。
最初にコマンドをインストールする。インストール方法はこちら。
自環境はMacなのでbrewでinstallする。
brew install fluxcd/tap/flux
補完機能を入れる人は以下も実施する。
echo "source <(flux completion bash)" >> ~/.bashrc
. ~/.bashrc
次にFluxがGitLabにアクセスするためのPersonal Access Tokenを発行する。参考にしたドキュメントはこの辺りになる。
適当にアカウントを作成し(ここではflux-testとした)、apiに対して読み書きを許可したTokenを発行する。
ここで発行したTokenはFluxの設定をGitリポジトリに格納するために使う。
発行したアクセスTokenを環境変数に設定する。
export GITLAB_TOKEN="xxxxxxxxxxxxxxx"
次にFluxの設定を書き込むリポジトリを用意する。空のリポジトリを作成し、先程作成したユーザ(flux-test)が参照できるように権限設定する。
準備が出来たらインストールをfluxコマンドで実施する。
flux bootstrap gitlab \
--hostname=gitlab.gitlab.hogeeee.info \
--owner=myapp \
--repository=flux-config \
--branch=main \
--token-auth
オプションは以下の意味となる。
-
--hostname
:GitLabのURL -
--owner
:GitLabのユーザ名かグループ名(上の実行例ではグループ名を指定) -
--repository
:リポジトリ名 -
--branch
:ブランチ名 -
--token-auth
:同期する際にSSHキーではなくPersonalAccessTokenで同期する -
--path
:リポジトリのパス(サブグループ等直下にない場合に指定する)
※今回は--path
は未使用。
インストールに成功すると、指定したリポジトリ内にファイルが作成される。
gotk-components.yaml
を見るとFluxがデプロイするコンポーネントに関するManifestであることが分かる。
また、以下のコンポーネントがクラスタに展開される。
$ kubectl get pod -n flux-system
NAME READY STATUS RESTARTS AGE
helm-controller-fcfbdb98f-hmvn7 1/1 Running 0 12m
kustomize-controller-644db84bbb-mtlq8 1/1 Running 0 12m
notification-controller-6766ff88ff-wxgjf 1/1 Running 0 12m
source-controller-5c596db589-9w7j9 1/1 Running 0 12m
インストールされたコンポーネントは以下のような関係性になっている。(画像は公式サイトより引用)
各コンポーネントの役割は以下である(多分)。
- Helm Controller:HelmChartの管理や各種動作の自動実行
- Kustomize Controller:k8sクラスタにKustomizeでManifestを適用する
- Notification Controller:各種ソースからの通知を受け取って各コントローラにハンドリングする
- Source Controller:各種ソース(Helm, Git等)の認証管理や変更検知
GitOpsの確認
次にGitに格納したManifestがデプロイできるかを確認する。
Manifestを格納するリポジトリを作成し、Cloneする。
git clone https://gitlab.gitlab.hogeeee.info/myapp/flux-demo-manifest.git
サンプルとなるManifestを格納する。kubectl-neatプラグインを使っているが、入れていない人は省いてリダイレクトしてもらってOK。
cd flux-demo-manifest
kubectl create deploy nginx --image nginx --replicas 1 --dry-run=client -o yaml | kubectl neat -f - > ./nginx-deploy.yaml
git add *
git commit -m "initial commit"
git push origin main
次にデプロイ用のTokenを作成する。リポジトリのSettings
->Deploy tokens
からread_repository
の権限をつけて作成する。
作成後、表示されたUsernameとTokenを控えておく。
次に、flux-demoというNamespaceを作成し、そこにFluxがGitを見に行くのに使うTokenを登録する。
kubectl create ns flux-demo
flux create secret git flux-deploy-authentication \
--url=https://gitlab.gitlab.hogeeee.info/myapp/flux-demo-manifest \
--namespace=flux-demo \
--username="gitlab+deploy-token-5" \
--password="xxxxxxxxx"
--username
と--password
は先程GitLabで作成したDeployトークンのユーザ名とTokenを設定する。
次にFluxが見に行くGitのリポジトリ情報を登録する。
cat << EOF > ./git-repo.yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: web-app-manifests
namespace: flux-demo
spec:
interval: 1m0s
ref:
branch: main
secretRef:
name: flux-deploy-authentication
url: https://gitlab.gitlab.hogeeee.info/myapp/flux-demo-manifest
EOF
kubectl apply -f ./git-repo.yaml
先程作成したSecretを見に行くので、Secretと同じNamespaceにデプロイする。
最後に、Kustomizationを作成して、実際にGitに格納したManifestをデプロイする。
cat << EOF > ./kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: nginx-source-kustomization
namespace: flux-demo
spec:
interval: 1m0s
path: ./
prune: true
sourceRef:
kind: GitRepository
name: web-app-manifests
namespace: flux-demo
targetNamespace: flux-demo
EOF
kubectl apply -f ./kustomization.yaml
暫く待つとPodが作成される。
$ kubectl get pod -n flux-demo
NAME READY STATUS RESTARTS AGE
nginx-8f458dc5b-pwd2l 1/1 Running 0 61s
なお、Kustomizationリソースはデプロイ直後はエラーを出力し、しばらくしてリコンサイルしてReconciliationSucceeded
に遷移する。イベントは以下のようになっていた。
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ArtifactFailed 106s (x5 over 5m46s) kustomize-controller failed to verify archive: computed checksum '918828706d3dda025af38db7a922fc4147a106893ef23950d805c2eefcc920c6' doesn't match provided 'eb37990198ab8bba00ebf28212088df917f5953c00bcb8fd9f3b17be36ef21a3' (check whether file size exceeds max download size)
Normal Progressing 46s kustomize-controller Deployment/flux-demo/nginx created
Normal ReconciliationSucceeded 46s kustomize-controller Reconciliation finished in 137.13567ms, next run in 1m0s
リコンサイルが効いている確認として、deploymentを削除してみる。
kubectl delete deploy nginx -n flux-demo
Kustomizationのintervalを1分で設定していたので、1分程度待てばdeploymentが再作成されてPodも立ち上がる。
$ kubectl get pod -n flux-demo
NAME READY STATUS RESTARTS AGE
nginx-8f458dc5b-lfnds 1/1 Running 0 9s
次にGit側のManifestにも修正を加えてみる。レプリカ数を3に変更してリポジトリにpushする。
vi nginx-deploy.yaml
git add nginx-deploy.yaml
git commit -m "changed replicas"
git push origin main
しばらくすると、GitRepositoryリソースの方で新しいrevisionを取得した旨が表示される。
$ kubectl describe gitrepositories web-app-manifests -n flux-demo
:(省略)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal NewArtifact 21m source-controller stored artifact for commit 'initial commit'
Normal info 20m (x2 over 21m) source-controller Fetched revision: main/269944292b0b955d01d10f5b820e0d1a69039892
Normal GitOperationSucceeded 2m44s (x19 over 20m) source-controller no changes since last reconcilation: observed revision 'main@sha1:269944292b0b955d01d10f5b820e0d1a69039892'
Normal NewArtifact 104s source-controller stored artifact for commit 'changed replicas'
Normal info 103s source-controller Fetched revision: main/ed5af1bd776d1f4d20a366964637b72f4339181b
GitRepositoryリソースで変更をキャッチ後、Kustomizationにも伝搬し、以下のようなイベント出力とともにdeploymentリソースが再デプロイされる。
Normal ReconciliationSucceeded 8m10s kustomize-controller Reconciliation finished in 109.090363ms, next run in 1m0s
Normal Progressing 7m10s (x3 over 15m) kustomize-controller Deployment/flux-demo/nginx created
Normal ReconciliationSucceeded 7m10s kustomize-controller Reconciliation finished in 136.902853ms, next run in 1m0s
Normal Progressing 3m54s kustomize-controller Deployment/flux-demo/nginx configured
最終的にPod数も3つになり、Git上の変更を自動で拾ってクラスタに反映していることが確認できる。
$ kubectl get pod -n flux-demo
NAME READY STATUS RESTARTS AGE
nginx-8f458dc5b-22qf2 1/1 Running 0 5m27s
nginx-8f458dc5b-lfnds 1/1 Running 0 8m43s
nginx-8f458dc5b-zsqbl 1/1 Running 0 5m27s
Gitにpush後の即時反映
CI/CDパイプラインに組み込むことを考えた場合、GitRepository
、Kustomization
それぞれのリソースのintervalを待たずにデプロイしたいケースが考えられる。その場合、GitRepository
に.spec.suspend
という一時停止のパラメタがあるので、これをtrue
->false
にすることで即時反映が可能となる。
kubectl patch gitrepository --type merge -p "{\"spec\":{\"suspend\":true}}" web-app-manifests -n flux-demo
kubectl patch gitrepository --type merge -p "{\"spec\":{\"suspend\":false}}" web-app-manifests -n flux-demo