
Flux 如何监听镜像标签更新实现 GitOps
前面我们在使用 Flux 进行 Gitops 实践的过程中,我们每次都需要在 CI 流水线去手动更新 Git 代码仓库中的 Values 文件的镜像版本,这样就会比较麻烦,和 Argo CD 类似,Flux 也提供了一个 Image Automation
控制器的功能。
原理
当新的容器镜像可用时,image-reflector-controller
和 image-automation-controller
可以协同工作来更新 Git 存储库。
-
image-reflector-controller
扫描镜像存储库并反射到 Kubernetes 资源中的镜像元数据。 -
image-automation-controller
根据扫描的最新镜像更新 YAML 文件,并将更改提交到指定的 Git 存储库。
但是需要注意的是默认情况下 Flux 不会自动安装 image-reflector-controller
和 image-automation-controller
,所以我们需要手动安装这两个控制器,可以通过 --components-extra
参数来指定要安装的组件,如下所示:
这两个控制器安装完成后,我们就可以使用 Flux 配置容器镜像扫描和部署发布了。对于容器镜像,可以将 Flux 配置为:
- 扫描镜像仓库并获取镜像标签
- 根据定义的策略(semver、calver、regex)选择最新的标签
- 替换 Kubernetes 清单中的标签(YAML 格式)
- 检出分支、提交并将更改推送到远程 Git 存储库
- 在集群中应用更改并变更容器镜像
对于生产环境,此功能允许你自动部署应用程序补丁(CVE 和错误修复),并在 Git 历史记录中保留所有部署的记录。
下面我们来思考下对于生产环境和测试环境 CI/CD 的工作流是怎样的?
生产环境 CI/CD 工作流
- DEV:将错误修复推送到应用程序存储库
- DEV:修改补丁版本并发布,例如
v1.0.1
- CI:构建并推送标记为
registry.domain/org/app:v1.0.1
的容器镜像 - CD:从镜像仓库中提取最新的镜像元数据(Flux 镜像扫描)
- CD:将应用程序清单中的镜像标签更新为
v1.0.1
(Flux 集群到 Git 调谐) - CD:将
v1.0.1
部署到生产集群(Flux Git 到集群调谐)
对于 Staging 环境,此功能允许你部署分支的最新版本,而无需在 Git 中手动编辑应用程序部署清单。
Staging 环境 CI/CD 工作流
- DEV:将代码更改推送到应用程序存储库主分支
- CI:构建并推送标记为
${GIT_BRANCH}-${GIT_SHA:0:7}-$(date +%s)
的容器镜像 - CD:从镜像仓库中提取最新的镜像元数据(Flux 镜像扫描)
- CD:将应用程序清单中的镜像标记更新为
main-2d3fcbd-1611906956
(Flux 集群到 Git 调谐) - CD:将
main-2d3fcbd-1611906956
部署到 Staging 环境集群(Flux Git 到集群调谐)
示例
比如这里的示例使用的镜像地址为 cnych/devops-demo
,我们可以先创建一个 ImageRepository
来告诉 Flux 扫描哪个镜像仓库以查找新标签:
不知道 ImageRepository
如何编写,我们可以通过上面的 flux
命令来帮我们生成即可,上面的命令会生成如下所示的资源清单文件:
对于私有镜像,可以使用 kubectl create secret docker-registry
在与 ImageRepository
相同的命名空间中创建 Kubernetes Secret。同样使用的密码需要通过 Docker Hub 后台创建 Access Token 来获取。
然后,可以通过引用 ImageRepository
中的 Kubernetes Secret 来配置 Flux 以使用凭据:
然后就可以应用上面的资源清单文件了:
可以看到 ImageRepository
对象已经创建成功了,并且扫描到了 21 个镜像标签。当然我们也可以通过 kubectl describe imagerepository k8s-demo
命令来查看 ImageRepository
的各种状态:
如果你要告诉 Flux 在过滤标签时使用哪个 semver
版本范围的标签,则开源创建一个 ImagePolicy
对象。比如选择标签为 ${GIT_BRANCH}-${GIT_SHA:0:7}-$(date +%s)
的最新主分支构建,则可以使用以下 ImagePolicy
:
选择最新的稳定版本(semver):
选择 1.x 范围内的最新稳定补丁版本 (semver):
选择最新版本,包括预发行版 (semver):
由于 ImagePolicy
对象的策略只支持三种:
-
SemVer
:语义版本 -
Alphabetical
:字母顺序 -
Numerical
:数字顺序
而前面我们的镜像标签是根据 git commit id 来生成的,不符合这里的规范,所以我们可以更改下镜像的 Tag 生成策略:
然后我们可以通过如下所示的 ImagePolicy
对象来告诉 Flux 如何过滤镜像标签:
直接应用该资源对象即可:
可以看到 ImagePolicy
对象创建后过滤到了最新的镜像标签为 main-25de3e1a-1695469144
。
接下来我们就可以创建一个 ImageUpdateAutomation
对象来告诉 Flux 将镜像更新写入哪个 Git 存储库,但是这里还有一个问题就是我们的应用是通过 Helm Chart 来部署的,ImageUpdateAutomation
如何知道要把我们更新后的镜像标签写入到哪个 Values 文件中呢?写入到哪个位置呢?
这就需要用到 marker 功能了,用来标记 Image Automation Controller 自动更新的位置。比如我们这里使用的是 Helm Chart 来部署应用,决定使用哪个版本的镜像是通过 my-values.yaml
这个 Values 文件来指定的:
所以我们需要在该文件中添加一个 marker 来告诉 Flux 将镜像标签写入到哪个位置,这个镜像策略的 marker 标记的格式有如下几种:
-
{"$imagepolicy": "<policy-namespace>:<policy-name>"}
-
{"$imagepolicy": "<policy-namespace>:<policy-name>:tag"}
-
{"$imagepolicy": "<policy-namespace>:<policy-name>:name"}
这些标记作为注解内联放置在目标 YAML 中,Setter
策略是指 Flux 可以在调谐期间找到并替换的 kyaml setter。
我们这里重新修改下 my-values.yaml
文件,添加上 marker 标记:
我们在上面的 Values 文件中的 image.repository
和 image.tag
字段添加了 marker 标记,分别使用的是上面创建的 ImagePolicy 对象的 name 和 tag,这样 Flux 就知道要将镜像标签写入到哪个位置了。
接下来我们再创建一个 ImageUpdateAutomation
对象来告诉 Flux 将镜像更新写入哪个 Git 存储库,同样开源使用 flux 命令来创建:
该命令生成的 ImageUpdateAutomation
对象如下所示:
同样直接更新该资源对象即可:
现在我们去修改我们的应用程序代码,然后提交,通过 Jenkins Pipeline 构建并推送镜像到镜像仓库即可,正常情况下 ImageRepository 对象会自动扫描到新的镜像标签,然后 ImagePolicy 对象会过滤到最新的镜像标签,最后通过 ImageUpdateAutomation 对象会自动将镜像标签更新到 Git 代码仓库中的 Values 文件中,然后 Flux 就会自动更新应用了。
从上面的事件中可以看到,Flux 已经自动将镜像标签更新到了 Git 代码仓库中的 Values 文件中了,然后 Flux 就会自动更新应用了。当然可以查看 Git 仓库中的提交记录来验证:
当然这个 git commit 的信息模板是可以根据自己的需求来定义的,这个模板可以使用 Go Template 和大部分 Sprig 库 的语法,比如:
文章转载自公众号:k8s技术圈
