GitOps ソフトウェアの Flux v1 にはイメージレジストリを監視してイメージタグを自動的に最新化する「Automate image updates(自動イメージ更新)機能」が組み込まれている.別名で「Image Ops」と言ったりもする.具体的には Deployment YAML などの annotations に fluxcd.io/automated: "true" を設定すると有効化できていた.
現在使われている Flux v2 にも「Automate image updates(自動イメージ更新)機能」は組み込まれている.しかし Flux v1 と互換性はなく,完全に異なる仕組みになっている.今回は以下のドキュメントを参考にしながら Flux v2 の「Automate image updates(自動イメージ更新)機能」を試していく!
環境
今回は kubeadm を使って構築した Kubernetes v1.23.1 クラスタを使う.
- Kubernetes v1.23.1
全体構成
全体構成をまとめておく.まず,Flux v2 の「Automate image updates(自動イメージ更新)機能」は CRD (Custom Resource Definitions) を使う.以下の2種類のコントローラーでイメージレジストリを監視したり,GitHub リポジトリを更新したりする.そして ImageRepository や ImageUpdateAutomation などの CRD も組み合わせて使う.公式ドキュメントから引用した図がわかりやすい!
- Image Reflector controller(イメージレジストリを監視する)
- Image Automation controller(Git リポジトリを更新する)

Flux CLI をセットアップする
準備として Flux CLI をセットアップしておく.さらに今回使う代表的なサブコマンドも以下にまとめておく.
- flux bootstrap github | Flux
- flux reconcile kustomization | Flux
- flux create image repository | Flux
- flux create image update | Flux
$ curl -s https://fluxcd.io/install.sh | sudo bash $ flux --version flux version 0.28.5
Flux v2 をセットアップする
最初は Kubernetes クラスタに Flux v2 をセットアップする.flux bootstrap github コマンドを使うと Flux v2 のセットアップと Flux の設定を管理する GitHub リポジトリを自動的に作れる.今回はドキュメントの通りに GitHub リポジトリ flux-image-updates を使うことにする.セットアップをするときは既に紹介した「Automate image updates(自動イメージ更新)機能」のコントローラもセットアップする必要があるため --components-extra=image-reflector-controller,image-automation-controller オプションも追加する.
image-reflector-controller(イメージレジストリを監視する)image-automation-controller(Git リポジトリを更新する)
$ export GITHUB_USER=kakakakakku $ flux bootstrap github \ --components-extra=image-reflector-controller,image-automation-controller \ --owner=${GITHUB_USER} \ --repository=flux-image-updates \ --branch=main \ --path=clusters/my-cluster \ --read-write-key \ --personal
セットアップ後に確認すると flux-system Namespace にコントローラが起動されていた.
$ kubectl get pod image-reflector-controller-86db8b6f78-n62lf -n flux-system NAME READY STATUS RESTARTS AGE image-reflector-controller-86db8b6f78-n62lf 1/1 Running 0 10m $ kubectl get pod image-automation-controller-77fd9657c6-7ft2m -n flux-system NAME READY STATUS RESTARTS AGE image-automation-controller-77fd9657c6-7ft2m 1/1 Running 0 10m
そして,自動的に作られた GitHub リポジトリ flux-image-updates は以下のようなディレクトリ構成になっている.Flux v2 は kustomize を使って構成されるため,設定ファイルとして gotk-components.yaml と gotk-sync.yaml も追加されている.
.
└── clusters
└── my-cluster
└── flux-system
├── gotk-components.yaml # Flux v2 コンポーネント群 (Service, Deployment, CustomResourceDefinition など)
├── gotk-sync.yaml # Flux v2 同期コンポーネント群 (GitRepository, Kustomization)
└── kustomization.yaml # Kustomize 設定 (Kustomization)
アプリケーションを追加する
さっそくアプリケーションを追加する.今回はサンプルとして stefanprodan/podinfo を使う.
作った GitHub リポジトリ flux-image-updates に Deployment YAML を ./clusters/my-cluster/podinfo-deployment.yaml として追加する.ポイントは Pod のイメージタグで spec.containers.image に GitHub Container Registry の ghcr.io/stefanprodan/podinfo:5.0.0 を指定している.5.0.0 を覚えておく!
$ git clone https://github.com/${GITHUB_USER}/flux-image-updates $ cd flux-image-updates $ cat <<EOF > ./clusters/my-cluster/podinfo-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: podinfo namespace: default spec: selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo spec: containers: - name: podinfod image: ghcr.io/stefanprodan/podinfo:5.0.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 9898 protocol: TCP EOF
GitHub リポジトリに Deployment YAML を追加して少し待つ(もしくは flux reconcile kustomization コマンドを使って同期する)と Flux v2 によって Pod がデプロイされる.実際にイメージタグは 5.0.0 になっている.
$ git add -A && \ git commit -m "add podinfo deployment" && \ git push origin main $ flux reconcile kustomization flux-system --with-source $ kubectl get deployments.apps podinfo NAME READY UP-TO-DATE AVAILABLE AGE podinfo 1/1 1 1 10s $ kubectl get deployments.apps podinfo -o yaml | grep 'image:' - image: ghcr.io/stefanprodan/podinfo:5.0.0
ImageRepository オブジェクトを追加する
次に flux create image repository コマンドを使って ImageRepository オブジェクトを追加する.
$ flux create image repository podinfo \ --image=ghcr.io/stefanprodan/podinfo \ --interval=1m \ --export > ./clusters/my-cluster/podinfo-registry.yaml
./clusters/my-cluster/podinfo-registry.yaml は以下となる.ImageRepository オブジェクトは指定したイメージリポジトリを監視して「新しいタグ」があるかを確認する.
--- apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImageRepository metadata: name: podinfo namespace: flux-system spec: image: ghcr.io/stefanprodan/podinfo interval: 1m0s
ImagePolicy オブジェクトを追加する
さらに flux create image policy コマンドを使って ImagePolicy オブジェクトを追加する.
$ flux create image policy podinfo \ --image-ref=podinfo \ --select-semver=5.0.x \ --export > ./clusters/my-cluster/podinfo-policy.yaml
./clusters/my-cluster/podinfo-policy.yaml は以下となる.ImagePolicy オブジェクトは「どういうポリシーで新しいイメージタグを探すか」を指定する.今回は policy.semver.range: 5.0.x なので「セマンティックバージョニング」で「パッチバージョンの最新」を探す.
--- apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImagePolicy metadata: name: podinfo namespace: flux-system spec: imageRepositoryRef: name: podinfo policy: semver: range: 5.0.x
GitHub Container Registry を確認すると 5.0.x の最新は 5.0.3 だった.

ちなみに「セマンティックバージョニング」 以外に <branch>-<sha1>-<timestamp> などのフォーマットを指定して,任意の「並べ替え可能な条件」もできる.詳しくはドキュメントに載っている.
ImageRepository と ImagePolicy を適用する
GitHub リポジトリに ImageRepository YAML と ImagePolicy YAML を追加して少し待つ(もしくは flux reconcile kustomization コマンドを使って同期する)と Flux v2 によってデプロイされる.準備 OK!
$ git add -A && \ git commit -m "add podinfo image scan" && \ git push origin main $ flux reconcile kustomization flux-system --with-source $ flux get image repository podinfo NAME LAST SCAN SUSPENDED READY MESSAGE podinfo 2022-04-18T00:00:00Z False True successful scan, found 33 tags $ flux get image policy podinfo NAME LATEST IMAGE READY MESSAGE podinfo ghcr.io/stefanprodan/podinfo:5.0.3 True Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5.0.3
ImageUpdateAutomation オブジェクトを追加する
Flux v2 の「Automate image updates(自動イメージ更新)機能」を有効化するためには Deployment YAML の spec.containers.image に # {"$imagepolicy": "flux-system:podinfo"} のようにコメントを書く必要がある.
spec: containers: - name: podinfod image: ghcr.io/stefanprodan/podinfo:5.0.0 # {"$imagepolicy": "flux-system:podinfo"}
そして flux create image update コマンドを使って ImageUpdateAutomation オブジェクトを追加する.
$ flux create image update flux-system \ --git-repo-ref=flux-system \ --git-repo-path="./clusters/my-cluster" \ --checkout-branch=main \ --push-branch=main \ --author-name=fluxcdbot \ --author-email=fluxcdbot@users.noreply.github.com \ --commit-template="{{range .Updated.Images}}{{println .}}{{end}}" \ --export > ./clusters/my-cluster/flux-system-automation.yaml
./clusters/my-cluster/flux-system-automation.yaml は以下となる.ImageUpdateAutomation オブジェクトは「どういう設定で GitHub リポジトリにコミットをするか」を指定する.
--- apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImageUpdateAutomation metadata: name: flux-system namespace: flux-system spec: git: checkout: ref: branch: main commit: author: email: fluxcdbot@users.noreply.github.com name: fluxcdbot messageTemplate: '{{range .Updated.Images}}{{println .}}{{end}}' push: branch: main interval: 1m0s sourceRef: kind: GitRepository name: flux-system update: path: ./clusters/my-cluster strategy: Setters
自動イメージ更新を待つ
GitHub リポジトリに ImageUpdateAutomation YAML を追加して少し待つ(もしくは flux reconcile kustomization コマンドを使って同期する)と Flux v2 によってデプロイされる.少し待っていると 5.0.0 から 5.0.3 に更新された!👏
$ git add -A && \ git commit -m "add image updates automation" && \ git push origin main $ kubectl get deployments.apps podinfo -o yaml | grep 'image:' - image: ghcr.io/stefanprodan/podinfo:5.0.0 (少し待つ...) $ kubectl get deployments.apps podinfo -o yaml | grep 'image:' - image: ghcr.io/stefanprodan/podinfo:5.0.3
GitHub の podinfo-deployment.yaml も Flux v2 によって更新されていた.
spec: containers: - name: podinfod image: ghcr.io/stefanprodan/podinfo:5.0.3 # {"$imagepolicy": "flux-system:podinfo"}
GitHub の差分も載せておく!

マイナーバージョンとパッチバージョンの最新を探す
今度は ImagePolicy オブジェクトを更新して「マイナーバージョンとパッチバージョンの最新」を探す.policy.semver.range: 5.0.x から policy.semver. range: ^5 にした.
--- apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImagePolicy metadata: name: podinfo namespace: flux-system spec: imageRepositoryRef: name: podinfo policy: semver: range: ^5
GitHub リポジトリに ImageUpdateAutomation YAML を追加して少し待つ(もしくは flux reconcile kustomization コマンドを使って同期する)と Flux v2 によってデプロイされる.少し待っていると 5.0.3 から 5.2.1 に更新された!👏
$ git add -A && \ git commit -m "update image policy" && \ git push origin main $ kubectl get deployments.apps podinfo -o yaml | grep 'image:' - image: ghcr.io/stefanprodan/podinfo:5.0.0 (少し待つ...) $ kubectl get deployments.apps podinfo -o yaml | grep 'image:' - image: ghcr.io/stefanprodan/podinfo:5.2.1
まとめ
Flux v2 でも「Automate image updates(自動イメージ更新)機能」を使って「Image Ops」を実現できることを確認できた.しかし Flux v1 と互換性はなく,多くの CRD (Custom Resource Definitions) を組み合わせた構成になっている点は覚えておくと良さそう.以下のドキュメントに Flux v1 → Flux v2 にマイグレーションする手順が載っている.