1、部署 jenkins master 及多 slave 环境
2、基于 jenkins 视图对 jenkins job 进行分类
3、总结 jenkins pipline 基本语法
4、部署代码质量检测服务 sonarqube
5、基于命令、shell 脚本和 pipline 实现代码质量检测
1、部署jenkins master 及多slave环境
接上周作业,通过密钥实现对gitlab仓库免认证克隆到jenkins服务器
gitlab上添加生成的公钥
jenkins添加生成的私钥
添加jenkins slave节点
manager jenkins ->Manage nodes and clouds 新增slave节点
完成创建后,jenkins会通过ssh凭证远程发送jar文件,生产jenkins slave节点
创建slave节点如下
2、总结jenkins视图及job类型分类
在dashboar面板点击+号新建视图
视图类型如下
build pipeline view
选择job,定义pipeline build 布局 实测实际用途不大,
dashboard 面板视图,可以自定义布局,将默认dashboard内的job加入dashboard
视图可以在jenkins权限划分时使用,添加不同的用户组,根据不同用户组,划分不同视图的管理权限
权限分为:
全部:所有对象管理、读取权限。
凭据:创建、删除、管理域、更新、浏览权限。
代理:构建、配置、连接、创建、删除、断开连接等权限。
作业:构建、取消、配置、创建、删除、发现、读取、移动、工作目录权限。
运行:删除、回放、更新。
视图:配置、创建、删除、读取。
job类型分类
freestyle project 自由风格的软件项目
构建一个自由风格的软件项目:这是 Jenkins 的主要功能, Jenkins 将会结合任何 SCM 和任何构建系统来构建你的项目,甚至可以构建软件以外的系统。
pipeline 流水线 组织一个可以长期运行在多个节点上的任务。适用于构建流水线(更加正式地应当称为工作流),增加或者组织难以采用自由风格的任务类型。
优势:
- 可持续性:jenkins重启或中断不影响已执行的pipeline job
- 支持暂停:可以交互停止或批准后在继续执行
- 可扩展:通过groovy 更容易扩展产检
- 并行执行:可以实现step,stage间并行执行,提高构建效率
3、总结pipeline基本语法
定义在pipeline块中,主要包含阶段:
- stage阶段:一个pipeline可以划分为若干个stage,每个stage都是一个操作阶段,可以跨多个node执行不同的stage
- step: jenkins pipeline最基本的操作单元,一个stage可以有多个step。
- node: jenkins工作节点,可以是master,或slave,node是执行step的具体服务器
- 基于agent指令选择jenkins节点:
pipeline {
//agent any //可以是任何节点,jenkins按node节点配置,自动分配
agent none //表明pipeline脚本没有定义在默认执行的jenkins节点,后续每个stage中单独定义节点
//agent{label 'jenkins-ci'} //基于label标签指定具体执行的步骤节点
/*
agent{
node{
label 'jenkins-cd'
customWorkspace "/home/jenkins"
}
}
//node和label功能类似,都用于指定节点,node可以自定义工作目录
*/
stages {
stage('git clone'){
agent{
node{
label 'jenkins-cd'
customWorkspace "/home/jenkins"
}
}
steps{
sh 'echo git clone'
}
}
stage('deploy'){
agent any
steps{
sh 'echo 代码部署'
}
}
}
}
- 基于input指令实现的交互式操作
message:input界面提示信息,必选
id: input标识符,默认为stage名称可选
ok: 确认按钮的显示信息,可选
submitter:可选,允许提交操作的用用户或组名称
parameters:提供一个参数列表
pipeline {
agent any
stages {
stage('test'){
input{
message "是否继续部署"
ok "继续部署"
submitter "admin"
}
steps {
echo "hello jenkins!"
}
}
}
}
- post指令: 用于pipeline流水线执行后的进一步处理,执行成功和失败做什么处理
#always : 无论pipeline或stage执行成功或失败,都执行post中定义的指令
#changed: pipeline或stage完成状态与它之前的运行不同时,从成功转换为失败或失败转换成成功时执行
#fixed : pipeline或stage成功,且上一次构建是失败或不稳定时执行
#regression: pipeline或stage状态为失败 不稳定或终止 ,且上一次为成功
#failure: 只有当前pipeline 或stage 完成状态为失败时执行
#success: 执行状态为成功时执行,执行post步骤
#unstable: 当前状态不稳定,测试失败或代码违规使用,web界面标记黄色
#aborted: 终止执行,流水线被手动终止
#unsuccessful 当前状态只要不是success,执行该步骤
#cleanup 无论完成状态如何,都允许该post中定义的指令,在post其他条件之后执行
pipeline {
agent any
stages {
steps {
sh 'cd /data/x' //定义一个失败条件,触发失败后邮件通知
}
}
post {
cleanup {
echo "post cleanup --> 测试是否执行"
}
always {
echo "post always"
}
aborted {
echo "post aborted"
}
success {
script {
mail to: 'test@qq.com'
subject: "pipeline Name: ${currentBuild.fullDisplayName}",
body:"${env.JOB_NAME}-Build Number - ${env.BUILD_NAMUBER} - 构建成功!\n 点击链接 ${env.BUILD_URL} 查看详情"
}
}
failure {
script {
mail to: 'test@qq.com'
subject: "pipeline Name: ${currentBuild.fullDisplayName}",
body:"${env.JOB_NAME}-Build Number - ${env.BUILD_NAMUBER} - 构建失败!\n 点击链接 ${env.BUILD_URL} 查看详情"
}
}
}
}
- 基于environment传递环境变量
pipeline {
agent any
environment { //全局变量,在当前pipeline中所有stage都会生效
NAME = 'user1'
PASSWD = '123456'
}
stages {
stage('打印环境变量') {
environment {
DATE = '20230311' //定义在stage中的环境变量只会在当前stage中生效
}
steps {
sh """
echo "$NAME"
echo "$PASSWD"
echo "$DATE"
"""
}
}
stage('打印环境变量2') {
steps {
sh """
echo "$NAME"
echo "$PASSWD"
"""
}
}
}
}
正常打印
加上变量$DATE时报错
- 基于parameters给step传递参数
基于parameters自定义参数,用与执行pipeline传递给step使用
#string : 字符串类型参数,传递账户名、密码等
#text: 文本类型参数,用于定义多行文本
#boolean: 布尔型参数
#choice: 选择型参数,给定几个可选值,然后选择
#password: 密码类型变量,控制台显示为*
pipeline {
agent any
parameters {
string(name: 'BRANCH',defaultValue: 'develop',description:'分支选择')
choice(name: 'DEPLOY_ENV',choices:['develop','production'],description:'部署环境选择')
}
stages{
stage('test1') {
steps {
sh "echo $BRANCH"
}
}
stage('test2') {
steps {
sh "echo $DEPLOY_ENV"
}
}
}
}
- 基于if指令实现判断
pipeline {
agent any
parameters {
string(name: 'BRANCH',defaultValue: 'develop',description:'分支选择')
choice(name: 'DEPLOY_ENV',choices:['develop','production'],description:'部署环境选择')
}
stages{
stage('test1') {
steps {
sh "echo $BRANCH"
}
}
stage('test2') {
steps {
sh "echo $DEPLOY_ENV"
}
}
stage('if test') {
steps {
script {
if (BRANCH == 'main') {
echo '我是master'
} else if (BRANCH == 'develop') {
echo '我是develop'
} else {
echo '我是默认的'
}
}
}
}
}
}
- options选项配置参数
# buildDiscarder(logRotator(numToKeepStr: '5')) //保留5个历史构建版本
# timeout(time: 5, unit: 'MINUTES') //定义任务执行超时时间
#timestamps() //在控制台显示命令执行时间
#retry(2) //流水线构建失败后重试次数
4、部署代码质量检测服务 sonarqube
下载地址:https://www.sonarsource.com/products/sonarqube/downloads/
软件依赖:https://docs.sonarqube.org/8.9/requirements/requirements/
- postgresql安装
sudo apt update
apt-cache madison postgresql
apt install postgresql
- 安装java环境
apt install -y openjdk-11-jdk
java -version 检查Java版本
修改内核参数
vim /etc/sysctl.conf
vm.max_map_count=262144
kernel.pid_max=4194303
fs.file-max=1000000
sysctl -p - 部署sonarqube 8.9
mkdir /apps && cd /apps
首次登录成功,默认密码admin/admin
新建servercie文件 vim /etc/systemd/system/sonarqube.service
[Unit]
Description=SonarQube service
After=syslog.target network.target
[Service]
Type=simple
User=sonarqube
Group=sonarqube
PermissionsStartOnly=true
ExecStart=/bin/nohup /usr/bin/java -Xms1024m -Xmx1024m -Djava.net.preferIPv4Stack=true -jar
/apps/sonarqube/lib/sonar-application-8.9.10.61524.jar
StandardOutput=syslog
LimitNOFILE=131072
LimitNPROC=8192
TimeoutStartSec=5
Restart=always
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
5、 基于命令、shell 脚本和 pipline 实现代码质量检测
#!groovy
@Library('jenkins_sharelibray') _
import org.devops.*
def sonar = new org.devops.sonar()
def tools = new org.devops.tools()
pipeline {
//全局
agent {
label 'cd'
}
environment {
LANG="en_US.UTF-8"
GOPROXY = "https://mirrors.aliyun.com/goproxy/"
GOROOT="/usr/local/go"
PATH="$PATH:$GOROOT/bin"
PROJECTKEY = "$JOB_BASE_NAME" //sonarqube新建项目key
PROJECTNAME = "$JOB_BASE_NAME" //sonarqube新建项目名
USERTOKEN= "" //发送commit id 用户 token
}
options {
timestamps() //日志添加时间戳
}
stages {
//管道状态,其中之一:created, waiting_for_resource, preparing, pending, running, success, failed, canceled, skipped, manual,scheduled
stage("拉取代码") {
steps {
script {
echo "${env.gitlabSourceBranch}"
timeout(time: 1, unit: 'MINUTES') {
try {
tools.PrintMes("开始拉取Test分支代码","green")
checkout([$class: 'GitSCM', branches:
[[name: "origin/${branch}"]], doGenerateSubmoduleConfigurations: false,extensions: [],submoduleCfg: [],userRemoteConfigs:
[[credentialsId: "", url: "${GITLAB_URL}"]]])
updateGitlabCommitStatus name: 'Test分支代码拉取', state: 'success'
}catch(Exception err){
if(branch == "master"){
throw new Exception("测试环境禁止拉取master分支")
}
updateGitlabCommitStatus name: '代码拉取', state: 'failed'
tools.PrintMes("代码拉取失败",'red')
throw new Exception("代码拉取失败")
}
sh "git branch"
sh "go env"
}
}
}
}
stage("sonarqube analysis") {
steps {
echo 'sonarqube analysis start'
script {
scannerHome = tool 'sonarqube'
if(code == 'true') {
tools.PrintMes("进行代码质量检测",'green')
try {
sonar.PrintSonar(PROJECTKEY,PROJECTNAME,PROJECTID,USERTOKEN,branch)
withSonarQubeEnv('sonarqube-89') {sh "${scannerHome}/bin/sonar-scanner"}
timeout(time: 1, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
updateGitlabCommitStatus name: 'sonarqube analysis', state: 'success'
}catch(Exception err){
updateGitlabCommitStatus name: 'sonarqube analysis', state: 'failed'
throw new Exception("代码质量检测未通过")
}
}else{
updateGitlabCommitStatus name: 'stop code analysis',state: 'success'
}
}
}
}
stage("build") {
steps {
script {
echo "build success"
}
}
}
stage("deploy") {
steps {
echo "print env"
sh "printenv | sort"
script {
echo "deploy success"
}
}
}
}
post {
success {
echo 'success'
updateGitlabCommitStatus name: 'code cd', state: 'success'
//通知构建成功
qyWechatNotification mentionedId: '', mentionedMobile: '', webhookUrl: ''
echo 'clean up our workspace'
deleteDir()
}
failure {
//当此Pipeline失败时打印消息
echo 'false'
updateGitlabCommitStatus name: 'code cd', state: 'failed'
//通知构建失败
qyWechatNotification mentionedId: '', mentionedMobile: '', webhookUrl: ''
echo 'clean up our workspace'
deleteDir()
}
}
}