美文网首页工具cicdDevOps
12. Jenkins分布式和Pipeline

12. Jenkins分布式和Pipeline

作者: 随便写写咯 | 来源:发表于2021-07-06 19:33 被阅读0次

    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都是和代码一起的.

    相关文章

      网友评论

        本文标题:12. Jenkins分布式和Pipeline

        本文链接:https://www.haomeiwen.com/subject/yaywultx.html