kaixin
Published on 2024-01-25 / 8 Visits
0

Jenkins

Jenkins

Jenkins是什么:

  • Jenkins是一个开源的自动化服务器,主要用于持续集成(CI)和持续交付(CD)。它由Java编写,基于Java Servlet技术运行在Servlet容器(如Apache Tomcat)中。Jenkins通过插件机制提供了强大的扩展性,能够支持各种开发工具、构建系统、测试框架和部署环境。

作用:

  1. 自动化构建,可以从版本控制系统中,拉去代码,然后进行构建认为。(当开发人员提交完毕代码,jenkins就会触发构建,编译代码进行部署)。
  2. 自动测试,在构建过程中,jenkins可以运行单元测试,集成测试等自动化用例,如果测试失败,开发人员可以及时发现问题并且修复。(在Java项目中,Jenkins可以调用JUnit测试框架来执行测试。)。
  3. 代码质量检查,jenkins可以继承代码分析工具(如sonarqube),对代码进行质量检查,包含风格,潜在的威胁。
  4. 自动化部署,将构建好的代码,自动的部署到测试服务器,预生产服务器,生产服务器。
  5. 可以记录每一次构建的版本信息,方便进行回溯和管理。可以通过ui界面查看相关信息。
  6. 支持复杂的构建和部署方式,通过pipline插件,像脚本一行来表述每一个工作流的阶段。(如:拉代码,编译,测试,部署测试服务器等等)。

场景:

  1. 软件开发团队:
    • 在软件开发过程中,jenkins可以作为一个自动化构建,自动化测试的工具,当开发人员提交代码,jenkins会触发构建流程,当构建完毕后进行测试流程,如果测试通过会告知开发人员(直接合并到主分支),如果测试失败也,就会将错误的信息发送给开发人员。这样不仅仅提升了效率,通过也避免代码生产环境的错误。
  2. 持续集成和持续交付(CI/CD)实践:
    • ​ 是实现CI/CD的关键工具之一。它可以帮助团队将代码的构建、测试、部署等环节自动化,从而提高软件交付的速度和质量。(比如一个电商网站,这类公司需要快速的对市场进行响应,所以代码部署的次数较多)。
  3. 多语言和多框架项目:
    • 支持多种编程语言和开发框架(Java、Python、Node.js、Ruby),对于一个大型项目,可能同时使用了多种技术栈。Jenkins可以通过插件和配置来支持这些不同的语言和框架,实现统一的构建和部署流程。(例如,微服务项目)。
  4. 分布式开发团队:
    • Jenkins可以支持分布式开发团队的协作。开发人员可以分布在不同的地理位置,通过Jenkins来共享构建和测试结果。Jenkins的分布式构建功能可以利用多个节点来并行执行构建任务,提高构建效率。

相关资料:

  1. 官网:https://www.jenkins.io
  2. 下载(英文):https://www.jenkins.io/download/
  3. 下载(中文):https://www.jenkins.io/zh/doc/
  4. 文档手册(中文):https://www.jenkins.io/zh/
  5. 文档手册(英文):https://www.jenkins.io/doc/book/installing/

1.线上代码发展史

说明:

  • 代码发布上线是每一个 IT 企业必须要面临的,而且不管是对开发或者是运维来说,代 码上线本身就是一个件非常痛苦的事情,很多时候每一次发布都是一次考验。为了提高效率,代码上线方式方法,工具也不断发展。

为什么需要学习CI/CD流水线方式:

  • 不学习:可以通过shell脚本 + GIT + Gitlab + ansible 的方式实现代码更新批量部署。因为开发在修改代码的时候,每次修改就有可能导致某个地方出现问题,那么如果出现问题,解决起来就比较麻烦(先发布到测试服务,ok在发布到正式服务)。
  • 学习:就可以省去这些步骤,自动化的方式实现这些功能。节省人力成本,提高效率。

没有jenkins时:

  • 软件在开发者的机器上通过脚本或者手动构建,源代码保存在代码服务器中,但是开发者经常要修改本地代码,因此每次发布,都需要手动合并代码,再进行手动构建,这个过程费时费力。
  • 静态语言,需要打包编译环境,比如:java或者go。动态语言,确保机器的解释器版本以及包环境是否正常。直接拉去代码即可。

image-20250707233910831

使用jenkins:

image-20250707234216473

部署时间段选择:

  • 一般采取晚上进行代码更新部署,为什么是晚上,因为白天业务都在正常运行,如果白天进行代码更新就会导致公司的损失,白天一般不会进行重启服务进行更新代码。只有晚上业务量没有那么大的情况下进行操作。真正的时间需要运维根据访问日志中用户量进行分析制定的时间。

2.安装部署

中文版手册:
    https://www.jenkins.io/zh/doc/ (版本不是最新的)
    
版本对照表:
    https://www.jenkins.io/doc/book/platform-information/support-policy-java/
    
 jdk官网:
     https://www.oracle.com/java/technologies/downloads/archive/ 
     
注意事项:
    1.jenkins默认是8080端口,请不要让端口进行冲突。
    2.软件需求:由于jenkins是使用java语言开发,因此运行需要安装java运行时环境(jdk)。
    3.可以通过清华镜像站下载jenkins安装包,以及jdk环境可以通过yum或者apt命令直接安装(rpm,deb)。
    4.注意jenkins与java的版本一定要对应。 # 重点

2-1.下载安装

1.去清华源下载
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/ # rpm包 jenkins
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/ # 插件 jenkins

2.进行安装
    yum localinstall jdk-8u181-linux-x64.rpm # 安装java
    rpm -ivh jenkins-2.385-1.1.noarch.rpm # 安装jenkins
    java -version # 查看java的版本
    rpm -q jenkins # jenkins版本

3.启动
    systemctl start jenkins

image-20250708232905260


2-2.查看安装后文件

1.安装后的文件 rpm -ql jenkins
    /etc/init.d/jenkins # 这是Jenkins服务的启动脚本
    /etc/logrotate.d/jenkins # 配置Jenkins日志的轮转(logrotate)规则文件。
    /etc/sysconfig/jenkins # Jenkins服务的环境变量和配置文件。
    /usr/lib/jenkins # Jenkins程序安装目录。
    /usr/lib/jenkins/jenkins.war # 核心的可执行程序
    /usr/sbin/rcjenkins # 这是另一种Jenkins启动脚本,类似 /etc/init.d/jenkins
    /var/cache/jenkins # Jenkins的缓存目录。
    /var/lib/jenkins # Jenkins的主数据目录,也称为JENKINS_HOME。
    /var/log/jenkins # 日志文件

    jenkins配置文件:/etc/sysconfig/jenkins
    jenkins核心目录:/var/lib/jenkins
    
2.查看默认的配置
    grep -iE '^[a-z]' /etc/sysconfig/jenkins
    JENKINS_USER="jenkins"
        启动进程的用户,当前用户jenkins,这个用户的权限是不够的,需要给这个用户提权或者设置root账户(不建议设置,除非测试)。
    JENKINS_PORT="8080"
        默认jenkins运行的端口为8080的原因,在/etc/init.d/jenkins 执行脚本中读取的端口也是这个,通过 cat /etc/init.d/jenkins | grep JENKINS_PORT
进行查看。


3.如果不修改用户为root,就设置提权
    1.提权:
        jenkins ALL=(ALL) NOPASSWD: /bin/systemctl restart docker, /usr/bin/docker, /path/to/some/script.sh # 无需密码执行某些命令
    2.在脚本中使用sudo提权:
        sudo /usr/bin/docker ps # Pipeline或脚本里使用
    3.将构建访问的目录或者脚本目录的权限设置为jenkins
        sudo chown -R jenkins:jenkins /path/to/dir 或者 sudo chmod -R 750 /path/to/dir
    4.将jenkins用户加入到相关用户组中
        sudo usermod -aG docker jenkins # 然后重启jenkins服务或重新登录jenkins用户,使组权限生效

image-20250708234539076


2-3.初始化操作

1.当部署完毕后,访问jenkins时会有一个初始化页面,会提示一个管理员密码
    cat /var/lib/jenkins/secrets/initialAdminPassword
    
2.在自定义jenkins页面(安装插件)直接关闭都是国外源下载太慢

3.直接开始使用即可

# 初始化后,用户相关的目录
    /var/lib/jenkins/users

# 补充如果出现部署后初始化完毕无法正常跳转首页,再次刷新时出现登录,回到初始化流程(或者重装)。生产环境不建议。
    sudo systemctl stop jenkins
    sudo rm -rf /var/lib/jenkins/*
    sudo systemctl start jenkins

image-20250709232828309


2-4.忘记密码重置操作

# 可以实现,无密码登录

1.拷贝jenkins的用户配置文件
    cp  /var/lib/jenkins/config.xml{,.bak}

2.删除 config.xml 的下面的内容 # 作用: Jenkins 不再启用用户登录认证机制
    <useSecurity>true</useSecurity>
        <authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
            <denyAnonymousReadAccess>true</denyAnonymousReadAccess>
        </authorizationStrategy>
        <securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
        <disableSignup>true</disableSignup>
        <enableCaptcha>false</enableCaptcha>
    </securityRealm>

3.重启jenkins
    systemctl restart jenkins

# 执行完毕上面的操作后,就可以实现不需要用户登录,访问主页。
    1.点击 Manage Jenkins (系统管理) -> 点击 Configure Global Security (全局安全配置)
        1.勾选 Enable security(启动安全)
        2.选择 Jenkins’ own user database (Jenkins专有用户数据库)
        3.保存
    
    2.进行重置密码
        1.点击 Manage Jenkins(系统管理) -> 点击 Manage Users (管理用户)
        2.选择需要重置密码的用户(admin),点击用户名进入用户的个人信息页面。
        3.修改重置密码登录,进行登录。
    
    
    3.执行完毕上述操作,请将config.xml恢复,不然不需登录就可以访问到主页

image-20250709231640905


2-5.jenkins的配置

1. /etc/sysconfig/jenkins 配置文件的关键参数
    JENKINS_PORT="8080" # 端口参数,默认8080
    JENKINS_USER="jenkins" # 运行jenkins程序的用户,这个用户需要对 JENKINS_HOME 有权限
        [root@jenkins jenkins]# ls -ld /var/lib/jenkins/
        drwxr-xr-x 12 jenkins jenkins 4096 Jul  9 11:31 /var/lib/jenkins/
    JENKINS_HOME="/var/lib/jenkins" # 主目录,jenkins的核心目录,内部有插件,执行任务的job文件等等
    JENKINS_WAR="/usr/lib/jenkins/jenkins.war" # 指定 Jenkins 主程序的位置,除非你手动安装的特定版本
    JENKINS_JAVA_CMD="" # java的路径,可设置自定义 Java 路径,比如使用特定版本的 OpenJDK
    JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true" # Jenkins 进程所需的 Java 参数,可以自行添加一些参数
        JENKINS_JAVA_OPTIONS="-Xms512m -Xmx2048m -Djava.awt.headless=true" # 比如添加了内存参数
    
    JENKINS_ARGS="--webroot=/var/cache/jenkins/war" # 其他参数传递给 jenkins.war
        JENKINS_ARGS="--webroot=/var/cache/jenkins/war --httpPort=8080" # 指定端口
        可以通过:java -jar /usr/lib/jenkins/jenkins.war  --help 进行查看参数指令有哪些

    # 修改完毕参数后:
        sudo systemctl daemon-reload # 重新加载system的配置文件
        sudo systemctl restart jenkins # 重新启动jenkins

2-6.JENKINS_HOME目录说明

JENKINS_HOME="/var/lib/jenkins" # 默认
目录结构:
├── config.xml # Jenkins 全局配置文件(安全策略、系统设置、代理配置等)
├── jobs # 所有 Jenkins 任务(Job)的配置和历史记录
├── logs # Job 和系统日志文件(非主日志,主日志在 /var/log/jenkins)
├── nodeMonitors.xml # 用于控制 Jenkins 对 master 和 agent 节点的健康状态监控机制。
├── nodes # 所有代理节点(agent)的配置文件
├── plugins # 安装的插件 .jpi 文件和其缓存目录,插件都在这里
├── secrets # 存放加密密钥、API token、credentials 等敏感数据
├── updates # 插件更新中心的缓存数据
├── userContent # 用于存放用户自定义的静态资源文件,例如:HTML,pdf等等 可以直接通过 http://<jenkins-url>/userContent/<文件名> 进行访问 ( Jenkins 用户(甚至匿名用户需要修改安全策略)都可以访问这个目录下的内容 )
└── users # 所有 Jenkins 用户的配置数据


需要关注的:
    config.xml # Jenkins 配置	
    jobs/ # 所有 Job	
    plugins/ # 所有的插件
    secrets/ # 加密秘钥
    users/ # 用户数据

2-7.jenkins插件

# 插件是什么:
    Jenkins 的功能扩展组件,它们允许你在基础 Jenkins 的核心功能上,添加各种能力,比如:
        集成版本控制系统(如 Git、SVN、GitHub)
        实现 CI/CD 流水线(Pipeline)
        构建、测试、部署工具链(如 Maven、Docker、Ansible)
        权限控制、安全认证(如 LDAP、OAuth)
        用户界面增强(如 Blue Ocean、Pipeline View)
        和外部系统打通(如 Slack、Email、Kubernetes)
        # jenkins是一个框架,所有的功能都是插件实现的。将插件(功能)集成到jenkins中。
        
# 注意:
    需要安装同版本的插件,如果是老版本的jenkins,无法从直接使用插件商城的插件。


# 查看插件
    点击 Manage Jenkins -> manage plugins 

官方插件地址:
    https://plugins.jenkins.io/

image-20250710000749803


2-7-1.插件导入

1.解压准备的插件压缩包
    tar -zxf jenkins_plugins.tar.gz 

2.将解压的插件拷贝到插件目录中
    mv * /var/lib/jenkins/plugins/ # 直接将插件移动到 plugins 目录中就可以,也可以直接进行下载或者其他方式都可以

3.重启jenkins
    systemctl restart jenkins

image-20250710001157497


2-7-2.插件的高级设置

1.代理设置
    需要设置梯子,才能使用国外源的插件下载安装。

2.下载.hpi文件,然后在jenkins里面导入上传即可,自动安装,重启生效
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/

3.可以更换插件源为清华的
    https://updates.jenkins.io/update-center.json 替换为 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

image-20250710001817447


2-7-3.添加外部下载的插件

# 插件作用:
    1.Publish over SSH 可以实现免密发送文件
    2.其实也可以使用scp也可以实现,或者ansible 都可以实现

1.下载插件
    在清华源下载:https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/publish-over-ssh/1.0/publish-over-ssh.hpi # 下载到当前宿主机

2.使用高级设置上传插件

3.重启jenkins
    systemctl restart jenkins

image-20250722231859374


3.jenkins使用

注意:
    为了让jenkins在执行命令时,不会被权限拒绝,一定要提高当前运行jenkins程序的用户权限。如果是普通用户运行(默认的jenkins)需要提权。

# 使用场景:
    实现CI/CD流水线操作,避免开发人员直接的接触服务器,通过jenkins中设置一个job给开发人员使用。防止服务器的环境出现错乱(不一定知道linux操作),与jumpserver性质不同。

image-20250710225730626


3-1.jenkins任务说明

jenkins的默认任务目录:
    /var/lib/jenkins/workspace # 只有执行构建任务时,才会在当前路径下发生,他会将任务(job)构建期间源码、脚本执行、构建产物等都会在这里进行。
    /var/lib/jenkins/jobs  # 创建任务后,就会在当前文件夹下创建于任务名称一样的文件夹

# 注意:
    1.每一个任务都会在 jobs/ 目录下创建一个文件 (文件名称就是任务名称)。
    2.需要关注的就是每次一构建任务后的控制台输出日志,查看当前构建执行任务成功与否,错误的原因,并修复问题。
    3.创建的任务名称是不能随意修改了,这个名称在 jobs/ 目录创建一个名字一模一样的文件,如果修改job就会出现错误。
    4.job任务的执行,是在对应生成工程目录下执行的。(workspace/job任务名称)
    5.jenkins的默认变量很重要,对于编写任务脚本提供很大的方便(比如说路径,就可以使用 JENKINS_HOST 内置变量 这个变量就是jeknins的任务目录)。
    6.jenkins可以同时运行多个构建任务,每个任务都有自己的工作目录。Jenkins 会在 workspace/ 目录中为每个构建任务创建一个独立的子目录,以避免不同任务之间的冲突和干扰。

image-20250710230859843


3-2.任务-自由风格创建

1.选择一个自有风格的任务

2.选择执行shell
    echo "当前主机名: $(hostname)"
    echo "jenkins是在哪执行的命令 : $(pwd)"
    echo "jenkins执行文件创建: $(touch 奥利给.log)"
    echo "搜索该文件,看看在哪创建: $(find / -name '奥利给.log')"
    # shell嵌入jenkins的内置变量,非常方便,对自己写的shell脚本很大帮助
    echo -e "查看jenskins如下内置变量
    JOB NAME ------ ${JOB_NAME}
    BUILD ID ------ ${BUILD_ID}
    WORKSPACE ----- ${WORKSPACE}
    JENKINS HOME -- ${JENKINS_HOME}"

3.保存执行

4.从控制台输出的信息
    /var/lib/jenkins/workspace 当前这个文件就是只有在执行时才有作用,所有的操作(文件相关)都在这个文件夹下进行。

image-20250710231848921


3-3.jenkins内置变量

还以一些内置变量是与安装的插件相关的,只有安装完插件才能使用
变量名 含义 示例输出
BUILD_NUMBER 构建编号 17
BUILD_ID 构建 ID(非唯一) 2025-07-10_13-45-02
BUILD_URL 当前构建的完整 URL http://your-jenkins/job/my-job/17/
JOB_NAME 任务名 my-job
WORKSPACE 当前构建的工作目录 /var/lib/jenkins/workspace/my-job
JENKINS_HOME Jenkins 主目录 /var/lib/jenkins
JENKINS_URL Jenkins 服务器地址 http://your-jenkins/
BRANCH_NAME 多分支流水线中的分支名 main
NODE_NAME 当前运行节点名,构建在代理上,则为代理的名称,如果在 master 上运行,则为“master” master or 节点名称
EXECUTOR_NUMBER 构建所使用的 executor 编号 0
BUILD_TAG 唯一标识构建的标签 jenkins-my-job-17
JOB_BASE_NAME 不含路径的 Job 名称 my-job

3-4.任务-界面说明

image-20250710234538690


1.工作区(工作空间)
    /var/lib/jenkins/workspace/ # 目录存放着当前job的相关文件(workspace/job的名称文件)
2.立即构建:执行当前的工程
3.配置:修改当前的工程内部的配置
4.构建历史:每一次构建的执行后的记录,成功是蓝色,失败是红色
5.Blue Ocean:就可以看到当前功能执行,每一个执行的就是看到执行的日志信息。

image-20250710235038294


3-5.jenkins构建过程说明

1.任务触发(点击任务构建)。
2.jenkins会在/var/lib/jenkins/workspace/<job-name>/创建或清理构建目录(WORKSPACE),并切换到该目录执行构建。
3.源码管理(如果是git或者svn的任务,就会将代码拉去到 workspace/ 下)。
4.执行构建步骤(例如:shell脚本,maven,自定义的其他脚本,测试)。
5.构建结果处理(1.显示构建状态成功或者失败,2.保存日志和构建产物,3.归档,4.通知下游任务设置的情况下,5.发送通知)。
6.构建产物管理(将构建产物上传服务器)。
7.部署(在CI/CD场景下,可以进行自动部署到服务器)。

3-6.pipline脚本

是什么:

  • 在编程和软件工程中,通常指的是一种自动化执行一系列任务的脚本。它最常见于 CI/CD(持续集成/持续部署)场景中,用来自动构建、测试、打包、部署软件项目。

脚本方式:

  1. 声明式(推荐使用)。语法固定结构清晰,jenkins会按照你的顺序进行执行。
  2. 脚本式。更加灵活,可以实现更加复杂的逻辑,但是需要懂一些 Groovy 编程。

声明式脚本关键字:

关键字 说明
pipeline Pipeline 的起点,必须有
agent 指定在哪个 Jenkins 节点上运行(如 any(全部的机器), none(不在 pipeline 层指定,需每个 stage 指定), 或指定标签agent { label 'linux' }(只在标记为 linux 的节点上执行)等等
environment 定义环境变量。
options 设置pipeline的行为规则,用来控制 Jenkins 构建流程的规则、限制、清理和输出行为的。
stages 构建流程的各个阶段集合
stage 每一个具体的阶段(如测试、构建)
steps 阶段中的具体操作(执行命令等)注意:在steps内执行shell命令需要使用sh包裹。 sh 'cat 123.log'
when 在阶段中是否进行判断。
post Pipeline 结束后执行的逻辑(无论成功或失败)关键字:always{'不管成功、失败、取消等情况都执行'},success{'仅构建成功时执行'},failure{'仅构建失败时执行'},unstable{'构建不稳定(测试失败等)时执行'},aborted{'构建被中断时执行'}
sh / bat 运行 Shell(Unix)或 bat(Windows)脚本命令
echo 是一个步骤step,用来向控制台输出文本消息,类似于命令行中的 echo 命令。例如: echo '开始构建...'
input 是一个步骤step,等待人工确认(适用于发布前审批)例如: input message: '确认是否继续部署?', ok: '确认'

image-20250714224801940

  • when关键字写法

    条件类型 说明 例子
    branch 判断当前构建的 Git 分支名 when { branch 'main' }
    environment 判断环境变量是否匹配 when { environment name: 'DEPLOY_ENV', value: 'prod' }
    expression 自定义 Groovy 表达式返回 true 执行,否则跳过 when { expression { return params.DEPLOY == 'yes' } }
    equals 判断两个字符串是否相等 when { equals expected: 'release', actual: env.BUILD_TYPE }
    changed 判断指定文件是否被修改过(支持多文件) when { changeset "src/**" }
    not 取反 when { not { branch 'dev' } }
    allOf 多个条件都满足时执行 when { allOf { branch 'main'; environment name: 'ENV', value: 'prod' } }
    anyOf 任意条件满足时执行 when { anyOf { branch 'main'; branch 'release' } }
    beforeAgent 表示 when 判断在 agent 分配之前执行(优化性能) when { beforeAgent true; branch 'dev' }
    triggeredBy 根据触发方式判断,如定时触发、手动触发 when { triggeredBy 'TimerTrigger' }

声明式脚本语法:

pipeline { # 外部的框架
    agent any  # 在任意节点执行

    environment { # 声明环境变量
        变量名 = "值"
    }

    options {
        // 可选的行为设置
        # 例如:
        timeout(time: 15, unit: 'MINUTES')           // 超时自动中止
        disableConcurrentBuilds()                    // 禁止并发构建
        buildDiscarder(logRotator(numToKeepStr: '5'))// 只保留最近 5 次构建,构建历史自动清除策略
        timestamps()                                 // 控制台输出加时间戳
        ansiColor('xterm')                           // 支持彩色输出
        skipDefaultCheckout()	 				   // 跳过默认自动拉代码的操作
    }

    parameters {
        // 用户构建前输入的参数
    }

    triggers {
        // 自动触发构建的规则
    }

    stages { # 各个子阶段的父级
        stage('阶段名称') { # 子阶段
            when {
                // 条件控制(可选)
            }
            steps {
                // 执行的命令
            }
            post {
                // 这个阶段结束后做的事
            }
        }

        // 可以有多个 stage
    }

    post {
        // 整个 pipeline 结束后的处理
        success {
            echo '成功了'
        }
        failure {
            echo '失败了'
        }
    }
}

简单的声明式脚本:

例如当前脚本:
    pipeline {
      agent any
      stages {
        stage('Hello') {
          steps {
            echo 'Hello, Jenkins!'
          }
        }
      }
    }

执行过程:
    1.点击“新建任务” → 输入任务名 → 选择“流水线”(Pipeline) → 点击确定
    2.在项目配置页面,找到“流水线”部分
    3.方式
        1.选择“流水线脚本来自 SCM”(源码管理)
            1.选择你的代码仓库类型(比如 Git)
            2.填写仓库地址和分支,Jenkins 会自动拉取包含 Jenkinsfile(你的Pipeline脚本的名称) 的代码 # Jenkinsfile	Pipeline 脚本文件名,固定叫这个,不能改成别的名字
            yourproject/
            ├── Jenkinsfile     ← 这里放 Pipeline 脚本
            ├── src/
            │   └── main.py
            └── README.md

        4.流水线脚本
            1.填写脚本即可。

image-20250714221602562

3-6-1.拉去并构建脚本

pipeline {
    agent any  // 在任何可用的节点上运行

    stages {
        stage('Checkout') {
            steps {
                echo '拉取代码...'
                git 'https://github.com/your/repo.git'
            }
        }

        stage('Install') {
            steps {
                echo '安装依赖...'
                sh 'npm install'  // 如果是 Node.js 项目
            }
        }

        stage('Test') {
            steps {
                echo '运行测试...'
                sh 'npm test'
            }
        }
    }

    post {
        success {
            echo '构建成功!'
        }
        failure {
            echo '构建失败,请检查错误日志'
        }
    }
}

3-6-2.带参数脚本

pipeline {
    agent any

    parameters {
        string(name: 'BRANCH', defaultValue: 'main', description: '请选择构建分支')
        booleanParam(name: 'RUN_TESTS', defaultValue: true, description: '是否执行测试')
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: "${params.BRANCH}", url: 'https://github.com/yourrepo/yourproject.git'
            }
        }

        stage('Build') {
            steps {
                echo "构建分支: ${params.BRANCH}"
                sh 'npm install'
            }
        }

        stage('Test') {
            when {
                expression { return params.RUN_TESTS }
            }
            steps {
                sh 'npm test'
            }
        }
    }
}

3-6-3.超时和并发控制脚本

pipeline {
    agent any

    options {
        timeout(time: 20, unit: 'MINUTES')       // 超时 20 分钟
        disableConcurrentBuilds()                 // 禁止并发执行
        timestamps()                             // 控制台输出带时间戳
    }

    stages {
        stage('Build') {
            steps {
                echo '开始构建...'
                sh './build.sh'
            }
        }
    }
}

3-6-4.简单部署脚本

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }

        stage('Deploy') {
            steps {
                echo '部署到服务器...'
                sh 'scp target/app.jar user@server:/deploy/path/'
                sh 'ssh user@server "systemctl restart myapp"'
            }
        }
    }
}

3-6-5.实验脚本

// 定义跨阶段共享变量
def create_d_success = false
def create_f_success = false
def write_success = false

pipeline {
    agent any
    // 不使用共享变量,直接使用环境变量
    environment {
        CREATE_D_SUCCESS = 'false'
        CREATE_F_SUCCESS = 'false'
        WRITE_SUCCESS = 'false'
    }
    stages {
        stage('create_d') {
            steps {
                script {
                    sh 'mkdir -p /opt/kenkins/'
                    create_d_success = true
                    env.CREATE_D_SUCCESS = 'true' // 修改环境变量的值
                }
            }
            post {
                success {
                    echo "第一阶段完成"
                }
            }
        }

        stage('create_f') {
            when {
                expression { return create_d_success }
            }
            steps {
                script {
                    sh 'touch /opt/kenkins/123.log'
                    create_f_success = true
                }
            }
            post {
                success {
                    echo "第二阶段完成"
                }
            }
        }

        stage('write') {
            when {
                expression { return create_f_success }
            }
            steps {
                script {
                    sh '''echo "asdasdsadasdas" > /opt/kenkins/123.log'''
                    write_success = true
                }
            }
            post {
                success {
                    echo "第三阶段完成"
                }
            }
        }

        stage('echo') {
            when {
                expression { return write_success }
            }
            steps {
                sh 'cat /opt/kenkins/123.log'
            }
            post {
                success {
                    echo "第四阶段完成"
                }
            }
        }
    }
}

4.jenkins操作

4-1.凭证设置

操作流程:
    1.登录 Jenkins 后,点击左侧的 "凭证" (Credentials)。
    2.选择 "(global)" 或者你希望存放凭证的域。
    3.点击 "添加凭证"。
    4.在 "凭证种类" 中选择 "Username with password"(如果是 Git 的 HTTP 凭证) HTTP 凭证:填写你的 Git 用户名和密码/Token。
    5.选择 "SSH Username with private key"(如果是 Git 的 SSH 凭证)。SSH 凭证:上传你的私钥并设置相应的用户名。
    6.点击保存。

# 注意git的认证方式:
    1.如果使用账密:
        选择类型"Username with password",输入git仓库的账密(必须是有权限访问这个仓库才可以)。
    2.如果使用ssh凭证:
        选择类型"SSH Username with private key",配置这个公钥的账户也需要有权限才可以。
            1.在git仓库中添加公钥 # 配置公钥
            2.在jenkins凭证中添加私钥 # 注意是私钥

# 注意:
    关于凭证的可见范围,可以针对性的设置(针对某个url或者主机名或者端口等方式)
    # 可以再job创建过程中添加凭证,也可以直接添加凭证在job中使用。

image-20250717002451639


4-2.实现CICD基础流水线

流程

  1. 创建远程仓库(gitlee,github,gitlab)。
  2. 开发人员推送代码到远程仓库。
  3. 创建一个自有风格的job,配置job(核心在与git的用户配置 1.http 2.ssh)。
  4. job内添加shell脚本,进行构建。
  5. 注意:必须有Git插件。

流程图:

image-20250716230422190

仓库链接测试:

采用ssh链接方式,需要进行公钥认证。# jenkins机器操作
    ssh-keygen # 创建秘钥
    git clone git@192.168.85.149:root/python_flask_test.git # 拉去代码测试

image-20250716232900433

4-2-1.http的账户密码认证方式

# 统一在安装jenkins机器上进行操作
使用http账密方式:
    http://192.168.85.149/root/python_flask_test.git # 仓库地址
    
创建一个自有风格的job # jenkins机器操作
    1.设置构建的保留策略
        勾选丢弃旧构建(1.设置保留天数 2.设置最大保留数量)
    2.选择源码管理
        点击Git(1.输入git的url 2.添加凭证)
        添加凭证:选择凭证类型(1.可以选择账密,2.也可以选择ssh) # 当前凭证方式是在job创建过程中添加
    3.构建
        /var/lib/jenkins/workspace/ # jenkins构建时,会产生的项目的文件,附件等内容都都会存储到这个文件夹(项目名称文件)下。
        构建的文件会在:/var/lib/jenkins/workspace/python_flask 文件夹中

image-20250716233329564


4-2-2.ssh-key的公钥认证方式

# 统一在安装jenkins机器上进行操作
使用ssh公钥方式:
    git@192.168.85.149:root/python_flask_test.git # 仓库地址
    
创建一个自有风格的job # jenkins机器操作
    1.设置构建的保留策略
        勾选丢弃旧构建(1.设置保留天数 2.设置最大保留数量)
    2.选择源码管理
        1.点击Git(1.输入git的url 2.添加凭证)
        2.添加凭证:选择凭证类型,选择ssh # 当前凭证方式是在job创建过程中添加
            1.gitlab中设置"公钥"
                ssh -i ~/.ssh/id_rsa git@192.168.85.149 # 进行确认是否需要输入密码
            2.jenkins中添加"私钥"凭证
            
        3.选择分支(默认是master分支),如果是其他的分支请修改
        
    3.构建
        /var/lib/jenkins/workspace/ # jenkins构建时,会产生的项目的文件,附件等内容都都会存储到这个文件夹(项目名称文件)下。
        构建的文件会在:/var/lib/jenkins/workspace/python_flask_2 文件夹中

# 注意:
    1.jenkins添加的凭证是"私钥"
    2.gitlab添加的ssh秘钥是"公钥"
    3.公钥与私钥必须是一对

image-20250717001323592


4-3.pipelne进行自构建

必要条件:
    1.Pipeline 插件
    2.Git 插件

# 整体流程
1.创建仓库,上传pipeline脚本
    仓库地址:git@192.168.85.149:root/pipeline.git
    对当前仓库push,jenkins pipeline脚本脚仓库 # 注意脚本名称要与流水线的job的脚本路径名称相同。
    
2.创建一个流水线的job # 当前操作会从远程仓库中自动拉去 Jenkinsfile 并执行
     # 注意脚本文件名称:Jenkinsfile,可以自定义,需要设置文件名称。
     1.选择模式:Pipeline script from SCM
     2.选择SCM:git
     3.输入仓库地址,选择仓库秘钥,选择仓库分支
     4.输入路径 # 默认是Jenkinsfile文件名称,Jenkins 会自动识别。
         如果是默认,那么你的远程仓库就根目录下必须有 Jenkinsfile(就是pipeline脚本) 文件存在。
             目录结构如下:# 脚本路径写:Jenkinsfile 	
                |—— .git
                |—— Jenkinsfile 
                |—— 其他文件.txt
                
        如果是嵌套到其他的目录下:
            目录结构如下:# 脚本路径写:script/Jenkinsfile 	
                |—— .git
                |—— script
                    |—— Jenkinsfile 
                |——其他文件.txt

image-20250717223311800


4-4.shell脚本自动化构建

jiekins可以创建一个自由风格,纯shell脚本的job进行操作,shell脚本内可以自定义执行内容,比如python环境安装下载,python启动等等。

# 注意:
    1.免密登录:需要设置jenkins机器其他机器的ssh免密登录,或者使用ansible主机。
        1.生成秘钥
            ssh-keygen
        2.进行免密操作
            ssh-copy-id root@192.168.85.149
        
1.shell脚本
    ssh root@192.168.85.149 "mkdir /opt/test_shell"
    ssh root@192.168.85.149 "echo 'asdasdsadas' > /opt/test_shell/123.txt"
    ssh root@192.168.85.149 "cat /opt/test_shell/123.txt"
    
3.创建自有风格的job进行构建
    1.创建自有风格的job
    2.选择构建,构建步骤
    3.在输入框中,添加shell命令,保存
    4.构建

image-20250717225536552


4-5.总结内容

过程:
    1.通过jeknins进行从gitlab下载源码到工作区目录下。
    2.通过构建中得shell操作,将工作目录(就是存储放置job操作的文件)进行打包压缩,发送到远程服务器(记得免密)。
    3.在将部署的脚本(可以直接将脚本在远程服务器写好,直接调用即可)发送到远程服务器,进行调用安装。

注意:
    1.关于工作目录是什么:是job在创建后第一次执行,会在jenkins工作区文件夹创建关于job的文件,这个文件路径就是当前job的工作区文件夹
    2.远程调用:注意免密操作,scp 发送文件 ssh 执行命令  或者直接使用ansible进行操作,可以远程执行命令,执行脚本(脚本在jenkins机器上需要先发送在执行)
    3.在编写脚本时注意:shell的编写,细心,正确。

简单来说:jenkins就是实现 拉去代码(打包),部署环境(测试环境,生产环境),发布代码的过程(测试,部署,验证,发布)等等操作。将人为的操作简化为自动化操作。
    # 现实中更为复杂。
    拉代码(+权限+缓存+审计)
      └── 构建(+测试+扫描+多架构)
          └── 发布(+灰度+监控+回滚+通知)

5.jenkins实际部署

# 部署情况说明:
    1.静态资源部署,比如纯html(前端框架打包后的静态资源),将代码发送给部署机器的根目录即可。
    2.动态部署,属于后端,需要重启服务。

5-1 .发布静态网址流水线

# 流程方式:
    gitlab + jenkins(自有风格的job) + ssh脚本方式(ssh免密链接,将代码发送给部署机器)
    
# 静态部署问题:
    只需要从git仓库中拉去代码到jenkins的job工作目录,对目录打包,发送到指定的服务器的网页根目录下,重启web服务器即可(nginx)。
    需要考虑的问题:
        1.确保每次的构建,后重启都是最新的资源,可以使用软连接,将网页根目录软连接。
        2.jenkins远程发送的包需要按照时间或者唯一值进行命名(保证文件的唯一性),解压到远程机器上,每次构建进行的软连接,都是最新的构建后的静态数据。
    
# 部署测试机器准备:
    1.jenkins机器(192.168.85.150),主要是实现拉去gitlab的源码然后发送给部署机器。# 注意需要将当前机器与部署机器进行免密处理
        ssh-copy-id root@192.168.85.151 # 免密
        ssh root@192.168.85.151 # 测试
    2.gitlab机器(192.168.85.149),主要用于存储源码。
    3.部署机器(192.168.85.151),主要展示jenkins构建后部署的情况。 

image-20250720223311188


5-1-1.准备源码仓库

选择在gitlab中导入仓库即可,填写导入后仓库的基本信息。
# 其他远程仓库地址:
    https://gitee.com/kangjie1209/monitor.git

# gitlab中创建的仓库地址:
    http://192.168.85.149/root/monitor.git
    git@192.168.85.149:root/monitor.git

image-20250720224512718


5-2-2.部署机器配置

1.安装nginx
    yum install nginx

2.添加配置
    mkdir -p /code/html # 创建根目录
    vim /etc/nginx/conf.d/html.conf # 创建nginx配置文件
    server {
        listen 80;
        server_name _;
        location / {
            root /code/html/; # 设置网页目录为解压代码文件
            index index.html;
        }
    }

5-2-3.创建一个job

# 整体流程
    1.拉去代码到工作目录,然后对工作目录进行压缩。
    2.将压缩后的文件发送给部署机器。
    3.在部署机器上对文件进行解压。
    4.重启nginx(需要判断是否有nginx,如果有检查配置文件)。

# job的shell脚本如下:
   get_code(){
        cd ${WORKSPACE} && rm -rf nginx_index.tar.gz  && tar -czf nginx_index.tar.gz ./*
    }
    scp_web_server(){
        DATE=$(date +%Y-%m-%d-%H-%M-%S)
        id_list="192.168.85.151"

        for nginx_ip in ${id_list}
        do
            scp nginx_index.tar.gz root@${nginx_ip}:/opt
            ssh root@${nginx_ip} "mkdir -p /code/web${DATE}  && tar -xzf /opt/nginx_index.tar.gz -C /code/web${DATE} && rm -rf /code/html && ln -s /code/web${DATE}  /code/html && nginx -s reload"
        done
    }
    
    deploy(){
        get_code
        scp_web_server
    }
    deploy

# job执行流程解释:
    1.拉去更新的源码(如果没有就会在当前的工作目录拉去创建,如果有就会更新仓库)。
    2.构建中添加的 shell 脚本代码
    3.会执行 deploy 函数内部的代码
        1.执行 get_code 函数。 
            cd ${WORKSPACE} && rm -rf nginx_index.tar.gz  && tar -czf nginx_index.tar.gz ./* # 先cd到工作目录,然后删除原有的压缩文件,在重新对目录下的文件进行压缩
        
        2.执行 scp_web_server 函数。
            内部代码就是,将压缩后的 nginx_index.tar.gz 发送到部署机器上,然后部署机器会根据"当前时间"创建一个新的 nginx的跟目录文件,与配置的根目录文件做软连接,然后重启nginx。

image-20250720231358879


5-2-4.模拟开发修改源代码推送构建

1.拉去源代码
    git clone git@192.168.85.149:root/monitor.git

2.修改源码
    将"将开发移动能效平台"修改"xxx公司专用"

3.推送
    git add .
    git commit -m "修改"
    git push origin master

4.在进行构建,访问查看

image-20250720232417795


5-2.webhook自动化触发构建

webhook自动化触发构建:
    是有外部系统(如 GitHub/GitLab/Gitea)主动的通知jenkins代码变化,然后jenkins进行构建。
    # 谁来触发:
        触发方(Webhook 源): 代码托管平台(GitHub/GitLab/Gitea 等)。
        被触发方(Webhook 目标): Jenkins 的一个特定 URL(JENKINS_URL/github-webhook/、/gitlab-webhook/、/gitea-webhook/ 等)。

运维发布的阶段:
    1.手动发布,shell脚本或者ansible批量操作
    2.jenkins手动构建实现发布,鼠标轻轻点击一下就操作完成了
    3.jenkins自动化构建发布,通过webhook进行触发,无需任何操作。
# 解释:
    1.自动化构建发布,当gitlab中存在有提交新版本,自动的就会触发条件,执行某个更新版本的job,进行全自动操作 以mstart分支。
    2.根据jenkins设置的触发条件,在gitlab中也进行设置,当push代码到master分支,直接就会触发事件,进行jenkins的自动构造。
动作 说明
用户 git push 代码更新到 GitHub
GitHub 发送 HTTP POST 推送到 https://JENKINS_URL/github-webhook/
(Payload 包含 commit、分支、仓库等信息)
Jenkins 收到 POST 插件(GitHub plugin)解析 Payload
匹配 Job 规则 检查哪些 Job 的 “构建触发器 → GitHub hook trigger” 已启用,且仓库 URL 匹配
立即排队构建 触发对应 Job 的新构建(Build #N+1)

5-2-1.job设置触发器

# 设置触发器
    点击触发器,选择触发器类型,当gitlab有push事件,就会执行这个job。
    jenkins提供url:
        http://192.168.85.150:8080/project/static_nginx
    选择触发条件:# 在什么条件时触发这个自动构建
        1.推送事件 # 当有人向 GitLab 仓库 push 代码(包括新建分支、直接 push 到主分支等)
            # 场景:
                持续集成(CI),每次提交代码都跑测试。
            # 注意:
                如果只是想监听某个特定分支,请在job中设置分支过滤。
                
        2.打开的合并请求事件 # 当 GitLab 中 新建一个 MR(从 feature → main),触发 Jenkins 构建。
            # 场景:
                跑 MR 的自动化测试(如单元测试、代码扫描)。Jenkins 会构建 MR 的“合并后状态”(即模拟合并到目标分支后的代码)。

        3.接受的合并请求事件	# 当 GitLab 中 MR 被合并(Accepted/Merged) 时,触发 Jenkins 构建。
            # 场景:
                 合并后自动部署到测试/预生产环境。
            # 注意:
                此时构建的是 合并后的目标分支(如 main)
                
        4.已关闭的合并请求事件 # 当 MR 被关闭(未合并),触发 Jenkins 构建。
            # 场景:
                很少用,一般用于清理临时环境(如关闭 MR 时自动销毁测试环境)。
        
        5.重新打开合并请求 # 当 目标分支更新(如 main 被 push 了新代码),重新构建所有未合并的 MR。
            # 场景:
                确保 MR 不会与最新主分支冲突(例如主分支更新后,重新跑 MR 的测试)。

        6. 已批准的合并请求(仅限 GitLab Enterprise Edition)# 当 MR 被 代码评审人点击“Approve” 后,触发 Jenkins 构建。
            # 场景: 
                需要人工审核后才能进入下一步(如部署到生产)。# 社区的无当前功能
            
        7.comments(备注触发)# 当 MR 或 Issue 下 新增一条评论 时,触发 Jenkins 构建。
            # 场景:
                通过评论命令控制 Jenkins(如评论 jenkins rebuild 重新跑测试)。


# 获取这个job的主要保留的信息
    1.url http://192.168.85.150:8080/project/static_nginx
        这个url会精准的定位到jenkins的这个job任务
    
    2.token值 7cf9d4cf6a3f26520e18036089c74516 
        jenkins的具体的job 和gitlab具体的仓库url进行对应,进行身份识别

# 注意:一定要进行保存

image-20250720235533752


5-2-2.在gitlab中设置

# 操作流程:
    1.选择当前在jenkins中job的项目
    2.进入当前项目的设置
        选择 设置->集成->填写url和token
            http://192.168.85.150:8080/project/static_nginx
            7cf9d4cf6a3f26520e18036089c74516 
    3.配置,并且发送请求进行测试 # 只要200ok说明配置正常

# 配置是出现:不允许对本地网络请求
    1.以管理员身份登录 GitLab(root 用户)。
    2.点击顶部导航栏的 “管理中心”(小扳手图标)。
    3.进入 “设置” → “网络” → “外发请求”(Outbound requests)。
    4.勾选以下选项:
        “允许 Webhook 和服务对本地网络的请求”(Allow requests to the local network from web hooks and services)。
    5.点击 保存更改。

image-20250721000824469


5-2-3.更新源码推送到仓库

1.开发修改代码"将标题修改为 '测试自动构建' ",提交进行push请求
    git add .  
    git commit -m 'v10'
    git push  origin master

2.查看构建记录
3.查看网站显示的内容

image-20250721001205616


5-3.构建python项目

5-3-1.安装环境-部署机器

1.安装依赖
     sudo yum groupinstall "Development Tools"
     sudo yum install gcc patch libffi-devel python-devel  zlib-devel bzip2 bzip2-devel openssl-devel ncurses-devel sqlite-devel sqlite readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz xz-devel -y # centos7
     
     sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget libsqlite3-dev # ubuntu

2.下载
    wget https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz
    wget https://www.python.org/ftp/python/3.9.10/Python-3.9.10.tgz # 安装3.9.10
    
3.解压
    tar -zxf Python-3.6.9.tgz && cd Python-3.6.9

4.安装
    ./configure   --prefix=/opt/python3
    make -j${nproc} && make install # 或 make altinstall
    
5.设置环境变量
    vim /etc/profile
    PATH=${PATH}:/opt/python3/bin/
    source /etc/profile
    
6.查看pip 与 python 
    pip3 -V && python3 -V

image-20250724231943543


5-3-2.创建Jenkins流水线

image-20250725000419682


5-3-3.流水线脚本

# flask的app.py脚本
from flask import Flask

app=Flask(__name__)


@app.route('/')
def index():
    return '我是python flask框架项目'
if __name__ == '__main__':
    app.run(host='0.0.0.0')

# 启动脚本 run_app.sh
    #! /bin/bash
    nohup  /opt/python3/bin/python3 /opt/app/app.py > /opt/app/app.log 2>&1 &


# 验证安装bash脚本 env_verify.sh
    #! /bin/bash
    if [ ! -x /opt/python3/bin/python3 ];then
        echo "未安装"
        exit 1
    fi
    # 判断 pip3 是否存在
    if [ ! -x /opt/python3/bin/pip3 ]; then
        echo "未安装 pip3"
        exit 2
    fi
    if [ ! $( /opt/python3/bin/pip3 show flask ) ];then
        pip3 install flask -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
    fi
    exit 0


# Jenkinsfile 脚本文件内容:

pipeline {
    agent any
    stages {
        stage('sending') {
            steps {
                script {
                    // 压缩当前目录所有内容
                       sh 'tar -czf app.tar.gz  *'  
                       // 清除原来的上传压缩包到远程服务器指定目录
                       sh 'ssh root@192.168.85.151 "rm -rf /opt/app/ /opt/app.tar.gz"'
                    sh 'scp ./app.tar.gz root@192.168.85.151:/opt/ '
                    // 远程解压到 /opt 目录
                    sh 'ssh root@192.168.85.151 "mkdir /opt/app/ && tar -xzf /opt/app.tar.gz -C /opt/app/"'
                }
            }
            post {
                success {
                    echo "Python程序发送成功"
                }
            }
        }

        stage('env verify') {
            steps {
                script {
                    def status = sh(
                        // 执行脚本验证环境
                        script: 'ssh root@192.168.85.151 "bash /opt/app/env_verify.sh"',
                        returnStatus: true
                    )
                    if (status != 0) {
                        error("环境检测失败:远程服务器python3未安装或环境不符合要求,终止Pipeline")
                    } else {
                        echo "环境检测通过"
                    }
                }
            }
            post {
                success {
                    echo "环境检查结束"
                }
            }
        }
        stage('start') {
            steps {
                // 停止原来的进程
                sh '''
                    ssh root@192.168.85.151 "ps -ef | grep '[p]ython3' | awk 'NR==1{print $2}' | xargs -i kill {}"
                '''
                // 启动-需要写成可执行脚本,Jenkins 的 sh 步骤运行在一个非交互式 shell 中,当 pipeline 的步骤结束时,这个 shell 也会退出。
                // nohup 不能保证进程不会被 Jenkins 杀掉,使用启动脚本是最好的选择,在启动完毕脚本后父进程关闭(这个sh脚本进程),子进程被init进程接管(内部启动python进程)。
                // 或者写一个system管理脚本让systemd进行管理。
                sh 'ssh root@192.168.85.151 "bash /opt/app/run_app.sh"'
            }
            post {
                success {
                    echo "启动完成"
                }
            }
        }
    }
}

5-4.构建前端项目

流程:
    1.在jenkins中安装node js
    2.创建一个pipeline的job
    3.配置job,从远程仓库中拉去代码,并且执行Jenkins脚本

5-4-1.安装nodejs

1.创建一个gitlab仓库
    git@192.168.85.149:root/hello-world.git

2.jenkins机器上安装nodejs # 注意版本
    wget https://nodejs.org/dist/v14.11.0/node-v14.11.0-linux-x64.tar.gz
    tar -zxf node-v14.11.0-linux-x64.tar.gz
    vim /etc/profile 
    PATH=${PATH}:/opt/node-v14.11.0-linux-x64/bin # 增加环境变量
    source /etc/profile
    node -v

image-20250728230014117


5-4-2.创建Jenkins流水线

image-20250728230644325


5-4-3.流水线脚本

# nginx的配置文件
    server {
        listen 80;
        server_name _;
        location / {
            root /opt/dist/;
            index index.html;
        }
    }


# Jenkins 脚本
pipeline {
    agent any
    stages {
        stage('build') {
            steps {
                script {
                    // 打包
                    sh '''
                        export PATH=/opt/node-v14.11.0-linux-x64/bin:$PATH
                        npm install && npm run build
                        '''
                    // 压缩打包的内容
                       sh 'tar -czf dist.tar.gz  ./dist'  
                       // 发送到服务器上
                       sh 'scp ./dist.tar.gz root@192.168.85.151:/opt/' 
                }
            }
            post {
                success {
                    echo "Python程序发送成功"
                }
            }
        }
        stage('start') {
            steps {
                // 解压打包的文件一定要要指定解压目录不然就会默认解压到用户目录下,重启nginx 
                sh 'ssh root@192.168.85.151 "tar -xzf /opt/dist.tar.gz -C /opt "'
                // 注意nginx的配置关于静态目录的指定问题
                sh 'ssh root@192.168.85.151 "systemctl restart nginx"'
            }
            post {
                success {
                    echo "启动完成"
                }
            }
        }
    }
}

6.jenkins操作java项目

# 流程
    1.gitlab拉去java项目源码
    2.jenkins,进行源码编译,打包为jar包
    3.将jar包发送到部署目标服务器上
    4.在对部署服务器进行运行jar包即可

目前市场上,部署java web的方式,主要有俩方案java部署方式:
    1. 开发交付给运维的是一个(*.war) zip类型的压缩包,这个压缩包里包含了网站的thml,配置文件,以及java代码,运维只需要提供应用容器(tomcat)即可发布这个java网站。(集团型的中大型公司,用该方案)
    2. 目前互联网公司以devops开发模式,快速迭代模型,并且java后端诞生spring Boot框架,最终开发交付的产物是(*.jar)也是zip类型的压缩包,且springboot该框架内置了应用容器(tomcat),最终运维只需要(jar -jar *.jar)即可运行java网站

# 注意: 
    java项目有jar与war包之分,jar包可以直接运行(内部自带tomcat,直接 java -jar xx.jar),而war包需要借助tomcat进行部署(或者其他)。


1.jar包部署方式(内置tomcat)
    1.开发打包好的直接就是 *.jar
    2.需要运维进行打包的 mave后在 *.jar 在进行java运行

2.war包方式
    1.需要安装tomcat
    2.将war包放到tomcat的webapps的目录下
    3.timcat自动解压缩这个war(本质上就是一个zip压缩包)
    4.拿到网站前后端代码,运行
    

jar与war区别:
    1. 运维拿到了war包,需要安装tomcat,将war包放入tomcat的webapps目录,该压缩包自动解压缩,然后即可访问
    2.运维拿到了jar包,无须自己部署tomcat,直接jar -jar *.jar运行项目进程即可
    3. 运维需要自己打包java源码,生成jar包
        - 进入项目根目录,执行maven打包命令,maven命令是java项目的编译打包工具
        - maven命令自动读取pom.xml配置文件,安装依赖关系
        - 在项目根目录下执行命令:mvn clean install,会在项目根目录的target目录下生成一个jar文件
        - 接着输入命令:java -jar target\springboot-0.0.1-SNAPSHOT.jar

6-1.java项目手动打包测试

6-1-1.maven工具下载

# 关于maven打包工具说明:依赖与java环境
    专门为java打造的管理构建工具
    主要有:
        1.提供依赖管理机制
        2.提供标准化构建流程
    通过这两条命令下载项目需要的依赖
        mvn clean package
        mvn install 
    类似于:python pip install 安装项目的依赖
   如果在以后的生成环境下,就是维护java项目,那么就需要多多学习maven打包工具的使用springbook的玩法
# 安装方式:
    1.使用yum安装,简单快捷
        yum install maven -y
        配置文件路径在 /etc/maven/settings.xml 

    2.下载2进制形式

# 修改配置
    vim /etc/maven/settings.xml 
    在<mirrors></mirror>节点下添加下面的内容
    <mirror>
        <id>alimaven</id>
        <mirrorOf>central</mirrorOf>
        <name>aliyun maven</name>
        <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
    </mirror>

image-20250721221320863


6-1-2.java程序打包测试

1.拉去仓库
    git clone https://gitee.com/yuco/springboot-test.git && cd springboot-test

2.进入java项目执行maven打包命令
     mvn clean package
    # 就会生成一个目录 target 目录内存在这个项目所属依赖,以及打包好的*.jar包   java项目/target/项目.jar 的jar包

3.运行并访问
    java -jar target/springboot-helloword-1.jar --server.port=8081 # 启动
    http://192.168.85.150:8081/say # 访问 

image-20250721222237030


6-1-3.打包流程说明

1.拿到源码
2.部署maven环境
3.进入源码,执行maven clean package 进行打包,还有其他可以选择参数
4.进入源码的target目录下,生成了一个*.jar包可以发布交付的代码包可以发布到任意拥有相同版本java机器上
5.用户访问

img


6-1-4.jar包直接运行

# 没有打包的这个操作过程,直接下载一个jar包,直接运行。
以halo博客为例,它就是使用的jar,直接选择版本下载即可
下载地址:https://download.halo.run/

1.下载源码
    wget https://dl.halo.run/release/halo-1.1.0.jar --no-check-certificate

2.直接运行
    java -jar  halo-1.1.0.jar

# 少了一步 'mvn clean package' 的操作。

6-2. jankins构建java项目

要求:
    1.要有java环境。
    2.要有maven工具。
    3.jenkins中需要有maven插件支持。

6-2-1.安装Maven与Java

1.安装java环境
    yum install java -y
    
    # 查看安环境
    [root@jenkins /opt]$java -version
    java version "1.8.0_181"
    Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
    Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

2.安装maven
    yum install maven -y # 安装
    # 清华源地址
    https://mirrors.tuna.tsinghua.edu.cn/apache/maven/ # 二进源码包
    wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz --no-check-certificate


3. 解压并设置环境变量 <图-1>
    tar -zxf apache-maven-3.9.4-bin.tar.gz
    echo "export PATH=${PATH}:/opt/apache-maven-3.9.4/bin" >> /etc/profile
    source /etc/profile


4.切换目录查看maven版本
    [root@jenkins ~]$mvn -v
    Apache Maven 3.9.4 (dfbb324ad4a7c8fb0bf182e6d91b0ae20e3d2dd9)
    Maven home: /opt/apache-maven-3.9.4
    Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: /usr/java/jdk1.8.0_181-amd64/jre
    Default locale: en_US, platform encoding: UTF-8
    OS name: "linux", version: "3.10.0-1160.el7.x86_64", arch: "amd64", family: "unix"


5.修改maven的源
    /opt/apache-maven-3.9.4/conf/settings.xml
    在<mirrors></mirrors>节点添加阿里云仓库
       <mirror>
           <id>alimaven</id>
           <mirrorOf>central</mirrorOf>
           <name>aliyun maven</name>
           <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
       </mirror>

6-2-2.检查Maven插件

系统管理 -> 插件管理 ->  搜索 Maven Integration
没有需要进行下载安装 # 根据当前jenkins的版本安装对应的 Maven 插件

image-20250722224500319


6-2-3.Jenkins配置全局工具

# 在jenkins的 系统设置 -> 全局工具 中进行配置

jenkins 配置 maven 和 java # 需要配置相应的 完整安装目录(家目录,所有必要的组件,比如 bin/, conf/, lib/ 等)
    1.需要设置maven的软件目录  MAVEN_HOME 目录
    2.还需要设置java软件的目录  JAVA_HOME 目录

# 注意如果使用 yum 或者 apt 安装的 java和maven home目录路径:
    JAVA_HOME:readlink -f $(which java) # 提取 JAVA_HOME 路径 然后去掉 /jre/bin/java,就是这个路径
        /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64/jre/bin/java # 查询的路径
        /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64 # JAVA_HOME 路径
        
    MAVEN_HOME:rpm -ql maven | grep 'bin/mvn'  # 提取MAVEN_HOME路径 然后去掉 /bin/java,就是这个路径 /usr/share/maven/
        [root@jenkins ~]# rpm -ql maven | grep 'bin/mvn'
        /usr/bin/mvn
        /usr/bin/mvnDebug
        /usr/bin/mvnyjp
        /usr/share/maven/bin/mvn  # /usr/share/maven  MAVEN_HOME的路径
        /usr/share/maven/bin/mvnDebug
        /usr/share/maven/bin/mvnyjp

image-20250722230817228


6-2-4.Jenkins全局工具配置

# 配置jenkins免密发送文件,需要安装 Publish over SSH 插件
 在jenkins的 系统设置 -> 系统设置 中进行配置
 
 配置的说明:
     Disable exec:禁止运行命令,这个不要勾选,否则没法执行命令
     点击高级:
         Use password authentication, or use a different key:可以替换公共配置(选中展开的就是公共配置的东西,这样做扩展性很好)
         Port:端口(默认22)
         Timeout (ms):超时时间(毫秒)默认即可

# 配置完成后Test Configuration下,提示success的话就没问题。

image-20250722233733855


6-2-5.配置Gitlab源码仓库

1.仓库地址
    https://gitee.com/yuco/springboot-test.git

2.进行克隆


3.克隆后的源码仓库地址
    git@192.168.85.149:root/springboot-test.git
    http://192.168.85.149/root/springboot-test.git

image-20250722234139436


6-2-6.Jenkins创建一个maven的job-基本

# 目标:配置基本的 maven的 job设置
1.创建
2.丢弃构建设置
    保持构建的天数 5
    保持构建的最大个数 5 
3.源码管理设置
    1.设置仓库地址:git@192.168.85.149:root/springboot-test.git
    2.设置拉去仓库的账户
    3.设置拉去的分支

4.设置构建触发器
    1.保留当前job的url
        http://192.168.85.150:8080/project/java_test
    2.生成一个token值
        b91d95b47979c62f7afbd070df80ed86

5.在gitlab的仓库中设置webhook
    添加jenkins构建触发器的url + 生成的token
        http://192.168.85.150:8080/project/java_test
        b91d95b47979c62f7afbd070df80ed86

image-20250722234955633


6-2-7.Jenkins创建一个maven的job-完善

# 目标:给job添加maven添加编译参数
1.勾选构建环境的 Add timestamps to the Console Output
    将时间戳添加到控制台输出

2.添加构建参数Build <图-2>
    # Root POM :就是当拉去代码存储在当前job工作区的pom.xml,maven的构建操作就是基于这个文件进行下载依赖,构建jar包等操作
    # Goals and options : 添加构建参数操作
    clean install -Dmaven.test.skip=true
    clean install 表示构建与 mvn clean package 性质一样
    -Dmaven.test.skip=true 表示跳过单元测试

3.点击构建测试jar包是否可以使用
    1.查看控制台构建的日志
    2.查看机器上的工作区的jar包
        ls /var/lib/jenkins/workspace/java_test/target/
    3.使用java -jar *.jar 进行执行查看
        java -jar /var/lib/jenkins/workspace/java_test/target/springboot-helloword-1.jar --server.port=8085

image-20250722235710728


6-2-7.Jenkins创建一个maven的job-配置机器

# 目标:设置脚本,将打包好的jar包发送到指定的机器上,并且启动。
1.编辑配置 选择构建后的动作 Post Steps

2.选择选择插件设置的ssh免密的服务器 
    Name 具体发送到那台机器
    Source files 原文件所,也就是jar包所在的路径,因为是job的工作区,只需要写入当前工作区下的jar的路径即可
    Remove prefix 删除前缀,只发送jar包,不要前缀路径
    Remote directory 远程的目录 与全局配置的ssh配置的路径是相对路径
    Exec command 执行的命令脚本名称,在远程机器上执行脚本,绝对路径,执行权限

image-20250723001045179


6-2-7.Jenkins创建一个maven的job-脚本

注意:
    1.这个脚本需要放置在部署服务器的机器上,在构建后的目录中
    2.设置执行权限:chmod +x build.sh



cat > /opt/build.sh <<'EOF'
#!/bin/bash

#格式化时间
DATE=$(date +%Y%m%d)

#设置程序目录
DIR=/usr/local/app

#设置Jar名称,也就是jenkins构建maven build后的产物
JARFILE=springboot-helloword-1.jar

#判断是否存在backp目录,如果不存储就创建
if [ ! -d $DIR/backup ];then
   mkdir -p $DIR/backup
fi

cd $DIR

#杀掉当前运行的旧程序
ps -ef | grep $JARFILE | grep -v grep | awk '{print $2}' | xargs -i kill -9 {}

# 备份旧程序,将旧的jar包备份到/usr/local/app/backup/*.jar时间的形式
if [ -f ${JARFILE} ];then
    mv $JARFILE $DIR/backup/$JARFILE$DATE
fi

# 部署新程序,将新的opt的jar包移动到/usr/local/app
mv -f /opt/$JARFILE .


echo "The service will be starting"

# 判断是否有java环境
which java > /dev/null 2>&1
if [ $? -ne 0 ];then
    yum install java > /dev/null
fi



#后台启动程序并设置Jvm参数、开启JMX、打印GC日志
# -Dserver.address=0.0.0.0 -Dserver.port=18888  -jar $JARFILE  # 主要的参数为在0.0.0.0:18888端口上运行
java -server -Xms1024M -Xmx1024M -XX:PermSize=256M \
-XX:MaxPermSize=256M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails \
-Xloggc:./gc.log \
-Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=127.0.0.1 \
-Dcom.sun.management.jmxremote.port=10086 -Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dserver.address=0.0.0.0 -Dserver.port=18888 \
-jar $JARFILE  --spring.profiles.active=dev > /nohup 2>&1>out.log &


# 运行成功后,30秒就会打印日志信息
if [ $? = 0 ];then
        sleep 30
        tail -n 50 out.log
fi

# 进入备份目录,删除旧数据
cd backup/
# ls -lt -t参数是按照时间进行排序,最新的事件在上面
# 删除大于5的行,保持备份的jar包只有5个
ls -lt|awk 'NR>5{print $NF}'|xargs rm -rf

echo "starting success!!!"
EOF


# 脚本的核心逻辑
    脚本的核心逻辑就是 # 将 opt目录的jar 移动到 /usr/local/app 下
        1.拿到旧的jar包,移动备份 
        2.关闭旧的java程序,执行新的程序
        3.检查备份目录,的备份数量超过5和进行删除,保持5个备份

6-2-8.构建测试

访问:http://192.168.85.151:18888/say

image-20250723001430438


6-2-9.添加一个钉钉通知

# 注意使用钉钉通信,需要响应的插件

1.检查插件

2.在钉钉中创建一个群
    团队邀请 -> 右上角+号添加群聊(内部外部都可以)-> 在群设置中添加一个机器人 -> 添加自定义类型的 -> 使用ip段 -> 保存(复制url)。
    机器人的token:31fa489dcb5716108675a78c5b2ce5e3434546c192b325bf34a8571acb58efc9

3.修改job,在构建后添加钉钉通知

4.保存后进行验证

image-20250723224837621


6-2-10.添加一个邮箱通知

1.需要有对应的插件支持
    Email Extension 插件
    
2.在jenkins系统管理中配置系统邮箱
    邮箱通知 
        1.填写SMTP服务器
        2.勾选使用SMTP认证
            1.填写邮箱
            2.填写邮箱邮箱授权码或者密码
            3.设置端口
    # 版本过低,测试发送邮箱失败:
        版本过低(java,支持TLS 1.0、1.1)的情况下,使用邮箱可能会导致发送失败,不支持(TLS 1.2以上,)需要手动添加参数强制开启 TLS 1.2
        在启动脚本 /etc/rc.d/init.d/jenkins 添加下面的参数,重启jenkins
            JAVA_ARGS="-Dmail.smtp.ssl.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2" # 需要在 -jar xxx.jar 前面才可以
        systemctl daemon-reload
        systemctl restart jenkins


3.需要再job构建后进行配置,添加构建后的通知选择 Editable Email Notification 

image-20250723235617979


6.Jenkins项目回滚操作

方法 稳定性 成本 推荐场景
构建产物归档部署回滚 最通用,适合中小型团队
Git Commit 回滚 有 Git 管控的项目,需重新构建
Docker 镜像回滚 容器化项目,DevOps 流水线部署
蓝绿部署回滚(流量切换) 非常高 高频发布

6-1.构建产物归档部署回滚

# 说明:
    1.就是将每一次构建的产物保存到某个文件夹内,通过git版本号或者日期进行后缀标明。
    2.在jenkins中添加一个job(Jenkins + Shell 脚本)方式,通过参数传递的方式进行回滚操作。

image-20250729225625085


6-1-1.部署的Job脚本

# 部署的脚本
pipeline {
    agent any
    stages {
        stage('build') {
            steps {
                script {
                    // 打包
                    sh '''
                        export PATH=/opt/node-v14.11.0-linux-x64/bin:$PATH
                        npm install && npm run build
                        '''
                    // 压缩打包的内容
                       sh 'tar -czf dist.tar.gz  ./dist'  
                       // 验证备份文件夹是否存在
                       sh '''
                           if [ ! -d /opt/releases ];then
                               mkdir -p /opt/releases/
                           else
                               echo "已存在"
                           fi
                       '''
                       // 备份构建
                       sh ' cp ./dist.tar.gz /opt/releases/dist_$(date +"%Y%m%d_%H%M").tar.gz'
                       // 发送到服务器上
                       sh 'scp ./dist.tar.gz root@192.168.85.151:/opt/' 
                }
            }
            post {
                success {
                    echo "Python程序发送成功"
                }
            }
        }
        stage('start') {
            steps {
                // 解压打包的文件一定要要指定解压目录不然就会默认解压到用户目录下,重启nginx 
                sh 'ssh root@192.168.85.151 "tar -xzf /opt/dist.tar.gz -C /opt "'
                // 注意nginx的配置关于静态目录的指定问题
                sh 'ssh root@192.168.85.151 "systemctl restart nginx"'
            }
            post {
                success {
                    echo "启动完成"
                }
            }
        }
    }
}



# 核心在构建时,将构建的产物进行备份
    // 验证备份文件夹是否存在
    sh '''
        if [ ! -d /opt/releases ];then
            mkdir -p /opt/releases/
        else
            echo "已存在"
        fi
    '''
    // 备份构建
    sh ' cp ./dist.tar.gz /opt/releases/dist_$(date +"%Y%m%d_%H%M").tar.gz'

6-1-2.创建一个回滚 Job

# 作用:
    1.是一个单独的 Jenkins 任务,用于回滚版本
    2.用户通过参数输入要回滚的版本号或构建号
    3.Jenkins 回滚 Job 从“备份构建产物文件夹”中拿到指定文件

# 回滚的脚本
pipeline {
    agent any

    parameters {
        string(name: 'ROLLBACK_VERSION', defaultValue: '', description: '输入要部署的构建产物文件名')
    }

    stages {
        stage('打印参数') {
            steps {
                echo "Rollback version: ${params.ROLLBACK_VERSION}"
            }
        }
         stage('部署') {
            steps {
                // 为了保险起见,先进行删除,然后在发送
                sh '''
               
                    echo "开始部署版本: $ROLLBACK_VERSION"
                    ssh root@192.168.85.151 "rm -rf /opt/dist.tar.gz /opt/dist"
                    scp /opt/releases/$ROLLBACK_VERSION root@192.168.85.151:/opt/dist.tar.gz
                    ssh root@192.168.85.151 "tar -xzf /opt/dist.tar.gz -C /opt "
                    ssh root@192.168.85.151 " systemctl restart nginx"
                '''
            }
        }
    }
}



# 核心:
parameters {
  string(name: 'ROLLBACK_VERSION', description: '输入要部署的构建产物文件名')
}

image-20250729232409092


6-2.Git Commit 回滚

# 说明
    通过git命令将指针指向需要回滚的版本,进行回滚。


# 注意: 不建议通过jenkins的方式回滚git仓库然后部署
    回滚一般是本地工作目录切换版本,不会自动推送远程,所以要谨慎操作远程仓库。
    如果你需要更新远程仓库(如推送 revert),需要配置 Jenkins 有权限推送。
    一般建议 Jenkins 只做部署切换,回滚远程仓库操作最好人工确认。
   
    
# 关于配置仓库:
    在流水线中配置好源码仓库,要不然就在脚本中配置好仓库。进行拉去到工作目录操作。
    
# 脚本
pipeline {
    agent any
    parameters {
        string(name: 'COMMIT_ID', defaultValue: 'HEAD', description: '回滚到的提交ID')
    }
    stages {
        stage('回滚') {
            steps {
                // 回滚到指定的版本号
                sh "git reset --hard ${params.COMMIT_ID}"
                // 远程仓库也回退到这个旧版本,需要 强制推送
                // sh "git push -f origin master"
            }
        }
        stage('部署') {
            steps {
            sh '''
                export PATH=/opt/node-v14.11.0-linux-x64/bin:$PATH
                npm install && npm run build
                tar -czf dist.tar.gz  ./dist
                scp ./dist.tar.gz root@192.168.85.151:/opt/
                ssh root@192.168.85.151 "tar -xzf /opt/dist.tar.gz -C /opt "
                ssh root@192.168.85.151 "systemctl restart nginx"
            '''
            }
        }
    }
}

image-20250729234600790


6-3.Docker 镜像回滚

# 说明:
    回滚 Docker 镜像,实质就是切换容器使用的镜像版本,比如用之前的旧版本镜像重新启动容器,关闭现有容器。
    
# 注意:
    jenkins这台机器只是用来执行脚本,执行docker命令还是需要远程操作。
    注意机器之间的免密操作,或者直接使用ansible进行操作。
    
# 脚本:
pipeline {
    agent any
    parameters {
        string(name: 'IMAGE_TAG', defaultValue: 'latest', description: '回滚到的Docker镜像标签,比如 v1.0 或 latest')
        string(name: 'CONTAINER_NAME', defaultValue: 'myapp', description: '容器名称')
        string(name: 'IMAGE_NAME', defaultValue: 'myrepo/myapp', description: '镜像仓库名')
    }
    stages {
        stage('Rollback Docker Image') {
            steps {
                script {
                    // 停止并删除旧容器(如果存在)
                    sh """
                        ssh root@192.168.85.151 'docker stop ${params.CONTAINER_NAME} || true'
                        ssh root@192.168.85.151 'docker rm ${params.CONTAINER_NAME} || true'
                    """

                    // 拉取指定版本镜像(可选,如果本地已有可以不拉)
                    sh "ssh root@192.168.85.151 'docker pull ${params.IMAGE_NAME}:${params.IMAGE_TAG}'"

                    // 用指定镜像启动容器
                    sh """
                        ssh root@192.168.85.151 'docker run -d --name ${params.CONTAINER_NAME} ${params.IMAGE_NAME}:${params.IMAGE_TAG}'
                    """
                }
            }
        }
    }
}

image-20250729235546184


6-4.蓝绿部署回滚(流量切换)

# 说明:
    同时准备两个几乎相同的生产环境(蓝色环境和绿色环境),切换流量指向新环境,如果新版本有问题,再切回旧环境(流量全部切到蓝环境,或者全部切到绿环境)。
    1.将部署的新版本到蓝或者绿机器上。
    2.Jenkins 通过调用负载均衡器、代理服务器(如 Nginx、HAProxy、云厂商的负载均衡服务)API 或修改配置,将流量从当前环境切换到新环境。
    3.如果新环境有问题,Jenkins 再次调用负载均衡器或代理配置,把流量切回旧环境。

# 注意:
    1.用容器编排系统(如 Kubernetes)时,蓝绿部署和回滚一般用 kubectl 或 Helm 结合 Jenkins 实现切换。
    2.用 Nginx 或 HAProxy,可以改写配置文件或修改 upstream 服务后重载配置实现流量切换。
    3.云厂商负载均衡(AWS ALB、Azure LB等),用 API 修改目标组或权重来切换流量。


# 脚本
pipeline {
    agent any
    parameters {
        choice(name: 'TARGET_ENV', choices: ['blue', 'green'], description: '部署目标环境')
        booleanParam(name: 'ROLLBACK', defaultValue: false, description: '是否回滚到旧环境')
    }
    stages {
        stage('部署') {
            steps {
                script {
                    if (params.ROLLBACK) {
                        echo "开始回滚,将流量切回另一环境"
                        // 调用脚本或API切回流量
                        sh "./switch_traffic.sh ${params.TARGET_ENV == 'blue' ? 'green' : 'blue'}"
                    } else {
                        echo "部署到目标环境 ${params.TARGET_ENV}"
                        // 部署代码到目标环境
                        sh "./deploy.sh ${params.TARGET_ENV}"
                        // 测试或验证
                        sh "./test.sh ${params.TARGET_ENV}"

                        // 流量切换到目标环境
                        sh "./switch_traffic.sh ${params.TARGET_ENV}"
                    }
                }
            }
        }
    }
}

6-4-1.例如:nginx配置

upstream backend_blue {
    server 192.168.1.10;
    server 192.168.1.11;
}

upstream backend_green {
    server 192.168.1.20;
    server 192.168.1.21;
}

server {
    listen 80;
    server_name www.example.com;

    location / {
        proxy_pass http://backend_current;  # 通过jenkins进行切换到新的环境中
    }
}