版本:v1.6

使用 FluxCD 做 GitOps

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

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

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

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

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

  1. ├── infrastructure
  2. ├── server-config.yaml
  3. └── server.yaml

部署如下 KubeVela GitOps 应用:

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

查看该 GitOps 应用状态:

  1. $ vela status infra-gitops
  2. About:
  3. Name: infra-gitops
  4. Namespace: default
  5. Created at: 2022-06-30 14:52:33 +0800 CST
  6. Status: running
  7. Workflow:
  8. mode: DAG
  9. finished: true
  10. Suspend: false
  11. Terminated: false
  12. Steps
  13. - id:dgatat8jag
  14. name:database-config
  15. type:apply-component
  16. phase:succeeded
  17. message:
  18. Services:
  19. - Name: database-config
  20. Cluster: local Namespace: default
  21. Type: kustomize
  22. Healthy
  23. No trait applied

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

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

  1. $ vela ls
  2. APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
  3. infra-gitops database-config kustomize running healthy 2022-06-30 14:52:33 +0800 CST
  4. server server webservice running healthy Ready:1/1 2022-06-30 14:52:35 +0800 CST
  5. $ kubectl get configmap
  6. NAME DATA AGE
  7. server-config 1 2m58s

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

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

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

application 中 my-app.yaml 如下:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: my-app
  5. namespace: default
  6. spec:
  7. components:
  8. - name: my-app
  9. type: webservice
  10. properties:
  11. image: nginx # {"$imagepolicy": "default:image-gitops"}

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

部署如下 KubeVela GitOps 应用:

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

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

  1. $ vela ls
  2. APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
  3. image-gitops image-gitops kustomize running healthy 2022-06-30 15:16:30 +0800 CST
  4. 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 中通过如下配置过滤:

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

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

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

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

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

使用 FluxCD 做 GitOps - 图2备注

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

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

使用 FluxCD 做 GitOps - 图3备注

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

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

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

  1. name: Auto Commit
  2. on:
  3. push:
  4. branches:
  5. - '*'
  6. jobs:
  7. run:
  8. name: Auto Commit
  9. runs-on: ubuntu-latest
  10. steps:
  11. - name: Checkout repo
  12. uses: actions/checkout@v2
  13. - name: Update publish version
  14. id: update
  15. run: |
  16. VERSION=${GITHUB_SHA::8}
  17. echo ::set-output name=VERSION::${VERSION}
  18. # 将 app.yaml 替换成你的应用文件名
  19. sed -i "s|app.oam.dev/publishVersion: .*|app.oam.dev/publishVersion: $VERSION|" app.yaml
  20. - name: Commit changes
  21. uses: EndBug/add-and-commit@v7
  22. with:
  23. default_author: github_actions
  24. add: '.'
  25. message: "[ci skip] deploy from ${{ steps.update.outputs.VERSION }}"
  26. signoff: true
  27. # 设置 branch
  28. # branch: main

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

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

Last updated on 2022年12月1日 by Somefive