关于CI & CD
CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。
具体而言,CI/CD 在整个应用生命周期内(从集成和测试阶段,到交付和部署)引入了持续自动化和持续监控。这些关联的事务通常被统称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。
关于Jenkins
Jenkins是一款CI/CD工具。Jenkins通过丰富的插件来实现自动化构建、测试和部署软件。
我们可以通过创建Jenkins pipeline的方式来创建一个自动化的流程。通过Jenkins pipeline的定义通常被写入Jenkinsfile中,从而将“简单到复杂”的交付流程实现为“持续交付即代码”。
为什么要用shared library
当下微服务(micro services)大行其道,一个大的项目中可能有许多微服务构成。每个微服务彼此间的构建过程可能非常相识,这样我们每个项目的Jenkinsfile的内容可能有很多重复的代码。每当要修改我们的流程定义的时候,我们就需要逐个项目去修改。
通过shared library我们可以把通用的Jenkins pipeline代码集中起来,存放到外部的源代码版本控制仓库中。当我们的微服务需要使用到shared library的时候只需引入相应的库即可。以下是示例代码:
// 引入shared library: notebook40@0.2.0
// "notebook40"是我们在Jenkins中定义的shared library的名字
// "0.2.0"是shared library的版本。Jenkins会自动匹配版本到源代码控制仓库的branch或tag...
@Library("notebook40@0.2.0") _
// 执行名为commonPipeline的脚本
commonPipeline()
示例
以下是使用shared library的示例。
安装Jenkins
-
由于我们需要用Jenkins来构建
Docker
镜像,最方便的方法是直接在Docker中运行Jenkins。docker run -d \ -u root\ -p 8080:8080 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /root/.m2:/root/.m2 \ --name jenkins \ jenkinsci/blueocean
-
-u root
使用root用户来运行Jenkins,这样Jenkins就能运行Docker了。 -
-v /var/run/docker.sock:/var/run/docker.sock
使Jenkins docker container能访问外部docker。
-
安装配置Jenkins用户名密码,并安装推荐的插件。
安装Pipeline Utility Steps插件。在示例代码中用来读取
maven
的pom.xml
。
shared library项目
Shared library用到groovy
脚本,以下是shared library项目的详细情况。
-
shared library项目的默认目录:
-
src
目录类似与java
的src
,用于存放groovy类文件。 -
vars
目录定义可从流水线访问的全局变量的脚本。 -
resources
目录允许从外部库中使用jenkins step:libraryResource
来加载文本文件。
-
-
groovy
类中使用jenkins step。在
groovy
类中我们不能直接使用Jenkins的step。我们可以通过把当前groovy
脚本对象传到groovy
中,来允许groovy
类调用Jenkins的step。以下代码演示如何在groovy中加载一个properties
文件。./vars/commonPipeline.groovy
import com.notebook40.jenkins.pipeline.Pipelines // shared library脚本的默认方法。 // 当Jenkinsfile中调用commonPipeline(当前脚本的文件名字的时候),call方法会被执行。 def call(Map pipelineParameters) { // 参数this把当前脚本对象传给groovy类,使groovy类能调用Jenkins step。 Pipelines.buildCommonPipeline(this, pipelineParameters) }
./src/.../Pipelines.groovy
package com.notebook40.jenkins.pipeline import com.notebook40.jenkins.context.Context class Pipelines { static def buildCommonPipeline(jenkins, Map pipelineParameters) { // 用jenkins(commonPipeline的this参数构建Context对象) Context context = new Context(jenkins, pipelineParameters) // 构建Jenkins pipeline new DefaultPipelineBuilder().build(context) } }
./src/.../DefaultPipelineBuilder.groovy
void loadProperties(Context context) { // 加载一个properties文件 String propertiesString = context.jenkins.libraryResource( "com/notebook40/jenkins/pipeline/defaultPipeline.properties" ) // 把properties文件内容加载到Properties对象中 Properties properties = new Properties() properties.load(new StringReader(propertiesString)) // ... }
-
下面是执行maven任务的例子。
./src/.../MavenStep.groovy
package com.notebook40.jenkins.step import com.notebook40.jenkins.context.Context abstract class MavenStep extends AbstractStep { // 用于执行maven的公用方法 // context参数用来执行jenkins step和获取运行pipeline的参数 Closure withMaven(Context context, Closure cl) { // 调用withDockerContainer来运行maven镜像 context.jenkins.withDockerContainer( // Maven的镜像名 "image": mavenImageName(context), // 运行Maven镜像的参数 "args": mavenImageArgs(context)) { // 需要执行的内容 cl() } } // ... }
./src/.../PackageStep.groovy
package com.notebook40.jenkins.step import com.notebook40.jenkins.context.Context class PackageStep extends MavenStep { @Override void process(Context context) { // 执行Maven任务 withMaven(context) { // 使用Maven打包项目 context.jenkins.sh 'mvn -B -DskipTests package' context.jenkins.archiveArtifacts artifacts: 'target/*.jar', fingerprint: true } } }
在Jenkins中配置shared library。详情请见:https://jenkins.io/doc/book/pipeline/shared-libraries/
在项目中创建Jenkins文件
-
./Jenkinsfile
@Library("notebook40@0.2.0") _ commonPipeline()
创建Jenkins pipeline
- 在Jenkins项目中创建pipeline,并运行:
示例代码源码
- jenkins common pipeline:https://github.com/notebook40/jenkins-common-pipeline
- jenkins common pipeline 使用示例:https://github.com/notebook40/jasypt-encryption
-
Jenkinsfile
为示例Jenkins pipeline定义文件。 - 需要将
pom.xml
中finalName
改为${project.artifactId}
-
附录
- Jenkins: https://jenkins.io
- Jenkins Pipeline Syntax: https://jenkins.io/doc/book/pipeline/syntax/
- Jenkins Steps: https://jenkins.io/doc/pipeline/steps/