Skip to main content
版本:预览版

使用 FluxCD 做 GitOps

在本文中,我们主要讲解直接使用 KubeVela 在 GitOps 模式下进行交付的步骤。

请确保你已经开启了 FluxCD Addon。

监听 Git 仓库并自动同步

准备配置仓库

GitOps 模式会自动同步仓库的配置到集群中,首先,我们需要一个仓库,里面存放着所有你需要的配置文件:如一些 Kubernetes 原生资源 Deployment,Secret,ConfigMap 等。当然,你可以在直接在仓库中存放 KubeVela 的 Application。

假设在我们的仓库中,有一个叫做 infrastructure 的文件夹,里面有一个叫做 server 的 KubeVela Application 以及一个叫做 server-config 的 ConfigMap。

配置仓库的目录结构如下:

├── infrastructure
   ├── server-config.yaml
   └── server.yaml

部署如下 KubeVela GitOps 应用:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: infra-gitops
spec:
components:
- name: database-config
type: kustomize
properties:
repoType: git
# 将此处替换成你需要监听的 git 配置仓库地址
url: https://github.com/FogDong/KubeVela-GitOps-Infra-Demo
# 如果是私有仓库,还需要关联 git secret
# secretRef: git-secret
# 自动拉取配置的时间间隔,由于基础设施的变动性较小,此处设置为十分钟
pullInterval: 10m
git:
# 监听变动的分支
branch: infra
# 监听变动的路径,指向仓库中 infrastructure 目录下的文件
path: ./infrastructure

查看该 GitOps 应用状态:

$ vela status infra-gitops
About:

Name: infra-gitops
Namespace: default
Created at: 2022-06-30 14:52:33 +0800 CST
Status: running

Workflow:

mode: DAG
finished: true
Suspend: false
Terminated: false
Steps
- id:dgatat8jag
name:database-config
type:apply-component
phase:succeeded
message:

Services:

- Name: database-config
Cluster: local Namespace: default
Type: kustomize
Healthy
No trait applied

可以看到,该 GitOps 应用已经正常运行。此时,该应用会以 10 分钟的间隔不断拉取仓库中的配置并在集群中进行同步。

查看集群中的资源,可以发现 server Application 以及 server-config ConfigMap 都已经被自动部署了。

$ vela ls
APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
infra-gitops database-config kustomize running healthy 2022-06-30 14:52:33 +0800 CST
server server webservice running healthy Ready:1/1 2022-06-30 14:52:35 +0800 CST

$ kubectl get configmap
NAME DATA AGE
server-config 1 2m58s

监听镜像仓库并自动同步

GitOps 也可以通过监听你的镜像仓库,获得最新镜像版本,并用最新版本来更新你代码仓库中的配置,从而达到自动更新镜像的目的。

假设我们代码仓库的目录结构如下:

├── application
   └── my-app.yaml

application 中 my-app.yaml 如下:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: my-app
namespace: default
spec:
components:
- name: my-app
type: webservice
properties:
image: nginx # {"$imagepolicy": "default:image-gitops"}

注意,image 字段后有 # {"$imagepolicy": "default:image-gitops"} 的注释。KubeVela 会通过该注释去更新对应的镜像字段。default:image-gitops 是我们即将部署的 GitOps 应用组件对应的命名空间和名称。

部署如下 KubeVela GitOps 应用:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: image-gitops
spec:
components:
- name: image-gitops
type: kustomize
properties:
repoType: git
# 将此处替换成你需要监听的 git 配置仓库地址
url: https://github.com/FogDong/KubeVela-GitOps-Infra-Demo
# 需要在此处声明你的 git secret,因为 GitOps 会用最新的镜像更新你仓库中的文件,需要写权限
secretRef: git-secret
pullInterval: 1m
git:
# 监听变动的分支
branch: image
# 监听变动的路径,指向仓库中 application 目录下的文件
path: ./application
imageRepository:
# 将此处替换成你需要的镜像地址
image: ghcr.io/fogdong/test-fog
# 如果这是一个私有的镜像仓库,可以通过 `kubectl create secret docker-registry` 创建对应的镜像秘钥并相关联
# secretRef: imagesecret
filterTags:
# 可对镜像 tag 进行过滤
pattern: '^master-[a-f0-9]+-(?P<ts>[0-9]+)'
extract: '$ts'
# 通过 policy 筛选出最新的镜像 Tag 并用于更新
policy:
numerical:
order: asc
# 追加提交信息
commitMessage: "Image: {{range .Updated.Images}}{{println .}}{{end}}"

应用部署成功后,可以看到 my-app 应用也已经被自动部署。此时,my-app 中的镜像为 nginx

$ vela ls
APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
image-gitops image-gitops kustomize running healthy 2022-06-30 15:16:30 +0800 CST
my-app my-app webservice running healthy Ready:1/1 2022-06-30 15:16:31 +0800 CST

隔了一段时间之后,我们配置的 imageRepository 会自动拉取到我们希望的最新镜像,并更新仓库中的应用镜像。

此时,可以看到配置仓库中有一条来自 kubevelabot 的提交,该提交将 nginx 镜像替换成了我们自己仓库的最新镜像。提交信息均带有 Update image automatically. 前缀。你也可以通过 {{range .Updated.Images}}{{println .}}{{end}}commitMessage 字段中追加你所需要的信息。

alt

值得注意的是,如果你希望将代码和配置放在同一个仓库,需要过滤掉来自 kubevelabot 的提交来防止流水线的重复构建。可以在 CI 中通过如下配置过滤:

jobs:
publish:
if: "!contains(github.event.head_commit.message, 'Update image automatically')"

重新查看集群中的应用,可以看到经过一段时间后,应用 my-app 的镜像已经被更新。

KubeVela 会通过你配置的 interval 时间间隔,来每隔一段时间分别从配置仓库及镜像仓库中获取最新信息:

  • 当 Git 仓库中的配置文件被更新时,KubeVela 将根据最新的配置更新集群中的应用。
  • 当镜像仓库中多了新的 Tag 时,KubeVela 将根据你配置的 policy 规则,筛选出最新的镜像 Tag,并更新到 Git 仓库中。而当代码仓库中的文件被更新后,KubeVela 将重复第一步,更新集群中的文件,从而达到了自动部署的效果。

FAQ

如何在 GitOps 中控制应用版本

当应用的 Spec 变化时,应用将重新运行其工作流以进行部署。如果你希望严格控制应用的版本和部署,你可以使用 Publish Version。有了它,你还可以浏览应用的历史版本、进行跨版本配置比对、版本回滚以及版本重新发布。

备注

如果你在应用中使用了外置策略或工作流,那么当你的外置策略或工作流变化时,你的应用 Spec 不一定会变化。此时,你可以使用 PublishVersion 来强制应用进行重新部署。

如果你希望在 GitOps 中控制应用版本,那么你需要在 CI 中更新应用的 PublishVersion,从而控制应用的版本和部署。

备注

在更新 PublishVersion 前,请确保你的应用中有一个初始版本:

metadata:
name: my-app
annotations:
app.oam.dev/publishVersion: <initial version>

你可以参考示例仓库或者配置如下的 CI 流水线来进行版本的更新:

name: Auto Commit
on:
push:
branches:
- '*'

jobs:
run:
name: Auto Commit
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2

- name: Update publish version
id: update
run: |
VERSION=${GITHUB_SHA::8}
echo ::set-output name=VERSION::${VERSION}
# 将 app.yaml 替换成你的应用文件名
sed -i "s|app.oam.dev/publishVersion: .*|app.oam.dev/publishVersion: $VERSION|" app.yaml

- name: Commit changes
uses: EndBug/add-and-commit@v7
with:
default_author: github_actions
add: '.'
message: "[ci skip] deploy from ${{ steps.update.outputs.VERSION }}"
signoff: true
# 设置 branch
# branch: main

这个 CI 会使用 GitHub SHA 作为版本号来更新应用的 PublishVersion。上述 CI 是一个 GitHub Action 的例子,如果你在使用别的 CI 工具,可以参考上述的逻辑来实现。

获取更多

你还可以查看 GitOps 博客 以及 视频实践 来更好地体验以及使用 GitOps 功能。