TECHSTEP

ITインフラ関連の記事を公開してます。

Flux v2に入門する

今回はGitOpsツールの一つであるFlux v2を試してみます。GitOpsについては以下の参考リンクなどをご参照ください。

※参考リンク:

Flux v2とは

Flux v2は、複数のCustom Controllerを組み合わせて、GitOpsの各機能を提供します。

Fluxの構成は以下の通りです。

Flux-component

※画像:Fluxドキュメントより

Fluxが実現する機能として、以下のような機能が挙げられています。

GitなどのリソースとKubernetesクラスター間の"同期"

FluxはGitHub/GitLabなどのGitリポジトリ、Helmリポジトリ、そしてminioのようなS3-compatibleなオブジェクトバケットなどを、リソースとして管理し、Kubernetesクラスターとの同期を実行します。

source-controllers ※画像:Fluxドキュメントより

コンテナイメージの自動アップデート

Fluxはコンテナレジストリもリソースとして管理し、コンテナイメージのアップデートを検知します。またイメージ更新を検知すると、対象のKubernetesマニフェストファイルのイメージタグを自動的に更新し、最終的にはクラスター上のPodのイメージをアップデートします。

image-update-controllers ※画像:Fluxドキュメントより

リソースの状態変化の通知

Fluxは、管理するリソースの状態変化に応じて、SlackやDiscordなどの外部システムに通知を送る機能が備わっています。

notification-controllers ※画像:Fluxドキュメントより

その他

  • リソース間依存関係の管理: Fluxの Kustomization HelmRelease リソースには spec.dependsOn というフィールドがあり、依存関係のリソースを指定することで、対象のリソースが作成・起動するまでは、リソースの作成を行わないよう制御できます。

※参考リンク:Flux v2のdependsOnを簡単に検証してみた

  • 外部イベントの監視と応答:Fluxの Receiver というリソースではWebhook receiverを定義し、Reconciliationのトリガーとして利用できます。利用できるリソースには、GitHubやDockerHubなどがあります。

  • 他ソフトウェアとの相互運用性GitHub Actions / Argo / Tektonなどのワークフロープロバイダ、クラスター管理を行うCluster APIなどのソフトウェアとの相互運用性を提供します。

Flux v1 / v2の違い

Flux v2は、以前はv1として開発が進んでいましたが、長年要望されていた機能をより簡単に実装できるよう、v2として大きな変更を加えました。v1ではモノリスなオペレーターで全ての機能を実現していたのに対し、v2では各機能を専用のCustom Controllerに実装することで分離しています。

v1とv2の機能差分はこちらのページに記載されていますが、特に大きな違いは以下のあたりかと思います。

  • v1

    • 一つのGitリポジトリの同期をサポート
    • flux deploy時のみ、Gitのコンフィグや秘匿情報を指定可能
    • HEADの追跡のみサポート
  • v2

    • 複数のGitリポジトリの同期をサポート
    • GitRepositoryリソースでGitリポジトリの設定などを定義
    • 指定したブランチやタグの追跡をサポート
    • Prometheusなど、エコシステムのコアのコンポーネントと統合できる
    • マルチテナンシーをサポート(参考リンク

なお、現在v1はメンテナンスモードで、新機能の追加は行われず、バグ修正とCVEのパッチのみ対応しております。

Fluxではv2の利用が推奨されています。まだGAには至っていませんが、こちらのロードマップに沿って開発が進められています。

Flux v2を試す

ここから実際にFluxを動かしてみます。

前提条件の確認と動作環境

ここからはGet Startedの手順をベースに動かしてみます。操作を行う上での前提条件は以下の通りです。

  • k8s version: 1.16 以上
  • kubectl: 1.18 以上
  • GitHubリポジトリの用意
  • GitHub Personal Access Tokenの用意:scopeでは repo 配下の権限をすべて許可しておきます。

また今回は Amazon EKS上で動作検証を行いました。動作確認を行った環境の情報は以下の通りです。

$ eksctl version
0.57.0

$ eksctl create cluster -f eks-clusterconfig.yml

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.0", GitCommit:"af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38", GitTreeState:"clean", BuildDate:"2020-12-08T17:59:43Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20+", GitVersion:"v1.20.4-eks-6b7464", GitCommit:"6b746440c04cb81db4426842b4ae65c3f7035e53", GitTreeState:"clean", BuildDate:"2021-03-19T19:33:03Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl get nodes
NAME                                               STATUS   ROLES    AGE   VERSION
ip-192-168-0-173.ap-northeast-1.compute.internal   Ready    <none>   25m   v1.20.4-eks-6b7464
ip-192-168-1-253.ap-northeast-1.compute.internal   Ready    <none>   25m   v1.20.4-eks-6b7464
ip-192-168-2-59.ap-northeast-1.compute.internal    Ready    <none>   25m   v1.20.4-eks-6b7464

また、後ほどFluxからGitHubへのアクセスに利用する環境変数を設定しておきます。

export GITHUB_TOKEN=<GitHub Personal Access Token>
export GITHUB_USER=fy0323

Flux CLIのインストール

GitHubリポジトリとEKSクラスターが用意できたので、次に flux CLIのインストールを行います。Fluxは flux CLIを利用して、Flux自体のデプロイやリソースの作成・管理を行うことができます。今回の手順でも、リソースの作成や制御はほぼ flux CLIを利用して行います。

$ curl -s https://fluxcd.io/install.sh | sudo bash
[INFO]  Downloading metadata https://api.github.com/repos/fluxcd/flux2/releases/latest
[INFO]  Using 0.16.1 as release
[INFO]  Downloading hash https://github.com/fluxcd/flux2/releases/download/v0.16.1/flux_0.16.1_checksums.txt
[INFO]  Downloading binary https://github.com/fluxcd/flux2/releases/download/v0.16.1/flux_0.16.1_linux_amd64.tar.gz
[INFO]  Verifying binary download
[INFO]  Installing flux to /usr/local/bin/flux

$ flux --version
flux version 0.16.1

Fluxデプロイ

Fluxのデプロイを行うコマンドには flux install flux bootstrap の2種類があります。 flux install はFluxをクラスター上にインストールするだけですが、 flux bootstrap は、サブコマンドに指定したGitプロバイダに対して、Fluxインストール用のマニフェストファイルをコミットします。その後、コミットしたリポジトリをFluxの同期対象とし、クラスターと同期をすることでFluxのデプロイを実現します。

ここでは flux bootstrap コマンドを利用します。まずは flux check コマンドを実行し、Fluxのデプロイに必要な前提条件を満たすことを確認します。

$ flux check --pre
► checking prerequisites
✔ kubectl 1.20.0 >=1.18.0-0
✔ Kubernetes 1.20.4-eks-6b7464 >=1.16.0-0
✔ prerequisites checks passed

チェックで問題がないため、Fluxのデプロイを実行します。

$ flux bootstrap github \
>   --owner=$GITHUB_USER \
>   --repository=fluxv2-test \
>   --branch=main \
>   --path=./clusters/my-cluster \
>   --personal

(中略)

✔ source-controller: deployment ready
✔ kustomize-controller: deployment ready
✔ helm-controller: deployment ready
✔ notification-controller: deployment ready
✔ all components are healthy

flux bootstrap コマンド後、クラスター上にリソースが作成されたことが確認できます。

$ kubectl get pods -n flux-system
NAME                                       READY   STATUS    RESTARTS   AGE
helm-controller-5b96d94c7f-525lt           1/1     Running   0          13m
kustomize-controller-5b95b78ddc-wqkmg      1/1     Running   0          13m
notification-controller-55f94bc746-zx8m9   1/1     Running   0          13m
source-controller-78bfb8576-ftnxl          1/1     Running   0          13m

$ kubectl get gitrepository -n flux-system
NAME          URL                                       READY   STATUS                                                            AGE
flux-system   ssh://git@github.com/fy0323/fluxv2-test   True    Fetched revision: main/e1d0fb9ed858d425e0bce380ab096a34c4e7035c   15m

GitHubリポジトリとの同期によるアプリケーションのデプロイ

続いてアプリケーションのマニフェストファイルを含むGitHubリポジトリを登録し、クラスター間の同期によってデプロイを行います。

※参考リンク:

まずは作業用のリポジトリをクローンします。次に GitRepository というリソースを用意しますが、ここでは flux create コマンドを利用してマニフェストファイルを生成、リポジトリに保存することでクラスターと同期し、自動的にデプロイされる、という流れで作業します。

$ git clone https://github.com/fy0323/fluxv2-test
$ cd fluxv2-test/

# GitRepositoryリソースのマニフェストファイル生成
$ flux create source git podinfo \
>   --url=https://github.com/stefanprodan/podinfo \
>   --branch=master \
>   --interval=30s \
>   --export > ./clusters/my-cluster/podinfo-source.yaml

# コミット
$ git add .
$ git commit -m "add podinfo gitrepository"
$ git push

なお、上記コマンドで生成されたマニフェストファイルは以下のようになります。

podinfo-source.yaml

apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 30s
  ref:
    branch: master
  url: https://github.com/stefanprodan/podinfo

次に Kustomization というリソースを作成します。このリソースはその名の通り kustomizeが利用する kustomization.yaml のパスを指定し、Kubernetesマニフェストファイルの管理元を定義するリソースとなります。

# Kustomaizationリソースのマニフェストファイル生成
$ flux create kustomization podinfo \
>   --source=podinfo \
>   --path="./kustomize" \
>   --prune=true \
>   --validation=client \
>   --interval=5m \
>   --export > ./clusters/my-cluster/podinfo-kustomization.yaml

# コミット
$ git add .
$ git commit -m "add podinfo kustomization"
$ git push

podinfo-kustomization.yaml

---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 5m0s
  path: ./kustomize
  prune: true
  sourceRef:
    kind: GitRepository
    name: podinfo
  validation: client

しばらくするとリポジトリクラスター間での同期が発生し、以下の通り podinfo というアプリケーションがクラスターにデプロイされます。

# kustomizationリソースの状態確認
$ flux get kustomization
NAME            READY   MESSAGE                                                                 REVISION                                        SUSPENDED
flux-system     True    Applied revision: main/7e17dea66b87e57121472eb95abe876184c9ee8b         main/7e17dea66b87e57121472eb95abe876184c9ee8b   False
podinfo         True    Applied revision: master/627d5c4bb67b77185f37e31d734b085019ff2951       master/627d5c4bb67b77185f37e31d734b085019ff2951 False


# podinfoがデプロイされている
$ kubectl get all
NAME                           READY   STATUS    RESTARTS   AGE
pod/podinfo-576d5bf6bd-qssrz   1/1     Running   0          4m58s
pod/podinfo-576d5bf6bd-rqx8d   1/1     Running   0          5m14s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
service/kubernetes   ClusterIP   10.100.0.1      <none>        443/TCP             71m
service/podinfo      ClusterIP   10.100.113.99   <none>        9898/TCP,9999/TCP   5m14s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/podinfo   2/2     2            2           5m14s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/podinfo-576d5bf6bd   2         2         2       5m14s

NAME                                          REFERENCE            TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/podinfo   Deployment/podinfo   <unknown>/99%   2         4         2          5m14s

イメージの同期

次に、コンテナイメージの自動同期を試してみます。

※参考リンク:

まずは前項で利用した podinfo の定義ファイルを一度削除します。クラスターからリソースを削除しても、リポジトリと同期することで再作成されるため、リポジトリから削除します。

$ rm clusters/my-cluster/podinfo-kustomization.yaml
$ rm clusters/my-cluster/podinfo-source.yaml
$ git add .
$ git commit -m "remove podinfo-source & podinfo-kustomization"
$ git push

# 削除されたことの確認
$ kubectl get pods
No resources found in default namespace.
$ kubectl get gitrepository -n flux-system
NAME          URL                                       READY   STATUS                                                            AGE
flux-system   ssh://git@github.com/fy0323/fluxv2-test   True    Fetched revision: main/1c5df5beab6e782467663bddab02e33a525ad5a2   51m

次にFluxの再インストールを行います。Fluxのコンテナイメージの管理を行うのは image-reflector image-automation というControllerなのですが、これらはデフォルトではインストールされず、リソースを追加する必要があります。 flux bootstrap によるFluxのインストールは冪等であり、実行時に新しいバージョンがリリースされている場合は、新しいバージョンがインストールされます。

また、コンテナイメージの更新後、上記Controllerにより、マニフェストファイルのイメージタグを書き換えるため、デプロイ用のキーに書き込み権限を付与する必要があります。前項でFluxのインストールを実行した際は、読み取り権限のみを付与したキーが発行されており、これを変更する必要があります。

ここではFluxのキー情報が格納されている flux-system というSecretリソースを削除し、その後Fluxの再インストールを行います。

# Secretの削除
$ kubectl get secret -n flux-system
NAME                                      TYPE                                  DATA   AGE
default-token-649ts                       kubernetes.io/service-account-token   3      90m
flux-system                               Opaque                                3      90m
helm-controller-token-cdrqn               kubernetes.io/service-account-token   3      90m
image-automation-controller-token-8nrpz   kubernetes.io/service-account-token   3      49m
image-reflector-controller-token-p96zm    kubernetes.io/service-account-token   3      49m
kustomize-controller-token-k2zft          kubernetes.io/service-account-token   3      90m
notification-controller-token-z4npl       kubernetes.io/service-account-token   3      90m
source-controller-token-ssh2v             kubernetes.io/service-account-token   3      90m

$ kubectl delete secret -n flux-system flux-system
secret "flux-system" deleted


# Fluxの再インストール
$ flux bootstrap github \
> --components-extra=image-reflector-controller,image-automation-controller \
> --owner=$GITHUB_USER \
> --repository=fluxv2-test \
> --branch=main \
> --path=./clusters/my-cluster \
> --read-write-key \
> --personal

(中略)

✔ image-automation-controller: deployment ready
✔ source-controller: deployment ready
✔ kustomize-controller: deployment ready
✔ helm-controller: deployment ready
✔ notification-controller: deployment ready
✔ image-reflector-controller: deployment ready
✔ all components are healthy


# リソースの確認
$ kubectl get pods -n flux-system
NAME                                           READY   STATUS    RESTARTS   AGE
helm-controller-5b96d94c7f-525lt               1/1     Running   0          41m
image-automation-controller-5cf75fd555-px4r7   1/1     Running   0          45s
image-reflector-controller-6787985855-bssjr    1/1     Running   0          45s
kustomize-controller-5b95b78ddc-wqkmg          1/1     Running   0          41m
notification-controller-55f94bc746-zx8m9       1/1     Running   0          41m
source-controller-78bfb8576-ftnxl              1/1     Running   0          41m

※なお、ここでSecretリソースを削除せずにキー情報が更新されないと、後ほどの操作時に以下のようにエラーが発生します。

コンテナイメージアップデート時のエラー

# コンテナイメージのアップデート時にエラーが発生
$ flux get image update
NAME            READY   MESSAGE                                                                                 LAST RUNSUSPENDED
flux-system     False   remote: ERROR: The key you are authenticating with has been marked as read only.                False

Fluxの再デプロイが完了したので、テスト用のアプリケーションのデプロイを行います。ここではコンテナイメージが 5.0.0 のものを指定します。

# podinfoマニフェストファイルの取得
$ curl -sL https://raw.githubusercontent.com/stefanprodan/podinfo/5.0.0/kustomize/deployment.yaml > ./clusters/my-cluster/podinfo-deployment.yaml

# コミット
$ git add .
$ git commit -m "add podinfo deployment"
$ git push

podinfo-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  minReadySeconds: 3
  revisionHistoryLimit: 5
  progressDeadlineSeconds: 60
  strategy:
    rollingUpdate:
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9797"
      labels:
        app: podinfo
    spec:
      containers:
      - name: podinfod
        image: ghcr.io/stefanprodan/podinfo:5.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 9898
          protocol: TCP
        - name: http-metrics
          containerPort: 9797
          protocol: TCP
        - name: grpc
          containerPort: 9999
          protocol: TCP
        command:
        - ./podinfo
        - --port=9898
        - --port-metrics=9797
        - --grpc-port=9999
        - --grpc-service-name=podinfo
        - --level=info
        - --random-delay=false
        - --random-error=false
        env:
        - name: PODINFO_UI_COLOR
          value: "#34577c"
        livenessProbe:
          exec:
            command:
            - podcli
            - check
            - http
            - localhost:9898/healthz
          initialDelaySeconds: 5
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - podcli
            - check
            - http
            - localhost:9898/readyz
          initialDelaySeconds: 5
          timeoutSeconds: 5
        resources:
          limits:
            cpu: 2000m
            memory: 512Mi
          requests:
            cpu: 100m
            memory: 64Mi

続いてここでは flux reconcile コマンドを利用し、リポジトリクラスター間の同期を実行します。コマンドを実行しなくとも、一定間隔でリポジトリクラスター間の差分はチェックされており(ここでは10分間隔)、差分を検知すれば同期は行われます。

# リポジトリ・クラスター間の同期
$ flux reconcile kustomization flux-system --with-source
(中略)
✔ Kustomization reconciliation completed
✔ applied revision main/4301e2dda8423ab580df8ef5d025f9a278cb7664


# podinfoアプリがデプロイされる
$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
podinfo-c598c9677-v9rvq   1/1     Running   0          20s


# この時点ではコンテナイメージタグは5.0.0
$ kubectl get deployment podinfo -oyaml | grep 'image:'
                f:image: {}
        image: ghcr.io/stefanprodan/podinfo:5.0.0

次にコンテナレジストリを定義する ImageRepository 、同期するコンテナイメージの指定を行う ImagePolicy というリソースを作成します。今回指定する ImageRepository には、複数のバージョンのイメージが保存されています。ここで指定する 5.0.x の範囲では、 5.0.3 のタグが付与されたイメージが最新のバージョンとなります。

# ImageRegistryリソースのマニフェスト生成
$ flux create image repository podinfo \
> --image=ghcr.io/stefanprodan/podinfo \
> --interval=1m \
> --export > ./clusters/my-cluster/podinfo-registry.yaml


# ImagePolicyリソースのマニフェスト生成
$ flux create image policy podinfo \
> --image-ref=podinfo \
> --select-semver=5.0.x \
> --export > ./clusters/my-cluster/podinfo-policy.yaml


# コミット
$ git add . && git commit -m "add podinfo image scan"
$ git push

podinfo-registry.yaml

---
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  image: ghcr.io/stefanprodan/podinfo
  interval: 1m0s

podinfo-policy.yaml

---
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImagePolicy
metadata:
  name: podinfo
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: podinfo
  policy:
    semver:
      range: 5.0.x

ここでも flux reconcile コマンドを実行し、リポジトリクラスター間の同期を手動で実行します。

# リポジトリ・クラスター間の同期
$ flux reconcile kustomization flux-system --with-source
(中略)
✔ Kustomization reconciliation completed
✔ applied revision main/242b5514ff60e0c02a29b95564fc48a6e75c0ac0


# リソースの確認
$ kubectl get imagerepository -n flux-system
NAME      LAST SCAN              TAGS
podinfo   2021-07-18T02:27:06Z   19

$ kubectl get imagepolicy -n flux-system
NAME      LATESTIMAGE
podinfo   ghcr.io/stefanprodan/podinfo:5.0.3

なお、リソースの状態は flux get コマンドなどでも確認できます。

$ flux get image repository
NAME    READY   MESSAGE                         LAST SCAN                       SUSPENDED
podinfo True    successful scan, found 19 tags  2021-07-18T11:28:06+09:00       False

$ flux get image policy
NAME    READY   MESSAGE                                                                 LATEST IMAGE                    
podinfo True    Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5.0.3  ghcr.io/stefanprodan/podinfo:5.0.3

次に podinfo-deployment.yaml を一部修正します。コンテナイメージの自動更新を行う ImageUpdateAutomation というリソースは、マニフェスト中の特定のマーカーを目印にして、イメージタグの書き換えを行います。

※参考リンク:

$ vi clusters/my-cluster/podinfo-deployment.yaml

# 以下のように修正
    spec:
      containers:
      - name: podinfod
        image: ghcr.io/stefanprodan/podinfo:5.0.0 # {"$imagepolicy": "flux-system:podinfo"}
        imagePullPolicy: IfNotPresent

次に ImageUpdateAutomation リソースを作成し、コンテナイメージの自動更新を実行可能にします。

# 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


# コミット
$ git add . && git commit -m "add image updates automation" && git push

flux-system-automation.yaml

---
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

しばらくすると、以下のように ImageUpdateAutomation の作成が確認できます。

$ kubectl get imageupdateautomation -n flux-system
NAME          LAST RUN
flux-system   2021-07-18T02:46:40Z

$ flux get image update
NAME            READY   MESSAGE                                                                 LAST RUN                        SUSPENDED
flux-system     True    committed and pushed 614e62d52ec55844f61fcd7f5d67999757229729 to main   2021-07-18T11:45:33+09:00       False

マニフェストファイルを確認すると、イメージタグが 5.0.3 に更新されており、Podのイメージも更新されていることがわかります。

$ git pull
$ cat clusters/my-cluster/podinfo-deployment.yaml | grep "image:"
          image: ghcr.io/stefanprodan/podinfo:5.0.3 # {"$imagepolicy": "flux-system:podinfo"}


$ kubectl get deploy podinfo -oyaml | grep 'image:'
                f:image: {}
        image: ghcr.io/stefanprodan/podinfo:5.0.3


# イメージ関連のリソースの状態を一括で確認できる
$ flux get images all
NAME                    READY   MESSAGE                         LAST SCAN                       SUSPENDED
imagerepository/podinfo True    successful scan, found 19 tags  2021-07-18T11:51:18+09:00       False

NAME                    READY   MESSAGE                                                                 LATEST IMAGE    
imagepolicy/podinfo     True    Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5.0.3  ghcr.io/stefanprodan/podinfo:5.0.3

NAME                                    READY   MESSAGE                                                         LAST RUN                        SUSPENDED
imageupdateautomation/flux-system       True    no updates made; last commit 614e62d at 2021-07-18T02:45:33Z    2021-07-18T11:50:54+09:00       False

イメージ更新の停止

flux suspend コマンドはコンテナイメージの同期を一時的に停止するコマンドです。例えばあるイメージのバージョンに問題があり、一時的に同期を停止したい場合などに利用できます。停止後は flux resume コマンドにより、同期を再開することができます。

$ flux suspend image update flux-system
► suspending image update automation flux-system in flux-system namespace
✔ image update automation suspended


$ flux get image update
NAME            READY   MESSAGE                                                         LAST RUN                       SUSPENDED
flux-system     True    no updates made; last commit 614e62d at 2021-07-18T02:45:33Z    2021-07-18T11:53:01+09:00      True


$ flux resume image update flux-system
► resuming image update automation flux-system in flux-system namespace
✔ image update automation resumed
◎ waiting for ImageUpdateAutomation reconciliation
✔ ImageUpdateAutomation reconciliation completed
✔ no updates made; last commit 614e62d at 2021-07-18T02:45:33Z

コンテナイメージのロールバック

コンテナイメージを最新のバージョンから変更したい場合、 ImagePolicy で指定するイメージタグを修正することで、イメージのロールバックを実行することができます。

# 変更前のバージョン
$ kubectl describe imagepolicy podinfo -n flux-system

(中略)
Spec:
  Image Repository Ref:
    Name:  podinfo
  Policy:
    Semver:
      Range:  5.0.x


# イメージタグの変更
$ flux create image policy podinfo \
> --image-ref=podinfo \
> --select-semver=5.0.0
✚ generating ImagePolicy
► applying ImagePolicy
✔ ImageRepository updated
◎ waiting for ImagePolicy reconciliation
✔ ImagePolicy reconciliation completed


# 更新後のイメージタグ
$ kubectl describe imagepolicy podinfo -n flux-system | grep Semver -3
  Image Repository Ref:
    Name:  podinfo
  Policy:
    Semver:
      Range:  5.0.0
Status:
  Conditions:


# Podのイメージも変更されている
$ kubectl get deploy podinfo -oyaml | grep "image:"
                f:image: {}
        image: ghcr.io/stefanprodan/podinfo:5.0.0

なお、コンテナイメージの同期に利用できるレジストリは、DockerHubやGitHub Container Registryのほか、Amazon Elastic Container Registry (ECR) やAzure Container Registry (ACR)など、パブリッククラウドのサービスも利用可能です。ただし、これらはレジストリのアクセストークンの期限が一定時間で期限切れとなるため、それを更新するためのCronJobの利用方法が紹介されています

通知

次にFluxからの通知を試してみます。今回はSlackに通知を飛ばすよう設定します。

※参考リンク:

作業を行う前提として、SlackのIncoming Webhookを有効にし、Webhook URLを取得しておきます。Webhook URLの情報はSecretリソースとして登録しておきます。

# Slack Webhook URLの登録
$ kubectl -n flux-system create secret generic slack-url \
> --from-literal=address=<Slack Incoming Webhook URL>


$ kubectl get secret -n flux-system
NAME                                      TYPE                                  DATA   AGE
default-token-649ts                       kubernetes.io/service-account-token   3      117m
flux-system                               Opaque                                3      25m
helm-controller-token-cdrqn               kubernetes.io/service-account-token   3      117m
image-automation-controller-token-8nrpz   kubernetes.io/service-account-token   3      76m
image-reflector-controller-token-p96zm    kubernetes.io/service-account-token   3      76m
kustomize-controller-token-k2zft          kubernetes.io/service-account-token   3      117m
notification-controller-token-z4npl       kubernetes.io/service-account-token   3      117m
slack-url                                 Opaque                                1      15s
source-controller-token-ssh2v             kubernetes.io/service-account-token   3      117m

次にFluxで通知機能を利用するための Provider Alert というリソースを作成します。 Provider は通知先となるプロバイダーを、 Alertは通知の対象となるリソースや通知レベルの設定などを定義します。

# Providerリソースのマニフェスト生成
$ flux create alert-provider slack \
> --type slack \
> --channel fluxcd-test \
> --secret-ref slack-url \
> --export > ./clusters/my-cluster/slack-alert-provider.yaml


# Alertリソースのマニフェスト生成
$ flux create alert flux-system \
> --event-severity info \
> --event-source Kustomization/*,GitRepository/*,ImagePolicy/* \
> --provider-ref slack \
> --export > ./clusters/my-cluster/slack-alert.yaml


# コミット
$ git add . && git commit -m "add alert provider & alert" && git push

slack-alert-provider.yaml

---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
  name: slack
  namespace: flux-system
spec:
  channel: fluxcd-test
  secretRef:
    name: slack-url
  type: slack

slack-alert.yaml

---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Alert
metadata:
  name: flux-system
  namespace: flux-system
spec:
  eventSeverity: info
  eventSources:
  - kind: Kustomization
    name: '*'
  - kind: GitRepository
    name: '*'
  - kind: ImagePolicy
    name: '*'
  providerRef:
    name: slack

flux reconcile コマンドにより、リポジトリクラスター間を同期します。

$ flux reconcile kustomization flux-system --with-source


# リソースの状態確認
$ kubectl get provider -n flux-system
NAME    READY   STATUS        AGE
slack   True    Initialized   100s

$ kubectl get alert -n flux-system
NAME          READY   STATUS        AGE
flux-system   True    Initialized   6m55s

$ flux get alert-providers
NAME    READY   MESSAGE
slack   True    Initialized

$ flux get alerts
NAME            READY   MESSAGE         SUSPENDED
flux-system     True    Initialized     False

通知設定が完了したので、リソースの変更を行います。ここでは、先ほど変更した ImagePolicy のイメージタグを変更してみます。

$ flux create image policy podinfo \
> --image-ref=podinfo \
> --select-semver=5.0.x

上記設定からしばらくすると、Slackのほうに通知が飛ぶ様子が確認できます。

f:id:FY0323:20210719131304j:plain

Fluxのアンインストール

検証が完了したので、Fluxをアンインストールします。

$ flux uninstall --namespace=flux-system
? Are you sure you want to delete Flux and its custom resource definitions? [y/N] y
(中略)
✔ uninstall finished


# 削除の確認
$ kubectl get ns
NAME              STATUS   AGE
default           Active   12h
kube-node-lease   Active   12h
kube-public       Active   12h
kube-system       Active   12h