基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

【玩转容器持久化存储】点我进入活动页面

目录和架构(文章最后可获取更多资料)

本文分为7个段落,完成前5个段落即可实现标准的CI/CD环境,最后2个段落验证CI/CD环境的pipeline。
一、创建NAS资源
二、创建ACK集群
三、配置NAS挂载信息
四、创建GitLab平台
五、创建Jenkins平台
六、配置demo应用的CI/CD环境
七、演示demo应用的CI/CD的pipeline


CI/CD架构图:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

一、创建NAS资源

1. 开通NAS服务

阿里云文件存储NAS是一个可共享访问,弹性扩展,高可靠,高性能的分布式文件系统。它可以为容器提供持久化的存储服务。在接下来的操作里,您的网页文件将会被保存在NAS文件系统中,当容器pod被创建后即可直接调用NAS里的文件,并且在pod被销毁后,NAS里的文件也会继续留存。
如果您还没有开通NAS服务,请登录NAS开通页面,点击“立即开通”按钮,完成开通流程。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

2. 创建极速型NAS

网站服务需要存储系统提供低时延性能,所以极速型文件系统(时延0.3毫秒)最适合这种场景。其他NAS类型,如通用容量型主要适用于大容量文件存储类应用,通用性能型主要适用于高带宽文件访问类应用。
在您开通NAS服务之后,请登录NAS控制台,点击“创建极速型NAS文件系统”,选择您业务所在的地域,然后逐个查看可用区,直到“类型”一项显示“高级型”,最后点击“立即购买”,完成付款。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

3. 创建专有网络VPC

为了使容器集群能够挂载使用刚刚创建的NAS文件系统,您需要配置相应的网络环境,包括一个专有网络VPC和一个NAS挂载点。将虚拟交换机和NAS文件系统放在同一个可用区,可以将时延降到最低。
如果您在业务所在的地域还没有专有网络VPC,请登录VPC控制台,创建一个专有网络。在填写“交换机”信息时,请选择NAS所在的可用区。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

4. 创建NAS挂载点

NAS挂载点是计算平台挂载使用NAS所需的网络入口。如果把容器服务比喻成一台笔记本电脑,把NAS文件系统比喻成一个移动硬盘,那么NAS挂载点就相当于一条USB线,可以将二者连接起来。
回到NAS控制台,点击左侧引导栏中的“文件系统列表”,然后在页面最上方选择业务所在的地域,最后点击刚创建的文件系统ID,进入文件系统详情页。
进入文件系统详情页后,点击左侧引导栏中的“挂载使用”,点击“添加挂载点”,在对话框中选择“专有网络”、刚刚创建的专有网络VPC、刚刚创建的交换机、“VPC默认权限组”,点击确定,等待NAS挂载点创建完成。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

二、创建ACK集群

容器服务Kubernetes版(也称作ACK)提供托管的K8S容器服务,您可以使用图形化界面实现各种配置,例如挂载NAS、部署应用、配置应用弹性扩展等操作,比自建K8S使用起来方便许多。在接下来的操作里,ACK集群将作为网站的服务端运行NGINX框架,处理用户发来的HTTP请求。
登录“容器服务Kubernetes版”控制台,如果需要则完成授权流程,点击“创建集群”、“标准型集群”。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

1. 集群配置

在“集群配置”页面中,填写集群名称,选择NAS所在地域,选择NAS挂载点所在的专有网络VPC和交换机,其余选项保留默认,点击“下一步”继续。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

2. Worker配置

在“Worker配置”页面中,选择您业务需要的“实例规格”,配置“登录方式”,点击“下一步”继续。

3. 组件配置

在“组件配置”页面中,保留默认的“安装Ingress插件”、“公网”负载均衡类型和“CSI”存储插件,点击“下一步”继续。

4. 确认配置

在“确认配置”页面中,检查您的容器集群配置,如果“依赖检查”失败则处理相关问题,勾选同意服务条款,最后点击“创建集群”,等待大约10分钟后,集群创建成功。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

三、配置NAS挂载信息

要使用ACK服务挂载使用NAS,需要先配置容器存储卷PV和存储声明PVC信息,这些信息将会在您部署NGINX应用的时候用到。

1. 创建命名空间gitops

我们将会把gitlab和jenkins全部部署到此命名空间下,在ACK集群详情页面中,点击左侧引导栏中的“命名空间”,点击“创建”。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

2. 配置存储卷

回到ACK集群列表,点击刚刚创建的ACK集群名称,进入集群详情页。
进入集群详情页后,点击左侧引导栏中的“存储卷”,点击“存储卷”标签页,点击“创建”,选择“NAS”存储卷类型,填写存储卷名称,选择NAS挂载点,最后点击“创建”。其他内容保留默认值即可。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

3. 配置存储声明

完成存储卷配置后,请点击“存储声明”标签页(注意选择gitops命名空间),点击“创建”,选择“NAS”存储声明类型,填写存储声明名称,选择刚刚创建的存储卷,最后点击“创建”。其他内容保留默认值即可。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

四、创建GitLab平台

完成上述准备工作后,就可以创建GitLab平台。

1. 创建GitLab应用(可选项,可以对接已有GitLab环境)

容器服务控制台上依次点击 市场 -> 应用目录 -> gitlab-ce 。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
在 参数 中设置externalUrl和gitlabRootPassword后选择gitops命名空间并创建应用,本次实践中 externalUrl 设置为 http://gitlab.prytest.com/, 如果没有dns解析的话,可以在创建成功后直接使用ip。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
容器服务控制台上依次点击 集群 -> 服务 查看gitlab应用的访问地址,大约2分钟后可访问gitlab并登陆,管理员名为root,密码为刚配置的gitlabRootPassword:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

五、创建Jenkins平台

完成上述准备工作后,就可以创建Jenkins平台。

1. 创建Jenkins应用

容器服务控制台上依次点击 市场 -> 应用目录 ->  jenkins 。
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
在 参数 中设置Master.AdminPassword的值,选择gitops命名空间后点击创建:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
容器服务控制台上依次点击 集群 -> 服务 查看jenkins应用的访问地址,大约1分钟后可访问jenkins并登陆:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

2. 将NAS配置为Jenkins的workspace

NAS作为Jenkins的workspace有以下几个优点:

  • 无需为每个worker申请磁盘,所有worker共享一个NAS作为持久存储,无需为worker配置大量存储空间;
  • pipeline的git代码持久存储在NAS中,每次构建可增量构建,缩减git下载代码的时间,加速构建过程;
  • NAS持久存储如java maven的依赖库,所有应用共享依赖库,无需每次下载依赖库,加速构建过程;
  • 容器故障后需要在不同宿主节点进行切换,共享NAS存储可以保证在容器的持久化数据在切换过程中不丢失,达到增量构建的加速效果。


Jenkins控制台上依次点击 Manage Jenkins -> Manage Nodes and Clouds ->  Configure Clouds 
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


配置jenkins-nas作为/home/jenkins/agent的存储目录:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

六、配置demo应用的CI/CD环境

CI/CD的环境准备就绪,我们现在可以配置一个demo应用。

1. 新建private group application

基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

2. 新建并上传private project application-demo

创建private project application-demo, 示例源码地址:

https://code.aliyun.com/haoshuwei/application-demo.git

上传源码到自己的源码仓库之前需要注意修改application-demo.yaml文件中的cbf5fdabb9f6a4d5897190935ab3d3155字段为您自己的k8s集群id:

- host: INGRESS_HOST.cbf5fdabb9f6a4d5897190935ab3d3155.cn-beijing.alicontainer.com

基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


上传源码到自己的源码仓库之前需要注意删除application-demo.yaml文件中的nodePort字段,删除后nodePort会随机生成,避免发布应用的port冲突(参考链接:http://dockone.io/article/4884):
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


从master新建一个分支latest:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践




设置master和latest分支只有管理员才能merge和push代码的操作:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

3. 新建private group builds

基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

4. 新建并上传private project preview-pipeline staging-pipeline production-pipeline

preview-pipeline示例源码地址为:

https://code.aliyun.com/haoshuwei/preview-pipeline.git

staging-pipeline示例源码地址为:

https://code.aliyun.com/haoshuwei/staging-pipeline.git

production-pipeline示例源码地址为:

https://code.aliyun.com/haoshuwei/production-pipeline.git


上传3个构建项目之前需要替换以下字段:
IMAGE_REPO:应用容器镜像要上传到哪个镜像仓库,镜像仓库地址(仓库名为application-demo,设置为公共仓库);
dingTalkToken:钉钉通知所使用的钉钉机器人accessToken;
Fetch Git Repo -> credentialsId:用于Jenkins拉取git项目的证书名称,需要在Jenkins中创建名为gitlab的证书;
Fetch Git Repo -> url:Jenkins拉取git repo的url;
Maven Build -> cmd:修改mvn命令行为"mkdir -p /home/jenkins/agent/workspace/maven-repository;rm -rf /root/.m2;ln -s /home/jenkins/agent/workspace/maven-repository /root/.m2;mvn package -B -DskipTests",/root/.m2/repository为maven的默认本地缓存仓库,我们在这里创建一个软链接,链接到/home/jenkins/agent/workspace/maven-repository,即可实现将repository持久存储在NAS中,加速maven构建过程
Docker Build And Publish->kaniko:增加--skip-tls-verify选项,避免认证错误。


代码示例如下:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

5. 注册一个普通开发者用户developer

基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


管理员用户登录后将developer用户添加为application组的developer member:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


此时developer用户只有application组下projects的权限, 没有builds组的权限:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

6. 生成一个apiToken用于Jenkins配置gitlabConnection

生成并复制保存apiToken:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

7. 配置gitlabConnection

系统管理 -> 系统设置 -> Gitlab:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
配置完毕后点击 Save 保存。

8. 新建构建任务preview-pipeline

8.1 新建任务,输入名称选择流水线类型并点击创建:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


8.2 Build Triggers 区域勾选 GitLab 插件配置如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


点击 Advanced 进行高级选项配置如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
复制并保存GitLab webhook URL和Secret token的值用于在Gitlab上配置webhook。


8.3 Pipeline区域配置preview-pipeline构建项目的git repo
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
完成配置后点击 保存。

9. 新建构建任务staging-pipeline

9.1 新建任务,输入名称选择流水线类型并点击创建:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


9.2 Build Triggers 区域勾选 GitLab 插件配置如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


点击 Advanced 进行高级选项配置如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
复制并保存GitLab webhook URL和Secret token的值用于在Gitlab上配置webhook。


9.3 Pipeline区域配置staging-pipeline构建项目的git repo
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
完成配置后点击 保存。

10. 新建构建任务production-pipeline

10.1 新建任务,输入名称选择流水线类型并点击创建:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


10.2 Build Triggers 区域勾选 GitLab 插件配置如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


点击 Advanced 进行高级选项配置如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
复制并保存GitLab webhook URL和Secret token的值用于在Gitlab上配置webhook。


10.3 Pipeline区域配置production-pipeline构建项目的git repo
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
完成配置后点击 保存。

11. 创建docker registry auth secret

在K8s控制台点击使用CloudShell管理集群,该secret配置会用于jenkins push和pull镜像:

$ docker login registry.cn-shenzhen.aliyuncs.com
$ kubectl -n gitops create secret generic jenkins-docker-cfg --from-file=/home/shell/.docker/config.json

12. 创建clusterrolebinding授予serviceaccount default对gitops命名空间的管理权限

clusterrolebinding.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gitops-cluster-admin
subjects:
  - kind: ServiceAccount
    name: default
    namespace: gitops
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
$ kubectl create -f clusterrolebinding.yaml

13. 设置Jenkins匿名用户的可读权限

系统管理 ->全局安全管理-> Authorization -> 勾选 Allow anonymous read access 并保存:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

14. 配置GitLab webhook

进入application-demo项目的webhook配置页面:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

15. 配置触发jenkins job preview-pipeline的触发器

如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

16. 配置触发jenkins job staging-pipeline的触发器

如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

17. 配置触发jenkins job production-pipeline的触发器

如图所示:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

七、演示demo应用的CI/CD的pipeline

1. developer用户修改代码并提交MergeRequest到latest分支

1.1 在application-demo项目上新建一个开发分支features/change-index-1
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


1.2 修改src/main/resources/static/index.html中的kubernetes.svg为jenkins.svg并提交修改
1.3 创建请求合并到latest分支的Merge Request
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


Open MergeRequest的动作会触发jenkins job preview-pipeline的自动构建,并完成以下stages:
(1)拉取http://xxx.xxx.xxx/builds/preview-pipeline.git项目并按照Jenkins定义的内容继续执行以下内容
(2)Fetch Git Repo: 拉取应用源码项目http://xxx.xxx.xxx.xxx/application/application-demo.git
(3)Maven Build: 打包
(4)Maven Test: 测试
(5)Docker Build And Publish: docker镜像构建和推送
(6)Kubectl Deploy: 部署应用到Kubernetes集群(本示例使用的是本集群的一个动态创建的命名空间preview-xxx)
(7)Post Actions: 钉钉通知


developer可以查看Merge Request页面的内容
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


点击可跳转至jenkins构建日志:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


1.4 构建完成后可以看到一个application-demo应用的预览页面
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


点击预览应用:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践


也可以直接在钉钉群里查看应用访问链接等信息:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
1.5 应用预览验证后, developer可以申请管理员接受此合并

2. 管理员合并指向latest分支的MergeRequest

合并MR:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
Accept MR的动作或触发staging-pipeline的构建,拉取application-demo项目的latest分支代码并构建和部署到staging命名空间下。


查看钉钉通知并访问staging环境中的application-demo应用:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

3. 管理员创建latest到master分支的Merge Request并合并此指向master的Merge Request

Accept MR的动作或触发production-pipeline的构建,拉取application-demo项目的master分支代码并构建和部署到production命名空间下。
查看钉钉通知并访问production环境中的application-demo应用:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

4. 对比使用NAS后的构建加速的效果

未修改maven仓库为NAS目录前的Maven Build耗时7分钟,并且严重依赖优良的网络环境:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

修改maven仓库为NAS目录后的Maven Build耗时15秒:
基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

更多资料

阿里云文件存储NAS支持SMB、NFS、CPFS三款文件系统,满足Windows、Linux、高性能计算等全场景应用,欢迎进群交流高性能分布式存储技术。
•阿里云容器存储解决方案 https://www.aliyun.com/solution/datatest/containernas
•阿里云文件存储 NAS https://www.aliyun.com/product/nas
•阿里云文件存储 CPFS https://www.aliyun.com/product/nas_cpfs
•阿里云容器服务 ACK https://www.aliyun.com/product/kubernetes
•阿里云 Serverless 容器服务 ASK https://www.aliyun.com/product/cs/ask
•阿里云开发者社区-阿里云存储服务 https://developer.aliyun.com/group/storage

基于K8s、NAS、GitLab、Jenkins的持续集成交付容器环境最佳实践

上一篇:MySQL阶段二——sql语句基础(2)


下一篇:Java 异常设计最佳实践