从0搭建属于自己的Jenkins持续集成平台
nanshan 2024-11-15 22:52 27 浏览 0 评论
前言
??Jenkins在日常工作中占据了一个非常重要的角色,帮助我们节省了大量用于构建的时间。有些公司有运维大哥对Jenkins进行维护,如果没有那只能自己动手了。俗话说的好自己动手丰衣足食,所以本文就从0开始搭建属于自己的Jenkins持续平台。主要包含,普通项目构建、流水线构建、多分支流水线构建并将构建结果辅以钉钉通知。
前期准备
- centos7 服务器一台
确认是否能安装docker
?Docker要求CentOS系统的内核版本高于3.10.通过uname -r命令查看你当前的内核版本。
[root@CentOS ~]# uname -r
3.10.0-1127.8.2.el7.x86_64
更改yum源为阿里云
备份旧源
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
下载最新的源
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
生成缓存
yum makecache
更新
yum update
安装docker
官方安装文档
yum install -y yum-utils
添加docker源
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
安装docker
yum install docker-ce
启动docker
systemctl start docker
更改docker镜像源
vim /etc/docker/daemon.json
加入阿里云源地址
{
"registry-mirrors":["https://6kx4zyno.mirror.aliyuncs.com"]
}
重新读取配置
systemctl daemon-reload
重启docker
systemctl restart docker
安装jenkins
下载jenkins镜像
docker pull jenkins
启动jenkins
?设置端口为9090并映射jenkins_home到宿主机/home/jenkins_home。
docker run -d --name jenkins -p 9090:8080 -v /home/jenkins_home:/var/jenkins_home jenkins
?可以通过docker ps查看运行的容器。
[root@CentOS home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec6a4da6b83f jenkins "/bin/tini -- /usr/l…" About a minute ago Up About a minute 50000/tcp, 0.0.0.0:9090->8080/tcp jenkins
[root@CentOS home]#
把玩jenkins docker镜像遇到的volume权限问题
?在运行启动jenkins的命令时,可能会出现jenkins无法启动情况。
[root@CentOS home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b571f16dafbf jenkins "/bin/tini -- /usr/l…" 8 minutes ago Exited (1) 8 minutes ago jenkins
[root@CentOS home]#
?可以通过docker logs 镜像名称查看启动日志。
[root@CentOS home]# docker logs jenkins
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
[root@CentOS home]#
?查看输出的日志,如果出现 Permission denied 类似的错误。需要删除旧容器重新运行。
docker rm jenkins
?运行命令加入了-u 0重新运行。
docker run -d --name jenkins -p 9090:8080 -v /home/jenkins_home:/var/jenkins_home -u 0 jenkins
参考 https://blog.csdn.net/minicto/article/details/73539986
Jenkins初始化
?启动成功后输入 http://服务器:9090/
?如果无法访问,请检查一下防火墙端口是否开放,如果是云服务器还需要检查安全组设置
??首次启动jenkins需要输入密码,需要进入容器内获取密码。密码位于/var/jenkins_home/secrets/initialAdminPassword。
进入容器
docker exec -it jenkins /bin/bash
获取密码
cat /var/jenkins_home/secrets/initialAdminPassword
[root@CentOS jenkins_home]# docker exec -it jenkins /bin/bash
root@ec6a4da6b83f:/# cat /var/jenkins_home/secrets/initialAdminPassword
68eed23ad39541949972468e4f2ce1fd
root@ec6a4da6b83f:/#
??由于我们将/var/jenkins_home -- 挂载到--> /home/jenkins_home所以也可以直接cat /home/jenkins_home/secrets/initialAdminPassword 获取密码。
??输入密码以后,安装需要的插件,在安装途中由于网络原因会出现有些插件安装失败,这个可以不用理会。
设置jenkins的默认登录账号和密码
处理插件安装失败
??进入jenkins的主页面右上角可能会出现一些报错信息,主要是提示jenkins 需要的某些插件没有安装,或者说jenkins版本太低了,插件无法使用这个时候我们需要先升级jenkins做一个升级。
自动升级
Jenkins提供了自动升级的方式
手动升级
?可以去Jenkins的官网下载好最新jar包上传到服务器,也可以使用wget命令。
wget http://jenkins新版本的下载地址
#目前最新2.239
wget http://updates.jenkins-ci.org/download/war/2.239/jenkins.war
??Jenkins的更新主要是替换jenkins镜像里面的war包 ,我们可以把下载好的war包使用docker cp直接进行复制命令如下:
docker cp jenkins.war jenkins:/usr/share/jenkins
?重新启动Jenkins即可完成升级。
docker restart jenkins
更插件源
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
- 替换完源以后点击提交。
- 然后进入插件管理页面将出错的插件重新安装。
- 及时更新插件。
安装必要的插件
- Localization: Chinese (Simplified) 1.0.14 汉化包 搜索关键字 chinese
- Publish Over SSH 1.20.1 搜索关键字 ssh
- DingTalk 钉钉通知 2.3.0
配置jenkins
全局工具配置
??主要配置 jdk、maven、git等常用环境。需要注意配置的别名,后续构建将会使用到。
配置jdk
??因为jenkins镜像自带jdk所以无需安装直接使用即可,进入Jenkins容器,使用java -verbose查看java安装路径。
docker exec -it jenkins /bin/bash
java -verbose
配置git
?进入容器内使用whereis git即可查询到git安装路径。
root@6a9fbb129cbe:~# whereis git
git: /usr/bin/git /usr/share/man/man1/git.1.gz
root@6a9fbb129cbe:~#
配置maven
?maven直接使用自动安装即可。
系统设置
配置服务器
点击新增即可添加服务器,主要配置:
- Name 名称 - 构建的时候将会用到
- Hostname 服务器地址
- Username 用户名
- Remote Directory 远程目录 - 上传文件的目录 默认配置根目录即可/。
点击高级进行其他参数配置
- 如果需要使用密码登录,则选中Use password authentication, or use a different key 复选框即可,如下图所示。
??除了配置密码还可以配置端口Port,跳板机Jump Host的参数,可以根据实际情况配置。默认可以使用密码。
??配置完成以后点击Test Configuration按钮,如果配置正常会出现Success 反之出现错误信息,可以根据错误信息,调整配置参数。
配置钉钉
??钉钉主要用于构建通知,在配置前需要在钉钉群内,添加自定义机器人。
自由风格的软件项目
??以https://gitee.com/huangxunhui/jenkins_demo.git为例。
新建项目
设置项目简介
源码管理
- 配置仓库地址。
- 配置凭证-主要用于拉取代码。
- 配置需要构建的分支。
添加凭证
??如果项目是开源,则可以跳过这一步。反之需要设置凭证,要不然将无法拉取代码进行构建。
构建触发器
??可以根据实际情况选择,案例采用轮询的方式进行构建。
构建
构建后操作
- 将jar包发送到相应的服务器。
- Source files jar包的路径。支持通配符匹配.
- Remove prefix 移除前缀,一般jar包的路径都存在于**/target下,如果不移除,会在目标服务器上建立相应的目录结构。
- Remote directory 远程目录。
注意的点, 在之前配置服务器时也配置了Remote directory,这时候部署的实际目录是,服务器设置的远程目录+现在配置的远程目录。
- Exec command 执行脚本,主要用于将jar发送到目标服务器后,执行相应的启动脚本。
配置完成点击保存即可。
点击开始构建
发送钉钉通知
流水线
??流水线构建,将上述构建步骤代码化,方便调整。
项目创建
流水线编写
??由于配置步骤类似,前面简单的步骤可以参照,自由风格的软件项目。这里主要讲流水线如何编写。
注意右下角的流水线语法,后续会用上。
??我们可以点击右上角的下拉按钮,生成一个简单的流水线。比如说hello world。
pipeline {
// 表示所有机器都能运行
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
??通过上面的pipeline可以知道,有一个Hello的步骤,这个步骤执行的是,输出hello world。依葫芦画瓢,一次完整的构建我们可以总结出如下几个步骤:拉取代码(checkout) -> 打包(build) -> 部署(deploy)。
pipeline {
agent any
stages {
stage('checkout') {
steps {
}
}
stage('build') {
steps {
}
}
stage('deploy') {
steps {
}
}
}
}
??步骤梳理好了,这个时候就可以完善对应的步骤了,这就需要用到提到的,流水线语法。
将生成好的流水线脚本复制到对应的步骤即可。
注意:如果使用到maven需要将maven引入,tools相应的内容就是配置maven时配置的别名。
pipeline {
agent any
// 工具
tools {
maven 'maven'
jdk 'jdk'
}
stages {
stage('checkout') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'https://gitee.com/huangxunhui/jenkins_demo.git']]])
}
}
stage('build') {
steps {
sh 'mvn clean package -Dmaven.test.skip=true'
}
}
stage('deploy') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'dev', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''cd /home/project
nohup java -jar jenkins_demo.jar > nohup.out 2>&1 &''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/home/project', remoteDirectorySDF: false, removePrefix: '/target', sourceFiles: '**/target/jenkins_demo.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
配置完成点击应用即可。
构建测试
上面演示的是将流水线配置在jenkins内,其实我们还可以从SCM中获取,比如git。
我们可以建立一个仓库专门维护不同项目的构建脚本Jenkinsfile,也可以在每个项目下,建立对应的Jenkinsfile.
??注意的点:项目中的Jenkinsfile需要和配置的一致。比如说上面的配置,是扫描项目根目录下名字为Jenkinsfile的文件。
所以我们可以在jenkins_demo仓库内添加Jenkinsfile文件。
配置点击完成,即可。
多分支流水线
??在日常开发中,通常是基于git-flow进行开发的,前面两种都是基于单分支构建,如果每个分支都去配置,那将耗费大量时间。所以多分支流水线就是用来解决这个问题的。
创建项目
配置分支源
构建配置
扫描触发器
完成上述配置,点击应用即可。
编写`jenkinsfile`文件
??核心思想是,根据不同的分支使用不同的打包命令,发送到不同的服务器进行运行。
pipeline {
// 指定集群 any 表示所有
agent any
// 工具
tools {
maven 'maven'
jdk 'jdk'
}
// 定义常量
environment {
// 钉钉机器人编号
rebootId = 'a3c07482-d031-47a6-8542-05ac56c5f17a'
// 开始logo
imageOfStart = 'https://www.easyicon.net/api/resizeApi.php?id=1229977&size=128'
// 成功logo
imageOfSuccess = 'https://www.easyicon.net/api/resizeApi.php?id=1194837&size=128'
// 失败logo
imageOfFailure = 'https://www.easyicon.net/api/resizeApi.php?id=1201052&size=128'
// 不稳定logo
imageOfUnstable = 'https://www.easyicon.net/api/resizeApi.php?id=1219854&size=128'
// 终止logo
imageOfAborted = 'https://www.easyicon.net/api/resizeApi.php?id=1183198&size=128'
// 认证Id
credentialsId = '98e9c197-f0ae-44c3-8f67-4ca0339028a8'
// 仓库地址
repositoryUrl = 'https://gitee.com/huangxunhui/jenkins_demo.git'
// 打包命令 - 项目需要配置maven多环境
mavenProd = 'mvn clean package -P prod -Dmaven.test.skip=true'
mavenTest = 'mvn clean package -P test -Dmaven.test.skip=true'
mavenDev = 'mvn clean package -P dev -Dmaven.test.skip=true'
// 服务器名称 - 案例测试-全部部署到dev环境
devServer = 'dev'
testServer = 'dev'
prodServer = 'dev'
// sshPublisher 配置
removePrefix = '/target'
remoteDirectory = '/home/project/jenkins_demo'
sourceFiles = '**/target/jenkins_demo.jar'
execCommandProd = 'cd /home/project && ./manage.sh jenkins_demo/ restart'
execCommandTest = 'cd /home/project && ./manage.sh jenkins_demo/ restart'
execCommandDev = 'cd /home/project && ./manage.sh jenkins_demo/ restart'
}
stages {
stage('开始构建通知'){
steps {
dingtalk (
robot: "${rebootId}",
type: 'LINK',
title: "${env.JOB_NAME}",
text: [
"开始构建-编号为#${BUILD_NUMBER}"
],
messageUrl: "${env.BUILD_URL}",
picUrl: "${imageOfStart}"
)
}
}
stage('拉取代码'){
steps {
echo "拉取 ${BRANCH_NAME} 分支的代码。"
checkout([$class: 'GitSCM', branches: [[name: "*/${BRANCH_NAME}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${credentialsId}", url: "${repositoryUrl}"]]])
}
}
stage('进行打包'){
steps {
script {
if (env.BRANCH_NAME == 'master') {
sh "${mavenProd}"
} else if (env.BRANCH_NAME == 'test') {
sh "${mavenTest}"
} else if (env.BRANCH_NAME == 'dev') {
sh "${mavenDev}"
} else {
sh "${mavenDev}"
}
}
}
}
stage('项目部署'){
steps {
script {
if (env.BRANCH_NAME == 'master') {
// 部署生产环境
sshPublisher(publishers: [sshPublisherDesc(configName: "${prodServer}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommandProd}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: "${remoteDirectory}", remoteDirectorySDF: false, removePrefix: "${removePrefix}", sourceFiles: "${sourceFiles}")], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
} else if (env.BRANCH_NAME == 'test') {
// 部署测试环境
sshPublisher(publishers: [sshPublisherDesc(configName: "${testServer}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommandTest}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: "${remoteDirectory}", remoteDirectorySDF: false, removePrefix: "${removePrefix}", sourceFiles: "${sourceFiles}")], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
} else if (env.BRANCH_NAME == 'dev') {
// 部署开发环境
sshPublisher(publishers: [sshPublisherDesc(configName: "${devServer}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommandDev}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: "${remoteDirectory}", remoteDirectorySDF: false, removePrefix: "${removePrefix}", sourceFiles: "${sourceFiles}")], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
} else {
sshPublisher(publishers: [sshPublisherDesc(configName: "${devServer}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommandTest}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: "${remoteDirectory}", remoteDirectorySDF: false, removePrefix: "${removePrefix}", sourceFiles: "${sourceFiles}")], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
}
// 流水线结束通知
post {
// 成功通知
success {
dingtalk (
robot: "${rebootId}",
type: 'LINK',
title: "${env.JOB_NAME}",
text: [
"构建成功-编号为#${BUILD_NUMBER}"
],
messageUrl: "${env.BUILD_URL}",
picUrl: "${imageOfSuccess}"
)
}
// 失败通知
failure {
dingtalk (
robot: "${rebootId}",
type: 'LINK',
title: "${env.JOB_NAME}",
text: [
"构建失败-编号为#${BUILD_NUMBER}"
],
messageUrl: "${env.BUILD_URL}",
picUrl: "${imageOfFailure}"
)
}
// 构建不稳定通知
unstable {
dingtalk (
robot: "${rebootId}",
type: 'LINK',
title: "${env.JOB_NAME}",
text: [
"构建不稳定-编号为#${BUILD_NUMBER}"
],
messageUrl: "${env.BUILD_URL}",
picUrl: "${imageOfUnstable}"
)
}
// 构建终止通知
aborted {
dingtalk (
robot: "${rebootId}",
type: 'LINK',
title: "${env.JOB_NAME}",
text: [
"构建终止-编号为#${BUILD_NUMBER}"
],
messageUrl: "${env.BUILD_URL}",
picUrl: "${imageOfAborted}"
)
}
}
}
使用到的启动脚本manage.sh。
钉钉机器人插件使用文档
构建结果
结尾
??如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。
相关推荐
- 0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)
-
文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...
- ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes
-
为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...
- 生产环境starrocks 3.1存算一体集群部署
-
集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...
- 在CentOS上添加swap虚拟内存并设置优先级
-
现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...
- 国产深度(deepin)操作系统优化指南
-
1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...
- postgresql-15.4 多节点主从(读写分离)
-
1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...
- Docker 容器 Java 服务内存与 GC 优化实施方案
-
一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...
- 虚拟内存设置、解决linux内存不够问题
-
虚拟内存设置(解决linux内存不够情况)背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...
- Elasticsearch性能调优(5):服务器配置选择
-
在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...
- Es如何落地
-
一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...
- 针对Linux内存管理知识学习总结
-
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...
- MySQL进阶之性能优化
-
概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...
- Linux Cgroups(Control Groups)原理
-
LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...
- linux 常用性能优化参数及理解
-
1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...
- 如何在 Linux 中使用 Sysctl 命令?
-
sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)