Gitlab+Jenkins Pipeline+Docker+k8s+Helm自动化部署实践(干货!)
通过前面两篇文章,我们已经有了一个“嗷嗷待哺”的K8s集群环境,也对相关的概念与组件有了一个基本了解(前期对概念有个印象即可,因为只有实践了才能对其有深入理解,所谓“纸上得来终觉浅,绝知此事要躬行”),本文从实践角度介绍如何结合我们常用的Gitlab与Jenkins,通过K8s来实现项目的自动化部署,示例将包括基于SpringBoot的服务端项目与基于Vue.js的Web项目。
本文涉及到的工具与技术包括:
- Gitlab —— 常用的源代码管理系统
- Jenkins, Jenkins Pipeline —— 常用的自动化构建、部署工具,Pipeline以流水线的方式将构建、部署的各个步骤组织起来
- Docker,Dockerfile —— 容器引擎,所有应用最终都要以Docker容器运行,Dockerfile是Docker镜像定义文件
- Kubernetes —— Google开源的容器编排管理系统
- Helm —— Kubernetes的包管理工具,类似Linux的yum,apt,或Node的npm等包管理工具,能将Kubernetes中的应用及相关依赖服务以包(Chart)的形式组织管理
环境背景:
- 已使用Gitlab做源码管理,源码按不同的环境建立了develop(对应开发环境),pre-release(对应测试环境),master(对应生产环境)分支
- 已搭建了Jenkins服务
- 已有Docker Registry服务,用于Docker镜像存储(基于Docker Registry或Harbor自建,或使用云服务,本文使用阿里云容器镜像服务)
- 已搭建了K8s集群
预期效果:
- 分环境部署应用,开发环境、测试环境、生产环境分开来,部署在同一集群的不同namespace,或不同集群中(比如开发测试部署在本地集群的不同namespace中,生产环境部署在云端集群)
- 配置尽可能通用化,只需要通过修改少量配置文件的少量配置属性,就能完成新项目的自动化部署配置
- 开发测试环境在push代码时自动触发构建与部署,生产环境在master分支上添加版本tag并且push tag后触发自动部署
- 整体交互流程如下图
项目配置文件
首先我们需要在项目的根路径中添加一些必要的配置文件,如下图所示
包括:
- Dockerfile文件,用于构建Docker镜像的文件(参考 Docker笔记(十一):Dockerfile详解与最佳实践)
- Helm相关配置文件,Helm是Kubernetes的包管理工具,可以将应用部署相关的Deployment,Service,Ingress等打包进行发布与管理(Helm的具体介绍我们后面再补充)
- Jenkinsfile文件,Jenkins的pipeline定义文件,定义了各个阶段需执行的任务
Dockerfile
在项目根目录中添加一个Dockerfile文件(文件名就叫Dockerfile),定义如何构建Docker镜像,以Spring Boot项目为例,
1
|
FROM frolvlad/alpine-java:jdk8-slim
|
将SPRING_PROFILES_ACTIVE通过参数profile暴露出来,在构建的时候可以通过 –build-args profile=xxx 来进行动态设定,以满足不同环境的镜像构建要求。
SPRING_PROFILES_ACTIVE本可以在Docker容器启动时通过
docker run -e SPRING_PROFILES_ACTIVE=xxx
来设定,因这里使用Helm进行部署不直接通过docker run
运行,因此通过ARG在镜像构建时指定
Helm配置文件
Helm是Kubernetes的包管理工具,将应用部署相关的Deployment,Service,Ingress等打包进行发布与管理(可以像Docker镜像一样存储于仓库中)。如上图中Helm的配置文件包括:
1
|
helm - chart包的目录名
|
我们可以在Chart.yaml中定义每个项目的chart名称(类似安装包名),如
1
|
apiVersion: v2
|
在values.yaml中定义模板文件中需要用到的变量,如
1
|
#部署Pod的副本数,即运行多少个容器
|
这里在默认生成的基础上添加了container部分,可以在这里指定容器的端口号而不用去改模板文件(让模板文件在各个项目通用,通常不需要做更改),同时添加env的配置,可以在helm部署时往容器里传入环境变量。将Service type从默认的ClusterIp改为了NodePort。部署同类型的不同项目时,只需要根据项目情况配置Chart.yaml与values.yaml两个文件的少量配置项,templates目录下的模板文件可直接复用。
部署时需要在K8s环境中从Docker镜像仓库拉取镜像,因此需要在K8s中创建镜像仓库访问凭证(imagePullSecrets)
1
|
|
Jenkinsfile
Jenkinsfile是Jenkins pipeline配置文件,遵循Groovy语法,对于Spring Boot项目的构建部署, 编写Jenkinsfile脚本文件如下,
1
|
image_tag = "default" //定一个全局变量,存储Docker镜像的tag(版本)
|
Jenkinsfile定义了整个自动化构建部署的流程:
- Code Analyze,可以使用SonarQube之类的静态代码分析工具完成代码检查,这里先忽略
- Maven Build,启动一个Maven的Docker容器来完成项目的maven构建打包,挂载maven本地仓库目录到宿主机,避免每次都需要重新下载依赖包
- Docker Build,构建Docker镜像,并推送到镜像仓库,不同环境的镜像通过tag区分,开发环境使用dev.commitId的形式,如dev.88f5822,测试环境使用test.commitId,生产环境可以将webhook事件设置为tag push event,直接使用tag名称
- Helm Deploy,使用helm完成新项目的部署,或已有项目的升级,不同环境使用不同的参数配置,如访问域名,K8s集群的访问凭证kube_config等
Jenkins配置
Jenkins任务配置
在Jenkins中创建一个pipeline的任务,如图
配置构建触发器,将目标分支设置为develop分支,生成一个token,如图
记下这里的“GitLab webhook URL”及token值,在Gitlab配置中使用。
配置流水线,选择“Pipeline script from SCM”从项目源码中获取pipeline脚本文件,配置项目Git地址,拉取源码凭证等,如图
保存即完成了项目开发环境的Jenkins配置。测试环境只需将对应的分支修改为pre-release即可
Jenkins凭据配置
在Jenkinsfile文件中,我们使用到了两个访问凭证——Docker Registry凭证与本地K8s的kube凭证,
1
|
DOCKER_REGISTER_CREDS = credentials('aliyun-docker-repo-creds') //docker registry凭证
|
这两个凭证需要在Jenkins中创建。
添加Docker Registry登录凭证,在Jenkins 凭据页面,添加一个用户名密码类型的凭据,如图
添加K8s集群的访问凭证,在master节点上将/root/.kube/config文件内容进行base64编码,
1
|
base64 /root/.kube/config > kube-config-base64.txt
|
使用编码后的内容在Jenkins中创建一个Secret text类型的凭据,如图
在Secret文本框中输入base64编码后的内容。
Gitlab配置
在Gitlab项目的 Settings - Integrations 页面配置一个webhook,在URL与Secret Token中填入前面Jenkins触发器部分的“GitLab webhook URL”及token值,选中“Push events”作为触发事件,如图
开发、测试环境选择“Push events”则在开发人员push代码,或merge代码到develop,pre-release分支时,就会触发开发或测试环境的Jenkins pipeline任务完成自动化构建;生产环境选择“Tag push events”,在往master分支push tag时触发自动化构建。如图为pipeline构建视图
总结
本文介绍使用Gitlab+Jenkins Pipeline+Docker+Kubernetes+Helm来实现Spring Boot项目的自动化部署,只要稍加修改即可应用于其它基于Spring Boot的项目(具体修改的地方在源码的Readme文件中说明)。