前言在日常开发中,经常会有发布的需求,经常会遇到各种环境,比如:开发环境,测试环境,生产环境。虽然可以采用手动搭建和上传服务器的部署方式,但是微服务架构下的一个项目往往包含多个微服务的部署,如果手动使用会非常繁琐且容易出错。使用jenkins结合SCM可以实现代码的整个自动化构建和部署过程。本文自动化构建部署过程大致完成以下步骤:提交springboot项目代码并打上git标签,将代码和标签上传到gitlabgitlab通过webhook自动触发jenkins执行任务jenkins获取代码,执行代码编译,构建docker镜像,上传docker镜像到harbor镜像仓库,执行kubectl命令部署到k8s。本文使用jenkins管道执行整个jenkins构建过程,管道中使用docker执行maven构建。本文构建的docker镜像的tag直接采用了git中的tag。下面的例子中,jenkins版本为2.121.3,gitlab版本为10.0.2-ce。如果使用的版本不一致,可能会有一些设置上的差异。部署Jenkins这里使用docker来部署jenkins。在终端中运行docker命令以使用jenkinsci/blueocean镜像运行容器。dockerrun-d-uroot-p8080:8080-vjenkins_home:/var/jenkins_home-v/var/run/docker.sock:/var/run/docker.sockjenkinsci/blueocean访问http://localhost:8080地址,等待出现如下解锁界面。使用dockerlogs命令从日志消息中复制自动生成的密码(在两组星号之间)。在解锁Jenkins页面上,粘贴密码并继续。解锁jenkins后,在界面中选择“Installsuggestedplugins”。最后,jenkins要求创建一个管理员用户。新建一个用户或者使用admin用户,按照步骤登录并使用jenkis。注意:由于后面的jenkinspipeline任务会上传docker镜像到harbor仓库,如果harbor使用http,需要在/etc/docker/daemon.json中配置地址为insecure-registries;如果harbor使用的是自签名的https证书,则需要将ca证书添加到/etc/docker/certs.d/目录下。设置完成后需要重启docker服务。准备好java示例工程,下面新建一个springboot示例工程。示例工程的代码地址为:https://gitee.com/tinylk/pipe...创建springboot示例工程1.通过https://start.spring.io/生成springboot基础工程并添加一个示例控制器类。包com.example.demo.controller;导入org.springframework.web.bind.annotation.GetMapping;导入org.springframework.web.bind.annotation.RestController;@RestControllerpublicclassHomeController{@GetMapping("")publicStringhello(){返回“你好!”;}}2.修改应用配置文件,设置端口。spring.application.name=pipeline-demoserver.port=400803。编译运行,访问http://localhost:40080地址可以看到示例运行结果。添加Dockerfile在项目根目录下创建Dockerfile,构建docker镜像。${JAR_FILE}参数是在pipeline执行dockerbuild时通过build-arg参数传入的。FROMopenjdk:8-jdk-alpine#BuildparameterARGJAR_FILEARGWORK_PATH="/opt/demo"#EnvironmentvariableENVJAVA_OPTS=""JAR_FILE=${JAR_FILE}#SettimezoneRUNapkupdate&&apkaddca-certificates&&apk添加tzdata&&ln-sf/usr/share/zoneinfo/Asia/Shanghai/etc/localtime&&echo"Asia/Shanghai">/etc/timezoneCOPYtarget/$JAR_FILE$WORK_PATH/WORKDIR$WORK_PATHENTRYPOINTTSexecFIjava$AR_JAVA_k8s部署配置在项目根目录下创建一个k8s-deployment.tpl文件,作为k8syaml文件模板。当jenkenspipeline执行时,tpl文件中用{}括起来的自定义参数会被sed命令替换为实际内容。(由于对k8s了解有限,不知道有没有更好的实现方式)apiVersion:apps/v1kind:Deploymentmetadata:name:{APP_NAME}-deploymentlabels:app:{APP_NAME}spec:replicas:1selector:matchLabels:app:?{APP_NAME}??template:????metadata:??????labels:????????app:?{APP_NAME}????spec:??????containers:??????-?name:?{APP_NAME}????????image:?{IMAGE_URL}:{IMAGE_TAG}????????ports:????????-?containerPort:?40080????????env:??????????-?name:SPRING_PROFILES_ACTIVE值:{SPRING_PROFILE}添加Jenkinsfile在项目的根目录下创建一个Jenkinsfile来执行jenkins管道任务。Jenkinsfile的大致内容描述如下:环境中的变量描述,环境的文档描述可以在:https://jenkins.io/zh/doc/boo...。HARBOR_CREDS为harbor镜像仓库的用户密码,数据保存为jenkins的“用户名密码”类型凭证,使用credentials方法从凭证中获取。使用时通过HARBOR_CREDS_USR获取用户名,通过HARBOR_CREDS_PSW获取密码。k8S_CONFIG是k8s中kubectl命令的yaml配置文件内容,数据保存为jenkins的“SecretText”类型凭证,使用credentials方法从凭证中获取。这里保存的yaml配置文件内容是以base64编码格式保存的,设置凭证时必须进行base64编码。(这个base64编码不是必须的,如果直接保存原文,需要在下面的jenkinsfile中去掉base64-d解码)GIT_TAG变量通过执行sh命令获取当前的gittag值。由于后面构建docker镜像时会使用git标签作为镜像的标签,所以这个变量不能为空。参数HARBOR_HOST中的变量说明:Harbor镜像仓库地址。DOCKER_IMAGE:docker镜像名称,包括harbor项目名称。APP_NAME:k8s中的标签名称,对应k8syaml模板中的{APP_NAME}。K8S_NAMESPACE:k8s中命名空间的名字,kubectl命令会部署到这个命名空间。Stages说明:MavenBuild:以docker方式执行maven命令,并映射args参数中的.m2目录,避免执行过程中重复从远端获取依赖;将jar文件保存在隐藏步骤中以备后用。Docker构建:unstash获取jar文件。使用sh执行docker命令登录harbor,构建镜像,上传镜像,删除本地镜像。构建镜像时,会获取jar文件名,传递给JAR_FILE参数。Deploy:使用docker执行kubectl命令。执行前先base64解密K8S_CONFIG中的内容保存为~/.kube/config配置文件,然后执行sed命令将k8s-deployment.tpl文件中的“{parametername}”形参替换为实际参数值。最后执行kubectl命令部署到k8s。parameters中的参数在流水线任务中执行一次后,第二次执行时可以在界面上修改参数值。这里的阶段都是一个一个自动执行的。如果需要手动执行,可以使用输入命令来实现。参见:https://jenkins.io/zh/doc/boo...//需要在jenkinsCredentials设置管道中配置jenkins-harbor-creds和jenkins-k8s-config参数{agentanyenvironment{HARBOR_CREDS=credentials('jenkins-harbor-creds')K8S_CONFIG=credentials('jenkins-k8s-config')GIT_TAG=sh(returnStdout:true,script:'gitdescribe--tags--always').trim()}parameters{字符串(name:'HARBOR_HOST',defaultValue:'172.23.101.66',description:'harbor仓库地址')string(name:'DOCKER_IMAGE',defaultValue:'tssp/pipeline-demo',description:'docker镜像名称')string(name:'APP_NAME',defaultValue:'pipeline-demo',description:'k8s中的标签名称')string(name:'K8S_NAMESPACE',defaultValue:'demo',description:'k8snamespacename')}stages{stages('Maven构建'){当{表达式{env.git_tag!=Null}}Agent{Image'Maven:3-JDK-8-ARGS'-V$Home/.m2:/reot/.m2'}}sptep{sh'mvncleanpackage-dfile.encoding=utf-8-8-dskiptests=true'stash包括:'target/target/*。jar',name:'app'}}stage('dockerbuild'){{当{allof{eNv.git_tag!=null}}}}代理任何步骤{unStash'App'Sh'Dockerlogin-u${Harbor_creds_usr}-p${Harbor_creds_psw}${params.HARBOR_HOST}"sh"dockerbuild--build-argJAR_FILE=`lstarget/*.jar|cut-d'/'-f2`-t${params.HARBOR_HOST}/${params.DOCKER_IMAGE}:${GIT_TAG}。”sh“dockerpush${params.harbor_host}/${params.docker_image}:${git_tag}“sh”dockerrmi${params.harbor_host}/${params.docker_image}'部署'){当{allof{express{env.git_tag!=null}}}}agent{docker{image'lwolf/helm-kubectl-docker'}}sptep{sh“mkdir-p?/.kube”sh“sh”-d>~/.kube/config"sh"sed-e's#{IMAGE_URL}#${params.HARBOR_HOST}/${params.DOCKER_IMAGE}#g;s#{IMAGE_TAG}#${GIT_TAG}#g;s#{APP_NAME}#${params.APP_NAME}#g;s#{SPRING_PROFILE}#k8s-test#g'k8s-deployment.tpl>k8s-deployment.yml"sh'kubectlapply-fk8s-deployment.yml-namespace=${params.k8s_namespace}“}}}}}}}}配置詹金斯管道任务jenkinsPipeline任务Pipeline任务点击配置任务任务任务任务的的的的的,管道(管道),(管道),选择设置设置,选择,“来自scm”的“管道脚本”。然后在“其他行为”中添加“结帐前清洁”。配置harbor账号和密码,选择“Credentials”,然后点击下图位置的“AddCredentials”。在新的凭证设置界面,类型选择“Usernamewithpassword”,ID设置为“jenkins-harbor-creds”(这里的ID必须和Jenkinsfile中的一致)。Username和Password分别设置为harbor镜像私有库的用户名和密码。添加凭证设置habor账户密码配置k8skube.config配置信息在k8s中使用kubectl命令时,需要一个yaml格式的服务器和授权信息配置文件。在这里,kubectl的yaml配置文件的内容被base64编码并存储在jenkins的凭据中。pipeline任务执行时,先从jenkins凭证中获取内容,base64解码后将配置保存为~/.kube/config文件。kubectl配置文件内容如下:apiVersion:v1kind:Configclusters:-name:"test"cluster:server:"https://xxxxx"api-version:v1certificate-authority-data:"xxxxxx"users:-name:"user1"user:token:"xxxx"contexts:-name:"test"context:user:"user1"cluster:"test"current-context:"test"在linux下可以使用如下命令添加对kubectl的yaml配置文件进行base64编码。base64kube-config.yml>kube-config.txt然后和上一步类似,将配置文件的内容添加到jenkins凭证中。在凭证设置界面,类型选择“Secrettext”,设置ID为“jenkins-k8s-config”(这里的ID要和Jenkinsfile中的一致),设置Secret为base64编码的配置上面的文件内容。测试流水线任务在创建的流水线任务中,点击“BuildNow”立即执行流水线任务。Jenkins中有一个名为BlueOcean的新接口。流水线任务也可以在新界面执行,在新界面查看任务执行结果更清晰,所以建议在新界面查看执行结果日志。点击“开启蓝海”菜单进入新界面。在BlueOcean新界面中,点击“运行”即可执行流水线任务。执行管道任务时,执行“gitdescribe--tags”命令时出错。这是因为上例中的Jenkinsfile需要一个git标签。在git中添加tag,提交到gitlab即可解决。在git中添加tag,提交上传到gitlab后重新执行pipeline任务。所有步骤都成功执行。执行成功后查看harbor镜像仓库,docker镜像成功上传到harbor。执行成功后查看k8s中的pod运行日志,服务启动成功。设置gitlab自动触发jenkins在前面的步骤中,已经手动执行jenkins执行管道任务,完成构建部署任务。下面介绍如何让gitlab在提交代码后自动触发jenkins执行流水线任务。在jenkins中安装gitlab插件要实现gitlab自动触发jenkins任务,需要在jenkins中安装gitlab插件。从Jenkins的“系统管理”-“ManagementPlugins”找到gitlab插件,下载安装。重启Jenkins后生效。在gitlab中创建accesstoken在配置安装好的gitlab插件时,需要一个gitlabaccesstoken。首先,在gitlab中创建一个访问令牌。点击“用户设置”-“访问令牌”菜单,进入访问令牌设置界面。然后输入“Name”,勾选“Scopes”中的“api”,点击“Create...”按钮创建访问令牌。创建成功后,一定要保存好生成的token。您以后将无法再查看生成的令牌。如果不保存,以后只能重新生成了。在jenkins中配置gitlab插件在jenkins中,进入“系统管理”-“系统设置”-“Gitlab”配置。输入“Connectionname”,“GitlabhostURL”,在“Credentials”中点击“Add”添加gitlab的授权令牌。点击添加后,会进入添加凭证界面。在添加界面,选择类型为“GitLabAPItoken”,并将APItoken设置为之前在gitlab中创建的token值。然后单击“添加”按钮以创建凭据。添加gitlabapitoken后,在Gitlab设置界面“Credentials”中选择之前添加的token,然后点击“TestConnection”测试是否成功。测试成功后保存。配置pipeline任务,开启trigger进入jenkins的任务设置界面,在“buildtrigger”中勾选“BuildwhenachangepushedtoGitlab.GitlabwebhookURL...”(这里的webhookURL是后面配置的时候gitlabrequired),其他选项根据需要设置。点击“Advanced”按钮,然后点击“Generate”按钮生成一个Secrettoken(这里token后面配置gitlab时需要)。Gitlab配置webhook在gitlab的项目设置中选择“Integrations”,然后将上一步在jenkins设置中获取的内容填入URL和Secrettoken。由于本文是在git上打tag后触发jenkins执行任务,所以这里勾选“Tagpushevents”,然后去掉“EnableSSLverification”的勾选,点击“Addwebhook”按钮加上。如果每次代码提交都需要触发,应该选择“Pushevents”(注意:这里选择Pushevents后,还需要在Jenkinsfile中做相应的修改,去掉git标签相关的内容,否则执行时会报错).添加webhook测试后,可以在下方看到新添加的webhook。点击“测试”按钮,在弹出的菜单中选择“标签推送事件”,发送测试请求。发送成功后会提示“Hook执行成功”。标签推送Testpush成功,webhook发送成功后,可以看到Jenkins中正在执行触发的任务。配置成功后,只要将git标签提交到gitlab,就可以直接触发jenkins执行pipline任务。Webhook触发执行作者:tinylk原文:www.jianshu.com/p/2d89fd1b4403
