
基于 Jenkins、Gitlab、Harbor、Helm 和 Kubernetes 的 CI/CD二
作者 阳明
来源 | k8s技术圈(ID:kube100)
Pipeline
第一个阶段:单元测试,我们可以在这个阶段是运行一些单元测试或者静态代码分析的脚本,我们这里直接忽略。
第二个阶段:代码编译打包,我们可以看到我们是在一个 maven的容器中来执行的,所以我们只需要在该容器中获取到代码,然后在代码目录下面执行 maven 打包命令即可,如下所示:
第三个阶段:构建 Docker 镜像,要构建 Docker 镜像,就需要提供镜像的名称和 tag,要推送到 Harbor 仓库,就需要提供登录的用户名和密码,所以我们这里使用到了 withCredentials方法,在里面可以提供一个 credentialsId为 dockerhub的认证信息,如下:
其中 ${image} 和 ${imageTag} 我们可以在上面定义成全局变量:
docker 的用户名和密码信息则需要通过 凭据来进行添加,进入 jenkins 首页 -> 左侧菜单 凭据 -> 添加凭据,选择用户名和密码类型的,其中 ID 一定要和上面的 credentialsId的值保持一致:
第四个阶段:运行 kubectl 工具,其实在我们当前使用的流水线中是用不到 kubectl 工具的,那么为什么我们这里要使用呢?这还不是因为我们暂时还没有去写应用的 Helm Chart 包吗?所以我们先去用原始的 YAML 文件来编写应用部署的资源清单文件,这也是我们写出 Chart 包前提,因为只有知道了应用如何部署才可能知道 Chart 包如何编写,所以我们先编写应用部署资源清单。
首先当然就是 Deployment 控制器了,如下所示:(k8s.yaml)
可以看到我们上面的 YAML 文件中添加使用的镜像是用标签代替的: <IMAGE>:<IMAGE_TAG>,这是因为我们的镜像地址是动态的,下依赖我们在上一个阶段打包出来的镜像地址的,所以我们这里用标签代替,然后将标签替换成真正的值即可,另外为了保证应用的稳定性,我们还在应用中添加了健康检查,所以需要在代码中添加一个健康检查的 Controller:(src/main/java/com/example/polls/controller/StatusController.java)
最后就是环境变量了,还记得前面我们更改了资源文件中数据库的配置吗?(src/main/resources/application.properties)因为要尽量通用,我们在部署应用的时候很有可能已经有一个外部的数据库服务了,所以这个时候通过环境变量传入进来即可。另外由于我们这里使用的是私有镜像仓库,所以需要在集群中提前创建一个对应的 Secret 对象:
在代码根目录下面创建一个 manifests 的目录,用来存放上面的资源清单文件,正常来说是不是我们只需要在镜像构建成功后,将上面的 k8s.yaml 文件中的镜像标签替换掉就 OK,所以这一步的动作如下:
第五阶段:运行 Helm 工具,就是直接使用 Helm 来部署应用了,现在有了上面的基本的资源对象了,要创建 Chart 模板就相对容易了,Chart 模板仓库地址:https://github.com/cnych/polling-helm,我们可以根据 values.yaml文件来进行自定义安装,模板中我们定义了可以指定使用外部数据库服务或者内部独立的数据库服务,具体的我们可以去看模板中的定义。首先我们可以先使用这个模板在集群中来测试下。首先在集群中 Clone 上面的 Chart 模板:
然后我们使用内部的数据库服务,新建一个 custom.yaml 文件来覆盖 values.yaml 文件中的值:
可以看到我们这里使用了一个名为 database的 StorgeClass 对象,所以还得创建先创建这个资源对象:
然后我们就可以在 Chart 根目录下面安装应用,执行下面的命令:
- 注意我们这里安装也是使用的 helm upgrade命令,这样有助于安装和更新的时候命令统一。
安装完成后,查看下 Pod 的运行状态:
然后我们可以在本地 /etc/hosts里面加上 http://ui.polling.domain的的映射,这样我们就可以通过这个域名来访问我们安装的应用了,可以注册、登录、发表投票内容了:
这样我们就完成了使用 Helm Chart 安装应用的过程,但是现在我们使用的包还是直接使用的 git 仓库中的,平常我们正常安装的时候都是使用的 Chart 仓库中的包,所以我们需要将该 Chart 包上传到一个仓库中去,比较幸运的是我们的 Harbor 也是支持 Helm Chart 包的。我们可以选择手动通过 Harbor 的 Dashboard 将 Chart 包进行上传,也可以通过使用 HelmPush插件:
当然我们需要首先将 Harbor 提供的仓库添加到 helm repo 中,由于是私有仓库,所以在添加的时候我们需要添加用户名和密码:
这里的 repo 的地址是 <HarborURL>/chartrepo/<Harbor中项目名称>,Harbor 中每个项目是分开的 repo,如果不提供项目名称,则默认使用 library这个项目。
需要注意的是如果你的 Harbor 是采用的自建的 https 证书,这里就需要提供 ca 证书和私钥文件了,否则会出现证书校验失败的错误 x509:certificatesignedbyunknown authority。我们这里是通过 cert-manager为 Harbor 提供的一个信任的 https 证书,所以没有指定 ca 证书相关的参数。
然后我们将上面的 polling-helm这个 Chart 包上传到 Harbor 仓库中去:
这个时候我们登录的 Harbor 仓库中去,查看 course 这个项目下面的 HelmCharts就可以发现多了一个 polling 的应用了:
我们也可以在右下角看到有添加仓库和安装 Chart 的相关命令。
到这里 Helm 相关的工作就准备好了。那么我们如何在 Jenkins Pipeline 中去使用 Helm 呢?我们可以回顾下,我们平时的一个 CI/CD 的流程:开发代码 -> 提交代码 -> 触发镜像构建 -> 修改镜像tag -> 推送到镜像仓库中去 -> 然后更改 YAML 文件镜像版本 -> 使用 kubectl 工具更新应用。
现在我们是不是直接使用 Helm 了,就不需要去手动更改 YAML 文件了,也不需要使用 kubectl 工具来更新应用了,而是只需要去覆盖下 helm 中的镜像版本,直接 upgrade 是不是就可以达到应用更新的结果了。我们可以去查看下 chart 包的 values.yaml 文件中关于 api 服务的定义:
我们是不是只需要将上面关于 api 服务使用的镜像用我们这里 Jenkins 构建后的替换掉就可以了,这样我们更改上面的最后 运行Helm的阶段如下:
当然我们可以将需要更改的值都放入一个 YAML 之中来进行修改,我们这里通过 --set来覆盖对应的值,这样整个 API 服务的完整 Jenkinsfile 文件如下所示:
由于我们没有将 chart 包放入到 API 服务的代码仓库中,这是因为我们这里使用的 chart 包涉及到两个应用,一个 API 服务,一个是前端展示的服务,所以我们这里是通过脚本里面去主动获取到 chart 包来进行安装的,如果 chart 包跟随代码仓库一起管理当然就要简单许多了。
现在我们去更新 Jenkinsfile 文件,然后提交到 gitlab 中,然后去观察下 Jenkins 中的构建是否成功,我们重点观察下 Helm 阶段:
当然我们还可以去做一些必要的判断工作,比如根据分支判断是否需要自动部署等等,同样也可以切换到 Blue Occean 界面查看构建结果。
现在大家可以尝试去修改下代码,然后提交代码到 gitlab 上,观察下 Jenkins 是否能够自动帮我们完成整个 CI/CD 的过程。
作业:现在还有一个前端展示的项目:https://github.com/cnych/polling-app-client,大家针对这个项目使用上面的 gitlab + jenkins + harbor + helm 来完成一个 Jenkins Pipeline 流水线的编写,尝试去修改下前端页面内容,看是否能够生效。
相关链接:
https://github.com/cnych/polling-helm
https://github.com/cnych/polling-app-server
https://github.com/cnych/polling-app-client
