kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Flux v2 で Image Ops を実現する「自動イメージ更新機能」を試した

GitOps ソフトウェアの Flux v1 にはイメージレジストリを監視してイメージタグを自動的に最新化する「Automate image updates(自動イメージ更新)機能」が組み込まれている.別名で「Image Ops」と言ったりもする.具体的には Deployment YAML などの annotationsfluxcd.io/automated: "true" を設定すると有効化できていた.

現在使われている Flux v2 にも「Automate image updates(自動イメージ更新)機能」は組み込まれている.しかし Flux v1 と互換性はなく,完全に異なる仕組みになっている.今回は以下のドキュメントを参考にしながら Flux v2「Automate image updates(自動イメージ更新)機能」を試していく!

fluxcd.io

fluxcd.io

環境

今回は 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 リポジトリを更新する)

Image reflector and automation controllers より引用

Flux CLI をセットアップする

準備として Flux CLI をセットアップしておく.さらに今回使う代表的なサブコマンドも以下にまとめておく.

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

fluxcd.io

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.yamlgotk-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.com

作った GitHub リポジトリ flux-image-updates に Deployment YAML を ./clusters/my-cluster/podinfo-deployment.yaml として追加する.ポイントは Pod のイメージタグで spec.containers.imageGitHub Container Registryghcr.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> などのフォーマットを指定して,任意の「並べ替え可能な条件」もできる.詳しくはドキュメントに載っている.

fluxcd.io

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 にマイグレーションする手順が載っている.

fluxcd.io

fluxcd.io