侧边栏壁纸
博主头像
路小飞博主等级

行动起来,活在当下

  • 累计撰写 72 篇文章
  • 累计创建 12 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

05-从0配置Jenkins

路小飞
2025-02-23 / 0 评论 / 0 点赞 / 35 阅读 / 27585 字

1.1 Jenkins 安装与配置

在现代软件开发流程中,持续集成与持续部署(CI/CD)是实现高效开发、快速迭代的关键环节,而 Jenkins 作为一款强大的开源自动化服务器,在其中扮演着至关重要的角色。本文将详细介绍如何在 Linux 环境下完成 Jenkins 的安装、配置与使用,助力您搭建起高效稳定的 CI/CD 流水线。

1.1.1 环境要求

本文将采用war包的形式部署。搭建 Jenkins 服务,首先要准备一台性能适配的 Linux 服务器。其硬件配置建议为:不低于 2 核 CPU、4GB 内存和 40GB 硬盘,本文将以 Jenkins 2.462 版本为例,详细阐述搭建及使用流程。

需注意,中文网站版本可能较低,下载插件时可能因版本不兼容而失败。

1.1.2 安装步骤

1. 配置 Yum 源

为提高软件包下载速度,将系统的 Yum 源替换为阿里云镜像源。

# 备份原有的 CentOS 基础 Yum 源配置文件
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

# 下载阿里云的 CentOS 7 Yum 源配置文件
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 移除配置文件中可能存在的特定镜像地址(可选优化)
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo

# 清理 Yum 缓存
yum clean all

# 重新生成 Yum 缓存
yum makecache
2. 安装 JDK

Jenkins 基于 Java 运行,因此需要安装 Java 开发工具包。这里选择安装 OpenJDK 11。

yum install -y java-11-openjdk
3. 安装 Jenkins
# 创建 Jenkins 主目录和日志目录
mkdir -p /usr/local/jenkins /usr/local/jenkins/logs

# 下载 Jenkins WAR 包
wget -P /usr/local/jenkins https://get.jenkins.io/war-stable/2.462/jenkins.war

# 国内地址
wget -P /usr/local/jenkins https://mirrors.huaweicloud.com/jenkins/war-stable/2.462.3/jenkins.war
4. 启动 Jenkins

jenkins-start.sh

#!/bin/bash

# 定义配置变量,方便后续修改和管理
JAVA_BINARY="/usr/bin/java"
JENKINS_HOME="/usr/local/jenkins"
JENKINS_WAR_FILE="${JENKINS_HOME}/jenkins.war"
LOG_FILE="${JENKINS_HOME}/logs/jenkins.log"
WEBROOT="/var/cache/jenkins/war"
HTTP_PORT=9999
DEBUG_LEVEL=5

# 检查 Jenkins 主目录是否存在
if [ ! -d "$JENKINS_HOME" ]; then
    echo "Jenkins 主目录 $JENKINS_HOME 不存在,请检查配置。"
    exit 1
fi

# 检查 Jenkins WAR 文件是否存在
if [ ! -f "$JENKINS_WAR_FILE" ]; then
    echo "Jenkins WAR 文件 $JENKINS_WAR_FILE 不存在,请检查配置。"
    exit 1
fi

# 确保日志目录存在
LOG_DIR=$(dirname "$LOG_FILE")
mkdir -p "$LOG_DIR"

# 构建 Java 命令
JAVA_COMMAND=(
    "$JAVA_BINARY"
    -Djava.awt.headless=true
    -DJENKINS_HOME="$JENKINS_HOME"
    -jar "$JENKINS_WAR_FILE"
    --logfile="$LOG_FILE"
    --webroot="$WEBROOT"
    --httpPort="$HTTP_PORT"
    --debug="$DEBUG_LEVEL"
)

# 启动 Jenkins 并使用 nohup 使其在后台持续运行
nohup "${JAVA_COMMAND[@]}" >/dev/null 2>&1 &
jenkins_pid=$!

# 检查 Jenkins 进程是否成功启动
if ps -p "$jenkins_pid" > /dev/null; then
    echo "Jenkins 已成功启动,进程 ID 为 $jenkins_pid。"
else
    echo "Jenkins 启动失败,请检查日志文件 $LOG_FILE 以获取更多信息。"
    exit 1
fi

# 可选:记录启动信息到日志文件
echo "$(date +'%Y-%m-%d %H:%M:%S') - Jenkins 启动,进程 ID 为 $jenkins_pid。" >> "$LOG_FILE"

jenkins-stop.sh

#!/bin/bash

# 通过 ps 命令查找 Jenkins 进程的 PID
JENKINS_PID=$(ps aux | grep 'jenkins.war' | grep -v grep | awk '{print $2}')

if [ -z "$JENKINS_PID" ]; then
  echo "Jenkins process not found."
  exit 1
else
  echo "Stopping Jenkins with PID: $JENKINS_PID"
  # 发送 SIGTERM 信号给 Jenkins 进程,停止它
  kill "$JENKINS_PID"
  if [ $? -eq 0 ]; then
    echo "Jenkins has been stopped successfully."
  else
    echo "Failed to stop Jenkins."
  fi
fi

启动 Jenkins 后,可通过查看日志文件来确认是否成功启动。

# 实时查看 Jenkins 日志文件
[root@master-02 ~]# tail -f /usr/local/jenkins/logs/jenkins.log 
c8837c4adda14fc7aa8f7de705e93cb8

This may also be found at: /usr/local/jenkins/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

2025-02-22 14:59:04.854+0000 [id=30]	INFO	jenkins.InitReactorRunner$1#onAttained: Completed initialization
2025-02-22 14:59:04.867+0000 [id=22]	INFO	hudson.lifecycle.Lifecycle#onReady: Jenkins is fully up and running

当看到 Jenkins is fully up and running 字段时,说明 Jenkins 已成功启动。此时,可通过浏览器访问 http://服务器IP地址:9999 完成初始化操作。

5. 初始化
  • 输入初始密码:在日志文件或 /usr/local/jenkins/secrets/initialAdminPassword 文件中找到初始密码,输入后点击 “继续”。
  • 选择插件安装方式:在插件安装界面,可选择 “安装推荐的插件”,安装成功或失败都不影响后续使用,后续也可手动安装插件。
  • 创建用户:创建一个用于登录 Jenkins 的用户。
  • 实例配置:实例配置界面直接使用默认值,点击 “保存并完成”,至此完成初始化动作。

1.1.3 常用插件安装

1. 配置国内插件源

为加快插件下载速度,将 Jenkins 插件源更改为国内的清华大学镜像源。
操作步骤:单击 Manage Jenkins 》Plugins 》Advanced settings ,将插件源更改为 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json或者https://mirrors.huaweicloud.com/jenkins/updates/update-center.json

2. 安装常用插件

本文需要的插件如下:

Git
Git Parameter
Git Pipeline for Blue Ocean
Credentials
Credentials Binding
Blue Ocean
Blue Ocean Pipeline Editor
Blue Ocean Core JS
Pipeline SCM API for Blue Ocean
Dashboard for Blue Ocean
Build With Parameters
DynamicExtended Choice Parameter Plug-In
Extend Choice Parameter
List Git Branches Parameter
Pipeline
Pipeline: Declarative
Kubernetes
Kubernetes CLI
Kubernetes Credentials
Image Tag Parameter
Active Choices
Role-based Authorization Strategy
Timestamper
# Timestamper安装后需要在Sysytem中勾选 "Timestamper.Enabled for all Pipeline builds" 字段方可生效,该插件能够为构建日志添加时间戳,方便用户跟踪和排查问题,提高构建过程的可追溯性

安装方法:在 Available plugins 中勾选需要安装的插件,点击 “安装”。若搜索不到某个插件,可能该插件已安装,可在 Inslxfled plugins 中查看。

![image-20250223000407635](Jenkins使用流程(新).assets/图6 安装插件.png)

![image-20250223010148135](Jenkins使用流程(新).assets/图6-2 Timestamper插件配置.png)

3. 重启 Jenkins

在安装插件时,勾选安装完成后重启Jenkins(空闲时)选项。这一步骤能够确保插件安装后能够及时生效。

1.1.4 Jenkins 服务器相应组件安装

在 Jenkins 服务器搭建完成并完成初始化及插件安装后,需根据实际项目的具体需求,进一步配置相应的工具,如 Git、Maven 等。倘若服务器中已安装这些工具,并且其版本完全满足项目要求,那么直接使用已安装的版本即可,这样可以有效避免重复安装造成的资源浪费。若尚未安装,则需严格按照对应 Linux 系统的安装方式进行安装和配置,确保各个工具的环境变量设置正确,依赖库安装完整,从而保证 Jenkins 能够顺利调用这些工具,高效实现持续集成与持续交付(CI/CD)流程,提升软件开发的效率和质量 。

1. Git

Jenkins 的 Git 插件主要是提供在 Jenkins 界面中与 Git 进行交互的功能接口,比如在构建任务配置中方便地指定 Git 仓库地址、分支等信息,实现代码的拉取等操作。但它本身并不包含 Git 的完整功能,无法替代 Git 在服务器上的本地操作。因此,在服务器上安装 Git 是必不可少的,执行以下命令即可完成安装:

yum -y inslxfl git
2. maven

如果需要部署的代码中有 java 项目,就需要使用 maven 工具来处理依赖。Maven 是一款强大的项目管理和构建工具,能够自动化处理项目的依赖关系、编译、测试等过程。其官方网站为:https://maven.apache.org/ 。下载软件包后,将其复制到 Jenkins 所在服务器并解压缩即可完成基本安装,后续还需根据项目需求进行详细配置。

1.1.5 配置节点的 executors

在 Jenkins 中,“executors”(执行器)是指 Jenkins 节点上用于执行任务的进程或线程。每个 Jenkins 节点可以配置多个执行器,它们是 Jenkins 分配任务执行资源的基本单位。比如一个节点有多个 CPU 核心或多个计算资源单元,就可以通过配置多个执行器来充分利用这些资源,让多个任务能够并行执行。

配置方法:在首页点击 Manage Jenkins》Nodes》节点右侧的齿轮 ,通过 Number of executors 字段进行配置。

![image-20250223013323388](Jenkins使用流程(新).assets/图6-3 executors.png)

1.1.6 配置分布式Jenkins集群

在项目开发过程中,根据项目规模的不同,对 Jenkins 的部署方式也有所差异。对于小型项目,通过一个节点直接运行即可满足需求,其部署简单、成本较低。然而,对于稍大一点的项目,为了提高构建效率、分散负载,通常会配置多个 Jenkins 节点,任务运行在从节点上。这种分布式的部署方式能够充分利用集群资源,加快构建速度,提升项目的整体开发效率。配置分布式 Jenkins 集群需要进行一系列的网络配置、节点注册、权限设置等操作,以确保各个节点之间能够协同工作,为项目的 CI/CD 流程提供稳定可靠的支持。

待补充……

1.1.7 权限分配

1. 背景

Jenkins 安装完成后,默认的授权策略是登陆的用户可以做任何事。对于大的项目老说,这是极具安全隐患的存在。

可以通过 Role-Based Strategy 插件进行权限管理。这个插件主要提供的功能为:Manage Roles(管理角色)、 Assign Roles (授权角色)。该插件按照 RBAC(Role - Based Access Control,基于角色的访问控制)的的核心思想,将访问权限与角色关联起来,用户通过被赋予不同角色来获取相应的操作权限。具体而言,它会创建角色,把 Jenkins 系统内的各种操作权限(像创建任务、构建任务、管理用户等)整合到这些角色中,之后再把角色分配给用户或者用户组。

该插件我们在前面已经安装过,可以将授权策略修改为 Role-Based Stra

image-20250223015201737

首先,我们创建一个测试用户,该测试人员需要任务名称是test* 的所有任务构建权限,

接下来我们进行一些配置:

在首页依次点击:Dashboard 》Manage Jenkins 》Manage and Assign Roles》Manage Roles

2. 管理角色(Manage Roles)

首先创建管理角色。管理角色就是创建一个具有某些规则的 Role,有全局级别(Global)和项目(Item)级别。

Global Roles

Global Roles适用于Jenkins中的所有项目,并覆盖您在“Item Roles”中指定的任何内容。也就是说,当您授予角色“Global Roles”中的“Job Read”权限时,则无论您在“Item Roles”中指定的内容如何,都允许该角色读取所有作业。

默认情况下,能够看到一个admin 用户具有了所有的权限。

权限分为:

全部:所有对象管理、读取权限。

凭据:创建、删除、管理域、更新、浏览权限。

代理:构建、配置、连接、创建、删除、断开连接等权限。

作业:构建、取消、配置、创建、删除、发现、读取、移动、工作目录权限。

运行:删除、回放、更新。

视图:配置、创建、删除、读取。

在这里将整个平台角色可以分为管理员、二级管理员、普通用户。对于管理员admin具有所有权限,对于二级管理员itemadmin具有作业完全控制权限,对于普通用户users具有对作业读取权限。角色划分完成,我们开始配置。

Item Roles

项目作业的权限,我们可以使用正则表达式对同类作业匹配。例如:我的流水线项目名称都是按照test-开头的,test-pipeline-service、test-pipeline-web。如果具有良好的项目命名规范,划分权限会更加容易一些。

首先定位到item Roles 然后填写Role to add字段的值为test意思是这个角色的名称,Pattern填写要匹配的项目test-.*,我们点击Add添加权限。为test角色勾选Job Build/Cancel/Discover/Read/Workspace权限。

分配权限后,点击 应用

image-20250223022132655

Node Roles

代理节点的权限也是可以按照Item Roles通过正则表达式配置,不过一般我们都会在流水线指定好相关的agent名称或者标签不会进行权限的控制,当然如果你需要对代理节点的配置进行权限控制,也是可以在这里实现的。

3. 分配角色(Assign Roles)

将用户与角色绑定。

Global roles 选项中为用户授权全局的权限。

Item Roles 选项为用户授权指定项目权限。

FAQ

如果不给用户分配 Global Roles 中的全部 Read 则会出现以下情况。

image-20250223021119510

安装 Role-based Authorization Strategy 插件后,可以将授权策略修改为 `Role-Based Stra

image-20250223015201737

1.1.8 创建Jenkins任务

接下来我们创建一个简单的任务测试一下。

1 创建pipeline

单击首页的 新建Item 选项,输入任务名称,类型为Pipeline,最后单击确定。

![image-20250223002349754](Jenkins使用流程(新).assets/图7 创建Pipeline.png)

2 配置pipeline

本文将Pipeline脚本存储在Gitee中(生产一般使用自己搭建的Gitlab)。

在新页面高级配置选项中,定义的下拉选项选择 Pipeline script from SCM ,然后输入pipeline脚本的仓库地址、分支以及脚本路径。

image-20250223010547781

附 pipeline-test.groovy 脚本内容
pipeline {
    agent any

    parameters {
        gitParameter branch: '', 
                     branchFilter: 'origin/(.*)', 
                     defaultValue: 'master', 
                     description: '代码分支', 
                     name: 'gitlab_branch', 
                     quickFilterEnabled: true, 
                     selectedValue: 'DEFAULT', 
                     sortMode: 'NONE', 
                     tagFilter: '*', 
                     type: 'PT_BRANCH'
    }

    // 定义环境变量
    environment {
        APP_NAME = "my-node-app"
        REGISTRY = "your-docker-registry-url"
        DOCKER_IMAGE = "${REGISTRY}/${APP_NAME}"
    }

    stages {
        // 清理工作区
        stage('01 Clean') {
            steps {
                sh "rm -rf ${WORKSPACE} && mkdir -p ${WORKSPACE}"
            }
        }

        // 拉取代码阶段
        stage('02 Pull') {
            steps {
                git url: 'https://gitee.com/linux-lxf/java.git', branch: "${params.gitlab_branch}"
            }
        }

        // 打包项目阶段
        stage('03Package') {
            steps {
                sh '''
                    echo "✅ 模拟执行构建命令:mvn clean package -DskipTests"
                    echo "构建产物:demo-1.0.0.jar | 构建状态:成功"
                '''
            }
        }

        // 测试阶段
        stage('04 Test') {
            steps {
                echo 'test'
            }
        }

        // 构建 Docker 镜像阶段
        stage('05 Build Docker Image') {
            steps {
                echo 'docker build -t ${DOCKER_IMAGE}:${env.BUILD_NUMBER} .'
            }
        }

        // 推送 Docker 镜像阶段
        stage('06 Push Docker Image') {
            steps {
                // 假设已在 Jenkins 中配置好 Docker 仓库凭证
                // withCredentials([usernamePassword(credentialsId: 'your-docker-credentials-id', passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
                    // "docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} ${REGISTRY}"
                // }
                echo 'docker push ${DOCKER_IMAGE}:${env.BUILD_NUMBER}'
            }
        }

        // 部署阶段
        stage('07 Deploy') {
            steps {
                // 假设使用 kubectl 部署到 Kubernetes 集群,需根据实际情况修改
                echo '部署到 Kubernetes'
            }
        }
    }

    // 后置操作
    post {
        success {
            echo 'Pipeline completed successfully!'
        }
        failure {
            echo 'Pipeline failed!'
        }
    }
}

1.2 Jenkins 部署 Java 项目

1.2.1 环境准备

在使用 Jenkins 部署 Java 项目之前,需要完成一系列环境准备工作,以确保部署过程的顺利进行。以下是详细的准备步骤:

1. 仓库信息

我们需要明确两个关键的仓库地址,分别是 Jenkins 配置仓库和应用代码仓库。

Jenkins代码仓库结构

Jenkins/
├── pipeline/                  # 流水线定义目录
│   ├── pipeline-go.groovy     # Jenkins 流水线脚本
│   ├── pipeline-java.groovy   # Jenkins 流水线脚本
│   ├── pipeline-php.groovy    # Jenkins 流水线脚本
│   └── pipeline-py.groovy     # Jenkins 流水线脚本
│  
├── scripts/                   # 自动化脚本目录
│   ├── docker-build.sh        # Docker 镜像构建脚本
│   ├── k8s-deploy.sh          # Kubernetes 部署相关脚本
│   └── k8s-check.sh           # Kubernetes 验证脚本
│
└── 1-hello-java/              # 项目目录
    ├── docker/                
    │   ├── Dockerfile         # Dockerfile
    └── k8s/                  
        └── k8s.yaml           # Kubernetes 资源清单
2. 安装 Maven 工具

Maven 是 Java 项目中广泛使用的构建工具,用于管理项目的依赖、编译、测试和打包等任务。在 Jenkins 服务器上安装 Maven 是部署 Java 项目的必要步骤。

访问 Maven 官方下载页面,选择合适的版本进行下载。例如,下载 Maven 3.8.6 版本:

wget https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
tar -zxvf apache-maven-3.9.9-bin.tar.gz
mkdir /usr/local/maven
mv apache-maven-3.9.9 /usr/local/maven
ln -s /usr/local/maven/apache-maven-3.9.9/bin/mvn /usr/bin/mvn
mvn -version
3. 在 Jenkins 中配置 Maven 路径

在 Jenkins 服务器上安装好 Maven 后,需要在 Jenkins 中配置 Maven 的路径,以便 Jenkins 能够正确调用 Maven 进行项目构建。

进入首页,点击 Manage Jenkins 》 Tools 》新增Maven

  • 名称:自定义一个名称,例如 Maven 3.9.9
  • MAVEN_HOME:填写 Maven 的安装路径,即 /usr/local/maven/apache-maven-3.9.9
  • 点击 “保存” 按钮,完成 Maven 路径的配置。

1.2.2 编写 Pipeline

本地运行简易版

pipeline-java.groovy

pipeline {
    agent any

    parameters {
        gitParameter branch: '', branchFilter: 'origin/(.*)', defaultValue: 'master', description: '代码分支', name: 'gitlab_branch', quickFilterEnabled: false, selectedValue: 'DEFAULT', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH'
    }

    // 定义环境变量
    environment {
        APP_NAME = "my-node-app"
        // 替换为实际的 Docker 镜像仓库地址
        REGISTRY = "your-real-docker-registry-url"
        DOCKER_IMAGE = "${REGISTRY}/${APP_NAME}"
        PROJECT_DIR = "${WORKSPACE}/MySimpleHttpServer"
        JAR_FILE = "MySimpleHttpServer-1.0-SNAPSHOT.jar"
        APP_DIR = "/usr/local/app/"
    }

    stages {
        // 清理工作区
        stage('Clean') {
            steps {
                script {
                    sh "rm -rf ${WORKSPACE} && mkdir -p ${WORKSPACE}"
                }
            }
        }

        // 拉取代码阶段
        stage('Pull') {
            steps {
                script {
                    git url: 'https://gitee.com/linux-lxf/java.git', branch: "${params.gitlab_branch}"
                }
            }
        }

        // 打包项目阶段
        stage('Package') {
            steps {
                script {
                    def packageCmd = "cd ${PROJECT_DIR} && mvn clean package"
                    try {
                        sh packageCmd
                    } catch (Exception e) {
                        echo "打包项目时出现错误: ${e.message}"
                        currentBuild.result = 'FAILURE'
                        error("打包项目失败")
                    }
                }
            }
        }

        // 部署阶段
        stage('Deploy') {
            steps {
                script {
                    try {
                        // 创建应用目录
                        sh "sudo mkdir -p ${APP_DIR}"
                        // 复制 JAR 文件
                        sh "sudo cp ${PROJECT_DIR}/target/${JAR_FILE} ${APP_DIR}"
                        // 后台运行应用(实际情况需要以脚本的形式运行)
                        sh "nohup java -jar ${APP_DIR}${JAR_FILE} > /dev/null 2>&1 &"
                    } catch (Exception e) {
                        echo "部署应用时出现错误: ${e.message}"
                        currentBuild.result = 'FAILURE'
                        error("部署应用失败")
                    }
                }
            }
        }
    }

    // 后置操作
    post {
        success {
            echo 'Pipeline completed successfully!'
        }
        failure {
            echo 'Pipeline failed!'
        }
    }
}
部署到 Kubernetes 集群(后期待优化)
pipeline {
    agent {
        label 'master'
    }
    options {
        timestamps()
        disableConcurrentBuilds() // 因为 docker build 慢,故取消并行限制
    }
    parameters {
        listGitBranches(
            branchFilter: 'refs/heads/(.*)',
            credentialsId: '',
            defaultValue: 'master',
            name: 'branch_name',
            quickFilterEnabled: true,
            remoteURL: '',
            selectedValue: 'DEFAULT',
            sortMode: 'DESCENDING',
            tagFilter: '*',
            type: 'PT_BRANCH'
        )
    }
    stages {
        stage('参数初始化') {
            steps {
                script {
                    def jobName = "${JOB_NAME}"
                    def projectName = jobName.split('-')[0]
                    def projectEnv = jobName.split('-')[1]

                    // 清理工作区
                    sh "rm -rf ${WORKSPACE} && mkdir -p ${WORKSPACE}"
                    // 克隆配置仓库
                    sh "git clone -b ${params.branch_name} https://gitee.com/linux-lxf/java.git ${WORKSPACE}"

                    // 读取配置参数
                    def gitAuthId = sh(script: "${WORKSPACE}/public_script/conf/read-config.sh ${jobName} ${projectEnv} jenkins.git-auth-id false", returnStdout: true).trim()
                    def appGit = sh(script: "${WORKSPACE}/public_script/conf/read-config.sh ${jobName} ${projectEnv} app true app-git", returnStdout: true).trim()
                    def toNodes = sh(script: "${WORKSPACE}/public_script/conf/read-config.sh ${jobName} ${projectEnv} app true to-nodes", returnStdout: true).trim()
                    def podCount = sh(script: "${WORKSPACE}/public_script/conf/read-config.sh ${jobName} ${projectEnv} app true pod-count", returnStdout: true).trim()
                    def postTagName = "-${new Date().format('yyyyMMddHHmmss')}-${BUILD_NUMBER}"

                    // 更新参数定义中的值
                    currentBuild.rawBuild.getAction(jenkins.model.BuildDiscarderProperty.class).parameters.find { it.name == 'credentialsId' }.value = gitAuthId
                    currentBuild.rawBuild.getAction(jenkins.model.BuildDiscarderProperty.class).parameters.find { it.name == 'remoteURL' }.value = appGit
                    currentBuild.rawBuild.getAction(jenkins.model.BuildDiscarderProperty.class).parameters.find { it.name == 'defaultValue' && it.definition.name == 'publishToNodes' }.value = toNodes

                    // 将参数存储到环境变量中
                    env.PROJECT_NAME = projectName
                    env.PROJECT_ENV = projectEnv
                    env.GIT_AUTH_ID = gitAuthId
                    env.APP_GIT = appGit
                    env.TO_NODES = toNodes
                    env.POD_COUNT = podCount
                    env.POST_TAG_NAME = postTagName
                }
            }
        }
        stage('初始化参数并验证') {
            steps {
                script {
                    def requiredParams = [
                        env.PROJECT_NAME, env.PROJECT_ENV, env.GIT_AUTH_ID,
                        env.APP_GIT, env.TO_NODES, env.POD_COUNT, env.POST_TAG_NAME
                    ]
                    if (requiredParams.any { it == null || it.trim() == '' }) {
                        def errorMsg = "the job: ${JOB_NAME} parameters check false (some parameters is null)"
                        echo errorMsg
                        currentBuild.result = 'FAILURE'
                        error errorMsg
                    }
                    def validEnvs = ["dev", "test", "gray", "prod"]
                    if (!validEnvs.contains(env.PROJECT_ENV)) {
                        def errorMsg = "the job: ${JOB_NAME} parameter env is not in dev,test,prod,gray"
                        echo errorMsg
                        currentBuild.result = 'FAILURE'
                        error errorMsg
                    }
                    echo "相关参数验证成功:job_name:${JOB_NAME} | project_name:${env.PROJECT_NAME} | project_env:${env.PROJECT_ENV} | git_auth_id:${env.GIT_AUTH_ID} | app_git:${env.APP_GIT} | to_nodes:${env.TO_NODES} | pod_count:${env.POD_COUNT} | post_tag_name:${env.POST_TAG_NAME} | "
                }
            }
        }
        stage('构建镜像推送至hb仓库') {
            steps {
                sh """
                    rm -rf ${WORKSPACE}/code
                    mkdir -p ${WORKSPACE}/code
                    git clone -b ${params.branch_name} https://oauth2:AsQK8nDc7DWymdrVS5hP@git.100lxf.com/jituan_gcxl_yach_spt/${env.PROJECT_NAME}.git ${WORKSPACE}/code
                    cd ${WORKSPACE}/code
                    mvn clean package -Dmaven.test.skip=true
                    cp ${WORKSPACE}/code/application/target/ROOT.war ${WORKSPACE}/${env.PROJECT_NAME}/app
                """
                sh """
                    docker build -t hub.lxf.com/yach/${env.PROJECT_NAME}:${params.branch_name}${env.POST_TAG_NAME} ${WORKSPACE}/${env.PROJECT_NAME}/app || exit
                    docker push hub.lxf.com/yach/${env.PROJECT_NAME}:${params.branch_name}${env.POST_TAG_NAME}
                """
                echo "镜像构建并推送完成 ->  hub.lxf.com/yach/${env.PROJECT_NAME}:${params.branch_name}${env.POST_TAG_NAME}"
            }
        }
        stage('发布-容器启动') {
            steps {
                sh "mkdir -p /tmp/${JOB_NAME}/${BUILD_NUMBER}"
                sh "cp ${env.PROJECT_NAME}/app/${env.PROJECT_ENV}/*.yml /tmp/${JOB_NAME}/${BUILD_NUMBER}/"
                sh "bash -x ${WORKSPACE}/public_script/pipeline/app/run-java.sh ${env.PROJECT_NAME} ${params.branch_name}${env.POST_TAG_NAME} /tmp/${JOB_NAME}/${BUILD_NUMBER} ${env.PROJECT_ENV} ${env.POD_COUNT} ${params.publishToNodes} ${env.POST_TAG_NAME} ${JOB_NAME}"
            }
        }
        stage('检查容器是否启动成功') {
            steps {
                script {
                    def exitValue = sh(script: "${WORKSPACE}/public_script/checkPublishComplete.sh hub.lxf.com/yach/${env.PROJECT_NAME}:${params.branch_name}${env.POST_TAG_NAME} ${env.PROJECT_NAME}-${env.PROJECT_ENV}-deploy ${env.PROJECT_ENV}", returnStatus: true)
                    if (exitValue != 0) {
                        def errorMsg = "检测是否发布成功达到上限还未成功,请核查"
                        echo errorMsg
                        currentBuild.result = 'FAILURE'
                        error errorMsg
                    }
                }
            }
        }
    }
}

K8S 部署物料

介绍如何创建一个 deploy 模板文件,并且编写一个脚本使用 envsubst 命令对模板进行赋值。

1. 创建 deploy 模板文件

首先,我们要创建一个 deploy 模板文件,这里以 Kubernetes 的 Deployment 配置文件为例。在这个模板文件里,使用环境变量占位符,后续会用实际的值来替换这些占位符。

# 创建 deploy 模板文件
cat << EOF > deploy.template.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ${APP_NAME}-deployment
spec:
  replicas: ${REPLICAS}
  selector:
    matchLabels:
      app: ${APP_NAME}
  template:
    metadata:
      labels:
        app: ${APP_NAME}
    spec:
      containers:
      - name: ${APP_NAME}-container
        image: ${IMAGE_NAME}
        ports:
        - containerPort: ${CONTAINER_PORT}
EOF

在上述模板文件中,${APP_NAME}${REPLICAS}${IMAGE_NAME}${CONTAINER_PORT} 是环境变量占位符,后续会用实际的值替换它们。

2. 编写脚本使用 envsubst 命令对模板进行赋值
#!/bin/bash

# 检查位置参数数量是否正确
if [ $# -ne 4 ]; then
    echo "用法: $0 <APP_NAME> <REPLICAS> <IMAGE_NAME> <CONTAINER_PORT>"
    exit 1
fi

# 从位置参数获取值并设置为环境变量
export APP_NAME="$1"
export REPLICAS="$2"
export IMAGE_NAME="$3"
export CONTAINER_PORT="$4"

# 使用 envsubst 命令替换模板文件中的占位符
envsubst < deploy.template.yaml > deploy.yaml

# 输出替换后的文件内容
echo "替换后的文件内容:"
cat deploy.yaml
  • 变量传递:将位置参数 $1$2$3$4 分别赋值给环境变量 APP_NAMEREPLICASIMAGE_NAMECONTAINER_PORT$1 代表第一个参数,$2 代表第二个参数,以此类推。
  • 设置环境变量:在脚本里,通过 export 命令设置了 APP_NAMEREPLICASIMAGE_NAMECONTAINER_PORT 这些环境变量,这些变量的值会用来替换模板文件中的占位符。
  • 使用 envsubs 命令envsubst 命令从标准输入读取模板文件内容,将其中的占位符替换为对应的环境变量值,然后将替换后的内容输出到 deploy.yaml 文件中。
  • 输出替换后的文件内容:使用 cat 命令输出替换后的 deploy.yaml 文件内容,方便查看替换结果。
0

评论区