微服务[学成在线] day20:项目部署与持续集成(DevOps)

微服务[学成在线] day20:项目部署与持续集成(DevOps)

😎 知识点概览

为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。

本章节为【学成在线】项目的 day20 的内容。

  •  原讲义中对该章节的 gitlabjenkins 安装步骤以及部署容器的内容和步骤描述得不够详细,在本文中做出了补充,详细的描述每个步骤。
  •  本章节建议还是尝试看笔记来完成一次操作,然后再去看视频资料,这样能理解得更深刻。

目录

内容会比较多,可以根据目录进行按需查阅。

一、DevOps介绍

DevOps 是 DevelopmentOperations 两个词的缩写,引用百度百科的定义:

image-20200607210842378

DevOps 是一种方法或理念,它涵盖开发、测试、运维的整个过程。DevOps 是提高软件开发、测试、运维、运营等各部门的沟通与协作质量的方法和过程,DevOps 强调软件开发人员与软件测试、软件运维、质量保障(QA)部门之间有效的沟通与协作,强调通过自动化的方法去管理软件变更、软件集成,使软件从构建到测试、发布更加快捷、可靠,最终按时交付软件。

image-20200607210903849

DevOps 兴起于2009年,近年来由于云计算、互联网的发展,促进了DevOps的基础设施及工具链的发展,涌现了一大批优秀的工具,这些工具包括开发、测试、运维的各各领域,例如:GitHub、Git/SVN、Docker、Jenkins、Hudson、Ant/Maven/Gradle、Selenium、QUnit、JMeter 等。下图是DevOps相关的工具集:

image-20200607210927381

二、使用GitLab管理项目

0x01 安装Gitlab

GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务。

GitLab 与 GitHub的功能相似,通常企业使用GitLab在局域网搭建自己的Git代码管理仓库

拉取gitlab、redis、postgresql,gitlab 依赖 redispostgresql

sudo docker pull sameersbn/redis
sudo docker pull sameersbn/postgresql
sudo docker pull gitlab/gitlab-ce:latest

新建容器的目录

sudo mkdir /var/docker/postgresql/data -p
sudo mkdir /var/docker/redis/data -p
sudo mkdir /var/docker/gitlab/data -p

创建 postgresql、redis 容器:

# 创建postgresql容器
sudo docker run --name postgresql -d --privileged=true -e 'DB_NAME=gitlabhq_production' -e 'DB_USER=gitlab' -e 'DB_PASS=123123' -e 'DB_EXTENSION=pg_trgm' -v /var/docker/postgresql/data:/var/lib/postgresql sameersbn/postgresql

# 创建redis容器
sudo docker run --name redis -d --privileged=true -v  /var/docker/redis/data:/var/lib/redis sameersbn/redis

创建gitlab容器:

sudo docker run --name gitlab -d --link postgresql:postgresql --link redis:redisio \
--hostname 10.1.1.161 -p 10022:22 -p 8910:80 -p 8911:443 -e 'GITLAB_PORT=8899' \
-e 'GITLAB_SSH_PORT=10022' \
-e 'GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string' \
-e 'GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alpha-numeric-string' \
-e 'GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string' \
-e  'GITLAB_HOST=10.1.1.161' \
-e 'SMTP_AUTHENTICATION=login' \
-v /var/docker/gitlab/data:/home/git/data docker.io/gitlab/gitlab-ce
  • 使用 \ 来标识shell命令的换行,在shell命令过长的情况下使用 \ 换行可以使内容更加清晰
  • --link:可以用来链接2个容器,使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,并且接收容器可以获取源容器的一些数据,如源容器的环境变量

浏览器访问:http://10.1.1.161:8910

初次访问需要等待一段时间。

查看 gitlab的启动日志

sudo docker logs -f gitlab

image-20200607182758861

启动完成后,配置初始密码,默认用户名为 root

image-20200607183035804

0x02 创建项目

登录 gitlab 后访问 http://10.1.1.161:8910/projects/new

填写项目的基本信息

image-20200608183302202

项目构建成功后,得到一个项目的链接 http://10.1.1.161:8910/root/xc-services-project

image-20200608175145298

0x03 将项目推送至gitlab

打开 cmd,进入到项目的目录下

1、运行 git init 初始化项目的git配置

2、在项目根目录下创建 .gitignore 文件,将一些编译后生成的文件排除在外 不上传至git仓库,内容如下

.idea
*/target/*.*
*/target/**/*.*
*.class
*.iml
##ignore this file##
.classpath
.project
.settings     
 ##filter databfile、sln file##
*.mdb  
*.ldb  
*.sln   
##class file##
*.com  
*.class  
*.dll  
*.exe  
*.o  
*.so 
# compression file
*.7z  
*.dmg  
*.gz  
*.iso  
*.jar  
*.rar  
*.tar  
*.zip  
*.via
*.tmp
*.err
# OS generated files #  
.DS_Store  
.DS_Store?  
._*  
.Spotlight-V100  
.Trashes  
Icon?  
ehthumbs.db  
Thumbs.db

3、执行 git add . 命令,暂存当前目录下的所有子目录以及文件到git记录

4、执行 git commit -m "第一次提交" 将暂存的记录正式提交到 git 记录内,-m 参数的内容为描述信息

5、执行以下命令,设置远程仓库的地址

git remote add origin "http://10.1.1.161:8910/root/xc-services-project.git" 

6、执行 git push origin master 推送代码到远程仓库

image-20200608184308041

推送成功,查看远程仓库

image-20200608194951105

三、部署微服务到Docker

0x00 Docker简介

服务器虚拟化主要有两种技术:

1、Hypervisor也叫VMM(virtual machine monitor)即虚拟机监视器

Hypervisor 是一种将操作系统与硬件抽象分离的方法,实现在宿主机(host machine)上能同时运行多个客户机(guest machine),每个客户机就是一个虚拟机,这些虚拟机高效地分享宿主机的硬件资源。

如下图:

image-20200608135503026

在服务器(宿主机)上安装操作系统,并安装hypervisor虚拟机管理软件,如VMware、VirtualBox等,由
hypervisor管理多个虚拟机,每个虚拟机上需要安装客户操作系统、依赖库、应用软件。

2、Containers容器化技术

image-20200608135556836

容器技术中 docker 引擎取代了 hypervisor,docker引擎是运行在住宿操作系统上的一个进程,该进程管理了多个docker容器,每个docker容器集成了应用软件、依赖库,容器之间相互隔离。

3、技术对比

资源占用:

虚拟机由于是独立的操作系统,占用资源比docker多。

启动速度:

虚拟机包括操作系统,启动虚拟机相当于启动一个操作系统,容器则不一样,容器中只包括操作系统的内核,启动
一个容器实例相当于启动一个进程,容器的启动速度比虚拟机快。

体积:

容器包括操作系统内核、软件及依赖库,虚拟机不仅包括软件和依赖库还将完整的操作系统打包进去,虚拟机的体
积比容器大的多。

4、Docker 容器架构

image-20200608135730960

  • Docker daemon(Docker守护进程)

    Docker守护进程是部署在操作系统上,负责支撑 Docker Container 的运行以及本地 Image 的管理。

  • Docker client

    用户不直接操作Docker daemon,用户通过 Docker client 访问 DockerDocker client 提供
    pull、run 等操作命令实现对docker的操作。

  • Docker Image

    Docker 镜像就是一个只读的模板。 例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Tomcat或用户需要的其它应用程序。 镜像可以用来创建 Docker 容器。 Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

  • Docker Container

    Docker 利用容器来运行应用。容器是从镜像创建的运行实例。它可以被启动、开始、停
    止、删除。每个容器都是相互隔离的、保证安全的平台。打个比方,镜像相当于类,容器相当于对象。

  • Docker Registry

    Docker 仓库分为公开仓库(Public)和私有仓库(Private)两种形式 最大的公开仓库是
    Docker Hub,存放了数量庞大的镜像供用户下载。 用户也可以在本地网络内创建一个私有仓库。 当用户创建自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

0x01 安装docker

Docker 可以运行在 MAC、Windows、Centos、DEBIAN、UBUNTU 等操作系统上,提供社区版和企业版,本教程基于Centos安装Docker。Centos6 对 docker 支持的不好,使用 docker 时建议升级到 centos7

1、在 Centos7 上安装Docker

直接通过yum安装即可:

yum install -y docker

启动docker:service docker start

查询docker版本: docker version

关于的 docker 的一些常用的命令和操作,参考 https://www.runoob.com/docker/docker-tutorial.html

0x02 部署流程

本项目微服务采用 SpringBoot 开发,将每个微服务工程打成Jar 包,最终在 Docker 容器中运行 jar,部署流程如下:

1、SpringBoot 工程最终打成 Jar

2、创建Docker镜像

3、创建容器

4、启动容器

0x03 打包

1、使用 maven 的打包插件:

将下边的插件依赖拷贝到微服务工程中,本例子将学成在线的 Eureka 工程打包:

<build>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

完整的 Eureka 工程 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>xc-framework-parent</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../xc-framework-parent/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>xc-govern-center</artifactId>
    <dependencies>
        <!-- 导入Eureka服务的依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、maven打包

在工程目录运行:mvn clear package

或通过IDEA执行 clear package 打包命令。

打包成功,如下图:

image-20200608151714281

打包成功后在 target 目录下生成一个 jar包

0x04 创建镜像

将上一步打包好的 jar 包拷贝到我们要部署微服务的Linux服务器,准备创建镜像。

安装jdk环境

sudo apt-get install openjdk-8-jdk

测试 jar 包是否可以运行,执行:java -jar xc-govern-center-1.0-SNAPSHOT.jar

image-20200608153244826

访问服务器地址 http://10.1.1.162:50101/

注意我这里的虚拟机IP地址为 10.1.1.162 ,测试的时候要更换你虚拟机的地址

image-20200608160630154

jar 包的目录下编写 Dockerfile 文件,执行 vim Dockerfile

FROM java:8
ENV ARTIFACTID xc-govern-center
ENV ARTIFACTVERSION 1.0-SNAPSHOT
ENV HOME_PATH /home
WORKDIR $HOME_PATH
ADD $ARTIFACTID-$ARTIFACTVERSION.jar $HOME_PATH/$ARTIFACTID.jar
ENTRYPOINT ["java", "-jar", "xc-govern-center.jar"]

dockerfile说明文档: https://www.runoob.com/docker/docker-dockerfile.html

在 Dockerfile 文件所在目录执行以下命令

docker build -t xc-govern-center:1.0-SNAPSHOT .

镜像创建成功,查询镜像

0x05 创建容器

基于前面我们生成的xc-govern-center:1.0-SNAPSHOT 镜像创建容器,容器名称为 xc-govern-center-test

docker create --name xc-govern-center-test -t -p 50101:50101 -e PORT=50101 \
-e EUREKA_SERVER=http://10.1.1.162:50101/eureka/,http://10.1.1.162:50102/eureka/ xc-govern-center:1.0-SNAPSHOT

docker create 语法 与 run 相同,create表示只创建不运行,而run是创建容器后并马上运行。

run命令说明文档 https://www.runoob.com/docker/docker-run-command.html

EUREKA_SERVER 为一个变量,用于服务启动时指定的 eureka 负载均衡到哪些 eureka 服务上,跟我们在 idea 的配置是一个道理,如下图

image-20200608165054580

容器创建成功后会回显一个容器的id,可通过 docker ps -a 命令看到该容器的信息

image-20200608165256155

0x06 启动容器

运行以下命令,启动容器

docker start xc-govern-center-test

容器启动完成可以通过 docker ps 查询正在运行中的容器。

image-20200608173443990

测试访问

image-20200608174322226

使用 docker logs -f xc-govern-center-test 可以查看容器的运行日志

image-20200608174430566

这里报错是因为我们做了负载均衡,两个 eureka 需要相互注册,但这里我们只启动了一个 eureka 服务,但不影响正常使用。

0x07 停止与删除

要删除的一个镜像重新创建,需要通过如下步骤:

1、停止正在运行的容器

docker stop 容器名

例如:docker stop xc-govern-center-test

2、删除容器

docker rm 容器名

例如:docker rm xc-govern-center-test

3、删除镜像

docker rmi 镜像名或镜像Id

例如:docker rmi xc-govern-center:1.0-SNAPSHOT

0x08 maven构建镜像

上边构建的过程是通过手工一步一步完成,maven 提供 docker-maven-plugin 插件可完成从打包到构建镜像、构建容器等过程。

1、将服务工程的 pom.xml 复制一份,命名为 pom_docker.xml 并将 build 标签的内容替换下面的内容

<build>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            <!--docker镜像相关的配置信息-->
            <configuration>
                <!--镜像名,这里用工程名-->
                <imageName>${project.artifactId}-${project.version}</imageName>
                <!--Dockerfile文件所在目录-->
 <dockerDirectory>${project.basedir}/src/main/resources</dockerDirectory>
                <!--TAG,这里用工程版本号-->
                <imageTags>
                    <imageTag>${project.version}</imageTag>
                </imageTags>
                <imageName>${project.artifactId}:${project.version}</imageName>
                <!--构建镜像的配置信息-->
                <resources>
                    <resource>
                        <targetPath>/</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${project.artifactId}-${project.version}.jar</include>
                    </resource>
                </resources>
            </configuration>
        </plugin>
    </plugins>
</build>

2、将 Dockerfile 文件拷贝到 src/main/resources

3、将更新的内容提交到gitlab,并在服务器内拉取项目代码到本地

提交并推送新增的配置到远程仓库

image-20200608200850974

在服务器内拉取项目代码到本地

image-20200608201008309

4、删除之前创建的 xc-govern-center 镜像

# 停止容器
sudo docker stop xc-govern-center-test
# 删除容器
sudo docker rm xc-govern-center-test
# 删除镜像
sudo docker rmi xc-govern-center:1.0-SNAPSHOT

5、进入工程根目录( pom_docker.xml 所在目录)执行

安装 maven 环境

sudo apt install maven

添加 maven 仓库国内源以及配置 pluginGroup,编辑 /usr/share/maven/conf/settings.xml 文件

mirrors 标签下添加如下内容

<mirror>
    <id>aliyun-public</id>
    <mirrorOf>*</mirrorOf>
    <name>aliyun public</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>

pluginGroups 标签下加入以下内容

 <pluginGroup>com.spotify</pluginGroup> 

如下图所示

image-20200608202134759

给项目的目录设置权限,否则打包的时候会报错

sudo chown -R 1000:1000 ~/xc-services/

进入到 eureka 工程下,执行打包命令

mvn -f pom_docker.xml clean package -DskipTests docker:build

等待依赖下载完成后开始构建镜像,创建镜像成功,结果如下:

image-20200608205339883

使用该镜像创建容器

docker create --name xc-govern-center-test -t -p 50101:50101 -e PORT=50101 \
-e EUREKA_SERVER=http://10.1.1.162:50101/eureka/,http://10.1.1.162:50102/eureka/ xc-govern-center:1.0-SNAPSHOT

容器创建成功

image-20200608205458488

四、持续集成

0x01 持续集成介绍

需求分析

传统的软件开发流程如下:

1、项目经理分配模块给开发人员

2、每个模块的开发人员并行开发,并进行单元测试

3、开发完毕,将代码集成部署到测试服务器,测试人员进行测试。

4、测试人员发现bug,提交bug、开发人员修改bug

5、bug修改完毕再次集成、测试。

有哪些问题?

1、模块之间依赖关系复杂,在集成时发现大量bug

2、测试人员等待测试时间过长

3、软件交付无法保障

解决上述问题的思考:

1、能否把集成测试时间提前?

2、能否使用自动化工具代替人工集成部署的过程?

什么是持续集成?

持续集成(Continuous integration)简称 CI,持续集成的思想是每天要多次将代码合并到主干,并进行集成、测试,这样就可以提早发现错误,进行修正。持久集成也属于 DevOps

持续集成的好处:

1、自动化集成部署,提高了集成效率。

2、更快的修复问题。

3、更快的进行交付。

4、提高了产品质量。

本项目持续集成流程

image-20200608210048479

0x02 搭建环境

安装Jenkins

Jenkins是一个领先的开源自动化服务器,可用于自动化构建,测试,部署软件等相关任务。

官网地址:https://jenkins.io

image-20200608210213712

image-20200608210914373

1、使用Docker安装Jenkins

本教程在 docker 下安装 Jenkins

拉取镜像

docker pull jenkinsci/blueocean

创建容器挂载目录,并且赋予权限

mkdir /var/docker/jenkins -p
sudo chown -R 1000:1000 /var/docker/jenkins  # 这里需要为jenkins的目录赋予1000权限

注意:在安装jenkins时候,挂在文件夹/var/docker/jenkins 的归属用户id必须是1000,否则会抛出无操作权限异常。

创建容器:

docker run -itd --name jenkins -u root -p 8900:8080 --privileged=true \
-v /var/docker/jenkins:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /home/jenkins:/home docker.io/jenkinsci/blueocean
  • docker run 创建容器并且运行

  • docker create 只创建而不运行

访问你虚拟机的 8900 端口,我这里的地址为 http://10.1.1.161:8900

初次运行 Jenkins 会经过一个安装过程,一般情况使用默认配置,下一步安装即可,其中一步需要输入密码,如下图

image-20200606140413863

出现上边的画面需要输入 jenkins 的初始密码,查看容器的运行日志,从日志中找到初始里面

sudo docker logs -f jenkins

日志如下图

image-20200607111618576

日志中没有找到初始密码?我们可以直接在该容器挂载到本地目录的文件下查看。

这里我们在创建容器时指定了 -v /var/docker/jenkins:/var/jenkins_home ,表示将 /var/docker/jenkins 目录映射到 jenkins 容器上的 /var/jenkins_home 目录上,所以我们可以直接在本地执行如下命令,查看 jenkins 的初始密码

cat /var/docker/jenkins/secrets/initialAdminPassword

初始密码如下

image-20200607101707269

输入初始密码到 jenkins 页面后,继续完成后续的初始化步骤。

如果出现一直停留在在 ready 页面,如下图

image-20200607111259258

修改 jenkins 的配置文件 hudson.model.UpdateCenter.xml 将 url 修改为国内的 jenkins

https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

运行以下命令,并替换url标签内值为上述地址

vim /var/docker/jenkins/hudson.model.UpdateCenter.xml

image-20200607111740728

输入密码后进入到插件安装页面

image-20200607112006171

如果愿意等的话,可以选择第一个安装所有默认推荐的插件,但是大概需要1小时左右才能安装完成。

为了节省时间我们可以选择第二个,取消默认选择的插件,然后继续下一步操作。

如果选择了安装推荐,则需要等待插件安装完成,如下图

image-20200607112232774

插件安装完成后,设置管理员信息

image-20200607161327005

本项目使用 Jenkins 需要配置Jdk1.8、Git、maven。

1)Maven 安装:

到官网下载最新版的maven http://maven.apache.org/download.cgi

解压 maven 压缩包到容器的挂载目录下

tar zxvf apache-maven-3.6.3-bin.tar.gz -C /var/docker/jenkins/lib/

在控制台 Global Tool Configuration 配置maven路径为容器内的目录 /var/jenkins_home/lib/apache-maven-3.6.3/

image-20200607171140658

2)Jdk安装配置

如果jenkins镜像里面有该环境则不需要再安装

宿主机安装java

sudo apt-get install openjdk-8-jdk

拷贝本地 JDK 环境到 jenkins 容器的挂载目录的 lib 目录下

mkdir -p /var/docker/jenkins/lib/java-1.8.0-openjdk-amd64 && cp -r /usr/lib/jvm/java-1.8.0-openjdk-amd64/* /var/docker/jenkins/lib/java-1.8.0-openjdk-amd64

在 jenkins 设置 jdk的路径为 /var/jenkins_home/lib/java-1.8.0-openjdk-amd64,该路径为容器里面的路径

image-20200606140553273

3)Git安装方法同上

如果jenkins镜像里面有该环境则不需要再安装

宿主机安装git

apt-get install git

复制git到容器挂载的目录下

mkdir /var/docker/jenkins/lib/git && cp -r /usr/lib/git-core/* /var/docker/jenkins/lib/git

jenkins控制台上配置容器中的 git 文件的路径 /var/jenkins_home/lib/git/git

image-20200607175332443

2、配置 SSH Remote Hosts

SSH remote hosts 是 Jenkins 提供的一种远程访问 ssh 服务器的方法,通过如下步骤测试此功能:

1)安装插件SSH plugin

访问虚拟机的地址 http://10.1.1.161:8900/pluginManager/

从可选插件中选择SSH Plugin进行安装

image-20200607171628455

安装成功可在已安装插件中查询:

image-20200607171720075

2)配置凭证

访问虚拟机 http://10.1.1.161:8900/credentials/store/system/domain/_/newCredentials

配置部署服务的虚拟机的 SSH 登录账号和密码:

image-20200606140717614

3)配置SSH sites

访问 http://10.1.1.161:8900/configure

找到 ssh sites 的配置,输入你要远程配置的服务器 IP端口 等信息,并选择你刚才添加的凭证信息。

image-20200607172721808

4)在任务构建中编写脚本

下拉到 “构建” 的选项,选择 Execute shell 的选项

image-20200607174116753

选择刚才添加的 ssh sites, 填写你要执行的shell命令,然后保存

image-20200607174305189

点击保存后,点击左边的立即构建,测试是否能够执行 shell 命令到指定的服务器上。

image-20200607174350348

远程命令执行成功,执行了 echo 命令写入内容到文件上,如下图

image-20200607174407110

搭建Docker私有仓库

微服务的镜像会上传到 Docker 仓库保存,常用的公网 Docker 仓库有阿里云,网易云等,在企业局域网也可以搭建自己的 Docker 私有仓库,本教程使用 Docker 提供的私有仓库 registry

进入 Docker 私有仓库所在服务器执行:

1、安装 Docker

2、创建私有仓库容器

sudo docker run --name docker-registry -d -p 5000:5000 registry

执行结果如下:

image-20200607180928284

上边显示 registry 镜像已经创建,并且 docker-registry 容器已经启动成功。

访问:http://10.1.1.161:5000/v2/_catalog

响应结果如下:

{"repositories":[]}

上边的响应结果说明在 docker 私有仓库中还没有镜像。

默认 docker-registry 只允许 https 提交镜像,如下配置使 docker-registry 支持 http

在宿主机 /etc/docker 下,创建 daemon.json 文件,写入:

{
    "insecure-registries":["10.1.1.161:5000"]
}

重启 docker:

systemctl restart docker.service

启动 docker-registry

sudo docker start docker-registry

安装Gitlab

由于前面的内容就已经需要用到 gitlab,所以在本文开始的内容中已经介绍了整个 gitlab 安装部署流程

编写pom

本例子将 xc-govern-center 工程使用 Jenkins 进行构建。

在 xc-govern-center 工程根目录编写 pom_docker_registry.xml

此文件相比工程原有 pom_docker.xml 增加了docker-maven-plugin 插件,其作用是构建docker镜像并将镜像推送到 Docker 私有仓库,我的docker仓库地址是 10.1.1.161:5000

<?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>xc-framework-parent</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../xc-framework-parent/pom.xml</relativePath>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xuecheng</groupId>
    <artifactId>xc-govern-center</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <!--docker镜像相关的配置信息-->
                <configuration>
                    <!--镜像名,这里用工程名-->
                    <imageName>${project.artifactId}-${project.version}</imageName>
                    <!--Dockerfile文件所在目录-->
                    <dockerDirectory>${project.basedir}/src/main/resources</dockerDirectory>
                    <!--TAG,这里用工程版本号-->
                    <imageTags>
                        <imageTag>${project.version}</imageTag>
                    </imageTags>
                    <!--私有docker仓库地址-->
                    <registryUrl>10.1.1.161:5000</registryUrl>
                    <pushImage>true</pushImage>
                    <!--构建后的镜像名称-->
                    <imageName>10.1.1.161:5000/${project.artifactId}:${project.version}
                    </imageName>
                    <!--构建镜像的配置信息-->
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.artifactId}-${project.version}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

稍后我们结合 jenkins 来进行自动构建。

0x03 创建持续集成任务

创建jenkins的构建任务

新建一个任务 xc-edu,选择 “构建一个自由风格的软件项目” ,点击确定

image-20200609173403898

配置git仓库

1、配置git凭证

此凭证用于远程从 git 仓库克隆工程源代码

输入 git 仓库的账号和密码,这里如果使用码云,下边需要配置码云的账号和密码。

访问 http://10.1.1.161:8900/credentials/store/system/domain/_/newCredentials

image-20200610155838201

2、在刚才我们新建的 xc-edu 任务下配置 git 仓库地址,此地址即 xc-edu 项目的地址

image-20200609170051196

配置自动构建流程

实现目标:

使用 jenkins 重复构建不要产生重复镜像

使用 jenkins 停止容器、删除容器、删除镜像之间进行判断

构建过程分为三步:

本例子以构建 xc-govern-center 工程为例,其它工程构建方式类似。

1、停止容器、删除容器、删除镜像

shell脚本如下:

#!/bin/bash
result=$(docker ps | grep "192.168.101.64:5000/xc-govern-center")
if [[ "$result" != "" ]]
then
echo "stop xc-govern-center"
sudo docker stop xc-govern-center
fi
result1=$(docker ps -a | grep "192.168.101.64:5000/xc-govern-center")
if [[ "$result1" != "" ]]
then
echo "rm xc-govern-center"
sudo docker rm xc-govern-center
fi
result2=$(docker images | grep "192.168.101.64:5000/xc-govern-center")
if [[ "$result2" != "" ]]
then
echo "192.168.101.64:5000/xc-govern-center:1.0-SNAPSHOT"
sudo docker rmi 192.168.101.64:5000/xc-govern-center:1.0-SNAPSHOT
fi
  1. 检查指定镜像是否有容器在运行,有则停止容器

  2. 检查指定镜像是否创建了容器,有则删除容器

  3. 检查是否存在指定镜像,存在则删除该镜像

添加一个构建步骤

image-20200609175013408

选择我们的服务器地址,将脚本内容复制 command 中,作为第一步需要执行的内容

注意,如果在jenkins远程执行的 SSH凭证root 用户,需要在远程服务器上执行以下命令,将当前用户加入到 docker 组内

sudo usermod -aG docker $USER

2、配置maven步骤

添加一个构建步骤,选择 调用顶层maven目标,如下图

image-20200609175128767

配置第二步,执行如下maven指令

clean package -f xc-govern-center/pom_docker_registry.xml -DskipTests docker:build

如下图所示

image-20200609175242308

3、配置docker步骤

继续添加一个执行 shell 的构建步骤

image-20200609175314254

配置第三步,从 docker 私有仓库拉取镜像并创建容器,启动容器

# 如果指定容器容器不存在则拉取后再进行创建,并且创建后自动执行
docker run --name xc-govern-center -p 50101:50101 -idt 10.1.1.161:5000/xc-govern-center:1.0-SNAPSHOT
docker logs xc-govern-center

注意使用log输出容器启动状态时不要加-f参数,否则会一直输出容器日志,导致任务一直处于构建中。c

如下图

image-20200611152804801

添加完第三步后,点击保存

执行任务

1、进入任务页面,点击 “立即构建”

image-20200609171946626

2、开始构建,查看日志

image-20200610165006790

构建成功,如上图所示。

使用Gitlab通知Jenkins进行自动部署

1、安装gitlab hook插件

image-20200610173808935

2、配置webhook

GitLab 中使用 webhookjenkins 通知,当有代码 push 后将通知 jenkins 进行构建。

1、新建一个任务 "xc-edu",在 Jenkins 中找到通知地址

image-20200607103230924

2、进入Jenkins设置允许匿名访问jenkins,这样 GitLab 才能访问通知地址去通知 Jenkins 进行工作

进入到配置页面 http://10.1.1.161:8900/configure ,取消认证的勾选,认证默认是开启的。

image-20200610174958486

3、使用管理员帐号 root 登录 Gitlab,密码就是你 gitlab 搭建好之后第一次输入的密码,设置允许请求本地网络服务

image-20200607103253653

4、设置钩子地址,即 jenkins 中的项目地址

访问项目的配置地址 http://10.1.1.161:8910/root/xc-services-project/-/settings/integrations

点击开启webhooks

image-20200610175240440

jenkins 的触发地址设置到 gitlabwebhooks 地址中 ,点击最下面的添加即可。

image-20200610175458275

如果出现添加失败,并且显示如下错误

image-20200610175721074

参考 https://blog.csdn.net/anqixiang/article/details/104968469 即可解决,并添加webhooks的白名单

由于webhooks的钩子是允许匿名访问的,建议还是设置白名单来提高安全性

image-20200610175956666

配置完成后再回到之前的操作,添加webhooks的钩子地址即可,添加成功的效果如下

image-20200610180136855

3、测试

尝试提交一个代码更新,观察jenkins是否能够收到通知并且执行构建任务

image-20200611151650255

jenkins开始自动构建

image-20200611151643554

构建成功,并自动启动容器

image-20200611152118926

0x04 思考一些问题

1、如何实现自动构建指定的服务工程?

需求分析

例如我们在整个微服务项目当中有A、B、C三个服务,在代码更新时只更新了 服务A 相关的代码,而 jenkins 进行自动部署的时候,只需要部署 服务A 的代码即可。

实现思路

  • Comment (regex) for triggering a build 不可用,该选项只匹配 merge request 的 commit
  • Gitlab 在同一个项目里面是否能够添加多个jenkins任务钩子?如何在gitlab上实现按需通知

😁 认识作者

作者:👦 LCyee ,一个向往体面生活的代码🐕

自建博客:https://www.codeyee.com

记录学习以及项目开发过程中的笔记与心得,记录认知迭代的过程,分享想法与观点。

CSDN 博客:https://blog.csdn.net/codeyee

记录和分享一些开发过程中遇到的问题以及解决的思路。

欢迎加入微服务练习生的队伍,一起交流项目学习过程中的一些问题、分享学习心得等,不定期组织一起刷题、刷项目,共同见证成长。

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://codeyee.com/archives/xuecheng-day20-devops.html