本文共 6862 字,大约阅读时间需要 22 分钟。
Jenkins 2.0新特性:Pipeline as code,全新的开箱体验和UI可用性提升以及完全向后兼容。
我们在定义一个Jenkins项目的时候,希望它是一个清晰的范围。也就是说,如果这个项目叫mvn test and build,我们就应该在脚本里实现测试和jar/war包打包。而事实上是,接下来的需求很多时候是把测试结果展示出来,还有上传jar/war包。这个时候,Devops工程师会陷入一种纠结,就是值不值得为了这个需求再重新创建一个freeStyle的项目。明明可能只有两个语句,却需要整个重新配置一个项目。新建意味着付出更多的精力并且后期维护成本增加;在原有的项目里实现,意味着项目臃肿,定义模糊。Jenkins 2.0 提供的Pipeline项目类型给出了很好的解决办法。
下面我们将用java web源代码来演示一个Pipeline项目如何优雅地实现代码提交触发测试,war包打包,测试结果展示,war包本地存储以及上传OSS,构建镜像,部署应用,邮件推送结果的持续交付方案。 在最后一部分,我们将介绍动态生成slave,执行job,销毁slave。
先给张图来个Pipeline项目的视觉感受:
阿里云容器服务的官方示例模板已经新增了Jenkins 2.0镜像版本,只需要将镜像版本号1.651.3改成2.19.2。编排模板如下:
jenkins: image: 'registry.aliyuncs.com/acs-sample/jenkins:2.19.2' ports: - '8080:8080' - '50000:50000' volumes: - /var/lib/docker/jenkins:/var/jenkins_home privileged: true restart: always labels: aliyun.scale: '1' aliyun.probe.url: 'tcp://container:8080' aliyun.probe.initial_delay_seconds: '10' aliyun.routing.port_8080: jenkins links: - slave-javaslave-java: image: 'registry.aliyuncs.com/acs-sample/jenkins-slave-dind-java' volumes: - /var/run/docker.sock:/var/run/docker.sock restart: always labels: aliyun.scale: '1'
(updated)有的情况下用户需要使用root用户来启动slave容器,下面更新的这个模版里的slave镜像registry.cn-beijing.aliyuncs.com/qinyujia-test/jenkins-slave-dind-java-maven是以root用户(密码是passwd)启动的,docker client version为1.12.5,使用容器服务部署的时候请先升级Docker版本到最新版。
jenkins: image: 'registry.cn-hangzhou.aliyuncs.com/qinyujia-test/jenkins:2.19.2' ports: - '8080:8080' - '50000:50000' volumes: - /var/lib/docker/jenkins:/var/jenkins_home privileged: true restart: always labels: aliyun.scale: '1' aliyun.probe.url: 'tcp://container:8080' aliyun.probe.initial_delay_seconds: '10' aliyun.routing.port_8080: jenkins links: - slave-javaslave-java: image: 'registry.cn-beijing.aliyuncs.com/qinyujia-test/jenkins-slave-dind-java-maven' volumes: - /var/run/docker.sock:/var/run/docker.sock restart: always labels: aliyun.scale: '1'
在Jenkins master中配置slave。
选择Jenkins,添加类型为User with Password的Credentials,存储GitLab账号密码。同样添加存储OSS以及阿里云容器服务Registry账号密码的Credentials。了解OSS请参考
Note: 请打开上图中的Pipeline Syntax链接,Jenkins提供了很大程度上帮用户生成脚本的功能。
完整的脚本如下:
node指定的是slave节点,必须使用Jenkins已经管理的节点名称。 stage指的是一个view,名称由用户自己指定。本示例一共创建了6个stage来实现持续交付。其中deploy是连接了一个freestyle的应用部署项目。node('slave-java') { stage('Prepare') { withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'gitlab', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { sh 'rm -rf java-demo' sh "git clone http://'${USERNAME}':'${PASSWORD}'@139.129.99.183:10080/root/java-demo.git" } } stage('mvn test and build') { sh 'ls' dir('./java-demo') { sh 'mvn -version' sh 'mvn -Dmaven.test.failure.ignore clean package' } } stage('publish and archive') { dir('./java-demo') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.war' } } stage('Upload to oss') { withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'gitlab', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { sh 'rm -rf oss' sh "git clone http://'${USERNAME}':'${PASSWORD}'@139.129.99.183:10080/root/oss.git" } dir('./oss') { sh 'unzip OSS_Python_API_20160419.zip' withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'oss', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { sh 'python osscmd put ../java-demo/target/boot-api.war oss://cs-jenkins/boot-api.war --host=oss-cn-qingdao.aliyuncs.com --id=${USERNAME} --key=${PASSWORD}' } } } stage('image build') { dir('./java-demo') { sh 'cp target/boot-api.war .' withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'registry', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { sh 'sudo docker login -u ${USERNAME} -p ${PASSWORD} -e yujia.qyj@alibaba-inc.com registry.cn-beijing.aliyuncs.com' sh 'sudo docker build -t registry.cn-beijing.aliyuncs.com/qinyujia/boot-api .' sh 'sudo docker push registry.cn-beijing.aliyuncs.com/qinyujia/boot-api' } } } stage('deploy') { build 'deploy' } stage('email') { emailext body: '''Project: $PROJECT_NAME Build Number: # $BUILD_NUMBER Build Status: $BUILD_STATUS Check console output at $BUILD_URL to view the results.''', recipientProviders: [[$class: 'DevelopersRecipientProvider']], subject: '$BUILD_STATUS - $PROJECT_NAME - Build # $BUILD_NUMBER', to: 'yujia.qyj@alibaba-inc.com' }}
下面我们来介绍一下如何配置动态的生成slave,执行Jenkins job,销毁slave。
首先安装yet another docker插件。 然后选择Manage Jenkins,Configure System。 创建一个阿里云服务的集群,作为slave容器的承载。 Docker URL中填写集群接入点地址。 Host Credentials中添加 Docker Host Certificate Authentication类型的证书。按照图中提示把集群相应的证书输入。这时候可以使用Test Connection来测试集群的连通性。Docker Image Name中填写slave镜像。本示例中使用的是阿里云容器服务提供的示例镜像registry.aliyuncs.com/acs-sample/jenkins-slave-dind-java。
Registry Credentials中添加类型为User with Password的Credentials,输入阿里云容器服务镜像仓库的账号和密码。 Create Container Settings中在Volumes对话框中挂载两个数据卷: /var/run/docker.sock:/var/run/docker.sock #用来让slave可以使用宿主机的docker deamon。 /home/jenkins/.m2:/root/.m2 #将maven仓库存储在ECS的数据卷中,这样即使容器删除,maven repository还能保留,接下来新生成的slave可以不用重新下载依赖包。node('docker')
这套持续交付的方案,最大的两个特性在于,一,使用了Jenkins Pipeline Project,通过Jenkinsfile脚本简化整个配置过程,增加了artifacts存储,加强了结果展示,UT结果看板以及stage时间统计。二,Dynamic slave,提供了动态生成slave,执行Jenkins job,销毁slave的能力。
想查看阿里云容器服务提供了哪些slave节点,请访问
想了解更多容器服务内容,请访问转载地址:http://nduol.baihongyu.com/