jenkins基础

基础概念

持续集成CI

概念

continuous integration,持续集成的重点是构建编译和测试,通过自动化的构建(主要是构建编译、自动化测试)来验证,从而尽早发现集成错误。

持续集成的工作流程

  • 初始化CI流程 基本的CI流程的配置,如脚本、定时任务
  • 拉取最新代码 从gitlab仓库拉取最新代码到构建服务器磁盘
  • 构建 通过配置的脚本触发执行构建,如java构建一般基于maven或gradle
  • 执行测试 一般包括单元测试和集成测试,Java的单元测试默认Junit
  • 结果处理 一般都要通知给对应人员,如邮件、钉钉、短信

持续交付CD

continuous delivery,将产品尽快的发布上线的过程。持续交付是在持续集成的基础上的扩展,也就是说除了自动化编译、自动化测试,为尽快上线还要自动化发布

持续部署

continuous deployment,在持续交付的基础上,将编译、测试、打包部署到生产环境的过程实现自动化。当然,一般非生产环境保证自动化,生产环境还是手动。

DevOps

概念

开发和运维的组合,打破开发和运维的壁垒,通过工具链,将开发、测试、运维的工作串联起来,将全部流程自动化,减少人力重复投入,降低人为风险。

工具链

  • 编码 代码开发和审查、源码管理工具、代码合并 gitlab
  • 构建 持续集成工具 Jenkins maven
  • 测试 持续测试工具 selenium Jmeter
  • 发布 变更管理、发布审批、发布自动化
  • 容器平台 docker k8s
  • 配置 基础设置配置和管理 Ansible
  • 监控 应用性能监控、终端用户体验 logstash nagios kibana zabbix

jenkins

文档 https://www.jenkins.io/zh/doc/

背景

前身hudson,Oracle收购sun之后hudson归Oracle所有,贡献者基于hudson改为jenkins。目前hudson已停止开发,Jenkins成为使用最多的CICD工具。持续集成是Jenkins的核心功能。

应用场景

  • 集成svn/git客户端实现源码checkout
  • 集成maven/ant/gradle/npm等构建工具实现源码编译打包和单元测试
  • 集成ansible实现自动化部署发布
  • 集成jmeter/k8s…
  • 可自定义插件或脚本通过Jenkins传参运行
  • 非常灵活,日常运维工作都可自动化

版本

  • Jenkins 2.x 主流,支持pipeline

  • Jenkins X 基于k8s的持续集成

搭建

主从集群,将构建任务分发到多个从节点执行,支撑多个项目的大量构建任务

部署方式:

  • 服务器直接运行war
  • 服务器yum下载Jenkins安装包
  • docker容器运行

环境说明

  • centos7

  • jdk1.8

  • maven3.x

  • git 1.8.3

  • jenkins 最新版本

  • master主机 centos30

  • slave主机 centos31

master安装

jdk
1
2
3
4
5
6
7
8
9
10
# 上传jdk包
# 配置Java环境变量
vi /etc/profile
export JAVA_HOME=/opt/jdk1.8.0_301
export JRE_HOME=/opt/jdk1.8.0_301/jre
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
# 使用source命令,使其生效
source /etc/profile
# 验证安装成功
java -version
git安装
1
2
3
yum install -y git
# 验证是否安装成功
git --version
sshpass安装
1
2
# 远程连接工具,备份恢复使用
yum install sshpass -y
wget安装
1
yum install wget -y
axel安装

多线程下载工具

1
2
wget http://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/a/axel-2.4-9.el7.x86_64.rpm
rpm -ivh axel-2.4-9.el7.x86_64.rpm
TODO 创建Jenkins用户
1
2
useradd -d /home/jenkins -m -s /bin/bash jenkins
# 密码
maven安装
1
2
3
4
5
6
7
8
9
# 上传压缩包,解压到/opt
# 配置环境变量
vi /etc/profile
export MAVEN_HOME=/opt/apache-maven-3.8.5
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$MAVEN_HOME/bin
# source
source /etc/profile
# 验证
mvn -v

配置镜像加速

1
2
3
4
5
6
7
8
9
10
maven下的conf/settings.xml找到<mirrors>和</mirrors>标签,添加
vi /opt/apache-maven-3.8.5/conf/settings.xml

<!-- 配置镜像加速 -->
<mirror>
<id>alimaven</id>
<name>alimaven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

注意:如果配置本地仓库的地址,一定要赋予该目录其他用户可读写的权限

rsync安装

跨机器文件同步

1
yum install rsync -y
关闭防火墙
1
2
3
systemctl stop firewalld
# 永久关闭
systemctl disable firewalld
Jenkins安装
1
2
3
4
5
6
mkdir /opt/jenkins
# 为jenkins用户授权
chown -R jenkins:jenkins /opt/jenkins
su jenkins
# 下载Jenkins最新版
axel -n 20 http://mirrors.jenkins-ci.org/war/latest/jenkins.war

创建启动脚本 vi jenkins.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/bin/bash
args=$1
#注意修改jenkinswar包的目录
jenkins_war_path="/opt/jenkins"
#jenkins开放端口
jenkins_http_port="8888"
#java安装路径
java_home="/opt/jdk1.8.0_301"
function isRuning(){
local jenkinsPID=`ps -ef|grep jenkins.war|grep -v grep|awk '{print $2}'`
if [ -z ${jenkinsPID} ];then
echo "0"
else
echo ${jenkinsPID}
fi
}

#停止jenkins
function stop(){
local runFlag=$(isRuning)
if [ ${runFlag} -eq "0" ];then
echo "Jenkins is already stoped."
else
`kill -9 ${runFlag}`
echo "Stop jenkins success."
fi
}

#启动jenkins
function start(){
local runFlag=$(isRuning)
echo "${runFlag}"
if [ ${runFlag} -eq "0" ];then
`${java_home}/bin/java -jar ${jenkins_war_path}/jenkins.war --httpPort=${jenkins_http_port} &` > /dev/null
if [ $? -eq 0 ];then

echo "Start jenkins success."
exit
else
echo "Start jenkins fail."
fi
else
echo "Jenkins is running now."
fi
}

#重启jenkins
function restart(){
local runFlag=$(isRuning)
if [ ${runFlag} -eq "0" ];then
echo "Jenkins is already stoped."
exit
else
stop
start
echo "Restart jenkins success."
fi
}

#根据输入的参数执行不同的动作
#参数不能为空
if [ -z ${args} ];then
echo "Arg can not be null."
exit
#参数个数必须为1个
elif [ $# -ne 1 ];then
echo "Only one arg is required:start|stop|restart"
#参数为start时启动jenkins
elif [ ${args} = "start" ];then
start
#参数为stop时停止jenkins
elif [ ${args} = "stop" ];then
stop
#参数为restart时重启jenkins
elif [ ${args} = "restart" ];then
restart
else
echo "One of following args is required: start|stop|restart"
exit 0
fi

启动jenkins

1
sh jenkins.sh start

配置加速

vi /home/jenkins/.jenkins/hudson.model.UpdateCenter.xml
将xml的url替换为http://mirror.xmission.com/jenkins/updates/update-center.json

1
2
3
4
5
6
7
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>http://mirror.xmission.com/jenkins/updates/update-center.json</url>
</site>
</sites>

或在web界面manage jenkins->manage plugins->Advanced->Update Site修改

访问Jenkins http://ip:8888

获取管理员密码 cat /home/jenkins/.jenkins/secrets/initialAdminPassword

修改管理员密码

页面左上角jenkins->people->admin->configure修改

插件安装

需要安装ssh、Pipeline、Role-based Authorization Strategy、Git、Gitee、Git Parameter、thinBackup这些插件,manage jenkins->manage plugins,点击available搜索下载

插件名 作用
Pipeline 流水线部署项目
Role-based Authorization Strategy 基于角色的用户管理权限策略,最常用的jenkins权限策略管理插件
Git 支持使用GitHub、gitlab等源码仓库,创建普通job会用到
Gitee Gitee基于gitlab plugin开发的插件,配置Jenkins触发器,接受gitee平台发送的webhook触发jenkins进行自动化持续集成或持续部署,并可将构建状态反馈gitee平台
Git Parameter 可把git的tag branch作为构建参数传进来,方便使用branch构建
Extended Choice Parameter 参数化构建
Maven Integration 为maven2/3项目提供高级集成功能
SonarQube Scanner 代码扫描
Email Extension 扩展发送告警邮件的控制粒度,可定义邮件触发器、邮件内容、收件人
Workspace Cleanup 每次build之前删除workspace目录下指定的文件
Monitoring 监控Jenkins节点的CPU、系统负载、平均响应时间和内存使用
Build Monitor View 将Jenkins项目以看板的形式呈现
ThinBackup 单元测试覆盖率
jacoco 单元测试覆盖率
Generic Webhook Trigger webhook

jenkins的配置

Jenkins->Manage jenkins->Configure System 进入系统配置页面

令牌配置

证书令牌

分组管理

new view即可

备份恢复

存储结构

在Jenkins中,所有数据默认都以文件形式存储在$JENKINS_HOME目录。占用空间最大的是jobs目录和workspace目录。

  • jobs目录 项目在Jenkins上的配置、构建日志、构建结果等所在的目录,对应/home/jenkins/.jenkins/jobs目录
  • workspace目录 项目在Jenkins上配置的源码仓库地址下载的源码所在的目录,如Java的maven构建操作就在此目录,对应/data/jenkins_data/workspace目录

结构

  • jobs目录下的一级目录名,均为在Jenkins上新建的job名称
  • 二级目录下的build里面出现的数字1,2,3…表示构建历史所在的目录,也就是一次构建有一个构建版本号,从1开始随着构建次数增加递增
  • workspace下面都是空的,因为还没拉取代码

pipeline

概念

流水线即代码,流水线的代码定义了整个的构建过程,包括构建、测试和交付应用程序的阶段,对流水线的定义写在Jenkinsfile文件中,可被提交到源码仓库。创建Jenkinsfile并提交到源码仓库的好处:

  • 自动为所有分支创建流水线构建过程并拉取请求
  • 在流水线上代码复查/迭代
  • 对流水线进行审计跟踪
  • 该流水线的真正源码可被团队成员共同查看和编辑

语法支持

Jenkinsfile能用两种语法编写,都能用pipeline内置的插件和steps

  • Declarative Pipeline声明式 推荐使用,语法更严格,有固定的组织结构
  • Scripted Pipeline 脚本化 groovy语言,只对结构和语法限制,用户可自己灵活实现和扩展

基本概念

  • stage 阶段,一个pipeline分为多个stage,每个stage代表一组操作,stage是一个逻辑分组的概念,可跨多个node
  • node 构建服务器节点,一个node就是要给Jenkins节点,或master或agent,是执行step的具体运行期环境
  • step 步骤,最基本的操作单元,小到创建一个目录,大到构建一个docker镜像,由各类Jenkins plugin提供

pipeline语法

参考https://www.jenkins.io/zh/doc/book/pipeline/syntax/#declarative-directives

  • 声明式pipeline必须包含在固定格式的pipeline{}内

    1
    2
    3
    pipeline {
    // insert declarative pipeline here
    }
  • 每个声明语句必须独立一行,行尾无需分号

  • 块blocks 由大括号括起来的语句如 pipeline{} parameters{} script{}

  • 章节sections 通常包括一个或多个指令或步骤 如agent post stages steps

  • 指令directives 如 environment option parameter trigger stage tools when

  • 步骤step 执行脚本式pipeline,如script{}

  • 块只能由阶段stages{}、指令、步骤(steps{})或赋值语句组成

  • 属性引用语句被视为无参方法调用,如input()

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// jenkinsfile(declarative pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'make'
echo "Hello world"
script {
def browsers = ['chrome','firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
stage('Test') {
steps {
sh 'make check'
junit 'reports/**/*.xml'
}
}
stage('Deploy') {
steps {
sh 'make publish'
}
}
}
}

说明:

  • pipeline是声明式流水线的一种特定语法,定义了包含执行整个流水线的所有内容和指令的block
  • agent 指示Jenkins为整个流水线分配一个执行器(在Jenkins环境中的任何可用代理/节点上)和工作区。一般用作指定在哪个节点上构建,如果不指定就写any表示任意节点
  • 定义Build Test Deploy三个阶段,每个阶段执行不同的步骤
  • stage 描述stage of this pipeline的语法块,定义在pipeline的不同阶段
  • steps 声明式流水线的特定语法,描述这个stage中要运行的步骤
  • sh 是一个执行给定的shell命令的流水线
  • echo 简单的字符串到控制台输出
  • junit 另一个聚合测试报告的流水线
  • stage括号的值表示阶段名称,内容不固定,自定义即可

gitee的demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
pipeline {
//指定运行的节点,slave运行
agent {
node {
label 'follower'
}
}
//定义各个阶段
stages {
// 获取git代码,credentialsId是配置的git账号
stage('git') {
steps {
git credentialsId: 'gitee-username', url: 'xxx'
}
}
// test阶段
stage('test') {
steps {
//可从environment获取
sh '${MAVEN_HOME}/bin/mvn test'
}
}
// 编译打包阶段,打jar包
stage('build') {
steps {
sh '${MAVEN_HOME}/bin/mvn clean package -DskipTests'
}
}
// docker镜像
stage('docker') {
steps {
sh 'docker build -t jenkins-demo:${BUILD_NUMBER} .'
}
}
// 部署阶段,停掉旧的docker进程,启动新镜像
stage('deploy') {
steps {
//如果test-boot没有在启动中,如果不跟或语句,会执行失败
sh 'docker rm -f jenkins-demo || sleep 0'
sh 'docker run --name jenkins-demo -d -p 8080:8080 jenkins-demo:${BUILD_NUMBER}'
}
}
}
}

其他常见语法:

  • when 允许流水线根据给定的条件决定是否应该执行阶段,必须包含至少一个条件

  • environment

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    pipeline {
    environment {
    // 顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤
    }
    stages {
    stage('Example') {
    environment {
    //在一个 stage 中定义的 environment 指令只会将给定的环境变量应用于 stage 中的步骤
    AN_ACCESS_KEY = credentials('my-prefined-secret-text')
    }
    steps {
    sh 'printenv'
    }
    }
    }
    }
  • options 从流水线内部配置特定于流水线的选项,如超时,中止流水线

    1
    2
    3
    4
    5
    6
    7
    pipeline { 

    options {
    timeout(time: 30, unit: 'SECONDS') //unit根据需要可选值有:SECONDS、MINUTES、HOURS
    retry(2)
    }
    }
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2023-2024 Larry Wang
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信