12. Jenkins分布式和Pipeline

1 Jenkins分布式

1.1 Jenkins分布式的使用场景

在众多 Job 的场景下,单台 jenkins master 同时执行代码 clone、编译、打包及构建,其性能可能会出现瓶颈从而会影响代码部署效率,jenkins 官方提供了 jenkins 分布式构建,将众多 job 分散运行到不同的 jenkins slave 节点,大幅提高并行 job 的处理能力

图片.png

1.2 Slave节点的划分

当部署的服务器众多时, 可以考虑使用分布式, Slave节点的划分需要根据业务情况进行划分

根据机房划分: 如果有多个机房, 一般可以在主机房, 部署Jenkins Master, 在每个机房部署两个Jenkins Slave实现高可用, 每个机房的Slave节点只负责本机房的部署

根据业务划分: 当某个业务需要部署的机器众多时, 可以给这个业务单独部署Slave节点, 这些Slave节点只负责该业务的代码部署

1.3 Slave节点的部署

10.0.0.159 jenkins-slave-1
10.0.0.169 jenkins-slave-2
4G 2c

Slave 服务器需要手动创建工作目录,如果 slave 需要执行编译 job,则也需要配置 java 环境并且安装 git、svn、maven 等与 master 相同的基础运行环境,另外也要创建与 master 相同的数据目录,因为脚本中调用的路径都是和master一样的路径,此路径在master 与各 node 节点必须保持一致

1.3.1 各Slave节点安装jdk, git

apt -y install openjdk-8-jdk git

1.3.2 各Slave节点创建/var/lib/jenkins目录

该目录用来保存jenkins数据, mater节点的目录由安装jenkins包时自动创建, slave节点需要手动创建

mkdir -p /var/lib/jenkins

1.3.3 Master节点添加Slave节点

图片.png
图片.png

图片.png

1.3.3.1 添加slave-1 10.0.0.159

图片.png

图片.png

图片.png

图片.png
  • 保存后, 点击刷新状态, 验证添加成功
图片.png
  • 添加成功后, 会在slave节点启动一个java进程, 该进程是由master节点拷贝过去的jar包启动的
root@jenkins-slave-1:~# find / -name remoting.jar
/var/lib/jenkins/remoting.jar
root@jenkins-slave-1:~# ps aux | grep java
root       7825  5.5  3.8 3478560 154860 ?      Ssl  01:42   0:04 java -jar remoting.jar -workDir /var/lib/jenkins -jar-cache /var/lib/jenkins/remoting/jarCache

1.3.3.2 添加slave-1 10.0.0.169

再次添加slave节点, 可以从第一个slave-1进行复制, 只需要修改名称, ip地址, 账号密码等即可

图片.png
图片.png

图片.png

图片.png

2 Pipeline

官方介绍: https://jenkins.io/2.0/ jenkins 2.X 官方介绍
https://jenkins.io/zh/doc/book/pipeline/ 官方 pipline 示例

pipline 是帮助 Jenkins 实现 CI 到 CD 转变的重要角色,是运行在 jenkins 2.X 版本的核心件,简单来说 Pipline 就是一套运行于 Jenkins 上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程,从而实现单个任务很难实现的复杂流程编排和任务可视化,Pipeline 的实现方式是一套Groovy DSL,任何发布流程都可以表述为一段 Groovy 脚本

2.1 Pipeline语法

Stage:阶段,一个 pipline 可以划分为若干个 stage,每个 stage 都是一个操作步骤,比如 clone 代码、代码编译、代码测试和代码部署,阶段是一个逻辑分组,可以跨多个 node 执行。

Node:节点,每个 node 都是一个 jenkins 节点,可以是 jenkins master 也可以是jenkins agent,node 是执行 step 的具体服务器。

Step:步骤,step 是 jenkins pipline 最基本的操作单元,从在服务器创建目录到构建容器镜像,由各类 Jenkins 插件提供实现,一个 stage 中可以有多个 step,例如: sh “make”

2.2 Pipeline优势

可持续性:jenkins 的重启或者中断后不影响已经执行的 Pipline Job

支持暂停:pipeline 可以选择停止并等待人工输入或批准后再继续执行

可扩展:通过 groovy 的编程更容易的扩展插件

并行执行:通过 groovy 脚本可以实现 step,stage 间的并行执行,和更复杂的相互依赖
关系

2.3 Pipeline Job测试

2.3.1 创建Pipeline

图片.png

2.3.2 Hello World流水线示例

图片.png
图片.png

2.4 Pipeline案例

Pipeline相比Shell命令的优点就是可以指定构建任务运行在哪个Jenkins服务器上, 只需要按照Pipeline的语法, 把Shell脚本改成Pipeline格式, 并且指定运行在哪个Jenkins节点即可

  • Shell脚本执行构建
cd /var/lib/jenkins/workspace/projectA-web1
tar czvf myapp.tar.gz index.html
scp myapp.tar.gz tomcat@10.0.0.199:/data/tomcat/tomcat_zip
scp myapp.tar.gz tomcat@10.0.0.209:/data/tomcat/tomcat_zip
scp myapp.tar.gz tomcat@10.0.0.219:/data/tomcat/tomcat_zip

ssh tomcat@10.0.0.199 "/etc/init.d/tomcat.sh stop"
ssh tomcat@10.0.0.209 "/etc/init.d/tomcat.sh stop"
ssh tomcat@10.0.0.219 "/etc/init.d/tomcat.sh stop"

ssh tomcat@10.0.0.199 "tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp/"
ssh tomcat@10.0.0.209 "tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp/"
ssh tomcat@10.0.0.219 "tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp/"

ssh tomcat@10.0.0.199 "/etc/init.d/tomcat.sh start"
ssh tomcat@10.0.0.209 "/etc/init.d/tomcat.sh start"
ssh tomcat@10.0.0.219 "/etc/init.d/tomcat.sh start"

2.4.1 脚本式Pipeline案例

  • 准备工作:

利用Pipeline工具, 生成克隆代码的语法

图片.png
图片.png
git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
  • 步骤1: 先用伪代码写出Pipeline框架
node {

    stage("代码clone"){

        git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
    }

    stage("代码测试"){

        echo "代码测试"

    }

    stage("代码编译"){

        echo "代码编译"

    }

    stage("服务停止"){

        echo "服务停止"

    }

    stage("代码copy"){

        echo "代码copy"

    }

    stage("服务启动"){

        echo "服务启动"

    }

}
图片.png
  • 步骤2: 指定构建的运行节点
node("节点标签"){
}
node ("jenkins-slave-1-10.0.0.159") {

    stage("代码clone"){
        git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
    }

    stage("代码测试"){

        echo "代码测试"

    }

    stage("代码编译"){

        echo "代码编译"

    }

    stage("服务停止"){

        echo "服务停止"

    }

    stage("代码copy"){

        echo "代码copy"

    }

    stage("服务启动"){

        echo "服务启动"

    }

}

验证构建运行在slave-1

图片.png

代码克隆到workspace目录下, 如果想自定义代码克隆的目录, 那么就要手动使用git命令去克隆, 不能用流水线语法生成的命令克隆

root@jenkins-slave-1:~# ll /var/lib/jenkins/workspace/
total 16
drwxr-xr-x 4 root root 4096 Jul  6 15:40  ./
drwxr-xr-x 4 root root 4096 Jul  6 15:40  ../
drwxr-xr-x 3 root root 4096 Jul  6 15:40  pipeline-test1/
drwxr-xr-x 2 root root 4096 Jul  6 15:40 'pipeline-test1@tmp'/

  • 步骤3: 代码打包
node ("jenkins-slave-1-10.0.0.159") {

    stage("代码clone"){
        sh "cd /var/lib/jenkins/workspace/pipeline-test1 && rm -rf ./*" # 克隆代码前, 把原有的代码删除
        git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
        sh "echo 代码克隆完成"
    }

    stage("代码打包"){
        sh "cd /var/lib/jenkins/workspace/pipeline-test1" # 进到workspace
        sh "tar czvf myapp.tar.gz ./index.html" # 把代码打包
        sh "echo 代码打包完成"

    }

    stage("代码编译"){

        echo "代码编译"

    }

    stage("服务停止"){

        echo "服务停止"

    }

    stage("代码copy"){

        echo "代码copy"

    }

    stage("服务启动"){

        echo "服务启动"

    }

}

验证打包成功

root@jenkins-slave-1:/var/lib/jenkins/workspace/pipeline-test1# ls
index.html  myapp.tar.gz
  • 步骤4: 在slave-1节点上, 把myapp.tar.gz包拷贝到后端的三个tomcat服务器

slave-1节点需要对tomcat服务器做免密认证

root@jenkins-slave-1:~# ssh-keygen # slave节点用root启动的remoting.jar程序, 因此, 生成root用户的公钥
root@jenkins-slave-1:~# ssh-copy-id tomcat@10.0.0.199 # tomcat服务器用的tomcat账号启动tomcat, 因此, 公钥要复制到tomcat用户下
root@jenkins-slave-1:~# ssh-copy-id tomcat@10.0.0.209
root@jenkins-slave-1:~# ssh-copy-id tomcat@10.0.0.219
node ("jenkins-slave-1-10.0.0.159") {

    stage("代码clone"){
        sh "cd /var/lib/jenkins/workspace/pipeline-test1 && rm -rf ./*"
        git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
        sh "echo 代码克隆完成"
    }

    stage("代码打包"){
        sh "cd /var/lib/jenkins/workspace/pipeline-test1"
        sh "tar czvf myapp.tar.gz ./index.html"
        sh "echo 代码打包完成"

    }


    stage("服务停止"){

        sh "ssh tomcat@10.0.0.199 '/etc/init.d/tomcat.sh stop'"
        sh "ssh tomcat@10.0.0.209 '/etc/init.d/tomcat.sh stop'"
        sh "ssh tomcat@10.0.0.219 '/etc/init.d/tomcat.sh stop'"

    }

    stage("代码copy"){

        sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.199:/data/tomcat/tomcat_zip"
        sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.209:/data/tomcat/tomcat_zip"
        sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.219:/data/tomcat/tomcat_zip"

    }



    stage("服务启动"){

        echo "服务启动"

    }

}
root@tomcat-1:~# ll /data/tomcat/tomcat_zip
total 12
drwxr-xr-x 2 tomcat tomcat 4096 Jul  4 23:10 ./
drwxr-xr-x 5 tomcat tomcat 4096 Jul  3 00:19 ../
-rw-r--r-- 1 tomcat tomcat  263 Jul  6 16:12 myapp.tar.gz

  • 步骤5: 代码解压替换, 服务启动
node ("jenkins-slave-1-10.0.0.159") {

    stage("代码clone"){
        sh "cd /var/lib/jenkins/workspace/pipeline-test1 && rm -rf ./*"
        git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
        sh "echo 代码克隆完成"
    }

    stage("代码打包"){
        sh "cd /var/lib/jenkins/workspace/pipeline-test1"
        sh "tar czvf myapp.tar.gz ./index.html"
        sh "echo 代码打包完成"

    }


    stage("服务停止"){

        sh "ssh tomcat@10.0.0.199 '/etc/init.d/tomcat.sh stop'"
        sh "ssh tomcat@10.0.0.209 '/etc/init.d/tomcat.sh stop'"
        sh "ssh tomcat@10.0.0.219 '/etc/init.d/tomcat.sh stop'"

    }

    stage("代码copy"){

        sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.199:/data/tomcat/tomcat_zip"
        sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.209:/data/tomcat/tomcat_zip"
        sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.219:/data/tomcat/tomcat_zip"

    }


    stage("代码解压替换"){

        sh "ssh tomcat@10.0.0.199 'rm -rf /data/tomcat/tomcat_file/myapp/* && tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp'"
        sh "ssh tomcat@10.0.0.209 'rm -rf /data/tomcat/tomcat_file/myapp/* && tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp'"
        sh "ssh tomcat@10.0.0.219 'rm -rf /data/tomcat/tomcat_file/myapp/* && tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp'"
    }


    stage("服务启动"){

        sh "ssh tomcat@10.0.0.199 '/etc/init.d/tomcat.sh start'"
        sh "ssh tomcat@10.0.0.209 '/etc/init.d/tomcat.sh start'"
        sh "ssh tomcat@10.0.0.219 '/etc/init.d/tomcat.sh start'"

    }

}

先提交一个新版本v11到master分支, 然后测试构建结果

图片.png
  • 如果需要部署开发分支的代码, 只需要用流水线语法生成开发分支的拉取命令
图片.png
  • 这样就完成了通过脚本式流水线, 指定构建jenkins节点, 将代码部署到指定的服务器

2.4.2 利用Jenkinsfile来做代码部署

将部署脚本, 写到Jenkinsfile中, 上传到gitlab上, 通过gitlab上的Jenkinsfile来完成部署
避免人为把jenkins上写的部署脚本修改, 导致部署失败
  • 步骤1: 将代码写到Jenkinsfile, 上传到gitlab
root@git-client:~# cd /opt
root@git-client:/opt# cd web-02/
root@git-client:/opt/web-02# vim Jenkinsfile
root@git-client:~# cd /opt
root@git-client:/opt# cd web-02/
root@git-client:/opt/web-02# vim Jenkinsfile
root@git-client:/opt/web-02# git branch
  develop
* master
root@git-client:/opt/web-02# git add .
root@git-client:/opt/web-02# git commit -m "commit Jenkinsfile"
[master a57882c] commit Jenkinsfile
 1 file changed, 50 insertions(+)
 create mode 100644 Jenkinsfile
root@git-client:/opt/web-02# git push -u origin 
Username for 'http://10.0.0.239': developer-01
Password for 'http://developer-01@10.0.0.239': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 763 bytes | 763.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To http://10.0.0.239/qq/web-02.git
   8f5052d..a57882c  master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

  • 步骤2: 修改构建配置
图片.png
  • 步骤3: 项目构建

这时在构建时, Jenkins会克隆gitlab里的Jenkinsfile, 做解析, 然后执行. 这个文件会随着开发的项目代码一起提交, 开发结束后, 会修改Jenkinsfile一并提交到gitlab, 之后只需要在Jenkins上构建即可

2.4.3 声明式Pipeline案例

pipeline{

    agent { label "jenkins-slave-1-10.0.0.159" }
        stages {
                stage("代码clone"){

                        steps{
                                sh "cd /var/lib/jenkins/workspace/pipeline-test1 && rm -rf ./*"
                                git credentialsId: '53b5595a-d8c1-4a36-adfd-e80a378da79c', url: 'git@10.0.0.239:qq/web-02.git'
                                sh "echo 代码克隆完成"
                        }
                }
                stage("代码打包"){

                        steps{
                                sh "cd /var/lib/jenkins/workspace/pipeline-test1"
                                sh "tar czvf myapp.tar.gz ./index.html"
                                sh "echo 代码打包完成" 
                        }
                }
                stage("服务停止"){

                        steps{
                                sh "ssh tomcat@10.0.0.199 '/etc/init.d/tomcat.sh stop'"
                                sh "ssh tomcat@10.0.0.209 '/etc/init.d/tomcat.sh stop'"
                                sh "ssh tomcat@10.0.0.219 '/etc/init.d/tomcat.sh stop'" 
                        }
                }
                stage("代码copy"){

                        steps{
                                sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.199:/data/tomcat/tomcat_zip"
                                sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.209:/data/tomcat/tomcat_zip"
                                sh "scp /var/lib/jenkins/workspace/pipeline-test1/myapp.tar.gz tomcat@10.0.0.219:/data/tomcat/tomcat_zip"
                        }
                }
                stage("代码解压替换"){

                        steps{
                                sh "ssh tomcat@10.0.0.199 'rm -rf /data/tomcat/tomcat_file/myapp/* && tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp'"
                                sh "ssh tomcat@10.0.0.209 'rm -rf /data/tomcat/tomcat_file/myapp/* && tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp'"
                                sh "ssh tomcat@10.0.0.219 'rm -rf /data/tomcat/tomcat_file/myapp/* && tar xvf /data/tomcat/tomcat_zip/myapp.tar.gz -C /data/tomcat/tomcat_file/myapp'"
                        }
                }
                stage("服务启动"){

                        steps{
                                sh "ssh tomcat@10.0.0.199 '/etc/init.d/tomcat.sh start'"
                                sh "ssh tomcat@10.0.0.209 '/etc/init.d/tomcat.sh start'"
                                sh "ssh tomcat@10.0.0.219 '/etc/init.d/tomcat.sh start'"
                        }
                }

        }
}

提交一个新版本v13, 测试构建

图片.png
  • 之后, 可以把声明式脚本写入到Jenkinsfile里, 和每个版本的代码一起提交, 如果需要回滚, 那么每次回滚后, 直接构建即可, 无需修改Jenkinsfile, 因为每个版本的Jenkinsfile都是和代码一起的.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容