Flux CD Flux CD

使用 Flux 镜像自动化实现镜像更新自动化

让 Flux 检测新的容器镜像标签,并将其提交回 Git。

15 min 中级

在大多数 GitOps 配置中,你的 CI 流水线会构建镜像,然后把新的标签提交到配置仓库。Flux 提供了一种替代方案:两个可选的控制器监视你的容器镜像仓库,挑选出匹配规则的最新标签,并自己把变更提交到 Git。集群仍然只因 Git 提交而改变,因此你保留了审计轨迹。本指南使用公开的 podinfo 镜像。

各部分如何配合

三种资源协同工作:

  • ImageRepository 扫描镜像仓库,获取某个镜像的标签。
  • ImagePolicy 从该列表中选出一个标签,例如某个范围内最高的语义化版本。
  • ImageUpdateAutomation 在你的 Git 仓库中,按标记所指示的位置编辑 YAML,然后提交并推送。

这三者都使用 image.toolkit.fluxcd.io/v1 API。较旧的 v1beta2 版本已在 Flux 2.9 中从 CRD 里移除,因此升级之前请迁移任何旧清单。

安装额外的控制器

镜像控制器不属于默认安装。请再次 bootstrap 并加上它们,同时允许 Flux 向仓库推送:

flux bootstrap github \
  --owner=<your-github-user> \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/dev \
  --personal \
  --components-extra=image-reflector-controller,image-automation-controller \
  --read-write-key

Bootstrap 可以安全地重复执行。它会提交新的控制器清单并安装它们。--read-write-key 使部署密钥可写,这样自动化才能推送。用 kubectl get pods -n flux-system 进行验证。

扫描镜像仓库

apps/podinfo/image-repository.yaml,与你的 deployment 在同一个文件夹中:

apiVersion: image.toolkit.fluxcd.io/v1
kind: ImageRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  image: ghcr.io/stefanprodan/podinfo
  interval: 5m

对于私有镜像仓库,添加指向 Docker registry Secret 的 secretRef,该 Secret 可通过 kubectl create secret docker-registry 或 flux create secret oci 创建。

用策略选择标签

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

semver 配合 range: 6.x 会选择最高的 6.x 版本。其他策略类型有 numerical(最大数字)和 alphabetical,适用于构建号或日期之类的标签。对于基于标签名称的规则,请在策略中添加带正则表达式的 filterTags。

标记要更新的行

Flux 会更新你用注释标记的那些行。在 apps/podinfo/deployment.yaml 中:

    spec:
      containers:
        - name: podinfo
          image: ghcr.io/stefanprodan/podinfo:6.5.0 # {"$imagepolicy": "flux-system:podinfo"}

标记的格式是 namespace:policy-name。默认情况下它会替换整个镜像引用。若只想更新标签,请使用 {"$imagepolicy": "flux-system:podinfo:tag"};对于 Helm values 或 Kustomize 的 images 条目,同样的标记也可用于包含标签的那一行。没有标记的内容不会被改动。

告诉 Flux 如何提交

apiVersion: image.toolkit.fluxcd.io/v1
kind: ImageUpdateAutomation
metadata:
  name: flux-system
  namespace: flux-system
spec:
  interval: 30m
  sourceRef:
    kind: GitRepository
    name: flux-system
  git:
    checkout:
      ref:
        branch: main
    commit:
      author:
        name: fluxcdbot
        email: fluxcdbot@users.noreply.github.com
      messageTemplate: |
        Automated image update

        {{range .Changed.Changes}}
        - {{.OldValue}} -> {{.NewValue}}
        {{end}}
    push:
      branch: main
  update:
    path: ./apps
    strategy: Setters

关键部分说明:

  • sourceRef 是要提交到的 Git 仓库。它必须是可写的,因此需要 --read-write-key。
  • checkout.ref.branch 是它起始所在的分支,push.branch 是提交被推送到的分支。
  • update.path 限制扫描哪些文件夹中的标记。
  • messageTemplate 控制提交信息,使历史记录易读。

直接推送到 main 会让一切完全自动化。在你建立信任的过程中,可以改为推送到单独的分支(例如 push.branch: flux-image-updates),待满意后再合并拉取请求。变更只有在合并之后才会到达集群。

观察它的工作

提交并推送这些文件,然后检查每个阶段:

flux get image repository
flux get image policy
flux get image update

镜像仓库会显示扫描到的标签数量,策略会显示它选中的标签,而 update automation 会显示它最后推送的提交。如果选中的标签比你 YAML 中的更新,Git 中就会出现一次提交,然后 Flux 会像对待其他变更一样应用它。调试时,对每个对象使用 kubectl describe:标记错误、策略范围没有匹配到任何东西,或者部署密钥是只读的,是通常的罪魁祸首。

该选哪种方式

如果已经有一条流水线掌管着发布晋升,并且你希望只有一个地方决定发布什么,请使用由 CI 驱动的提交。如果你希望集群配置仓库能自行跟随镜像仓库,例如让 dev 环境始终保持在最新的补丁版本,请使用 Flux 镜像自动化。两者可以共存。

热门指南