一、概述
Jenkins,原名Hudson, 2011 年改为现在的名字,它 是一个开源的实现持续集成的软件工具。官方网站:http://jenkins-ci.org/。 Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图表的形式形象地展示项目构建的趋势和稳定性。 特点:
- 易安装:仅仅一个 java - jar jenkins.war,从官网下载该文件后,直接运行,无需额外的安装,更无需安装数据库;
- 易配置:提供友好的GUI配置界面; 变更支持:Jenkins能从代码仓库(Subversion/CVS)中获取并产生代码更新列表并输出到编译输出信息中;
- 支持永久链接:用户是通过web来访问Jenkins的,而这些web页面的链接地址都是永久链接地址,因此,你可以在各种文档中直接使用该链接; 集成E-Mail/RSS/IM:当完成一次集成时,可通过这些工具实时告诉你集成结果(据我所知,构建一次集成需要花费一定时间,有了这个功能,你就可以在等待结果过程中,干别的事情);
- JUnit/TestNG测试报告:也就是用以图表等形式提供详细的测试报表功能;
- 支持分布式构建:Jenkins可以把集成构建等工作分发到多台计算机中完成;
- 文件指纹信息:Jenkins会保存哪次集成构建产生了哪些jars文件,哪一次集成构建使用了哪个版本的jars文件等构建记录;
- 支持第三方插件:使得 Jenkins 变得越来越强大
1.1 持续集成流程说明
1)首先,开发人员每天进行代码提交,提交到Git仓库
2)然后,Jenkins作为持续集成工具,使用Git工具到Git仓库拉取代码到集成服务器,再配合JDK,Maven等软件完成代码编译,代码测试与审查,测试,打包等工作,在这个过程中每一步出错,都重新再执行一次整个流程。
3)最后,Jenkins把生成的jar或war包分发到测试服务器或者生产服务器,测试人员或用户就可以访问应用。
1.2 相关概念
软件开发生命周期:软件开发生命周期又叫做SDLC(Software Development Life Cycle),它是集合了计划、开发、测试和部署过程的集合
敏捷开发:敏捷开发(Agile Development) 的核心是迭代开发(Iterative Development) 与 增量开发(Incremental Development) 。
持续集成:持续集成( Continuous integration , 简称 CI )指的是,频繁地(一天多次)将代码集成到主干。**持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。**它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
二、页面操作
2.1 插件安装
以安装maven插件为例,演示插件的安装
( 1 )点击左侧的“系统管理”菜单 ,然后点击 管理插件
( 2 )选择“可选插件”选项卡,搜索maven,在列表中选择Maven Integration ,点击“直接安装”按钮
2.2 全局工具配置
- 在服务其中安装maven,配置本地仓库地址
- jenkin选择jdk配置,设置javahome路径 git配置 maven配置
2.3 用户权限管理
使用Role-based Authorization Strategy 插件来管理Jenkins用户权限
开启权限全局安全配置
Manage Jenkins -> Configure Global Security -> 授权策略切换为"Role-Based Strategy",保存
创建角色
在系统管理页面进入 Manage and Assign Roles -> 点击"Manage Roles"
Global roles(全局角色):管理员等高级用户可以创建基于全局的角色 Project roles(项目角色):针对某个或者某些项目的角色 Slave roles(奴隶角色):节点相关的权限
创建用户
在系统管理页面进入 Manage Users -》 新建用户
给用户分配角色
系统管理页面进入Manage and Assign Roles,点击Assign Roles
2.4 凭证管理
凭据可以用来存储需要密文保护的数据库密码、Gitlab密码信息、Docker私有仓库密码等,以便Jenkins可以和这些第三方的应用进行交互。
需要安装Credentials Binding插件,安装后,左侧会添加凭据菜单。
可以添加的凭证有5种:
Username with password:用户名和密码
SSH Username with private key:
使用SSH用户和密钥
- Secret fifile:需要保密的文本文件,使用时Jenkins会将文件复制到一个临时目录中,再将文件路径
- 设置到一个变量中,等构建结束后,所复制的Secret fifile就会被删除。
- Secret text:需要保存的一个加密的文本串,如钉钉机器人或Github的api token
- Certifificate:通过上传证书文件的方式
常用的凭证类型有:Username with password(用户密码)和SSH Username with private key(SSH密钥)
创建凭证
- 用户名密码
Jenkins->凭证->系统->全局凭证->添加凭证-》选择"Username with password",输入Gitlab的用户名和密码,点击"确定"。 即可获取Gitlab中的项目信息。
- SSH密钥类型
使用root用户生成公钥和私钥 ssh-keygen -t rsa id_rsa:私钥文件 id_rsa.pub:公钥文件
把生成的公钥放在Gitlab中 以root账户登录->点击头像->Settings->SSH Keys -》复制刚才id_rsa.pub文件的内容到这里,点击"Add Key"
在Jenkins中添加凭证,在Jenkins添加一个新的凭证,类型为"SSH Username with private key",把刚才生成私有文件内容复制过来
即可获取Gitlab中的项目信息
2.5 Maven配置
配置Maven的环境变量
sh# vi /etc/profile export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk export MAVEN_HOME=/opt/maven export PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin # 配置生效 source /etc/profile全局工具配置关联JDK和Maven
Jenkins->Global Tool Confifiguration->JDK->新增JDK-》添加jdk的home路径
Jenkins->Global Tool Confifiguration->Maven->新增Maven-》添加maven的路径
修改Maven的settings.xml
修改本地仓库地址和远程仓库。
验证
构建->增加构建步骤->Execute Shell -》 输入
mvn clean package
添加Jenkins全局变量
Manage Jenkins->Confifigure System->Global Properties
2.6 Tomcat安装和配置
配置Tomcat用户角色权限
默认情况下Tomcat是没有配置用户角色权限的,但是,后续Jenkins部署项目到Tomcat服务器,需要用到Tomcat的用户
sh# vi /tomcat/conf/tomcat-users.xml <tomcat-users> <role rolename="tomcat"/> <role rolename="role1"/> <role rolename="manager-script"/> <role rolename="manager-gui"/> <role rolename="manager-status"/> <role rolename="admin-gui"/> <role rolename="admin-script"/> <user username="tomcat" password="tomcat" roles="manager-gui,manager- script,tomcat,admin-gui,admin-script"/> </tomcat-users> # vi /opt/tomcat/webapps/manager/META-INF/context.xml # 注释以下内容 <!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
三、项目构建
3.1 常用构建触发器
Jenkins内置4种构建触发器:
触发远程构建
其他工程构建后触发(Build after other projects are build)
定时构建(Build periodically)
轮询SCM(Poll SCM)
触发远程构建
配置token值,当请求构建url:http://ip:端口/job/项目名/build?token=token值会进行项目构建
其他工程构建后触发
1)创建pre_job流水线工程 -》 2)配置需要触发的工程 -》 选择构建时的方式
定时构建
build periodically中配置 分 时 日 月 周
轮询SCM
轮询SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。
poll scm中配置定时扫描时间。
3.2 Git hook自动触发构建
利用Gitlab的webhook实现代码push到仓库,立即触发项目自动构建。
1)安装Gitlab Hook插件
2)Jenkins设置自动构建 把生成的webhook URL配置到Gitlab中。
3)Gitlab配置webhook
开启webhook功能
使用root账户登录到后台,点击Admin Area -> Settings -> Network勾选"Allow requests to the local network from web hooks and services"
在项目添加webhook
点击项目->Settings->Integrations 填写url 和pushevent
Manage Jenkins->Confifigure System关闭Enable authen...
Jenkins的参数化构建
- 在Jenkins添加选择类型参数
- 在pipeline中 通过${参数名}引用参数
配置邮箱服务器发送构建结果
1)安装Email Extension插件
2)Jenkins设置邮箱相关参数 Manage Jenkins->Configure System 配置邮件通知的相关信息,可发送测试邮件看配置是否存在问题。
3)准备邮件内容,html格式,将文件上传到gitlab,
4) 编写Jenkinsfile添加构建后发送邮件
pipeline {
agent any stages {
stage('拉取代码') {
steps { checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
stage('编译构建') {
steps { sh label: '', script: 'mvn clean package' } }
stage('项目部署') {
steps {deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f- b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war' } } }
post {
always {
emailext( subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}!', body: '${FILE,path="email.html"}', to: 'xxx@qq.com' ) } } }PS:邮件相关全局参数参考列表:系统设置->Extended E-mail Notification->Content Token Reference,点击旁边的?号
四、代码审查SonarQube
SonarQube是一个用于管理代码质量的开放平台,可以快速的定位代码中潜在的或者明显的错误。目前支持java,C#,C/C++,Python,PL/SQL,Cobol,JavaScrip,Groovy等二十几种编程语言的代码质量管理与检测。 官网:https://www.sonarqube.org/
4.1 安装SonarQube
安装:
yum install unzip
# 解压
<NolebasePageProperties />
unzip sonarqube-6.7.4.zip
# 创建目录
mkdir /opt/sonar
# 移动文件
mv sonarqube-6.7.4/* /opt/sonar
# 创建sonar用户,必须sonar用于启动,否则报错
useradd sonar
# 更改sonar目录及文件权限
chown -R sonar. /opt/sonar修改sonar配置文件
# vi /opt/sonarqube-6.7.4/conf/sonar.properties
sonar.jdbc.username=root sonar.jdbc.password=Root@123
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=
maxPerformance&useSSL=false注意:sonar默认监听9000端口,如果9000端口被占用,需要更改
启动sonar
cd /opt/sonarqube-6.7.4
# 启动
su sonar ./bin/linux-x86-64/sonar.sh start
# 查看状态
su sonar ./bin/linux-x86-64/sonar.sh status
# 停止
su sonar ./bin/linux-x86-64/sonar.sh stop
# 查看日志
tail -f logs/sonar.logs访问sonar http://ip:9000 默认账户:admin/admin
4.2 与jenkins集成
1)创建sonar的token
2)安装SonarQube Scanner插件
3)添加SonarQube凭证 选择Secret text类型
4)Jenkins进行SonarQube配置 Manage Jenkins->Confifigure System->SonarQube servers 配置名称和地址
5)Manage Jenkins->Global Tool Configuration,选择自动安装及版本呢
6)SonaQube关闭审查结果上传到SCM功能 SCM-》Administration->打开Disable the scm sensor
7)在项目添加SonaQube代码审查
非流水线项目
properties# must be unique in a given SonarQube instance sonar.projectKey=web_demo # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=web_demo sonar.projectVersion=1.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # This property is optional if sonar.modules is set. sonar.sources=. sonar.exclusions=**/test/**,**/target/** sonar.java.source=1.8 sonar.java.target=1.8 # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8在项目添加SonaQube代码审查(流水线项目)
项目根目录下,创建sonar-project.properties文件
properties# must be unique in a given SonarQube instance sonar.projectKey=web_demo_pipline # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=web_demo_pipline sonar.projectVersion=1.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # This property is optional if sonar.modules is set. sonar.sources=. sonar.exclusions=**/test/**,**/target/** sonar.java.source=1.8 sonar.java.target=1.8 # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8修改Jenkinsfifile,加入SonarQube代码审查阶段
jsonpipeline { agent any stages { stage('拉取代码') { steps { checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]]) } } stage('编译构建') { steps { sh label: '', script: 'mvn clean package' } } stage('SonarQube代码审查') { steps{ script { scannerHome = tool 'sonarqube-scanner' } withSonarQubeEnv('sonarqube6.7.4') { sh "${scannerHome}/bin/sonar-scanner" } } } stage('项目部署') { steps { deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f- b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war' } } } post { always { emailext( subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}!', body: '${FILE,path="email.html"}', to: '1014671449@qq.com' ) } } }8)到SonarQube的UI界面查看审查结果
五、构建maven项目
Jenkins中自动构建项目的类型有很多,常用的有以下三种:
自由风格软件项目(FreeStyle Project)
Maven项目(Maven Project)
流水线项目(Pipeline Project)
推荐使用流水线类型,因为灵活度非常高
5.1 自由风格软件项目
1)创建项目
2)配置源码管理,从gitlab拉取代码
3)编译打包 构建->添加构建步骤->Executor Shell
echo "开始编译和打包"
mvn clean package
echo "编译和打包结束"4)部署 把项目部署到远程的Tomcat里面
安装 Deploy to container插件 -》 添加Tomcat用户凭证 -》 添加构建后操作 -》 选择 Deploy war...
5.2 Maven项目构建
1)安装Maven Integration插件
2)创建Maven项目
3)配置项目 bulid中配置pom.xml的路径 及maven的打包命令 clean package mvn前缀不需要添加
5.3 Pipeline流水线项目构建
Pipeline,简单来说,就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
Pipeline 脚本是由 Groovy 语言实现的,但是我们没必要单独去学习 GroovyPipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)语法Pipeline 也有两种创建方法:可以直接在 Jenkins 的 Web UI 界面中输入脚本;也可以通过创建一个 Jenkinsfifile 脚本文件放入项目源码库中(一般我们都推荐在 Jenkins 中直接从源代码控制(SCM)中直接载入 Jenkinsfifile Pipeline 这种方法)。
安装Pipeline插件
Manage Jenkins->Manage Plugins->可选插件 -》 Pipeline
Declarative声明式-Pipeline
创建项目-》 流水线->选择HelloWorld模板
生成内容如下:
pipeline {
agent any
stages {
stage('拉取代码') {
steps { echo '拉取代码' }
}
stage('编译构建') {
steps { echo '编译构建' }
}
stage('项目部署') {
steps { echo '项目部署' }
}
}
}stages:代表整个流水线的所有执行阶段。通常stages只有1个,里面包含多个stage
stage:代表流水线中的某个阶段,可能出现n个。一般分为拉取代码,编译构建,部署等阶段。
steps:代表一个阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等任意内容。
Scripted Pipeline脚本式
创建项目 - > 流水线 -》 选择"Scripted Pipeline"
pipeline {
agent any stages {
stage('拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
}
}
stage('编译构建') {
steps { sh label: '', script: 'mvn clean package' }
}
stage('项目部署') {
steps {
deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f- b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war'
}
}
}
}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 命令一样。
Pipeline Script from SCM
1)在项目根目录建立Jenkinsfifile文件,把pipeline脚本存在文件中
2) 构建时流水线选择Pipeline Script from SCM,然后选择pipeline脚本的路径。
六、Jenkins+Docker+SpringCloud微服务持续集成
6.1 持续集成流程
1)开发人员每天把代码提交到Gitlab代码仓库
2)Jenkins从Gitlab中拉取项目源码,编译并打成jar包,然后构建成Docker镜像,将镜像上传到
Harbor私有仓库。
3)Jenkins发送SSH远程命令,让生产部署服务器到Harbor私有仓库拉取镜像到本地,然后创建容器。
4)最后,用户可以访问到容器
6.2 使用Dockerfile编译、生成镜像
利用dockerfile-maven-plugin插件构建Docker镜像
1)在每个微服务项目的pom.xml加入dockerfile-maven-plugin插件
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>2)在每个微服务项目根目录下建立Dockerfile文件
#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java","-jar","/app.jar"]3)修改Jenkinsfile构建脚本 通过docker构建并上传到Harbor
需要再jenkinx中创建harbor的凭证
//gitlab的凭证
def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.66.102:85/tensquare/"
node {
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'git@192.168.66.100:itheima_group/tensquare_back.git']]]) }
stage('代码审查') {
def scannerHome = tool 'sonarqube-scanner'
withSonarQubeEnv('sonarqube6.7.4') {
sh """ cd ${project_name} ${scannerHome}/bin/sonar-scanner """ } }
stage('编译,构建镜像') {
//定义镜像名称
def imageName = "${project_name}:${tag}"
//编译,安装公共工程
sh "mvn -f tensquare_common clean install"
//编译,构建本地镜像
sh "mvn -f ${project_name} clean package dockerfile:build"
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" }
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}" }6.3 拉取镜像和发布应用
安装 Publish Over SSH 插件,可以实现远程发送Shell命令
1)拷贝公钥到远程服务器
2)系统配置->添加远程服务器
3)修改Jenkinsfile构建脚本
//gitlab的凭证
def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.66.102:85"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "ef499f29-f138-44dd-975e-ff1ca1d8c933"
node {
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'git@192.168.66.100:itheima_group/tensquare_back.git']]]) }
stage('代码审查') {
def scannerHome = tool 'sonarqube-scanner'
withSonarQubeEnv('sonarqube6.7.4') {
sh """ cd ${project_name} ${scannerHome}/bin/sonar-scanner """ } }
stage('编译,构建镜像,部署服务') {
//定义镜像名称
def imageName = "${project_name}:${tag}"
//编译并安装公共工程
sh "mvn -f tensquare_common clean install"
//编译,构建本地镜像
sh "mvn -f ${project_name} clean package dockerfile:build"
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" }
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) } }编写deploy.sh部署脚本,放到/opt/jenkins_shell目录下,且文件至少有执行权限
#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
imageName=$harbor_url/$harbor_project_name/$project_name:$tag
echo "$imageName"
#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
#停掉容器
docker stop $containerId
#删除容器
docker rm $containerId
echo "成功删除容器"
fi
#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name | awk '{print $3}'`
if [ "$imageId" != "" ] ; then
#删除镜像
docker rmi -f $imageId
echo "成功删除镜像"
fi
# 登录Harbor
docker login -u eric -p Eric123456 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $port:$port $imageName
echo "容器启动成功"6.4 部署前端静态web网站
前提:安装nginx、关闭se-linux
安装NodeJS插件 Manage Jenkins->Global Tool Configuration
创建前端流水线项目
建立Jenkinsfile构建脚本
json//gitlab的凭证 def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8" node { stage('拉取代码') { checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'git@192.168.66.100:itheima_group/tensquare_front.git']]]) } stage('打包,部署网站') { //使用NodeJS的npm进行打包 nodejs('nodejs12'){ sh '''npm install npm run build ''' } //=====以下为远程调用进行项目部署======== sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/usr/share/nginx/html', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) } }
6.5 同时构建多个项目并部署到多个服务器
设计Jenkins集群项目的构建参数
1)安装Extended Choice Parameter插件
2)创建流水线项目
3)添加参数 添加分支名称 和项目多选框 ,多选框可配置描述和默认选项
tensquare_eureka_server@10086,tensquare_zuul@10020,tensquare_admin_service@9001, tensquare_gathering@90024)完成微服务构建镜像,上传私服
//gitlab的凭证
def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.66.102:85"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "ef499f29-f138-44dd-975e-ff1ca1d8c933"
node {
//把选择的项目信息转为数组
def selectedProjects = "${project_name}".split(',')
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '${git_auth}', url: 'git@192.168.66.100:itheima_group/tensquare_back_cluster.git']]]) }
stage('代码审查') {
def scannerHome = tool 'sonarqube-scanner'
withSonarQubeEnv('sonarqube6.7.4') {
for(int i=0;i<selectedProjects.size();i++){
//取出每个项目的名称和端口
def currentProject = selectedProjects[i];
//项目名称
def currentProjectName = currentProject.split('@')[0]
//项目启动端口
def currentProjectPort = currentProject.split('@')[1]
sh """cd ${currentProjectName} ${scannerHome}/bin/sonar-scanner """
echo "${currentProjectName}完成代码审查" } } }
stage('编译,构建镜像,部署服务') {
//编译并安装公共工程
sh "mvn -f tensquare_common clean install"
for(int i=0;i<selectedProjects.size();i++){
//取出每个项目的名称和端口
def currentProject = selectedProjects[i];
//项目名称
def currentProjectName = currentProject.split('@')[0]
//项目启动端口
def currentProjectPort = currentProject.split('@')[1]
//定义镜像名称
def imageName = "${currentProjectName}:${tag}"
//编译,构建本地镜像
sh "mvn -f ${currentProjectName} clean package dockerfile:build"
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" }
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
//=====以下为远程调用进行项目部署========
//sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deployCluster.sh $harbor_url $harbor_project_name $currentProjectName $tag $currentProjectPort", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo "${currentProjectName}完成编译,构建镜像" } } }微服务多服务器远程发布
1)拷贝公钥到远程服务器
2)系统配置->添加远程服务器
3)修改Docker配置信任Harbor私服地址 重启Docker
4) 添加部署服务器多选框
5)修改Jenkinsfile构建脚本
//gitlab的凭证
def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.66.102:85"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "ef499f29-f138-44dd-975e-ff1ca1d8c933"
node {
//把选择的项目信息转为数组
def selectedProjects = "${project_name}".split(',')
//把选择的服务区信息转为数组
def selectedServers = "${publish_server}".split(',')
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '${git_auth}', url: 'git@192.168.66.100:itheima_group/tensquare_back_cluster.git']]]) }
stage('代码审查') {
def scannerHome = tool 'sonarqube-scanner'
withSonarQubeEnv('sonarqube6.7.4') {
for(int i=0;i<selectedProjects.size();i++){
//取出每个项目的名称和端口
def currentProject = selectedProjects[i];
//项目名称
def currentProjectName = currentProject.split('@')[0]
//项目启动端口
def currentProjectPort = currentProject.split('@')[1]
sh """cd ${currentProjectName} ${scannerHome}/bin/sonar-scanner """
echo "${currentProjectName}完成代码审查" } } }
stage('编译,构建镜像,部署服务') {
//编译并安装公共工程
sh "mvn -f tensquare_common clean install"
for(int i=0;i<selectedProjects.size();i++){
//取出每个项目的名称和端口
def currentProject = selectedProjects[i];
//项目名称
def currentProjectName = currentProject.split('@')[0]
//项目启动端口
def currentProjectPort = currentProject.split('@')[1]
//定义镜像名称
def imageName = "${currentProjectName}:${tag}"
//编译,构建本地镜像
sh "mvn -f ${currentProjectName} clean package dockerfile:build"
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" }
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
//=====以下为远程调用进行项目部署========
for(int j=0;j<selectedServers.size();j++){
//每个服务名称
def currentServer = selectedServers[j]
//添加微服务运行时的参数:
spring.profiles.active def activeProfile = "--spring.profiles.active="
if(currentServer=="master_server"){
activeProfile = activeProfile+"eureka-server1"
}else if(currentServer=="slave_server1"){
activeProfile = activeProfile+"eureka-server2"
}
sshPublisher(publishers: [sshPublisherDesc(configName: "${currentServer}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deployCluster.sh $harbor_url $harbor_project_name $currentProjectName $tag $currentProjectPort $activeProfile", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) }
echo "${currentProjectName}完成编译,构建镜像" } } }6)编写deployCluster.sh部署脚本
#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
profile=$6
imageName=$harbor_url/$harbor_project_name/$project_name:$tag
echo "$imageName"
#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
#停掉容器
docker stop $containerId
#删除容器
docker rm $containerId
echo "成功删除容器"
fi
#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name | awk '{print $3}'`
if [ "$imageId" != "" ] ; then
#删除镜像
docker rmi -f $imageId
echo "成功删除镜像"
fi
# 登录Harbor
docker login -u eric -p Eric123456 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $port:$port $imageName $profile
echo "容器启动成功"七、基于Kubernetes/K8S构建Jenkins持续集成平台
7.1 Jenkins的Master-Slave分布式构建
Jenkins的Master-Slave分布式构建,就是通过将构建过程分配到从属Slave节点上,从而减轻Master节点的压力,而且可以同时构建多个,有点类似负载均衡的概念。
实现分布式构建
1)开启代理程序的TCP端口 Manage Jenkins -> Configure Global Security -》代理——》 随机选取
2)新建节点 Manage Jenkins—Manage Nodes—新建节点
安装和配置节点
下载agent.jar,并上传到Slave节点,然后执行页面提示的命令:
java -jar agent.jar -jnlpUrl http://192.168.66.101:8888/computer/slave1/slave- agent.jnlp -secret f2ecbb99e0c81331e8b7a7917a94d478f39cb9763fc6c66d9a9741c61f9ae6d6 -workDir "/root/jenkins"7.2 Kubernetes实现Master-Slave分布式构建方案
NFS安装
NFS(Network File System),它最大的功能就是可以通过网络,让不同的机器、不同的操作系统可以共享彼此的文件。我们可以利用NFS共享Jenkins运行的配置文件、Maven的仓库依赖文件等
1)安装NFS服务(在所有K8S的节点都需要安装)
yum install -y nfs-utils2)创建共享目录
mkdir -p /opt/nfs/jenkins
vi /etc/exports
# 编写NFS的共享配置 内容如下:
# *代表对所有IP都开放此目录,rw是读写
/opt/nfs/jenkins *(rw,no_root_squash)3)启动服务
# 开机启动
systemctl enable nfs
# 启动
systemctl start nfs4)查看NFS共享目录
showmount -e 192.168.66.1017.3 在Kubernetes安装Jenkins-Master
创建NFS client provisioner
nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储。
1)上传nfs-client-provisioner构建文件 修改deployment.yaml,使用之前配置NFS服务器和目录
# class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "true"# deployment.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: lizhenliang/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 192.168.66.101
- name: NFS_PATH
value: /opt/nfs/jenkins/
volumes:
- name: nfs-client-root
nfs:
server: 192.168.66.101
path: /opt/nfs/jenkins/# rbac.yaml
kind: ServiceAccount
apiVersion: v1
metadata:
name: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io2)构建nfs-client-provisioner的pod资源
cd nfs-client
kubectl create -f .3)查看pod是否创建成功
安装Jenkins-Master
1)上传Jenkins-Master构建文件
# rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
namespace: kube-ops
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: jenkins
namespace: kube-ops
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: kube-ops
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkinsClusterRole
namespace: kube-ops
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: jenkinsClusterRuleBinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkinsClusterRole
subjects:
- kind: ServiceAccount
name: jenkins
namespace: kube-ops# Service.yaml
apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: kube-ops
labels:
app: jenkins
spec:
selector:
app: jenkins
type: NodePort
ports:
- name: web
port: 8080
targetPort: web
- name: agent
port: 50000
targetPort: agent# ServiceaAcount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: kube-ops# StatefulSet.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: jenkins
labels:
name: jenkins
namespace: kube-ops
spec:
serviceName: jenkins
selector:
matchLabels:
app: jenkins
replicas: 1
updateStrategy:
type: RollingUpdate
template:
metadata:
name: jenkins
labels:
app: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccountName: jenkins
containers:
- name: jenkins
image: jenkins/jenkins:lts-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 0.5
memory: 500Mi
env:
- name: LIMITS_MEMORY
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Mi
- name: JAVA_OPTS
value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
securityContext:
fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: jenkins-home
spec:
storageClassName: "managed-nfs-storage"
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi在StatefulSet.yaml文件,声明了利用nfs-client-provisioner进行Jenkins-Master文件存储
Service发布方法采用NodePort,会随机产生节点访问端口
2)创建kube-ops的namespace
kubectl create namespace kube-ops3)构建Jenkins-Master的pod资源
cd jenkins-master
kubectl create -f .4)查看pod是否创建成功
kubectl get pods -n kube-ops5)查看信息,并访问
kubectl describe pods -n kube-ops
# 查看分配端口
kubectl get service -n kube-ops7.4 Jenkins与Kubernetes整合
1)安装Kubernetes插件 系统管理->插件管理->可选插件
2)实现Jenkins与Kubernetes整合 系统管理->系统配置->云->新建云->Kubernetes
kubernetes地址采用了kube的服务器发现:https://kubernetes.default.svc.cluster.local
namespace填kube-ops,然后点击Test Connection,如果出现 Connection test successful 的提示信息证明 Jenkins 已经可以和 Kubernetes 系统正常通信 Jenkins URL 地址:http://jenkins.kube-ops.svc.cluster.local:8080
构建Jenkins-Slave自定义镜像
Dockerfile文件内容如下:
FROM jenkins/jnlp-slave:latest
MAINTAINER itcast
# 切换到 root 账户进行操作
USER root
# 安装 maven
COPY apache-maven-3.6.2-bin.tar.gz .
RUN tar -zxf apache-maven-3.6.2-bin.tar.gz && \
mv apache-maven-3.6.2 /usr/local && \
rm -f apache-maven-3.6.2-bin.tar.gz && \
ln -s /usr/local/apache-maven-3.6.2/bin/mvn /usr/bin/mvn && \
ln -s /usr/local/apache-maven-3.6.2 /usr/local/apache-maven && \
mkdir -p /usr/local/apache-maven/repo
COPY settings.xml /usr/local/apache-maven/conf/settings.xml
USER jenkins构建出一个新镜像:jenkins-slave-maven:latest
然把镜像上传到Harbor的公共库library中
docker tag jenkins-slave-maven:latest 192.168.66.102:85/library/jenkins-slave- maven:latest
docker push 192.168.66.102:85/library/jenkins-slave-maven:latest测试Jenkins-Slave的流水线项目
def git_address = "http://192.168.66.100:82/itheima_group/tensquare_back_cluster.git"
def git_auth = "9d9a2707-eab7-4dc9-b106-e52f329cbc95"
//创建一个Pod的模板,label为jenkins-slave
podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
containerTemplate(
name: 'jnlp',
image: "192.168.66.102:85/library/jenkins-slave-maven:latest"
)
]
)
{
//引用jenkins-slave的pod模块来构建Jenkins-Slave的pod
node("jenkins-slave"){
// 第一步
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: 'master']], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
}
}
}7.5 Jenkins+Kubernetes+Docker完成微服务持续集成
1)创建NFS共享目录 让所有Jenkins-Slave构建指向NFS的Maven的共享仓库目录
vi /etc/exports
# 添加内容:
/opt/nfs/jenkins *(rw,no_root_squash)
/opt/nfs/maven *(rw,no_root_squash)
# 重启NFS
systemctl restart nfs2)创建项目,编写构建Pipeline
def git_address = "http://192.168.66.100:82/itheima_group/tensquare_back_cluster.git"
def git_auth = "9d9a2707-eab7-4dc9-b106-e52f329cbc95"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.66.102:85"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "71eff071-ec17-4219-bae1-5d0093e3d060"
def secret_name = "registry-auth-secret"
//k8s凭证
def k8s_auth = "c5fe8670-f5a7-4b1a-811c-48ab5de2aed9";
podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
containerTemplate(
name: 'jnlp',
image: "192.168.66.102:85/library/jenkins-slave-maven:latest"
),
containerTemplate(
name: 'docker',
image: "docker:stable",
ttyEnabled: true,
command: 'cat'
),
],
volumes: [
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
nfsVolume(mountPath: '/usr/local/apache-maven/repo', serverAddress: '192.168.66.101' , serverPath: '/opt/nfs/maven'),
],
)
{
node("jenkins-slave"){
// 第一步
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: '${branch}']], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
}
// 第二步
stage('代码编译'){
//编译并安装公共工程
sh "mvn -f tensquare_common clean install"
}
// 第三步
stage('构建镜像,部署项目'){
//把选择的项目信息转为数组
def selectedProjects = "${project_name}".split(',')
for(int i=0;i<selectedProjects.size();i++){
//取出每个项目的名称和端口
def currentProject = selectedProjects[i];
//项目名称
def currentProjectName = currentProject.split('@')[0]
//项目启动端口
def currentProjectPort = currentProject.split('@')[1]
//定义镜像名称
def imageName = "${currentProjectName}:${tag}"
//编译,构建本地镜像
sh "mvn -f ${currentProjectName} clean package dockerfile:build"
container('docker') {
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
}
def deploy_image_name = "${harbor_url}/${harbor_project_name}/${imageName}"
//部署到K8S
sh """
sed -i 's#\$IMAGE_NAME#${deploy_image_name}#' ${currentProjectName}/deploy.yml
sed -i 's#\$SECRET_NAME#${secret_name}#' ${currentProjectName}/deploy.yml
"""
kubernetesDeploy configs: "${currentProjectName}/deploy.yml", kubeconfigId: "${k8s_auth}"
}
}
}
}3)建立k8s认证凭证
kubeconfig到k8s的Master节点复制 cat /root/.kube/config
4)生成Docker凭证
Docker凭证,用于Kubernetes到Docker私服拉取镜像
#登录Harbor
docker login -u itcast -p Itcast123 192.168.66.102:85
# 生成
kubectl create secret docker-registry registry-auth-secret --docker- server=192.168.66.102:85 --docker-username=itcast --docker-password=Itcast123 -- docker-email=itcast@itcast.cn
# 查看密钥
kubectl get secret5)在每个项目下建立deploy.yml
---
apiVersion: v1
kind: Service
metadata:
name: eureka
labels:
app: eureka
spec:
type: NodePort
ports:
- port: 10086
name: eureka
targetPort: 10086
selector:
app: eureka
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: eureka
spec:
serviceName: "eureka"
replicas: 2
selector:
matchLabels:
app: eureka
template:
metadata:
labels:
app: eureka
spec:
imagePullSecrets:
- name: $SECRET_NAME
containers:
- name: eureka
image: $IMAGE_NAME
ports:
- containerPort: 10086
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: EUREKA_SERVER
value: "http://eureka-0.eureka:10086/eureka/,http://eureka-1.eureka:10086/eureka/"
- name: EUREKA_INSTANCE_HOSTNAME
value: ${MY_POD_NAME}.eureka
podManagementPolicy: "Parallel"6)项目构建后,查看服务创建情况
kubectl get pods -owide
kubectl get service八、安装
需安装jdk环境
8.1 常规安装
下载
wget https://pkg.jenkins.io/redhat/jenkins‐ 2. 83 ‐ 1. 1 .noarch.rpm安装
rpm ‐ivh jenkins‐ 2. 83 ‐ 1. 1 .noarch.rpm配置用户的端口
properties# /etc/sysconfig/jenkins JENKINS_USER="root" JENKINS_PORT="8888"启动服务
systemctl start jenkins访问
ip : 8888从 /var/lib/jenkins/secrets/initialAdminPassword中获取初始密码串跳过插件安装(Jenkins插件需要连接默认官网下载,速度非常慢)
创建管理员账户。
修改Jenkins插件下载地址
Jenkins->Manage Jenkins->Manage Plugins,点击Available
sh# cd /var/lib/jenkins/updates sed -i 's/http:\/\/updates.jenkinsci.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.jsonManage Plugins点击Advanced,把Update Site改为国内插件下载地址
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
Sumbit后,在浏览器输入:
http://192.168.66.101:8888/restart ,重启Jenkins。
8.2 插件安装
汉化插件
Jenkins->Manage Jenkins->Manage Plugins,点击Available,搜索"Chinese"