第一部分 Jenkins持续集成平台搭建
一、整体配置
大致流程说明:
- 开发人员把代码提交到Gitlab代码仓库
- Jenkins从Gitlab中拉取项目源码,编译并打成jar包,然后构建成Docker镜像,将镜像上传到Harbor私有仓库。
- Jenkins发送SSH远程命令,让生产部署服务器到Harbor私有仓库拉取镜像到本地,然后创建容器。
- 最后,用户可以访问到容器
二、代码托管平台搭建
2.1.GitLab安装及配置
1.安装相关依赖
yum -y install policycoreutils openssh-server openssh-clients postfix
2.启动ssh服务&设置为开机启动
systemctl enable sshd && sudo systemctl start sshd
3.设置postfix开机自启,并启动
systemctl enable postfix && systemctl start postfix
4.关闭防火墙
systemctl stop firewalld.service
5.下载GitLab包,并安装
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el6/gitlab-ce-12.4.2-ce.0.el6.x86_64.rpm
rpm -i gitlab-ce-12.4.2-ce.0.el6.x86_64.rpm
6.修改GitLab配置
vim /etc/gitlab/gitlab.rb
external_url 'http://192.168.1.220:8888'
nginx['listen_port'] = 8888
7.重载配置并启动GitLab
gitlab-ctl reconfigure
gitlab-ctl restart
在浏览器输入**http://192.168.1.220:8888
** 即可进行访问。
三、持续集成平台搭建
3.1.Jenkins安装及配置
3.1.安装JDK
yum install java-1.8.0-openjdk* -y
安装目录为:/usr/lib/jvm
3.2.安装Jenkins
1.获取Jenkins安装包
下载地址:https://jenkins.io/zh/download/
安装文件:jenkins-2.323-1.1.noarch.rpm
2.把安装包上传到**192.168.1.222
**,进行安装
rpm -ivh jenkins-2.323-1.1.noarch.rpm
3.修改Jenkins配置
vim /etc/syscofig/jenkins
JENKINS_USER="root
JENKINS_PORT="8080"
4.启动Jenkins
systemctl start jenkins
systemctl enable jenkins //开机自启
5.打开浏览器访问
6.获取admin账户密码
cat /var/lib/jenkins/secrets/initialAdminPassword
7.自定义Jenkins->安装推荐的插件
8.创建用户,直接下一步完成。
3.3.安装Git插件和Git工具
3.3.1.安装Git工具
yum install git -y
3.3.2.安装Git插件
3.3.3.Git访问配置
3.3.3.1.用户密码类型
Jenkins->凭证->系统->全局凭证->添加凭证选择"Username with password",输入Gitlab的用户名和密码,点击"确定"。
3.3.3.2.SSH密钥类型
1.使用root用户生成公钥和私钥
ssh-keygen -t rsa
2.把生成的公钥放在GitLab中
以root账户登录->点击头像->Settings->SSH Keys
复制刚才id_rsa.pub文件的内容到这里,点击"Add Key"
3.在Jenkins中添加凭证,配置私钥
在Jenkins添加一个新的凭证,类型为"SSH Username with private key",把刚才生成私有文件内容复制过来
3.3.4.Maven安装
1.先上传maven软件到**192.168.1.222
**中
#解压
tar -xzf apache-maven-3.6.3-bin.tar.gz
#创建maven安装目录
mkdir -p /usr/local/java/maven
#移动解压后的文件到安装目录
mv apache-maven-3.6.3/* /usr/local/java/maven
2.配置环境
vim /etc/profile
export JAVA_HOME=/usr/local/java/jdk1.8
export MAVEN_HOME=/usr/local/java/maven
export PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin
#重载配置文件
source /etc/profile
3.3.5.Docker安装
1.卸载旧版本
#列出当前所有docker的包
yum list installed | grep docker
#卸载docker包
yum -y remove docker的包名称
#删除docker的所有镜像和容器
rm -rf /var/lib/docker
2.安装必要软件包
sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
3.设置下载的镜像仓库
sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
4.安装docker
sudo yum install docker-ce-20.10.11.ce
5.启动Docker
#启动
sudo systemctl start docker
#设置开机启动
sudo systemctl enable docker
6.添加阿里云镜像加速地址
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://xmgk9z80.mirror.aliyuncs.com"],
/*
添加Harbor地址到Docker的信任列表,不加后续的镜像上传及拉取会有问题
The push refers to repository [xxx.xxx.xxx.xxx:xx/xx/xx] Get https://xxx.xxx.xxx.xxx:xx/xx/: http: server gave HTTP response to HTTPS client
*/
"insecure-registries": ["192.168.1.221:81"]
}
7.重启Docker
sudo systemctl restart docker
3.4.配置JDK、Maven环境
1.配置JDK环境
2.配置maven环境
在后续Jenkins构建的时候会出现无法找到jdk和maven,需要创建软连接
ln -s /usr/local/java/jdk1.8/bin/java /usr/bin/java
ln -s /usr/local/java/apache-maven-3.6.3/bin/mvn /usr/bin/mvn
3.2.安装SonarQube
3.2.1.安装MySQL数据库
1.下载官方repo
wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
2.安装
yum -y install mysql57-community-release-el7-10.noarch.rpm
3.安装MySQL服务器
yum -y install mysql-community-server
4.启动MySQL
systemctl start mysqld.service
5.查找root用户密码
grep "password" /var/log/mysqld.log
6.修改root密码
# 进入数据库
mysql -uroot -p
#修改密码
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
#开启远程访问
grant all privileges on *.* to 'root'@'%' identified by 'password' with grant option;
#刷新MySQL的系统权限相关表
flush privileges;
7.修改MySQL编码
vim /etc/my.cnf
[client]
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci
8.重启MySQL
systemctl restart mysqld.servie
3.2.2.安装SonarQube
1.在MySQL数据库中创建sonar数据库
2.下载SonarQube安装包
https://www.sonarqube.org/downloads/
3.将安装包上传到**192.168.1.222
**
4.解压并设置权限
#安装unzip
yum install unzip
#解压
unzip sonarqube-6.7.4.zip
#创建目录
mkdir /usr/local/java/sonar
#移动文件
mv sonarqube-6.7.4/* /usr/local/java/sonar
#创建sonar用户,必须sonar用于启动,否则报错
useradd sonar
#更改sonar目录及文件权限
chown -R sonar. /usr/local/java/sonar
5.修改sonar配置文件
vim /usr/local/java/sonar/conf/sonar.properties
sonar.jdbc.username=root
sonar.jdbc.password=xxxxxx
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
6.启动sonar
cd /usr/local/java/sonar
#启动
su sonar ./bin/linux-x86-64/sonar.sh start
7.访问sonar
默认账户密码:admin/admin
8.创建token
token一定要记下来,配置需要使用
3.2.3.安装SonarQube Scanner插件
1.安装插件
2.添加SonarQube凭证
3.在Jenkins中配置SonarQube
4.SonarQube关闭审查结构上传到SCM功能
3.3部署应用环境搭建
1.安装Publish Over SSH插件
2.拷贝公钥到远程服务器
#拷贝公钥到远程服务器
ssh-copy-id 192.168.66.103
3.在Jenkins中配置环境
四、Docker仓库搭建
4.1.Harbor安装及配置
1.安装Docker
2.安装docker-compose,并添加执行权限
#安装docker-compose
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker- compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
#添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
3.下载Harbor安装包
https://github.com/goharbor/harbor/releases
4.上传安装包到**192.168.1.221
**,并解压
tar -xzf harbor-offline-installer-v1.9.2.tgz
mkdir /usr/local/java/harbor
mv harbor/* /usr/local/java/harbor
cd /usr/local/java/harbor
5.修改Harbor配置
vim harbor.yml
hostname: 192.168.1.221
port: 81
6.安装Harbor
./perpare
./install.sh
7.启动Harbor
docker-compose up -d
8.访问Harbor
默认账户密码:admin/Harbor12345
五、部署服务器搭建
5.1.安装Docker
安装步骤和上边一致
{
"registry-mirrors": ["https://xmgk9z80.mirror.aliyuncs.com"],
/*
添加Harbor地址到Docker的信任列表,不加后续的镜像上传及拉取会有问题
The push refers to repository [xxx.xxx.xxx.xxx:xx/xx/xx] Get https://xxx.xxx.xxx.xxx:xx/xx/: http: server gave HTTP response to HTTPS client
*/
"insecure-registries": ["192.168.1.221:81"]
}
第二部分 Jenkins持续集成平台使用
一、Jenkins部分
1.1.创建一个Item
1.2.配置Item
3.点击应用保存即可
这里我们测试Demo为前后端分离,一个后台代码,一个前端代码
二、代码部分
2.1.后台代码
2.1.1.pom文件添加依赖
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- dockerfile插件 -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
2.1.2.添加Dockerfile文件
在项目根目录添加名为**Dockerfile
**文件
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java", "-jar", "/app.jar"]
2.1.3.添加Jenkinsfile文件
在项目根目录添加名为**Jenkinsfile
**文件
内容根据自己项目进行修改
//项目分支
def branch = "master"
//gitlab平台jenkins凭证ID
def gitlab_auth = "801603ce-e268-4349-8b8e-6e517e1ea8be"
//代码仓库地址
def gitlab_url = "http://192.168.1.220:8888/root/jenkins-demo.git"
//Harbor平台jenkins凭证ID
def harbor_auth = "49867939-b8e4-4e4c-a230-71f724022575"
//Docker镜像仓库地址
def harbor_url = "192.168.1.221:81"
//Docker仓库项目名称
def harbor_project = "jenkins"
//应用镜像名称
def image_name = "jenkins-demo"
//镜像版本号
def tag = "latest"
//应用端口
def port = "10086"
//部署脚本地址
def shell_url = "/usr/local/java/jenkins_shell/deploy.sh"
try{
node {
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${gitlab_auth}", url: "${gitlab_url}"]]])
}
stage('编译打包,构建Dokcer镜像') {
//编译,构建本地镜像
sh "mvn clean package dockerfile:build"
}
stage('上传镜像到Docker仓库') {
//给镜像打标签
sh "docker tag ${image_name} ${harbor_url}/${harbor_project}/${image_name}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登录到Harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project}/${image_name}"
}
//删除本地镜像
sh "docker rmi -f ${image_name}"
sh "docker rmi -f ${harbor_url}/${harbor_project}/${image_name}"
}
stage('代码审查') {
//定义scanner工具
script {
scannerHome = tool 'scanner'
}
//执行SonarQubeScanner
withSonarQubeEnv('sonarqube') {
sh "${scannerHome}/bin/sonar-scanner"
}
}
stage('应用发布') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '${shell_url} ${harbor_url} ${harbor_project} ${image_name} ${tag} ${port}', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
catch (err){
currentBuild.result="FAILURE"
}
finally{
//构建后操作,发送构建结果到指定邮箱
node(env.BuildMachineLabel){
stage("发送邮件") {
emailext(
subject: '构建通知: ${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}!',
body: '${FILE, path="email-template.html"}',
to: 'xxxxxx@xx.xx'
)
}
}
}
2.1.4.添加邮件模板(随意)
文件名称根据流水线脚本来,我这里设置的是**email-template.html
**
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0">
<table width="95%" cellpadding="0" cellspacing="0"
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<td>(本邮件程序自动下发,请勿回复!)</td>
</tr>
<tr>
<td><h2>
<font color="#0000FF">构建结果 - ${BUILD_STATUS}</font>
</h2></td>
</tr>
<tr>
<td><br/>
<b><font color="#0B610B">构建信息</font></b>
<hr size="2" width="100%" align="center"/>
</td>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li>
<li>构建TAG : ${BUILD_TAG}</li>
<li>构建编号 : 第${BUILD_NUMBER}次构建</li>
<li>触发原因: ${CAUSE}</li>
<li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建 Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul>
</td>
</tr>
<tr>
<td><b><font color="#0B610B">Changes Since Last
Successful Build:</font></b>
<hr size="2" width="100%" align="center"/>
</td>
</tr>
<tr>
<td>
<ul>
<li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
</ul>
${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br/>%c<br/>",showPaths=true,changesFormat="
<pre>[%a]<br/>%m</pre>
",pathFormat=" %p"}
</td>
</tr>
<tr>
<td><b>Failed Test Results</b>
<hr size="2" width="100%" align="center"/>
</td>
</tr>
<tr>
<td><pre
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre>
<br/></td>
</tr>
<tr>
<td><b><font color="#0B610B">构建日志 (最后 100行):</font></b>
<hr size="2" width="100%" align="center"/>
</td>
</tr>
<tr>
<td><textarea cols="80" rows="30" readonly="readonly"
style="font-family: Courier New">${BUILD_LOG, maxLines=100}</textarea>
</td>
</tr>
</table>
</body>
</html>
2.2.前端部分
2.2.1.添加Jenkinsfile文件
在项目根目录添加名为**Jenkinsfile
**文件
//项目分支
def branch = "master"
//gitlab平台jenkins凭证ID
def gitlab_auth = "801603ce-e268-4349-8b8e-6e517e1ea8be"
//代码仓库地址
def gitlab_url = "http://192.168.1.220:8888/root/jenkins-ui.git"
node {
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${gitlab_auth}", url: "${gitlab_url}"]]])
}
stage('node安装及项目构建') {
nodejs('nodejs') {
sh '''
npm install
npm run build
'''
}
}
stage('项目部署') {
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)])
}
}
三、部署服务器部分
3.1.部署shell脚本
1.在服务器中创建一个目录,存放部署脚本
mkdir /usr/local/java/jenkins_shell
cd /usr/local/java/jenkins_shell
2.创建部署shell脚本
vim deploy.sh
#! /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 admin -p Harbor12345 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $port:$port $imageName
echo "容器启动成功"
3.为部署脚本添加执行权限
chmod +x deploy.sh
四、在Jenkins中进行构建
构建项目
构建日志控制台输出
邮件接收内容
grep -w $project_name | awk '{print $3}'` if [ "$imageId" != "" ] ; then #删除镜像 docker rmi -f $imageId echo "成功删除镜像" fi # 登录Harbor私服 docker login -u admin -p Harbor12345 $harbor_url # 下载镜像 docker pull $imageName # 启动容器 docker run -di -p $port:$port $imageName echo "容器启动成功" ```
3.为部署脚本添加执行权限
chmod +x deploy.sh
四、在Jenkins中进行构建
构建项目
构建日志控制台输出
邮件接收内容