Jenkins


一、安装jenkins

开源 Devops 工具 Jenkins 宣布:从 6 月 22 日发布的 Jenkins 2.356 和即将发布的 9 月 LTS 版本开始,Jenkins 最低需要 Java 11。

如果出现版本问题导致插件无法安装,可在下面链接下载后手动安装

http://updates.jenkins-ci.org/download/plugins/

0、前提

安装jdk和maven并配置环境

安装git

yum install -y git

1、war 包安装

(1)配置数据存储路径

配置环境变量

vim /etc/profile

最后一行添加

export JENKINS_HOME=/data/jenkins_data/

刷新环境变量

source /etc/profile

如果用 java -jar 方式启动

nohup java -DJENKINS_HOME=/data/jenkins_data/ -jar jenkins.war --httpPort=8080 &

配置访问前缀

nohup java -jar jenkins.war --httpPort=8080 --prefix="/jenkins" > jenkins.log 2>&1 &

(2)下载

https://www.jenkins.io/download/

并上传到linux服务器,并复制到tomcat的webapps目录下

(3)启动tomcat

  1. 启动后,访问服务器主机名:8080/jenkins
  2. 根据网页提示信息到服务器的相应路径下获取密码,解锁jenkins
  3. 关闭网页

(4)配置镜像源

进入更新配置位置

cd  /root/.jenkins/updates    

输入以下命令

sed -i 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json && sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json

(5)重启tomcat

访问刚才的网页,选择安装推荐插件

安装完后,创建用户,实例配置为默认

2、yum安装

二、docker安装

1、安装

拉取镜像,不要docker pull jenkins ,jenkins版本太旧已不维护了。

docker pull jenkins/jenkins

创建挂载数据的文件夹

mkdir /data/docker/jenkins

设置权限

chmod -R 777 /data/docker/jenkins

运行容器

docker run -d --name jenkins \
-p 8888:8080 -p 50000:50000 \
--restart=always --privileged=true \
-e TZ="Asia/Shanghai" \
-e JENKINS_OPTS="--prefix=/jenkins" \
-e JENKINS_ARGS="--prefix=/jenkins" \
-e JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=utf-8 -Xms128m -Xmx128m -XX:MaxPermSize=64M" \
-v /etc/localtime:/etc/localtime:ro \
-v /data/docker/jenkins:/var/jenkins_home \
jenkins/jenkins

参数解析:

  • -d 后台运行容器,并返回容器ID;

  • –name 为容器起一个容易区分且容易书写的名字

  • -p 映射宿主机端口到容器端口,宿主机端口:容器端口

  • –restart=always 机器重启时自动启动容器

  • -e  设定一些必须的环境变量。

    • -e TZ="Asia/Shanghai" 设定时区为上海,强烈建议国内设定,否则容器内打印的所有日志时间都会差8小时。
    • -e JENKINS_OPTS="--prefix=/jenkins" -e JENKINS_ARGS="--prefix=/jenkins" 设定jenkins访问的路径,非必选,如果是直接根目录或ip地址访问,则不需要添加,如果是想nginx反向代理且不在根目录下,则必须,否则只配置nginx会报静态文件404错误,此处名字应与文件夹名称一致。
  • -v 挂载宿主机文件到容器。本例两个分别为:

    • -v /etc/localtime:/etc/localtime:ro 挂载宿主机时间,保持容器时间正确。
    • -v /data/docker/jenkins:/var/jenkins_home 绑定挂载文件
  • -u 0 因为Jenkins镜像内部使用的用户是jenkins,但是我们启动容器时的账号是root,导致没有权限操作内部目录,所以加上参数 -u 0 就能解决了:

    • -u :覆盖容器中内置的账号
    • 0:root账号id
  • --privileged=true 解决访问目录无权限

2、配置镜像源

cd /data/docker/jenkins/updates

配置清华镜像

sed -i 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json && sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json

重启docker

docker restart jenkins

3、汉化

安装 Localization: Chinese (Simplified) 插件

三、配置jenkins

1、获取jdk、maven、git安装路径

在服务器中输入which jdk,获取jdk和maven的安装目录

输入which git获取git的安装目录

2、配置jdk、maven

进入全局配置

按以下配置jdk、git、maven(maven有两个,改下面的

image-20211201221805637

3、mvn命令不存在

进入系统设置

image-20210818142345919

在服务器中执行以下命令获取PATH环境变量

echo $PATH

将返回的PATH变量填到jenkins的系统设置中

image-20210818142624346

4、配置svn

当项目不是使用git,而是svn时,需要配置svn

在插件管理中搜索以下插件安装即可

image-20210817212716868

构建任务时

image-20210817212536307

四、自动化部署

1、项目修改

在pom文件添加插件

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>        
</build>

添加打包方式

<groupId>com.rewind</groupId>
<artifactId>graduation-project</artifactId>
<packaging>jar</packaging>  <!--添加这一行-->
<version>0.0.1-SNAPSHOT</version>

2、添加文件Dockerfile

如果直接使用shell脚本启动,可不使用

在项目根目录下(pom的同级目录)下,添加Dockerfile文件(无后缀),内容如下

FROM java:8

EXPOSE 8080

VOLUME /tmp
ADD ./target/renren-fast.jar  /app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-jar","/app.jar"]

3、jenkins创建任务

输入任务名称,选择自由风格,确定

添加项目的git仓库,并添加git用户(填写用户名密码即可),选择分支

方式一、docker

找到构建,选择执行shell,并把docker脚本(本文末尾)粘贴到框中,修改下面部分

点击保存

#!/bin/bash
#maven打包
mvn clean package
echo 'package ok!'
echo 'build start!'

# 服务名,镜像名,容器名
service_name="eureka-server"
# 服务端口
service_prot=8080
# 对应宿主机端口
host_port=8888

#查看镜像id
IID=$(docker images | grep "$service_name" | awk '{print $3}')
echo "IID $IID"
if [ -n "$IID" ]
then
    echo "exist $SERVER_NAME image,IID=$IID"
    #删除镜像
    docker rmi -f $service_name
    echo "delete $SERVER_NAME image"
    #构建
    docker build -t $service_name .
    echo "build $SERVER_NAME image"
else
    echo "no exist $SERVER_NAME image,build docker"
    #构建
    docker build -t $service_name .
    echo "build $SERVER_NAME image"
fi
#查看容器id
CID=$(docker ps | grep "$SERVER_NAME" | awk '{print $1}')
echo "CID $CID"
if [ -n "$CID" ]
then
    echo "exist $SERVER_NAME container,CID=$CID"
    #停止
    docker stop $service_name
    #删除容器
    docker rm $service_name
else
    echo "no exist $SERVER_NAME container"
fi
#启动
docker run -d --name $service_name -p $host_port:$service_prot $service_name
#查看启动日志
#docker logs -f  $service_name
方式二、maven
image-20210818142844887
port=8083
#根据端口号查询对应的pid
pid=$(netstat -nlp | grep :$port | awk '{print $7}' | awk -F"/" '{ print $1 }');

#杀掉对应的进程,如果pid不存在,则不执行
if [  -n  "$pid"  ];  then
    kill  -9  $pid;
fi

#####################################################################
mvn clean package
#####################################################################

# 禁止jenkins杀死衍生进程,jenkins默认构建完会杀死所有衍生进程
BUILD_ID=DONTKILLME

cd /root/.jenkins/workspace/teway-tms/target
tar -zxvf teway-tms-1.0-SNAPSHOT-assembly.tar.gz
cd /root/.jenkins/workspace/teway-tms/target/c12-tms-1.0-SNAPSHOT/bin
./start.sh

4、构建

如果是docker方式,则需要启动docker

点击此处查看控制台输出

五、Publish Over SSH

【Publish Over SSH】插件是通过SSH连接其他Linux机器,远程传输文件及执行Shell命令
有两种验证方式,密码方式和秘钥方式

1、密码方式

Manage Jenkins -> Configure System -> SSH Servers

image-20220507161743416

填写名称、主机ip、ssh用户名、远程的目录(最好写/,后面就可以用绝对路径了)

然后点击高级,勾选【Use password authentication, or use a different key】使用密码登录,填写密码、端口(默认是22)、连接超时(默认300000ms)

image-20220507162013371

点击【Test Configuration】,测试连接,显示Success即可

2、秘钥方式

秘钥方式
Manage Jenkins -> Configure System -> SSH Servers

1、生成一个密钥对,命令:ssh-keygen

把生成的id_rsa.pub(公钥)内容复制到要远程的机器的authorized_keys文件下,.ssh文件夹的权限为600,authorized_keys文件的权限为700;

把id_rsa(私钥)的内容填写在Jenkins SSH Key -> Key 里面
或者指定Path to key(jenkins机器私钥的文件路径)也可以

填写名称、主机ip、ssh用户名、远程的目录(最好写/,后面就可以用绝对路径了)

然后点击高级,填写密码、端口、连接超时即可;不要勾选【Use password authentication, or use a different key】使用密码登录

点击【Test Configuration】,测试连接,显示Success即可;

3、使用方式

项目中增加构建步骤,或者构建后步骤

image-20220507162358391

image-20220507162642880

参数详解:

  • Name:SSH Sverver的名字列表

  • Source files:

jenkins本机上的文件,相对 workspace/当前项目的路径,如上图中表示的是 /root/.jenkins/workspace/项目1/test 下的所有文件和文件名

  • Remove prefix:文件复制时要过滤的目录,要不然会创建多层目录

  • Remote directory:

远程机上的目录,此目录是相对于【SSH Server】中的【Remote directory】的,如果不存在将会自动创建,设置为/根目录的话,这里可以用绝对路径

  • Exec command:远程机器上执行的命令或脚本

4、远程执行脚本失败

  1. 执行命令前需要先 source /etc/profile 命令,同步环境
  2. javajar包 和 日志文位置都用全路径。
  3. shell 命令加 #!/bin/bash

六、Pipeline流水线构建

1、概念

Pipeline,简单来说,就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。

  • 代码:Pipeline以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流程。

  • 持久:无论是计划内的还是计划外的服务器重启,Pipeline都是可恢复的。

  • 可停止:Pipeline可接收交互式输入,以确定是否继续执行Pipeline。

  • 多功能:Pipeline支持现实世界中复杂的持续交付要求。它支持fork/join、循环执行,并行执行任务的功能。

  • 可扩展:Pipeline插件支持其DSL的自定义扩展 ,以及与其他插件集成的多个选项

如何创建 Jenkins Pipeline

Pipeline 脚本是由 Groovy 语言实现的,但是我们没必要单独去学习 Groovy

Pipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)语法

Pipeline 也有两种创建方法:

  • 可以直接在 Jenkins 的 Web UI 界面中输入脚本;
  • 也可以通过创建一个 Jenkinsfifile 脚本文件放入项目源码库中(一般我们都推荐在 Jenkins 中直接从源代码控制(SCM)中直接载入 Jenkinsfifile Pipeline 这种方法)。

安装插件

Manage Jenkins->Manage Plugins->搜索Pipeline

2、Declarative声明式

创建一个流水线项目,脚本选择 Hello world

image-20230818103535742

pipeline {
    agent any

    stages {
        stage('Hello') {
            steps {
                echo 'Hello World'
            }
        }
    }
}
  • stages:代表整个流水线的所有执行阶段。通常stages只有1个,里面包含多个stage

  • stage:代表流水线中的某个阶段,可能出现n个。一般分为拉取代码,编译构建,部署等阶段。

  • steps:代表一个阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等任意内容。

编写一个简单声明式Pipeline:

pipeline {
    agent any
    stages {
        stage('拉取代码') {
            steps {
                echo '拉取代码'
            }
        }
        stage('编译构建') {
            steps {
                echo '编译构建'
            }
        }
        stage('项目部署') {
            steps {
                echo '项目部署'
            }
        }
    }
}

点击构建,可以看到整个构建过程

image-20230818104310983

3、Scripted Pipeline脚本式

创建流水线工程,脚本选择”Scripted Pipeline”

image-20230818104712457

node {
    def mvnHome
    stage('Preparation') { // for display purposes
        // 拉取代码
        // Get some code from a GitHub repository
        git 'https://github.com/jglick/simple-maven-project-with-tests.git'
        // Get the Maven tool.
        // ** NOTE: This 'M3' Maven tool must be configured
        // **       in the global configuration.
        mvnHome = tool 'M3'
    }
    stage('Build') {
        // 编译构建
        // Run the maven build
        withEnv(["MVN_HOME=$mvnHome"]) {
            if (isUnix()) {
                sh '"$MVN_HOME/bin/mvn" -Dmaven.test.failure.ignore clean package'
            } else {
                bat(/"%MVN_HOME%\bin\mvn" -Dmaven.test.failure.ignore clean package/)
            }
        }
    }
    stage('Results') {
        // 部署
        junit '**/target/surefire-reports/TEST-*.xml'
        archiveArtifacts 'target/*.jar'
    }
}
  • Node:节点,一个 Node 就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境,后续讲到Jenkins的Master-Slave架构的时候用到。

  • Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作,比如:Build、Test、Deploy,Stage 是一个逻辑分组的概念。

  • Step:步骤,Step 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins 插件提供,比如命令:sh ‘make’,就相当于我们平时 shell 终端中执行 make 命令一样。

4、SCM脚本

刚才我们都是直接在Jenkins的UI界面编写Pipeline代码,这样不方便脚本维护,建议把Pipeline脚本放在项目中(一起进行版本控制)

1)在项目根目录建立Jenkinsfifile文件,把脚本内容复制到该文件中

2)在项目中引用该文件

image-20230818172137045

5、脚本语法

可以通过下面的流水线语法自动生成脚本

image-20230818165505824

(1)拉取代码

流水线语法页面选择

image-20230818165617324

填入信息生成脚本

checkout([$class: 'GitSCM', branches: [[name: '*/分支名']], extensions: [], userRemoteConfigs: [[credentialsId: '用户凭据id', url: 'git地址']]])

(2)执行shell脚本

sh 'mvn clean package'

(3)执行publish over ssh

image-20230818171651125

sshPublisher(publishers: [sshPublisherDesc(configName: 'prod', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: """
source /etc/profile
BUILD_ID=DONTKILLME
touch 1.txt
""", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

重点:execCommand后面必须使用三个双引号,不能使用单引号,否则无法获取到环境变量

(4)docker

七、构建触发器

Jenkins内置4种构建触发器:

  • 触发远程构建

  • 其他工程构建后触发(Build after other projects are build)

  • 定时构建(Build periodically)

  • 轮询SCM(Poll SCM)

1、触发远程构建

image-20230818172541926

只需请求一下路径即可触发构建

JENKINS_URL/job/pipeline-test/build?token=自定义的TOKEN

2、其他工程构建后触发

image-20230818172831238

3、定时构建

image-20230818173326689

定时字符串从左往右分别为:

分 时 日 月 周一些定时表达式的例子:

  • 每30分钟构建一次:H代表形参 H/30 * * * * 10:02 10:32

  • 每2个小时构建一次: H H/2 * * *

  • 每天的8点,12点,22点,一天构建3次: (多个时间点中间用逗号隔开) 0 8,12,22 * * *

  • 每天中午12点定时构建一次 H 12 * * *

  • 每天下午18点定时构建一次 H 18 * * *

  • 在每个小时的前半个小时内的每10分钟 H(0-29)/10 * * * *

  • 每两小时一次,每个工作日上午9点到下午5点(也许是上午10:38,下午12:38,下午2:38,下午4:38) H H(9-16)/2 * * 1-5

4、轮询SCM

轮询SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。

注意:这次构建触发器,Jenkins会定时扫描本地整个项目的代码,增大系统的开销,不建议使用。

5、Git hook

利用Git的webhook实现代码push到仓库,立即触发项目自动构建。


  目录