
在现在的云原生世界里面 GitOps 不断的被提及,这种持续交付的模式越来越受到了大家的青睐,我们前面也有文章详细讲解了 GitOps 的相关概念,在网上也可以找到很多关于它的资源,但是关于 GitOps 相关的工作流实践的示例却并不多见,我们这里就将详细介绍一个使用示例,希望对大家实践 GitOps 有所帮助。
GitOps Workflow
上图是当前示例中的 GitOps 工作流程。GitLab 和 Argo CD 是两个主要的核心组件:
Argo CD 是一个声明式、GitOps 持续交付的 Kubernetes 工具,它的配置和使用非常简单,并且自带一个简单易用的 Dashboard 页面,更重要的是 Argo CD 支持 kustomzie、helm、ksonnet 等多种工具。应用程序可以通过 Argo CD 提供的 CRD 资源对象进行配置,可以在指定的目标环境中自动部署所需的应用程序。关于 Argo CD 更多的信息可以查看官方文档了解更多。
GitLab CI 是 GitLab 的持续集成和持续交付的工具,也是非常流行的 CI/CD 工具,相比 Jenkins 更加轻量级,更重要的是和 GitLab 天然集成在一起的,所以非常方便。
当前前提条件是有一个可用的 Kubernetes 集群,通过 kubectl 可以正常访问集群,为了访问 Argo CD 的 Dashboard 页面,我们可以通过 Ingress 来暴露服务,为此需要在 Kubernetes 中安装一个 Ingress Controller,我这里已经提前安装了 ingress-nginx,接下来我们将 Helm3 来安装 Argo CD,关于 Helm 以及 ingress-nginx 的使用我们前面的文章中已经多次提到,这里就不再详细介绍他们的使用了。
首先创建一个 argocd 的命名空间:
然后添加 argocd 的 chart 仓库地址:
接下来我们就可以使用 Helm 安装 Argo CD 了:
其中 values.yaml 文件如下所示,用来定制安装的 Argo CD:
执行上面的安装命令后,Argo CD 就会被安装在 argocd 命名空间之下,可以在本地 /etc/hosts 中添加一个映射,将 argocd.k8s.local 映射到 ingress-nginx 所在的节点即可:
当所有 Pod 变成 Running 状态后,我们就可以通过浏览器访问 Argo CD 的 Dashboard 页面了:
默认的用户名为 admin,密码为 server Pod 的名称,可以通过如下所示的命令来获取:
用上面的用户名和密码即可登录成功,接下来我们在 GitLab 中来创建示例项目。
我们这里使用的示例项目是一个 Golang 程序,在页面上显示一个文本信息和 Pod 名称,代码地址:https://github.com/cnych/gitops-webapp-demo。我们可以将该项目代码上传到我们自己的 GitLab 上面去,我这里的 GitLab 安装在 Kubernetes 之上,通过配置域名 git.k8s.local 进行访问,调整过后我们本地的代码仓库地址为:http://git.k8s.local/course/gitops-webapp 。
接下来需要添加一些在 GitLab CI 流水线中用到的环境变量(Settings → CI/CD → Variables):
CI_REGISTRY - 镜像仓库地址,值为:https://index.docker.io/v1/
CI_REGISTRY_IMAGE - 镜像名称,值为:cnych/gitops-webapp
CI_REGISTRY_USER - Docker Hub 仓库用户名,值为 cnych
CI_REGISTRY_PASSWORD - Docker Hub 仓库密码
CI_PASSWORD - Git 仓库访问密码
CI_USERNAME - Git 仓库访问用户名
现在我们可以开始使用 GitOps 来配置我们的 Kubernetes 中的应用了。Argo CD 自带了一套 CRD 对象,可以用来进行声明式配置,这当然也是推荐的方式,把我们的基础设施作为代码来进行托管,下面是我们为开发和生产两套环境配置的资源清单:
上面定义的 Application 这个资源,就是 Argo CD 用于描述应用的 CRD 对象:
name:Argo CD 应用程序的名称
project:应用程序将被配置的项目名称,这是在 Argo CD 中应用程序的一种组织方式
repoURL:源代码的仓库地址
targetRevision:想要使用的 git 分支
path:Kubernetes 资源清单在仓库中的路径
destination:Kubernetes 集群中的目标
然后同样使用 kubectl 工具直接部署上面的资源对象即可,将会创建两个 Application 类型的对象:
此时我们再去 Argo CD 的 Dashboard 首页同样将会看到两个 Application 的信息:
点击其中一个就可以看到关于应用的详细信息,我们可以在 gitops-webapp 代码仓库的 deployment/<env> 目录里面找到资源对象。我们可以看到,在每个文件夹下面都有一个 kustomization.yaml 文件,Argo CD 可以识别它,不需要任何其他的设置就可以使用。
由于我们这里的代码仓库是私有的 GitLab,所以我们还需要配置对应的仓库地址,在页面上 Settings → Repositories,点击 Connect Repo using HTTPS 按钮:
添加我们的代码仓库认证信息:
需要注意的是这里默认使用的是 HTTPS,所以我们需要勾选下方的 Skip server verification,然后点击上方的 CONNECT 按钮添加即可。然后重新同步上面的两个 Application,就可以看到正常的状态了。
接下来我们需要为应用程序创建流水线,自动构建我们的应用程序,推送到镜像仓库,然后更新 Kubernetes 的资源清单文件。
下面的示例并不是一个多么完美的流水线,但是基本上可以展示整个 GitOps 的工作流。开发人员在自己的分支上开发代码,他们分支的每一次提交都会触发一个阶段性的构建,当他们将自己的修改和主分支合并时,完整的流水线就被触发。将构建应用程序,打包成 Docker 镜像,将镜推送到 Docker 仓库,并自动更新 Kubernetes 资源清单,此外,一般情况下将应用部署到生产环境需要手动操作。
GitLab CI 中的流水线默认定义在代码仓库根目录下的 .gitlab-ci.yml 文件中,在该文件的最上面定义了一些构建阶段和环境变量、镜像以及一些前置脚本:
接下来是阶段的定义和所需的任务声明。我们这里的构建过程比较简单,只需要在一个 golang 镜像中执行一个构建命令即可,然后将编译好的二进制文件保存到下一个阶段处理,这一个阶段适合分支的任何变更:
然后就是构建镜像并推送到镜像仓库,这里我们使用 Kaniko,当然也可以使用 DinD 模式进行构建,只是安全性不高,这里我们可以使用 GIT 提交的 commit 哈希值作为镜像 tag,关于 Docker 镜像仓库的认证和镜像地址信息可以通过项目的参数来进行传递,不过这个阶段只在主分支发生变化时才会触发:
下一个阶段就是将应用程序部署到开发环境中,在 GitOps 中就意味着需要更新 Kubernetes 的资源清单,这样 Argo CD 就可以拉取更新的版本来部署应用。这里我们使用了为项目定义的环境变量,包括用户名和 TOKEN,此外在提交消息里面增加 [skip ci] 这样的关键字,这样流水线就不会被触发:
最后添加一个部署到 prod 环境的阶段,和前面非常类似,只是添加了一个手动操作的流程:
这样我们就完成了整个流水线的定义。
接下来我们来看看它们是如何一起工作的。我们将开发和线上两个环境的应用分别部署在了 dev 和 prod 命名空间之下,通过 Ingress 暴露服务,同样需要将两个应用的域名 http://webapp.dev.k8s.local/ 与 http://webapp.prod.k8s.local/ 在本地 /etc/hosts 中添加映射。
如果一切正常的话现在我们可以在浏览器中来查看我们部署的 web 应用程序了。
Dev web app
然后我们来尝试修改下代码,编辑 main.go 文件,将变量 welcome 中的 GITOPS 修改为 GITOPS-K8S:
然后提交代码到 master 分支,然后进入 GitLab 项目 -> CI/CD -> Pipelines,就可以看到一个新的流水线开始构建了。
等待一会儿,正常情况下会执行到 dev 的部署阶段,然后变成 skipped 的状态,此时流水线已经将代码中的 dev 下的资源清单文件已经更新了。
GitLab CI/CD Pipeline
然后 Argo CD 在自动同步模式下在一分钟内变会更新 Kubernetes 的资源对象,我们也可以在 Argo CD 的页面中看到进度。当 Argo CD 中同步完成后我们再去查看 DEV 环境的应用,就可以看到页面上面的信息已经变成了 GITOPS-K8S 了。
Update Dev Web APP
最后如果需要部署到 prod 环境,我们只需要在 GitLab 的流水线中手动触发即可,之后,prod 中的镜像也会被更新。
GitLab CI/CD Prod deployment
下面是同步时 Argo CD 更新的页面状态变化图。
Argo CD Sync Workflow
到这里,我们就使用 GitOps 成功的将我们的应用部署到了开发和生产环境之中了。
https://www.weave.works/technologies/gitops/
https://argoproj.github.io/argo-cd/
https://docs.gitlab.com/ee/ci/yaml/
https://medium.com/@andrew.kaczynski/gitops-in-kubernetes-argo-cd-and-gitlab-ci-cd-5828c8eb34d6
https://github.com/cnych/gitops-webapp-demo