Devops

目的

本篇文章主要介绍Java代码从CI到CD的整个流程,帮助开发者在企业中自己实现代码自动化部署。

一、DevOps介绍

整体的软件开发流程包括:

  • PLAN:开发团队根据客户的目标制定开发计划
  • CODE:根据PLAN开始编码过程,需要将不同版本的代码存储在一个库中。
  • BUILD:编码完成后,需要将代码构建并且运行。
  • TEST:成功构建项目后,需要测试代码是否存在BUG或错误。
  • DEPLOY:代码经过手动测试和自动化测试后,认定代码已经准备好部署并且交给运维团队。
  • OPERATE:运维团队将代码部署到生产环境中。
  • MONITOR:项目部署上线后,需要持续的监控产品。
  • INTEGRATE:然后将监控阶段收到的反馈发送回PLAN阶段,整体反复的流程就是DevOps的核心,即持续集成、持续部署。
    2021-11-23_175935
    最终可以给DevOps下一个定义:DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件。

二、Code阶段工具

在code阶段,我们需要将不同版本的代码存储到一个仓库中,常见的版本控制工具就是SVN或者Git,这里我们采用Git作为版本控制工具,GitLab作为远程仓库。

2.1 Docker安装

镜像地址:http://hub.daocloud.io/

#1、下载Docker依赖组件
yum -y install yum-utils device-mapper-persistent-data lvm2

#2、设置下载Docker的镜像源为阿里云
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#3、安装Docker服务
yum -y install docker-ce

#4、安装成功后,启动Docker并设置开机自启
# 启动Docker服务
systemctl start docker
# 设置开机自动启动
systemctl enable docker

#5、测试安装成功
docker version

#6、配置docker加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://k1itnx3n.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

docker

2.2 Docker-Compose安装

docker编排工具

#1、准备阶段
docker version
docker-compose --version
#3、如果docker-compose,没有安装,则下载Docker-Compose:
#https://github.com/docker/compose/releases
#这里我们使用这个版本
wget https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-linux-x86_64

#4、将下载好的[docker-compose-linux-x86_64]文件移动到Linux操作系统
# 设置文件权限
chmod a+x docker-compose-linux-x86_64

#5、移动到/usr/bin目录下,并重命名为docker-compose
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose

#6、测试安装成功
docker-compose version
#虚拟机关闭防火墙,其他机器设置好安全组

docker-compose

2.3 Git安装

#1、安装相关依赖
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
#2、下载git
yum -y install git-core
#3、验证Git
git --version

git

2.4 GitLab安装

单独准备服务器,采用Docker安装

需要提前准备docker和安装docker-compose

#1、创建docker-compose目录,并且查看gitlab版本
cd /usr/local
mkdir docker
cd docker
mkdir gitlab_docker
cd gitlab_docker
docker search gitlab

#2、创建编排脚本
vi docker-compose.yml
#######################################################
version: '1.0'
services:
  gitlab:
    image: 'gitlab/gitlab-ce:latest'
    container_name: gitlab
    restart: always
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://192.168.86.112:8929' # web站点访问地址,同主机ip
        gitlab_rails['gitlab_shell_ssh_port'] = 2224
    ports:
      - '8929:8929'  # 注意宿主机和容器内部的端口要一致,否则external_url无法访问
      - '2224:2224'
    volumes:
      - './config:/etc/gitlab'
      - './logs:/var/log/gitlab'
      - './data:/var/opt/gitlab'
#######################################################

#3、拉取镜像
docker pull gitlab/gitlab-ce

#4、启动(在刚才创建的docker-compose.yml目录下)
docker-compose up -d
#查看日志
docker-compose logs -f

#5、访问GitLab首页,如果访问出现502重启
http://192.168.86.112:8929

#6、查看root用户初始密码
#进入gitlab查看密码(默认用户root)
docker exec -it gitlab cat /etc/gitlab/initial_root_password
#如果找不到密码,可以用下面命令修改密码(比如root密码修改成miracle123)
gitlab-rake "gitlab:password:reset"

三、Build阶段工具

构建Java项目的工具一般有两种选择,一个是Maven,一个是Gradle。
这里我们选择Maven作为项目的编译工具。

如果我们代码是maven管理,并且为了安全起见,企业都为搭建自己的maven私服,那么这个时候我们就需要安装nexus

3.1 JDK安装

JDK的作用主要是为了给需要再java环境下运行的工具,例如jenkins要打包部署java代码等

#1、下载jdk https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
#把下载后的jdk上传到如下目录
mkdir -p /u01/software
cd /u01/software/

#2、解压到local目录下,然后配置环境变量
tar -zxvf jdk-8u171-linux-x64.tar.gz -C /usr/local/
vim /etc/profile
#在文件末尾追加
export JAVA_HOME=/usr/local/jdk1.8.0_171/
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
#使环境变量生效,并且优化jdk
source /etc/profile
vi $JAVA_HOME/jre/lib/security/java.security
####################################
securerandom.source=file:/dev/./urandom
####################################

3.2 maven安装

#1、下载maven
wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.9.5/binaries/apache-maven-3.9.5-bin.tar.gz

#2、解压移动位置
tar -zxvf apache-maven-3.9.5-bin.tar.gz -C /usr/local/

#3、添加maven环境变量
vim /etc/profile
#在文件末尾追加
export MAVEN_HOME=/usr/local/apache-maven-3.9.5/
export PATH=$MAVEN_HOME/bin:$PATH
#使用环境变量生效
source /etc/profile

#4、验证
mvn -v

3.2 nexus3安装

安装方式有很多,这里我们选择用docker安装
另外nexus可以用普通用户启动,这里我们实验直接使用root用户

#1、下载镜像
docker pull sonatype/nexus3

#2、创建docker-compose目录
cd /usr/local/docker
mkdir nexus3_docker
cd nexus3_docker
#创建数据挂载目录并修改权限
mkdir -p /opt/nexus/data && chmod 777 /opt/nexus/data
vim docker-compose.yml 
#########################################
version: '1'
services:
  nexus:
    restart: always
    image: sonatype/nexus3
    container_name: nexus3
    ports:
      - 8081:8081
      - 5000:5000
      - 5001:5001
    volumes:
      - /opt/nexus/data:/nexus-data
#########################################

#3、启动nexus3
docker-compose up -d
#查看日志
docker-compose logs -f

#4、访问
#因为上面启动比较慢,建议等待一会,等日志出现Started Sonatype Nexus OSS ****代表启动成功
#另外也可以查看8081端口是否启动成功来查看
lsof -i:8081
#访问并且查看密码
http://192.168.86.112:8081/
#查看密码
cat /opt/nexus/data/admin.password
#登录进去修改root密码(admin/admin123)

如果登录后,日志报如下错误,关闭如下服务即可
System -> Capabilities -> Outreach: Management修改为disable

在这里插入图片描述

四、Integrate工具

持续集成、持续部署的工具很多,其中Jenkins是一个开源的持续集成平台。
Jenkins应用广泛,大多数互联网公司都采用Jenkins配合GitLab、Docker、K8s作为实现DevOps的核心工具。
Jenkins最强大的就在于插件,Jenkins官方提供了大量的插件库,来自动化CI/CD过程中的各种琐碎功能。

4.1 Jenkins安装

jenkins依赖java环境,提前需要安装jdk

CI/CD可以理解为:

  • CI过程即是通过Jenkins将代码拉取、构建、制作镜像交给测试人员测试。

    • 持续集成:让软件代码可以持续的集成到主干上,并自动构建和测试。
  • CD过程即是通过Jenkins将打好标签的发行版本代码拉取、构建、制作镜像交给运维人员部署。

    • 持续交付:让经过持续集成的代码可以进行手动部署。
    • 持续部署:让可以持续交付的代码随时随地的自动化部署。
      CICD

jenkins官网:https://www.jenkins.io/
jenkins插件官网:https://updates.jenkins.io/

4.1.1 安装

#1、拉取镜像
docker pull jenkins/jenkins:2.401.2-lts

#2、创建对应docker-compose
mkdir /usr/local/docker/jenkins-docker
cd /usr/local/docker/jenkins-docker
vi docker-compose.yml
###################################################
version: "1.0"
services:
  jenkins:
    image: jenkins/jenkins:2.401.2-lts
    container_name: jenkins
    ports:
      - 8080:8080
      - 50000:50000
    volumes:
      - ./data/:/var/jenkins_home/
###################################################
#上面把jenkins_home目录映射到linux的/data目录下,直接启动会没有权限报错
#创建目录并且授权data目录
mkdir data
chmod -R 777 data/

#3、启动jenkins
docker-compose up -d
docker-compose logs -f
#查看日志
docker logs jenkins
http://192.168.86.112:8080
#查看日志,找到初始密码(root/root)
#这里我们选择推荐安装,然后修改default.json文件地址
vi /usr/local/docker/jenkins-docker/data/updates/default.json
#把检查链接connectionCheckUrl后面url路径改成百度

#由于Jenkins需要下载大量内容,但是由于默认下载地址下载速度较慢,需要重新设置下载地址为国内镜像站
vi /usr/local/docker/jenkins-docker/data/hudson.model.UpdateCenter.xml
#把url换成国内地址
http://mirror.esuni.jp/jenkins/updates/update-center.json或者https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
#再次重启Jenkins容器,访问Jenkins(需要稍微等会)
#查看密码登录Jenkins,并登录下载插件(账号密码:admin/admin)
docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

4.1.2 入门配置

1、配置简单任务

(1)构建任务

GitLab查看项目
 GitLab查看项目
新建项目
新建项目
构建任务
构建任务

(2)配置源码拉取地址

源码管理
源码管理

(3)Jenkins立即构建

点击任务test中的立即构建
 点击任务test中的立即构建
查看任务拉取Git源码日志
查看任务拉取Git源码日志

(4)查看Jenkins容器中/var/jenkins_home/workspace/test的源码
Jenkins中代码位置

2、配置Maven构建代码

代码拉取到Jenkins本地后,需要在Jenkins中对代码进行构建,这里需要Maven的环境,而Maven需要Java的环境,接下来需要把JDK和Maven配置到Jenkins服务。

前提安装好Maven Integration插件,以及配置好jdk和maven

(1)配置Maven的settings.xml

<!-- 阿里云镜像地址 -->
<mirror>  
    <id>alimaven</id>  
    <name>aliyun maven</name>  
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>          
</mirror>
<!-- JDK1.8编译插件 -->
<profile>
    <id>jdk-1.8</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.8</jdk>
    </activation>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
    </properties>        
</profile>

(2)配置JDK&Maven并保存

下面的jdk和maven具体路径,按照实际路径填写

由于我们安装的docker安装的jenkins,并且把jenkins目录映射到了./data地下,因此我们可以把jdk以及maven移动到该目录下
jdk+maven
但是实际在jenkins的目录如下:
docker中jdk目录

配置JDK
配置JDK
配置maven
配置maven

(3)配置Maven构建代码

配置maven构建代码
配置maven构建代码1
配置maven构建代码2
构建源码
构建源码

target

3、配置Publish发布&远程操作

安装Publish Over SSH插件

jar包构建好之后,就可以根据情况发布到测试或生产环境,这里需要用到之前下载好的插件Publish Over SSH。
(1)配置Publish Over SSH连接测试、生产环境

Publish Over SSH配置
POS
配置构建后操作
配置构建后操作1
配置构建后操作2
配置构建后操作3
立即构建,并去目标服务器查看
立即构建
jar

五、CI、CD入门操作

目的:

1、基于Jenkins拉取GitLab的SpringBoot代码进行构建发布到测试环境实现持续集成
2、基于Jenkins拉取GitLab指定发行版本的SpringBoot代码进行构建发布到生产环境实现CD实现持续部署

5.1 持续集成

1、添加Dockerfile文件
添加dockerfile
2、添加docker-compose.yml文件
添加docker-compose
3、追加Jenkins构建后操作脚本命令
构建后操作
4、发布到GitLab后由Jenkins立即构建并托送到目标服务器
发布
5、测试部署到目标服务器程序
测试
测试2

5.2 持续交付、部署

程序代码在经过多次集成操作到达最终可以交付,持续交付整体流程和持续集成类似,不过需要选取指定的发行版本

1、下载Git Parameter插件
git parameter
2、设置项目参数化构建
设置参数化构建
设置参数化构建2
3、给项目添加tag版本
添加Tag
4、任务构建时,采用Shell方式构建,拉取指定tag版本代码
拉取tag
5、基于Parameter构建任务,任务发布到目标服务器
发布到目标服务器

六、集成Sonar Qube

暂时不写

七、集成Harbor

7.1 Harbor

Harbor作为私有的Docker镜像仓库。让Jenkins统一将项目打包并制作成Docker镜像发布到Harbor仓库中,只需要通知目标服务,让目标服务统一去Harbor仓库上拉取镜像并在本地部署即可。

docker官方提供了Registry镜像仓库,但是Registry的功能相对简陋。Harbor是VMware公司提供的一款镜像仓库,提供了权限控制、分布式发布、强大的安全扫描与审查机制等功能

7.1.1 Harbor安装

这里采用原生的方式安装Harbor。
另外,harbor是要依赖于docker存在,他需要下载一些镜像,因此前提是已经安装了docker

1、下载harbor

https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz

以上为正常路径,但是github下载很慢,可以参考百度网盘进行下载如下:
链接:https://pan.baidu.com/s/1zvo8xyiIcT_H6J91kCmlmQ 提取码:ymf8

2、解压

#把下载好的文件放到/u01/software目录下
tar -zxvf harbor-offline-installer-v2.3.4.tgz -C /usr/local/

3、修改配置文件

#进入harbor目录下,首先复制一份harbor.yml配置
cd /usr/local/harbor/
cp harbor.yml.tmpl harbor.yml

编辑harbor.yml配置文件
harbor配置文件1
4、启动,并且登录harbor
./install.sh
http://192.168.86.112/(admin/Harbor12345)

7.2 Harbor使用方式

Harbor作为镜像仓库,主要的交互方式就是将镜像上传到Harbor上,以及从Harbor上下载指定镜像

在传输镜像前,可以先使用Harbor提供的权限管理,将项目设置为私有项目,并对不同用户设置不同角色,从而更方便管理镜像。

7.2.1 添加用户构建项目

1、创建用户
创建harbor用户
2、构建项目(设置为私有)
构建项目
3、给项目追加用户
加用户
4、切换测试用户
测试用户

7.2.2 发布镜像到Harbor

1、修改镜像名称

名称要求:harbor地址/项目名/镜像名:版本
修改方法:docker tag 镜像id或者镜像名称:版本 改变后的名称

镜像名称

2、docker修改daemon.json,支持Docker仓库,并重启Docker

vi /etc/docker/daemon.json
# 为了避免配置错误,粘贴下面即可,加速地址和harbor地址换成自己的即可,注意:如果这里配置有格式问题,可能导致docker不能启动

{
  "registry-mirrors": ["https://k1itnx3n.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.86.112:80"]
}

sudo systemctl daemon-reload
sudo systemctl restart docker

daemon

3、设置登录仓库信息

docker login -u 用户名 -p 密码 Harbor地址

登录

4、推送镜像到Harbor
推送
推送2

7.2.3 从Harbor拉取镜像

1、配置/etc/docker/daemon.json文件

{
  "registry-mirrors": ["https://k1itnx3n.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.86.112:80"]
}

2、拉取镜像,如果是私有仓库,需要先登录

docker pull 192.168.86.112/repository/demo:v1.0.0

7.2.4 Jenkins发布到harbor

1)配置jenkins

构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可

1、设置宿主机docker.sock权限:

#授权docker.sock为root用户root组
sudo chown root:root /var/run/docker.sock
#使其他用户也有读和写权限
sudo chmod o+rw /var/run/docker.sock

2、修改之前的jenkins-docker的compose文件

#这里使用上面创建好的compose文件
cd /usr/local/docker/jenkins-docker
vim docker-compose.yml
###################################
version: "1.0"
services:
  jenkins:
    image: jenkins/jenkins:2.401.2-lts
    container_name: jenkins
    ports:
      - 8080:8080
      - 50000:50000
    volumes:
      - ./data/:/var/jenkins_home/
      - /usr/bin/docker:/usr/bin/docker
      - /var/run/docker.sock:/var/run/docker.sock
      - /etc/docker/daemon.json:/etc/docker/daemon.json
###################################

3、重启docker

cd /usr/local/docker/jenkins-docker
docker-compose up -d

4、测试,如下图所示这个时候jenkins就可以访问本地的docker了
测试jenkins访问docker

2)、通过jenkins发布镜像到docker hub

1、删掉上面的构建后操作的发送到SSH,新增构建后操作(执行Shell)
构建后操作

7.2.5 harbor拉取镜像并部署

1、编写拉取脚本,然后利用jenkins执行

vi deploy.sh
#######################################
harbor_url=$1			 #harbor地址
harbor_project_name=$2	 #harbor仓库
project_name=$3    		 #镜像名称
tag=$4					 #版本
port=$5					 #运行容器时占用的端口

#拉取镜像名称
imageName=$harbor_url/$harbor_project_name/$project_name:$tag

#如果当前容器正在运行,则删除镜像
containerId=`docker ps -a | grep ${project_name} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
    docker stop $containerId
    docker rm $containerId
    echo "Delete Container Success"
fi

#如果容器存在,那么也删除容器
imageId=`docker images | grep ${project_name} | awk '{print $3}'`

if [ "$imageId" != "" ] ; then
    docker rmi -f $imageId
    echo "Delete Image Success"
fi

#登录harbor
docker login -u DevOps -p Miracle123 $harbor_url

#拉取镜像
docker pull $imageName

#运行镜像
docker run -d -p $port:$port --name $project_name $imageName

echo "Start Container Success"
echo $project_name
#######################################

2、授予可执行权限,并且放到环境变量中,这样任何地方都可以访问它

#授予可执行权限
chmod a+x deploy.sh
#移动到环境变量中(可以用echo $PATH查看)
mv deploy.sh /usr/bin

3、配置jenkins
port

执行

八、Jenkins流水线

Jenkins的自由风格构建的项目,每个步骤流程都要通过不同的方式设置,并且构建过程中整体流程是不可见的,无法确认每个流程花费的时间,并且问题不方便定位问题。

Jenkins的Pipeline可以让项目的发布整体流程可视化,明确执行的阶段,可以快速的定位问题。并且整个项目的生命周期可以通过一个Jenkinsfile文件管理,而且Jenkinsfile文件是可以放在项目中维护。

8.1 Jenkins流水线任务

8.1.1 构建Jenkins流水线任务

1、构建任务
构建
2、生成Groovy脚本
生成groovy
3、构建后查看视图
查看视图

8.1.2 Groovy脚本

1、Groovy脚本基础语法

// 所有脚本命令包含在pipeline{}中
pipeline {  
	// 指定任务在哪个节点执行(Jenkins支持分布式)
    agent any
    
    // 配置全局环境,指定变量名=变量值信息
    environment{
    	host = '192.168.11.11'
    }

    // 存放所有任务的合集
    stages {
    	// 单个任务
        stage('任务1') {
        	// 实现任务的具体流程
            steps {
                echo 'do something'
            }
        }
		// 单个任务
        stage('任务2') {
        	// 实现任务的具体流程
            steps {
                echo 'do something'
            }
        }
        // ……
    }
}

2、编写例子测试

pipeline {
    agent any

    // 存放所有任务的合集
    stages {
        stage('拉取Git代码') {
            steps {
                echo '拉取Git代码'
            }
        }

        stage('检测代码质量') {
            steps {
                echo '检测代码质量'
            }
        }

        stage('构建代码') {
            steps {
                echo '构建代码'
            }
        }

        stage('制作自定义镜像并发布Harbor') {
            steps {
                echo '制作自定义镜像并发布Harbor'
            }
        }

        stage('基于Harbor部署工程') {
            steps {
                echo '基于Harbor部署工程'
            }
        }
    }
}

3、配置Grovvy脚本
配置
4、查看效果,如下图我们可以看到每一步都很清晰
效果

8.1.3 Jenkinsfile实现

在实际开发中,每次来改动jenkins中的脚本显然不现实,因此我们使用jenkinsfile
Jenkinsfile方式需要将脚本内容编写到项目中的Jenkinsfile文件中,每次构建会自动拉取项目并且获取项目中Jenkinsfile文件对项目进行构建

正常情况下,我们只需要在自己项目(git根目录下)创建Jenkinsfile文件,然后编写脚本,如下配置即可
Jenkinsfile
配置jenkinsfile

8.2 Jenkins流水线任务实现

8.2.1 参数化构建

添加参数化构建,方便选择不的项目版本
参数化构建

8.2.2 拉取Git代码

生成拉取语法
生成拉取语法

pipeline {
    agent any
    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }
    }
}

8.2.3 构建代码

生成构建语法
构建语法

pipeline {
    agent any

    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }

        stage('构建代码') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }
}

8.2.4 代码质量检测

pipeline {
    agent any

    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }

        stage('构建代码') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }

        stage('检测代码质量') {
            steps {
                sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=31388be45653876c1f51ec02f0d478e2d9d0e1fa' 
            }
        }
    }
}

8.2.5 制作自定义镜像并发布

1、生成自定义镜像脚本

pipeline {
    agent any
    environment{
        harborHost = '192.168.11.11:80'
        harborRepo = 'repository'
        harborUser = 'DevOps'
        harborPasswd = 'P@ssw0rd'
    }

    // 存放所有任务的合集
    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }

        stage('构建代码') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }

        stage('检测代码质量') {
            steps {
                sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=31388be45653876c1f51ec02f0d478e2d9d0e1fa' 
            }
        }

        stage('制作自定义镜像并发布Harbor') {
            steps {
                sh '''cp ./target/*.jar ./docker/
                cd ./docker
                docker build -t ${JOB_NAME}:${tag} ./'''

                sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
                docker tag ${JOB_NAME}:${tag} ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}
                docker push ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}'''
            }
        }
    }
}

2、生成Publish Over SSH脚本

pipeline {
    agent any
    environment{
        harborHost = '192.168.11.11:80'
        harborRepo = 'repository'
        harborUser = 'DevOps'
        harborPasswd = 'P@ssw0rd'
    }

    // 存放所有任务的合集
    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }

        stage('构建代码') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }docker

        stage('检测代码质量') {
            steps {
                sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=7d66af4b39cfe4f52ac0a915d4c9d5c513207098' 
            }
        }

        stage('制作自定义镜像并发布Harbor') {
            steps {
                sh '''cp ./target/*.jar ./docker/
                cd ./docker
                docker build -t ${JOB_NAME}:${tag} ./'''

                sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
                docker tag ${JOB_NAME}:${tag} ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}
                docker push ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}'''
            }
        }
        
        stage('目标服务器拉取镜像并运行') {
            steps {
                sshPublisher(publishers: [sshPublisherDesc(configName: 'testEnvironment', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/usr/bin/deploy.sh $harborHost $harborRepo $JOB_NAME $tag $port ", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }
        }
    }
}

8.3 Jenkins流水线整合钉钉

在程序部署成功后,可以通过钉钉的机器人及时向群众发送部署的最终结果通知

1、安装插件
钉钉插件2、钉钉内部创建群组并构建机器人
机器人1
机器人2
机器人3

最终或获取到Webhook信息
https://oapi.dingtalk.com/robot/send?access_token=kej4ehkj34gjhg34jh5bh5jb34hj53b4

3、系统配置添加钉钉通知
通知
4、任务中追加流水线配置

pipeline {
    agent any

    environment {
        sonarLogin = '2bab7bf7d5af25e2c2ca2f178af2c3c55c64d5d8'
        harborUser = 'admin'
        harborPassword = 'Harbor12345'
        harborHost = '192.168.11.12:8888'
        harborRepo = 'repository'
    }

    stages {
        stage('拉取Git代码'){
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '$tag']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/lsx.git']]])
            }
        }
        stage('Maven构建代码'){
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }
        stage('SonarQube检测代码'){
            steps {
                sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=${sonarLogin}'
            }
        }
        stage('制作自定义镜像'){
            steps {
                sh '''cd docker
                mv ../target/*.jar ./
                docker build -t ${JOB_NAME}:$tag .
                '''
            }
        }

        stage('推送自定义镜像'){
            steps {
                sh '''docker login -u ${harborUser} -p ${harborPassword} ${harborHost}
                docker tag ${JOB_NAME}:$tag ${harborHost}/${harborRepo}/${JOB_NAME}:$tag
                docker push ${harborHost}/${harborRepo}/${JOB_NAME}:$tag'''
            }
        }

        stage('通知目标服务器'){
            steps {
                sshPublisher(publishers: [sshPublisherDesc(configName: 'centos-docker', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/usr/bin/deploy.sh $harborHost $harborRepo $JOB_NAME $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }  
        }
    }
    post {
        success {
            dingtalk (
                robot: 'Jenkins-DingDing',
                type:'MARKDOWN',
                title: "success: ${JOB_NAME}",
                text: ["- 成功构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
            )
        }
        failure {
            dingtalk (
                robot: 'Jenkins-DingDing',
                type:'MARKDOWN',
                title: "fail: ${JOB_NAME}",
                text: ["- 失败构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
            )
        }
    }
}

其他操作可以参考相关文档

九、Kubernetes

9.1 Kubernetes介绍

具体请参照我的这篇文章:k8s介绍

9.2 Kubernetes安装

具体请参照我的这篇文章:k8s安装

9.3 Jenkins集成Kubernetes

9.3.1 准备部署的yml文件

下面是部署到k8s的脚本:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: test
  name: pipeline
  labels:
    app: pipeline
spec:
  replicas: 2
  selector:
    matchLabels:
      app: pipeline
  template:
    metadata:
      labels:
        app: pipeline    
    spec:
      containers:
      - name: pipeline
        image: 192.168.11.102:80/repo/pipeline:v4.0.0
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  namespace: test
  labels:
    app: pipeline
  name: pipeline  
spec:
  selector:
    app: pipeline
  ports:
  - port: 8081
    targetPort: 8080
  type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: test
  name: pipeline
spec:
  ingressClassName: ingress
  rules:
  - host: mashibing.pipeline.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: pipeline
            port:
              number: 8081

9.3.2 Harbor私服配置

在尝试用kubernetes的yml文件启动pipeline服务时,会出现Kubernetes无法拉取镜像的问题,这里需要在kubernetes所在的Linux中配置Harbor服务信息,并且保证Kubernetes可以拉取Harbor上的镜像

1、设置K8s的Master和Worker的私服地址信息
设置私服地址
2、在Kuboard上设置私服密文信息
设置密文

9.3.3 测试使用效果

执行kubectl命令,基于yml启动服务
kubectl
测试2

9.3.4 Jenkins远程调用

下面我们将配置如何通过jenkins发布到k8s上

1、将pipeline.yml配置到Gitlab中

配置pipeline
2、配置Jenkins的目标服务器,可以将yml文件传输到K8s的Master上(注意k8上需要有该目录,没有的话创建)
传输

修改Jenkinsfile,重新设置流水线任务脚本,并测试效果
传输

3、Jenkins执行K8s命令

在最后一步其实我们需要在jenkins中执行k8s命令,那么如何在jenkins中执行远程调用k8s命令

(1)首先我们需要配置在jenkins中可以免密登录到k8s服务器

#将Jenkins中公钥信息复制到k8s-master的~/.ssh/authorized_keysz中,保证远程连接无密码
#1、进入docker的公钥目录(jenkins在docker中)
docker exec -it jenkins /bin/bash
#如果存在ssh目录,执行如下
cd ~
cd .ssh
#找到上面的id_rsa.pub文件
#如果不存在ssh目录,需要执行ssh-keygen一路回车,然后和上面步一样

#3、复制id_rsa.pub内容,到需要连接k8s的机器的~/.ssh目录下的authorized_keys文件中,此时jenkins就可以无密码访问k8s了

设置执行kubectl的脚本到Jenkinsfile
执行

9.4 基于GitLab的WebHooks(自动化持续集成)

实现自动化的一个CI操作,也就是开发人员Push代码到Git仓库后,Jenkins会自动的构建项目,将最新的提交点代码构建并进行打包部署,这里区别去上述的CD操作,CD操作需要基于某个版本进行部署,而这里每次都是将最新的提交点集成到主干上并测试。

9.4.1 WebHooks通知

1、开启Jenkins的自动构建
开启自动构建
2、设置Gitlab的Webhooks
设置gitlab的webHooks
如果上面那个提示不能再本地设置,需要在Settings->Network->Outbound Request中勾选允许请求发送到本地网路。
3、需要需要关闭Jenkins的Gitlab认证
关闭Gitlab认证

9.4.2 修改配置

1、修改Jenkinsfile实现基于最新提交点实现持续集成效果,将之前引用${tag}的全部去掉

// 所有的脚本命令都放在pipeline中
pipeline{
	// 指定任务再哪个集群节点中执行
	agent any

	// 声明全局变量,方便后面使用
	environment {
		harborUser = 'admin'
        harborPasswd = 'Harbor12345'
        harborAddress = '192.168.11.102:80'
        harborRepo = 'repo'
	}

    stages {
        stage('拉取git仓库代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[url: 'http://192.168.11.101:8929/root/mytest.git']]])
            }
        }
        stage('通过maven构建项目') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }
        stage('通过SonarQube做代码质量检测') {
            steps {
                sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.source=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target/ -Dsonar.login=40306ae8ea69a4792df2ceb4d9d25fe8a6ab1701'
            }
        }
        stage('通过Docker制作自定义镜像') {
            steps {
                sh '''mv ./target/*.jar ./docker/
                docker build -t ${JOB_NAME}:latest ./docker/'''
            }
        }
        stage('将自定义镜像推送到Harbor') {
            steps {
                sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborAddress}
                docker tag ${JOB_NAME}:latest  ${harborAddress}/${harborRepo}/${JOB_NAME}:latest
                docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:latest '''
            }
        }
        stage('将yml文件传到k8s-master上') {
            steps {
                sshPublisher(publishers: [sshPublisherDesc(configName: 'k8s', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'pipeline.yml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }
        }
        stage('远程执行k8s-master的kubectl命令') {
            steps {
               sh '''ssh root@192.168.11.201 kubectl apply -f /usr/local/k8s/pipeline.yml
                ssh root@192.168.11.201 kubectl rollout restart deployment pipeline -n test'''
            }
        }

    }
    post {
        success {
            dingtalk(
                robot: 'Jenkins-DingDing',
                type: 'MARKDOWN',
                title: "success: ${JOB_NAME}",
                text: ["- 成功构建:${JOB_NAME}! \n- 版本:latest \n- 持续时间:${currentBuild.durationString}" ]
            )
        }
        failure {
            dingtalk(
                robot: 'Jenkins-DingDing',
                type: 'MARKDOWN',
                title: "success: ${JOB_NAME}",
                text: ["- 构建失败:${JOB_NAME}! \n- 版本:latest \n- 持续时间:${currentBuild.durationString}" ]
            )
        }
    }
}

2、修改pipeline.yml,更改镜像版本

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: test
  name: pipeline
  labels:
    app: pipeline
spec:
  replicas: 2
  selector:
    matchLabels:
      app: pipeline
  template:
    metadata:
      labels:
        app: pipeline    
    spec:
      containers:
      - name: pipeline
        image: 192.168.11.102:80/repo/pipeline:latest   # 这里
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
# 省略其他内容…………

9.4.3 滚动更新

因为pipeline没有改变时,每次不会重新加载,这样会导致Pod中的容器不会动态更新,这里需要使用kubectl的rollout restart命令滚动更新
滚动更新

三、综合实战

3.1 部署流程

1、研发push到git代码库
2、jenkins构建,pull git代码,使用maven进行编译打包
3、打包生成的代码,生成一个新版本的镜像,push到本地docker仓库harbor
4、发布,测试机器pull新版本的镜像,并删除原来的容,重新运行新版本(部署k8s)

3.2 环境说明

注意:下面环境如果服务器允许,可以按照如下配置,如果不允许可以在很少机器上同时部署下面这些应用程序

1、代码仓库GitLab
主机名:gitlab
软件地址:http://192.168.86.112:8929/(账号密码:root/miracle123)
2、私有容器镜像harbor
主机名:harbor
软件:harbor
3、CICD服务器
主机名:jenkins
软件:jdk、jenkins、git、maven、docker、k8s
4、应用服务
主机名:docker或者k8s
未完待续

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值