基于Eureka搭建Springcloud微服务-16.使用持续集成快捷部署服务

lingwh原创2020年7月4日大约 21 分钟约 6376 字

16.使用持续集成快捷部署服务

16.1.章节内容概述

本章节涉及主要内容有:
 16.1.章节内容概述
 16.2.章节内容大纲
 16.3.持续集成微服务到Docker中
 16.4.持续集成微服务到k8s中
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

16.2.章节内容大纲

16.3.持续集成微服务到Docker中

16.3.1.持续集成微服务到Docker中流程说明

16.3.2.搭建Docker

在192.168.0.4上搭建docker

详细参考-> 搭建docker 开启192.168.0.4上的docker的2375端口(为使用docker的maven插件做准备)

vim /lib/systemd/system/docker.service
其中ExecStart=后添加配置-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
开放端口
firewall-cmd --zone=public --add-port=2375/tcp --permanent &&
firewall-cmd --reload
刷新daemon.json并重启动docker
systemctl daemon-reload &&
systemctl restart docker

16.3.3.搭建Harbor

在192.168.0.5上搭建harbor

详细参考-> 搭建Harbor 配置192.168.0.4上的Docker信任192.168.0.5上的harbor私服

vim /etc/docker/daemon.json
添加如下内容
{
    "insecure-registries":["192.168.0.5:5000"]
}
刷新daemon并重启docker
systemctl daemon-reload &&
systemctl restart docker

16.3.4.搭建Jenkins

在192.168.0.5上搭建Jenkins

详细参考-> 搭建Jenkins

在Jenkins中安装配置Publish Over SSH插件(需要先安装该插件)
配置Jenkins所在服务器到docker所在服务器的免密登录

进入Publish over SSH配置面板
DASHBOARD->Manage Jenkins/系统管理->Configure System(System Configuration下)/系统配置(系统配置)->Publish over SSH

配置如下字段
Publish over SSH
a.Passphrase(可以配置也可以不配置,下面的配置中会覆盖这个配置)
192.168.0.4机器的密码

Publish over SSH->SSH Servers->新增
a.Name(和Jenkinsfile中sshPublisherDesc.configName保持一致)
cidocker
b.Hostname
192.168.0.4
c.Username
root
d.Remote Directory
/

Publish over SSH->SSH Servers->勾选Use password authentication, or use a different key
a.Passphrase / Password(注意:这个配置会覆盖Publish over SSH下a.中的配置)
192.168.0.4机器的密码

测试连通性(成功返回Success)
Publish over SSH->SSH Servers->Test Configuration

保存配置
Publish over SSH->保存

16.3.5.搭建持续集成使用的微服务

16.3.5.1.模块简介

测试持续集成微服务到docker中使用到的微服务

16.3.5.2.模块目录结构

springcloud-ci-docker80
|-- docker
|   •-- Dockerfile
|-- src
|   •-- main
|       |-- java
|       |   •-- org
|       |       •-- openatom
|       |           •-- springcloud
|       |               |-- controller
|       |               |   •-- CiDockerController.java
|       |               •-- CiDocker80.java
|       •-- resources
|           •-- application.yml
•-- pom.xml

16.3.5.3.创建模块

在父工程(springcloud-eureka)中创建一个名为springcloud-ci-docker80的maven模块,注意:当前模块创建成功后,在父工程pom.xml中<modules></modules>中会自动生成有关当前模块的信息

16.3.5.4.编写模块pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-eureka</artifactId>
        <groupId>org.openatom</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-ci-docker80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <docker.registry.uri>192.168.0.5:5000</docker.registry.uri>
        <docker.registry.username>admin</docker.registry.username>
        <docker.registry.password>123456</docker.registry.password>
        <docker.host>tcp://192.168.0.4:2375</docker.host>
        <!--设置当前服务端口-->
        <docker.container.port>80</docker.container.port>
        <!--docker容器端口映射-->
        <docker.port.mapping>${docker.container.port}:${docker.container.port}</docker.port.mapping>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--引入公共的工程-->
        <dependency>
            <groupId>org.openatom</groupId>
            <artifactId>springcloud-api-commons</artifactId>
        </dependency>
    </dependencies>

    <!--热部署需要加这个-->
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <!--把当前插件repackage命令和maven的package绑定-->
                        <id>repackage-original</id>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <id>del-jar</id>
                        <phase>clean</phase>
                        <configuration>
                            <tasks>
                                <!-- 这是将当前模块下的target下的jar包删除-->
                                <delete file="docker/${build.finalName}.jar"/>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>copy-jar</id>
                        <phase>install</phase>
                        <configuration>
                            <tasks>
                                <!-- 这是将当前模块下的target下的jar包copy到当前模块根目录下docker目录中-->
                                <copy todir="docker" file="target/${build.finalName}.jar"></copy>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <configuration>
                    <dockerHost>${docker.host}</dockerHost>
                    <removeMode>true</removeMode>
                    <!--
                        harbor镜像仓库认证配置
                        注意:不管是harbor中是公开项目还是私密项目,这个配置都要加,不加无法push成功
                    -->
                    <authConfig>
                        <username>${docker.registry.username}</username>
                        <password>${docker.registry.password}</password>
                    </authConfig>
                    <images>
                        <image>
                            <!--显示日志的时候-->
                            <!--<alias>spring-cloud-eureka</alias>-->
                            <!--如果只给docker本地镜像库中推送,格式为 命名空间/项目名称:tags名称,示例:项目artifactId/模块artifactId-->
                            <!--<name>${project.parent.artifactId}/${project.name}</name>-->
                            <!--
                                如果要同时给私服中推送,格式为 registry的ip:命名空间/项目名称:tags名称,示例:私服的ip:项目artifactId/模块artifactId
                                也可将registry单独写在下面
                            -->
                            <!--<name>镜像名称:${docker.registry}/${project.parent.artifactId}/${project.name}</name>-->
                            <name>${project.parent.artifactId}/${project.name}:latest</name>
                            <registry>${docker.registry.uri}</registry>
                            <!--定义镜像构建行为-->
                            <build>
                                <!-- 指定dockerfile文件的位置-->
                                <dockerFile>${project.basedir}/docker/Dockerfile</dockerFile>
                            </build>
                            <!-- 定义容器启动行为-->
                            <run>
                                <!--设置容器名,可采用通配符-->
                                <containerNamePattern>${project.parent.artifactId}_${project.build.finalName}</containerNamePattern>
                                <!--设置端口映射-->
                                <ports>
                                    <port>${docker.port.mapping}</port>
                                </ports>
                            </run>
                        </image>
                    </images>
                    <buildArgs>
                        <!--docker私服地址-->
                        <DOCKER_REGISTRY_URL>${docker.registry.uri}</DOCKER_REGISTRY_URL>
                    </buildArgs>
                </configuration>
                <executions>
                    <!--如果想在项目install时构建镜像添加-->
                    <execution>
                        <id>build-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                    <!--如果想在项目install时构建镜像添加-->
                    <execution>
                        <id>tag-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>tag</goal>
                        </goals>
                    </execution>
                    <!--如果想在项目install时推送镜像到私服添加-->
                    <execution>
                        <id>push-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>push</goal>
                        </goals>
                    </execution>
                    <!--如果想在项目install时推送镜像到私服后删除并docker中本地build的镜像添加-->
                    <execution>
                        <id>remove-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>remove</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <!--打包多环境-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>application.yml</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

16.3.5.5.编写模块application.yml

server:
  port: 80

16.3.5.6.编写模块controller

package org.openatom.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.openatom.springcloud.entities.CommonResult;
import org.openatom.springcloud.entities.Payment;


@RestController
public class CiDockerController {

    @GetMapping("/ci/docker")
    public CommonResult<String> create(Payment payment) {
        return new CommonResult(200,"持续集成","测试持续集成到Docker+测试WebHook");
    }

}

16.3.5.7.编写模块主启动类

package org.openatom.springcloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CiDocker80 {
    public static void main(String[] args) {
        SpringApplication.run(CiDocker80.class, args);
    }

}

16.3.5.8.编写模块Dockerfile

注意:需要先在 项目根目录/springcloud-ci-docker80下创建docker文件夹

FROM java:8 VOLUME /software MAINTAINER lingwh COPY ${project.build.finalName}.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]

#### 16.3.5.9.本地测试模块
    在浏览器中访问

http://localhost/ci/docker

    返回数据
```json
{"code":200,"message":"持续集成","data":"测试持续集成到Docker"}

16.3.6.测试docker的maven插件

启动相关服务
在项目根目录下执行打包命令
mvn clean install
在项目根目录下执行复制生成的jar包到指定位置
cp springcloud-ci-docker80/target/springcloud-ci-docker80.jar springcloud-ci-docker80/docker
在idea中打开docker的maven插件操作面板
制作Docker镜像并上传镜像到docker
点击docker:build

上传镜像到docker后在docker中为该镜像创建容器并启动docker中的容器
点击docker:build->点击docker:run

测试部署到docker中的服务
http://192.168.0.4/ci/docker
返回结果
{"code":200,"message":"持续集成","data":"测试持续集成到Docker"}
在harbor私服中创建springcloud-eureka项目
推送到harbor私服
点击docker:build->点击docker:push
登录harbor私服查看刚才推送上去的的服务
http://192.168.0.5:5000/harbor/projects
点击springcloud-eureka这个项目
可以看到当前模块微服务已经被推送到了harbor私服中

16.3.7.持续集成Jekins相关配置

16.3.7.1.编写Jenkinsfile

在项目根目录下新建script文件夹,在script中新建JenkinsfileCiDocker,内容如下
//定义远程git仓库中项目的地址
def project_url='https://gitee.com/lingwh1995/springcloud-eureka.git'

def jenkins_ip='192.168.0.5'

node {
    echo '开始执行自动化...'
    /*指定在那台Jenkins节点上运行*/
    agent { label '${jenkins_ip}'}

    /*从远程仓库检出代码*/
    stage('从远程仓库检出代码') {
        echo '开始 从远程仓库检出代码...'
        checkout([
            $class: 'GitSCM',
            branches: [[name: '*/master']], extensions: [],
            userRemoteConfigs: [[url: "${project_url}"]]
        ])
        echo '完成 从远程仓库检出代码...'
    }

    /**
     * maven命令扩展:实现多模块情况下只针对某一个模块打包
     * -pl, --projects
     *      Build specified reactor projects instead of all projects
     *      指定项目其中的一个模块及其依赖
     *  -am, --also-make
     *      If project list is specified, also build projects required by the list
     *      自动构建该模块所依赖的其他模块
     *
     */
    stage('打包->安装->构建镜像->推送到私服->删除docker中本地镜像') {
        echo '开始 打包->安装->构建镜像->推送到私服->删除docker中本地镜像...'
        //如果install的是一个模块或者是多个模块
            //执行遍历依次次打包涉及的模块
        //如果是install的是整个项目
            //一次性打包整个项目
        sh "mvn clean install -T 1C -Dmaven.test.skip=true -Dmaven.compile.fork=true -pl springcloud-ci-docker80 -am"
        echo '完成 打包->安装->构建镜像->推送到私服->删除docker中本地镜像...'
    }

    /**
     *安装Publish Over SSH插件,使用插件的功能触发远程的shell脚本的执行
     */
    stage('自动部署上传到私服中的所有镜像到docker') {
        echo '开始 自动部署上传到私服中的所有镜像到docker...'
        sshPublisher(
            publishers:
                [
                    sshPublisherDesc(
                        configName: 'cidocker',
                        transfers: [
                            sshTransfer(
                                cleanRemote: false,
                                excludes: '',
                                execCommand: "cd / && ./springcloud-ci-docker.sh",
                                execTimeout: 600000,
                                flatten: false,
                                makeEmptyDirs: false,
                                noDefaultExcludes: false,
                                patternSeparator: '[, ]+',
                                remoteDirectory: '',
                                remoteDirectorySDF: false,
                                removePrefix: '',
                                sourceFiles: ''
                            )
                        ],
                        usePromotionTimestamp: false,
                        useWorkspaceInPromotion: false,
                        verbose: false
                    )
                ]
       )
       echo '结束 自动部署上传到私服中的所有镜像到docker...'
    }

    echo '完成执行自动化...'
}
注意事项
执行Jenkinsfile中执行了mvn install命令后,就会触发 将生成的jar拷贝到docker文件夹中->build镜像->tag镜像->push镜像 这些操作,这是由于在pom.xml中把这些操作都和install命令绑定在了一起,所以才会有这样的效果

16.3.7.2.在Jekins中配置项目

新建任务
DashBoard->新建任务->输入任务名称(springcloud-eureka)->流水线->确定
或
DashBoard->点击springcloud-eureka->配置

配置如下字段
配置流水线
a.定义
Pipeline script from SCM(点击下拉框选择)
b.定义->SCM
Git(点击下拉框选择)
c.定义->SCM->Repositories(根据自己的项目信息进行配置)
Repository URL
https://gitee.com/lingwh1995/springcloud-eureka.git
d.定义->SCM->脚本路径(根据自己的项目信息进行配置)
script/JenkinsfileCiDocker

16.3.7.3.编写持续集成脚本

在192.168.0.4上编写持续集成脚本
cd / &&
cat > springcloud-ci-docker.sh << EOF
docker login 192.168.0.5:5000 -uadmin -p123456
docker rmi -f 192.168.0.5:5000/springcloud-eureka/springcloud-ci-docker80
docker rm -f springcloud-ci-docker80
docker pull 192.168.0.5:5000/springcloud-eureka/springcloud-ci-docker80:latest
docker run -di --name=springcloud-ci-docker80 -p80:80 192.168.0.5:5000/springcloud-eureka/springcloud-ci-docker80
EOF
赋予可执行权限
chmod +x springcloud-ci-docker.sh

16.3.8.测试持续集成微服务到docker中

为了更明显的查看本次测试效果,首先删除192.168.0.4中docker中在前面环节产生的镜像和容器

访问项目主页,点击构建按钮
http://192.168.0.5:8080/jenkins/
访问服务
http://192.168.0.4/ci/docker
返回结果
{"code":200,"message":"持续集成","data":"测试持续集成到Docker"}

16.3.9.使用Webhook触发持续集成

16.3.9.1.webhook的作用

在前面的环节中,访问项目主页,点击构建按钮后才能触发持续集成,使用webhook可以更方便的触发持续集成,配置好webhook时,当提交代码时就会触发持续集成

16.3.9.2.使用webhook前准备工作

jenkins安装Gitee插件

详细参考-> jenkins安装Gitee插件

搭建内网穿透

详细参考-> 搭建内网穿透 搭建好了内网穿透后,可以使用新的地址来访问jenkins 不使用内网穿透访问jenkins的地址是

http://192.168.0.5:8080/jenkins/
使用内网穿透访问jenkins的地址是
http://8sybmw.natappfree.cc/jenkins

16.3.9.3.配置使用webhook

使用内网穿透访问jenkins的地址是
http://8sybmw.natappfree.cc/jenkins
在jenkins中配置job
jenkins具体项目->配置->构建触发器->Gitee webhook 触发构建->Gitee WebHook 密码—>得到密码 0d71d48f211af16c477cf9c817ac612d

配置gitee的webhook
进入gitee的webhook配置界面(这里的url根据自己的项目进行修改)
https://gitee.com/lingwh1995/springcloud-eureka/hooks
点击添加webHook->填写URL和WebHook 密码/签名密钥
URL
http://8sybmw.natappfree.cc/jenkins/gitee-project/springcloud-eureka
WebHook 密码/签名密钥(上面在jenkins中生成的)
0d71d48f211af16c477cf9c817ac612d

测试webhook是否配置成功(可以测试,也可以不测试)
点击测试->查看更多

16.3.9.4.配置使用的Jenkinsfile

DashBoard->点击springcloud-eureka->配置->流水线->脚本路径->输入 script/JenkinsfileCiDocker

16.3.9.5.测试使用Webhook触发持续集成

修改springcloud-eureka/springcloud-ci-docker80/src/main/java/org/openatom/springcloud/controller/CiK8sController.java中代码为
package org.openatom.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.openatom.springcloud.entities.CommonResult;
import org.openatom.springcloud.entities.Payment;


@RestController
public class CiDockerController {

    @GetMapping("/ci/docker")
    public CommonResult<String> create(Payment payment) {
        return new CommonResult(200,"持续集成","测试持续集成到Docker+测试WebHook");
    }

}
在git中提交代码

查看webhook触发jenkins构建
http://8sybmw.natappfree.cc/jenkins/job/springcloud-eureka/
在浏览器中访问
http://192.168.0.4/ci/docker
返回数据
{"code":200,"message":"持续集成","data":"测试持续集成到Docker+测试WebHook"}

16.4.持续集成微服务到k8s中

16.4.1.持续集成微服务到k8s中流程说明

16.4.2.搭建Docker

    在192.168.0.4上搭建docker

详细参考-> 搭建docker

开启minikube部署机器(192.168.0.4)上的docker2375端口(为使用docker的maven插件做准备)
vim /lib/systemd/system/docker.service
其中ExecStart=后添加配置-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
开放端口
firewall-cmd --zone=public --add-port=2375/tcp --permanent &&
firewall-cmd --reload
刷新daemon.json并重启动docker
systemctl daemon-reload &&
systemctl restart docker

16.4.3.搭建Harbor

在192.168.0.5上搭建Harbor

详细参考-> 搭建harbor 配置192.168.0.4上的docker信任192.168.0.5上的harbor私服

vim /etc/docker/daemon.json
添加如下内容
{
    "insecure-registries":["192.168.0.5:5000"]
}
刷新daemon并重启docker
systemctl daemon-reload &&
systemctl restart docker

16.4.4.搭建Jenkins

在192.168.0.5上搭建Jenkins

详细参考-> 搭建Jenkins

在Jenkins中安装配置Publish Over SSH插件(需要先安装该插件)
配置Jenkins所在服务器到docker所在服务器的免密登录

进入Publish over SSH配置面板
DASHBOARD->Manage Jenkins/系统管理->Configure System(System Configuration下)/系统配置(系统配置)->Publish over SSH

配置如下字段
Publish over SSH
a.Passphrase(可以配置也可以不配置,下面的配置中会覆盖这个配置)
192.168.0.4机器的密码

Publish over SSH->SSH Servers->新增
a.Name(和Jenkinsfile中sshPublisherDesc.configName保持一致)
cidocker
b.Hostname
192.168.0.4
c.Username
root
d.Remote Directory
/

Publish over SSH->SSH Servers->勾选Use password authentication, or use a different key
a.Passphrase / Password(注意:这个配置会覆盖Publish over SSH下a.中的配置)
192.168.0.4机器的密码

测试连通性(成功返回Success)
Publish over SSH->SSH Servers->Test Configuration

保存配置
Publish over SSH->保存

16.4.5.搭建Minikube或K8s

在192.168.0.4上搭建minikube

详细参考-> 搭建minikube

这里使用minikube作为k8s的演示环境,如要搭建适用于生产环境的k8s环境,请参考
kubeadm搭建kubernetes

详细参考-> minikube 二进制包搭建kubernetes 详细参考-> minikube

16.4.6.配置Minikube或Kubernetes

16.4.6.1.配置minikube

16.4.6.1.1.协议类型
docker: tcp
harbor: http
16.4.6.1.2.配置配置minikube的所有工作节点上的使用的docker
配置minikube或kubernetes的所有工作节点上的docker信任harbor私服
vim /etc/docker/daemon.json
添加如下内容
{
    "insecure-registries":["192.168.0.5:5000"]
}
刷新daemon并重启docker
systemctl daemon-reload &&
systemctl restart docker
16.4.6.1.3.配置docker中minikube容器内部使用的docker
进入minikube终端
minikube ssh
配置/usr/lib/systemd/system/docker.service
sudo vi /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd后添加insecure-registry配置
--insecure-registry=192.168.0.5:5000
刷新daemon并重启docker
sudo systemctl daemon-reload &&
sudo systemctl restart docker
16.4.6.1.4.配置Minikube从harbor拉取镜像时使用的秘钥
a.根据docker用户名密码创建秘钥
创建秘钥
kubectl create secret docker-registry harbor-login \
--docker-server=192.168.0.5:5000 \
--docker-username=admin \
--docker-password=123456
查看创建的秘钥
kubectl get secret
kubectl get secret regcred --output=yaml
b.基于现有docker登录凭证使用yaml创建秘钥
登录docker镜像仓库
docker login 192.168.0.4:5000 --username docker -password 123456
查看生成的docker登录凭证
cat ~/.docker/config.json
以base64编码格式查看docker登录凭证
cat ~/.docker/config.json | base64 -w 0
创建用于创建秘钥的yaml
cat > harbor_secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
  name: harbor-login
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjAuNTo1MDAwIjogewoJCQkiYXV0aCI6ICJZV1J0YVc0Nk1USXpORFUyIgoJCX0KCX0KfQ==
EOF
创建秘钥
kubectl create -f harbor_secret.yaml
查看创建的秘钥
kubectl get secret
kubectl get secret regcred --output=yaml
c.基于现有docker登录凭证引用config.json创建秘钥
登录docker镜像仓库
docker login 192.168.0.4:5000 --username docker -password 123456
查看生成的docker登录信息
cat ~/.docker/config.json
根据生成的docker登录信息创建秘钥
kubectl create secret generic harbor-login \
    --from-file=.dockerconfigjson=/root/.docker/config.json \
    --type=kubernetes.io/dockerconfigjson
查看创建的秘钥
kubectl get secret
kubectl get secret regcred --output=yaml

16.4.6.2.配置kubernetes

16.4.6.2.1.协议类型
docker: tcp
harbor: http

16.4.6.3.配置minikube

16.4.6.3.1.协议类型
docker: tcp
harbor: https

16.4.6.4.配置Kubernetes

16.4.6.4.1.协议类型
docker: tcp
harbor: https

16.4.7.搭建持续集成使用的微服务

16.4.7.1.模块简介

测试持续集成微服务到k8s中使用到的微服务

16.4.7.2.模块目录结构

springcloud-ci-k8s80
|-- docker
|   •-- Dockerfile
|-- src
|   •-- main
|       |-- java
|       |   •-- org
|       |       •-- openatom
|       |           •-- springcloud
|       |               |-- controller
|       |               |   •-- CiK8sController.java
|       |               •-- CiK8s80.java
|       •-- resources
|           •-- application.yml
•-- pom.xml

16.4.7.3.创建模块

在父工程(springcloud-eureka)中创建一个名为springcloud-ci-k8s80的maven模块,注意:当前模块创建成功后,在父工程pom.xml中<modules></modules>中会自动生成有关当前模块的信息

16.4.7.4.编写模块pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-eureka</artifactId>
        <groupId>org.openatom</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-ci-k8s80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <docker.registry.uri>192.168.0.5:5000</docker.registry.uri>
        <docker.registry.username>admin</docker.registry.username>
        <docker.registry.password>123456</docker.registry.password>
        <docker.host>tcp://192.168.0.4:2375</docker.host>
        <!--设置当前服务端口-->
        <docker.container.port>80</docker.container.port>
        <!--docker容器端口映射-->
        <docker.port.mapping>${docker.container.port}:${docker.container.port}</docker.port.mapping>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--引入公共的工程-->
        <dependency>
            <groupId>org.openatom</groupId>
            <artifactId>springcloud-api-commons</artifactId>
        </dependency>
    </dependencies>

    <!--热部署需要加这个-->
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <!--把当前插件repackage命令和maven的package绑定-->
                        <id>repackage-original</id>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <id>del-jar</id>
                        <phase>clean</phase>
                        <configuration>
                            <tasks>
                                <!-- 这是将当前模块下的target下的jar包删除-->
                                <delete file="docker/${build.finalName}.jar"/>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>copy-jar</id>
                        <phase>install</phase>
                        <configuration>
                            <tasks>
                                <!-- 这是将当前模块下的target下的jar包copy到当前模块根目录下docker目录中-->
                                <copy todir="docker" file="target/${build.finalName}.jar"></copy>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <configuration>
                    <dockerHost>${docker.host}</dockerHost>
                    <removeMode>true</removeMode>
                    <!--
                        harbor镜像仓库认证配置
                        注意:不管是harbor中是公开项目还是私密项目,这个配置都要加,不加无法push成功
                    -->
                    <authConfig>
                        <username>${docker.registry.username}</username>
                        <password>${docker.registry.password}</password>
                    </authConfig>
                    <images>
                        <image>
                            <!--显示日志的时候-->
                            <!--<alias>spring-cloud-eureka</alias>-->
                            <!--如果只给docker本地镜像库中推送,格式为 命名空间/项目名称:tags名称,示例:项目artifactId/模块artifactId-->
                            <!--<name>${project.parent.artifactId}/${project.name}</name>-->
                            <!--
                                如果要同时给私服中推送,格式为 registry的ip:命名空间/项目名称:tags名称,示例:私服的ip:项目artifactId/模块artifactId
                                也可将registry单独写在下面
                            -->
                            <!--<name>镜像名称:${docker.registry}/${project.parent.artifactId}/${project.name}</name>-->
                            <name>${project.parent.artifactId}/${project.name}:latest</name>
                            <registry>${docker.registry.uri}</registry>
                            <!--定义镜像构建行为-->
                            <build>
                                <!-- 指定dockerfile文件的位置-->
                                <dockerFile>${project.basedir}/docker/Dockerfile</dockerFile>
                            </build>
                            <!-- 定义容器启动行为-->
                            <run>
                                <!--设置容器名,可采用通配符-->
                                <containerNamePattern>${project.parent.artifactId}_${project.build.finalName}</containerNamePattern>
                                <!--设置端口映射-->
                                <ports>
                                    <port>${docker.port.mapping}</port>
                                </ports>
                            </run>
                        </image>
                    </images>
                    <buildArgs>
                        <!--docker私服地址-->
                        <DOCKER_REGISTRY_URL>${docker.registry.uri}</DOCKER_REGISTRY_URL>
                    </buildArgs>
                </configuration>
                <executions>
                    <!--如果想在项目install时构建镜像添加-->
                    <execution>
                        <id>build-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                    <!--如果想在项目install时构建镜像添加-->
                    <execution>
                        <id>tag-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>tag</goal>
                        </goals>
                    </execution>
                    <!--如果想在项目install时推送镜像到私服添加-->
                    <execution>
                        <id>push-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>push</goal>
                        </goals>
                    </execution>
                    <!--如果想在项目install时推送镜像到私服后删除并docker中本地build的镜像添加-->
                    <execution>
                        <id>remove-image</id>
                        <phase>install</phase>
                        <goals>
                            <goal>remove</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <!--打包多环境-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>application.yml</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

16.4.7.5.编写模块application.yml

server:
  port: 80

16.4.7.6.编写模块controller

package org.openatom.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.openatom.springcloud.entities.CommonResult;
import org.openatom.springcloud.entities.Payment;

@RestController
public class CiK8sController {


    @GetMapping("/ci/k8s")
    public CommonResult<String> create(Payment payment) {
        return new CommonResult(200,"持续集成","测试持续集成到K8s+测试WebHook");
    }

}

16.4.7.7.编写模块主启动类

package org.openatom.springcloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CiK8s80 {

    public static void main(String[] args) {
        SpringApplication.run(CiK8s80.class, args);
    }

}

16.4.7.8.编写模块Dockerfile

注意:需要先在 项目根目录/springcloud-ci-k8s80下创建docker文件夹

FROM java:8 VOLUME /software MAINTAINER lingwh COPY ${project.build.finalName}.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]

#### 16.4.7.9.本地测试模块
    在浏览器中访问

http://localhost/ci/k8s

    返回数据
```json
{"code":200,"message":"持续集成","data":"测试持续集成到K8s"}

16.4.8.测试docker的maven插件

启动相关服务
在项目根目录下执行打包命令
mvn clean install
在项目根目录下执行复制生成的jar包到指定位置
cp springcloud-ci-k8s80/target/springcloud-ci-k8s80.jar springcloud-ci-k8s80/docker
在idea中打开docker的maven插件操作面板
制作Docker镜像并上传镜像到docker制作Docker镜像
点击docker:build

上传镜像到docker后在docker中为该镜像创建容器并启动docker中的容器
点击docker:build->点击docker:run

测试部署到docker中的服务
http://192.168.0.4/ci/k8s
返回结果
{"code":200,"message":"持续集成","data":"测试持续集成到K8s"}
在harbor私服中创建springcloud-eureka项目
推送到harbor私服
点击docker:build->点击docker:push
登录harbor私服查看刚才推送上去的的服务
http://192.168.0.5:5000/harbor/projects
点击springcloud-eureka这个项目
可以看到当前模块微服务已经被推送到了harbor私服中

16.4.9.持续集成Jekins相关配置

16.4.9.1.编写Jenkinsfile

在项目根目录下新建script文件夹,在script中新建JenkinsfileCiK8s,内容如下
//定义远程git仓库中项目的地址
def project_url='https://gitee.com/lingwh1995/springcloud-eureka.git'

def jenkins_ip='192.168.0.5'

node {
    echo '开始执行自动化...'
    /*指定在那台Jenkins节点上运行*/
    agent { label '${jenkins_ip}'}

    /*从远程仓库检出代码*/
    stage('从远程仓库检出代码') {
        echo '开始 从远程仓库检出代码...'
        checkout([
            $class: 'GitSCM',
            branches: [[name: '*/master']], extensions: [],
            userRemoteConfigs: [[url: "${project_url}"]]
        ])
        echo '完成 从远程仓库检出代码...'
    }

    /**
     * maven命令扩展:实现多模块情况下只针对某一个模块打包
     * -pl, --projects
     *      Build specified reactor projects instead of all projects
     *      指定项目其中的一个模块及其依赖
     *  -am, --also-make
     *      If project list is specified, also build projects required by the list
     *      自动构建该模块所依赖的其他模块
     *
     */
    stage('打包->安装->构建镜像->推送到私服->删除docker中本地镜像') {
        echo '开始 打包->安装->构建镜像->推送到私服->删除docker中本地镜像...'
        //如果install的是一个模块或者是多个模块
            //执行遍历依次次打包涉及的模块
        //如果是install的是整个项目
            //一次性打包整个项目
        sh "mvn clean install -T 1C -Dmaven.test.skip=true -Dmaven.compile.fork=true -pl springcloud-ci-docker80 -am"
        echo '完成 打包->安装->构建镜像->推送到私服->删除docker中本地镜像...'
    }

    /**
     *安装Publish Over SSH插件,使用插件的功能触发远程的shell脚本的执行
     */
    stage('自动部署上传到私服中的所有镜像到docker') {
        echo '开始 自动部署上传到私服中的所有镜像到k8s...'
        sshPublisher(
            publishers:
                [
                    sshPublisherDesc(
                        configName: 'cik8s',
                        transfers: [
                            sshTransfer(
                                cleanRemote: false,
                                excludes: '',
                                execCommand: "cd / && ./springcloud-ci-k8s.sh",
                                execTimeout: 600000,
                                flatten: false,
                                makeEmptyDirs: false,
                                noDefaultExcludes: false,
                                patternSeparator: '[, ]+',
                                remoteDirectory: '',
                                remoteDirectorySDF: false,
                                removePrefix: '',
                                sourceFiles: ''
                            )
                        ],
                        usePromotionTimestamp: false,
                        useWorkspaceInPromotion: false,
                        verbose: false
                    )
                ]
       )
       echo '结束 自动部署上传到私服中的所有镜像到k8s...'
    }

    echo '完成执行自动化...'
}
注意事项
执行Jenkinsfile中执行了mvn install命令后,就会触发 将生成的jar拷贝到docker文件夹中->build镜像->tag镜像->push镜像 这些操作,这是由于在pom.xml中把这些操作都和install命令绑定在了一起,所以才会有这样的效果

16.4.9.2.在Jekins中配置项目

新建任务
DashBoard->新建任务->输入任务名称(springcloud-eureka)->流水线->确定

配置如下字段
配置流水线
a.定义
Pipeline script from SCM(点击下拉框选择)
b.定义->SCM
Git(点击下拉框选择)
c.定义->SCM->Repositories(根据自己的项目信息进行配置)
Repository URL
https://gitee.com/lingwh1995/springcloud-eureka.git
d.定义->SCM->脚本路径(根据自己的项目信息进行配置)
script/JenkinsfileCiK8s

16.4.9.3.编写yaml和持续集成脚本

在192.168.0.4编写springcloud-ci-k8s.yaml
cat > springcloud-ci-k8s.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: springcloud-ci-k8s80
spec:
  replicas: 1
  selector:
    matchLabels:
      app: springcloud-ci-k8s80
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: springcloud-ci-k8s80
    spec:
      imagePullSecrets:
      - name: harbor-login
      containers:
      - name: springcloud-ci-k8s80
        image: 192.168.0.5:5000/springcloud-eureka/springcloud-ci-k8s80:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80    #containerPort是在pod控制器中定义的、pod中的容器需要暴露的端口

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: springcloud-ci-k8s80
  name: springcloud-ci-k8s80
  namespace: default
spec:
  ports:
  - name: springcloud-ci-k8s80
    protocol: TCP
    targetPort: 80
    nodePort: 30090
    port: 80
  selector:
    app: springcloud-ci-k8s80
  type: NodePort
EOF
在192.168.0.4上编写持续集成脚本
cd / &&
cat > springcloud-ci-k8s.sh << EOF
kubectl apply -f springcloud-ci-k8s.yaml
EOF
赋予可执行权限
chmod +x springcloud-ci-k8s.sh

16.4.10.测试持续集成微服务到minikube中或k8s中

16.4.10.1.测试持续集成微服务到minikube中

不用删除192.168.0.4中docker中在前面环节产生的镜像和容器,因为minikube使用的是minikube内部的docker拉取镜像

访问项目主页,点击构建按钮
http://192.168.0.5:8080/jenkins/
访问之前需要先在192.168.0.4上开放相关端口并开启端口转发
firewall-cmd --zone=public --add-port=9080/tcp --permanent &&
firewall-cmd --reload &&
kubectl port-forward --address 0.0.0.0 service/springcloud-ci-k8s80 9080:80
在浏览器中访问
http://192.168.0.4:9080/ci/k8s
返回结果
{"code":200,"message":"持续集成","data":"测试持续集成到K8s"}

16.4.10.使用Webhook触发持续集成

16.4.10.1.webhook的作用

在前面的环节中,访问项目主页,点击构建按钮后才能触发持续集成,使用webhook可以更方便的触发持续集成,配置好webhook时,当提交代码时就会触发持续集成

16.4.10.2.使用webhook前准备工作

jenkins安装Gitee插件

详细参考-> jenkins安装Gitee插件

搭建内网穿透

详细参考-> 搭建内网穿透 搭建好了内网穿透后,可以使用新的地址来访问jenkins 不使用内网穿透访问jenkins的地址是

http://192.168.0.5:8080/jenkins/
使用内网穿透访问jenkins的地址是
http://8sybmw.natappfree.cc/jenkins

16.4.10.3.配置使用webhook

使用内网穿透访问jenkins的地址是
http://8sybmw.natappfree.cc/jenkins
在jenkins中配置job
jenkins具体项目->配置->构建触发器->Gitee webhook 触发构建->Gitee WebHook 密码—>得到密码 0d71d48f211af16c477cf9c817ac612d

配置gitee的webhook
进入gitee的webhook配置界面(这里的url根据自己的项目进行修改)
https://gitee.com/lingwh1995/springcloud-eureka/hooks
点击添加webHook->填写URL和WebHook 密码/签名密钥
URL
http://8sybmw.natappfree.cc/jenkins/gitee-project/springcloud-eureka
WebHook 密码/签名密钥(上面在jenkins中生成的)
0d71d48f211af16c477cf9c817ac612d

测试webhook是否配置成功(可以测试,也可以不测试)
点击测试->查看更多

16.4.10.4.配置使用的Jenkinsfile

DashBoard->点击springcloud-eureka->配置->流水线->脚本路径->输入 script/JenkinsfileCiK8s

16.4.10.5.测试使用Webhook触发持续集成

修改springcloud-eureka/springcloud-ci-k8s80/src/main/java/org/openatom/springcloud/controller/CiK8sController.java中代码为
package org.openatom.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.openatom.springcloud.entities.CommonResult;
import org.openatom.springcloud.entities.Payment;

@RestController
public class CiK8sController {


    @GetMapping("/ci/k8s")
    public CommonResult<String> create(Payment payment) {
        return new CommonResult(200,"持续集成","测试持续集成到K8s+测试WebHook");
    }

}
在git中提交代码

查看webhook触发jenkins构建
http://8sybmw.natappfree.cc/jenkins/job/springcloud-eureka/
访问之前需要先在192.168.0.4上开放相关端口并开启端口转发
firewall-cmd --zone=public --add-port=9080/tcp --permanent &&
firewall-cmd --reload &&
kubectl port-forward --address 0.0.0.0 service/springcloud-ci-k8s80 9080:80
在浏览器中访问
http://192.168.0.4:9080/ci/k8s
返回数据
{"code":200,"message":"持续集成","data":"测试持续集成到K8s+测试WebHook"}
上次编辑于: 2022/9/9 06:18:47
贡献者: lingwh
评论