使用jenkins自动化部署mall-swarm



在微服务架构中,随着服务越来越多,服务的打包部署就会成为一个相当麻烦的事情。比如说我的mall-swarm项目目前就有8个服务需要部署,有没有什么办法让我们部署一次之后,只要点击执行就可以自动部署呢?当然有!下面我们使用Jenkins来完成一个微服务架构中的自动化部署工作。


1、基础环境部署

mall-swarm运行需要的系统组件如下,Docker容器中安装这些组件的方法直接参考该文章即可:mall在Linux环境下的部署(基于Docker容器)

组件 版本号
JDK 1.8
Mysql 5.7
Redis 3.2
Elasticsearch 6.4.0
MongoDb 3.2
RabbitMq 3.7.15
Nginx 1.10

1.1、运行配置要求

CenterOS7.6版本,推荐4G以上内存


1.2、部署相关文件


1.3、部署前准备

1)下载所有需要安装的Docker镜像

设置docker源(https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://k8spv7nq.mirror.aliyuncs.com"]
}

sudo systemctl daemon-reload
sudo systemctl restart docker
1
2
3
4
5
6
7
docker pull mysql:5.7
docker pull redis:3.2
docker pull nginx:1.10
docker pull rabbitmq:3.7.15-management
docker pull elasticsearch:6.4.0
docker pull kibana:6.4.0
docker pull mongo:3.2

2)elasticsearch

  • 需要设置系统内核参数,否则会因为内存不足无法启动。

    1
    2
    3
    4
    # 改变设置
    sysctl -w vm.max_map_count=262144
    # 使之立即生效
    sysctl -p
  • 需要创建/carloz/data/elasticsearch/data目录并设置权限,否则会因为无权限访问而启动失败。

    1
    2
    3
    4
    # 创建目录
    mkdir -p /carloz/data/elasticsearch/data/
    # 创建并改变该目录权限
    chmod 777 /carloz/data/elasticsearch/data

3)nginx

需要拷贝nginx配置文件,否则挂载时会因为没有配置文件而启动失败。

1
2
3
4
5
6
7
8
9
# 创建目录之后将nginx.conf文件上传到该目录下面
mkdir -p /carloz/data/nginx/

docker run -p 80:80 --name nginx \
-v /carloz/data/nginx/html:/usr/share/nginx/html \
-v /carloz/data/nginx/logs:/var/log/nginx \
-d nginx:1.10
docker container cp nginx:/etc/nginx/nginx.conf /carloz/data/nginx/
docker rm -f nginx

1.4、执行docker-compose-env.yml脚本

将该文件上传的linux服务器上,执行docker-compose up命令即可启动mall所依赖的所有服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
version: '3'
services:
mysql:
image: mysql:5.7
container_name: mysql
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
environment:
MYSQL_ROOT_PASSWORD: root #设置root帐号密码
ports:
- 3306:3306
volumes:
- /carloz/data/mysql/data/db:/var/lib/mysql #数据文件挂载
- /carloz/data/mysql/data/conf:/etc/mysql/conf.d #配置文件挂载
- /carloz/data/mysql/log:/var/log/mysql #日志文件挂载
redis:
image: redis:3.2
container_name: redis
command: redis-server --appendonly yes
volumes:
- /carloz/data/redis/data:/data #数据文件挂载
ports:
- 6379:6379
nginx:
image: nginx:1.10
container_name: nginx
volumes:
- /carloz/data/nginx/nginx.conf:/etc/nginx/nginx.conf #配置文件挂载
- /carloz/data/nginx/html:/usr/share/nginx/html #静态资源根目录挂载
- /carloz/data/nginx/log:/var/log/nginx #日志文件挂载
ports:
- 80:80
rabbitmq:
image: rabbitmq:3.7.15-management
container_name: rabbitmq
volumes:
- /carloz/data/rabbitmq/data:/var/lib/rabbitmq #数据文件挂载
- /carloz/data/rabbitmq/log:/var/log/rabbitmq #日志文件挂载
ports:
- 5672:5672
- 15672:15672
elasticsearch:
image: elasticsearch:6.4.0
container_name: elasticsearch
environment:
- "cluster.name=elasticsearch" #设置集群名称为elasticsearch
- "discovery.type=single-node" #以单一节点模式启动
- "ES_JAVA_OPTS=-Xms512m -Xmx512m" #设置使用jvm内存大小
volumes:
- /carloz/data/elasticsearch/plugins:/usr/share/elasticsearch/plugins #插件文件挂载
- /carloz/data/elasticsearch/data:/usr/share/elasticsearch/data #数据文件挂载
ports:
- 9200:9200
kibana:
image: kibana:6.4.0
container_name: kibana
links:
- elasticsearch:es #可以用es这个域名访问elasticsearch服务
depends_on:
- elasticsearch #kibana在elasticsearch启动之后再启动
environment:
- "elasticsearch.hosts=http://es:9200" #设置访问elasticsearch的地址
ports:
- 5601:5601
mongo:
image: mongo:3.2
container_name: mongo
volumes:
- /carloz/data/mongo/db:/data/db #数据文件挂载
ports:
- 27017:27017

上传完后在当前目录下执行如下命令:

1
2
3
4
5
6
7
8
# Create and start containers
docker-compose -f /carloz/data/docker-compose-env.yml up -d
# Stop and remove containers, networks, images, and volumes
docker-compose -f /carloz/data/docker-compose-env.yml down
# stop
docker-compose -f /carloz/data/docker-compose-env.yml stop
# start
docker-compose -f /carloz/data/docker-compose-env.yml start


1.5、对依赖服务进行以下设置

当所有依赖服务启动完成后,需要对以下服务进行一些设置。

1)mysql

需要创建mall数据库并创建一个可以远程访问的对象reader。

  • 将mall.sql文件拷贝到mysql容器的/目录下:

    1
    2
    3
    vim /carloz/data/mall.sql
    # 下载文件:https://gitee.com/macrozheng/mall-swarm/blob/master/document/sql/mall.sql
    docker cp /carloz/data/mall.sql mysql:/
  • 进入mysql容器并执行如下操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #进入mysql容器
    docker exec -it mysql /bin/bash
    #连接到mysql服务
    mysql -uroot -proot --default-character-set=utf8
    #创建远程访问用户
    grant all privileges on *.* to 'reader' @'%' identified by '123456';
    #创建mall数据库
    create database mall character set utf8;
    #使用mall数据库
    use mall;
    #导入mall.sql脚本
    source /mall.sql;

2)elasticsearch

需要安装中文分词器IKAnalyzer,并重新启动。

1
2
3
4
5
6
7
8
9
10
11
# 手动下载ik分词器,上传到docker中/usr/share/elasticsearch/plugins目录下
cd /carloz/data/elasticsearch/plugins
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.0/elasticsearch-analysis-ik-6.4.0.zip

tar -zxf elasticsearch-analysis-ik-v6.4.0.tar.gz
rm -f elasticsearch-analysis-ik-v6.4.0.tar.gz

docker exec -it elasticsearch /bin/bash
# 检查 /usr/share/elasticsearch/plugins 目录下的ik分词器是否存在
docker restart elasticsearch
docker logs -f elasticsearch

3)rabbitmq

需要创建一个mall用户并设置虚拟host为/mall。

  • 访问管理页面地址:http://192.168.145.137:15672/ img
  • 输入账号密码并登录:guest guest
  • 创建帐号并设置其角色为管理员:mall mall img
  • 创建一个新的虚拟host为:/mall img
  • 点击mall用户进入用户配置页面 img
  • 给mall用户配置该虚拟host的权限 img


2、可视化管理工具portainer

Portainer 是一款轻量级的应用,它提供了图形化界面,用于方便的管理Docker环境,包括单机环境和集群环境,下面我们将用Portainer来管理Docker容器中的应用。

1
docker pull portainer/portainer
  • 使用docker容器运行Portainer:
1
2
3
4
5
docker run -p 9000:9000 -p 8000:8000 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /carloz/data/portainer/data:/data \
-d portainer/portainer
  • 开放端口
1
2
3
firewall-cmd --permanent --add-port=9000/tcp
firewall-cmd --permanent --add-port=8000/tcp
firewall-cmd --reload
  • 修改客户端host
1
2
3
4
5
C:\Windows\System32\drivers\etc\
hosts
# 文件改为读写
192.168.145.137 czportainer.com
# 文件改为只读


3、jenkins安装配置

  • 使用gitee代替gitlab;
  • kubernetes集群(暂时不用), 使用shell脚本拉取部署镜像

3.1、宿主机软件安装

jdk

1
2
[root@centos7cz tools]# whereis java
java: /usr/bin/java /carloz/tools/jdk1.8.0_231/bin/java

maven

  1. 下载解压
1
2
3
4
5
6
7
cd /carloz/tools/
wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
tar -zxf apache-maven-3.6.3-bin.tar.gz
mv apache-maven-3.6.3 maven-3.6.3
cd maven-3.6.3/
pwd
/carloz/tools/maven-3.6.3
  1. 配置环境变量
1
2
3
4
5
vi /etc/profile
MAVEN_HOME=/carloz/tools/maven-3.6.3
export PATH=${MAVEN_HOME}/bin:${PATH}

source /etc/profile
  1. 查看结果
1
mvn -v
  1. 替换阿里源
1
vi /carloz/tools/maven-3.6.3/conf/settings.xml

找到<mirrors></mirrors>标签对,添加一下代码:

1
2
3
4
5
6
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
  1. 指定下载资源位置
1
2
3
mkdir -p /data/maven-repo
vi /carloz/tools/maven-3.6.3/conf/settings.xml
<localRepository>/data/maven-repo</localRepository>
  1. 指定jdk版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
vi /carloz/tools/maven-3.6.3/conf/settings.xml

<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>

git

1
2
3
4
5
6
[root@centos7cz ~]# yum install -y git
[root@centos7cz ~]# whereis git
git: /usr/bin/git /usr/share/man/man1/git.1.gz
[root@centos7cz ~]# git --version
git version 1.8.3.1
[root@centos7cz ~]#

3.2、安装jenkins

https://carlo-z.com/devops/jenkins/jenkins-centos7-setup/


3.3、jenkins做常规配置

点击系统管理->插件管理,进行一些自定义的插件安装:

角色管理权限插件

Role-based Authorization Strategy

ssh

安装ssh插件

配置公钥凭证

在系统管理->系统配置中添加全局ssh的配置,这样Jenkins使用ssh就可以执行远程的linux脚本了:

jdk

路径: 系统管理 -> 全局工具配置 -> JDK

maven

通过系统管理->全局工具配置来进行全局工具的配置,比如maven的配置

git

安装插件:

  • Build With Parameters

  • Git Parameter

git可执行文件配置

gitee

在线安装

  • 前往 Manage Jenkins -> Manage Plugins -> Available
  • 右侧 Filter 输入: Gitee
  • 下方可选列表中勾选 Gitee(如列表中不存在 Gitee,则点击 Check now 更新插件列表)
  • 点击 Download now and install after restart

添加码云链接配置

  1. 前往 Jenkins -> Manage Jenkins -> Configure System -> Gitee Configuration -> Gitee connections

  2. Connection name 中输入 Gitee 或者你想要的名字

  3. Gitee host URL 中输入码云完整 URL地址: https://gitee.com (码云私有化客户输入部署的域名)

  4. Credentials 中如还未配置码云 APIV5 私人令牌,点击Add- > Jenkins

    1. Domain 选择 Global credentials
    2. Kind 选择 Gitee API Token
    3. Scope 选择你需要的范围
    4. Gitee API Token 输入你的码云私人令牌,获取地址:https://gitee.com/profile/personal_access_tokens
    5. ID, Descripiton 中输入你想要的 ID 和描述即可。
  5. Credentials 选择配置好的 Gitee APIV5 Token

  6. 点击 Advanced ,可配置是否忽略 SSL 错误(适您的Jenkins环境是否支持),并可设置链接测超时时间(适您的网络环境而定)

  7. 点击 Test Connection 测试链接是否成功,如失败请检查以上 3,5,6 步骤。

配置成功后如图所示:


4、mall-swarm部署


4.1、在harbor中新建仓库

harbor安装:https://carlo-z.com/devops/docker/harbor-setup/


4.2、配置springboot部署参数

1、maven配置harbor登录密码

1
2
3
4
5
6
7
8
9
vi /carloz/tools/maven-3.6.3/conf/settings.xml
<server>
<id>docker-harbor</id>
<username>admin</username>
<password>123456</password>
<configuration>
<email>iceleader@126.com</email>
</configuration>
</server>

2、修改pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<properties>
...
<docker.repostory>czharbor.com</docker.repostory>
<docker.registry.name>mall</docker.registry.name>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version}</imageName>
<!-- 指定Dockerfile所在的路径 -->
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<serverId>docker-harbor</serverId>
<registryUrl>${docker.repostory}</registryUrl>
<pushImage>true</pushImage>
</configuration>
</plugin>
</plugins>
</build>

4.3、执行脚本准备

首先我们先把需要远程执行的脚本准备好。

脚本文件都存放在了mall-swarm项目的/document/sh目录下

上传脚本前在IDEA中修改所有脚本文件的换行符格式为LF,否则脚本会无法执行;

将所有脚本文件上传到指定目录,这里我们上传到/malldata/sh目录下;

1
2
3
4
mkdir -p /malldata/sh

# 将所有脚本文件都修改为可执行文件:
chmod +x /malldata/sh/mall-*


4.4、Jenkins中创建任务

接下来我们将通过在Jenkins中创建任务来实现自动化部署。由于我们的mall-swarm是个多模块的项目,部署上面和曾经的单模块项目还是有所区别的

mall-registry

由于各个模块的执行任务的创建都大同小异,下面将详细讲解mall-admin模块任务的创建,其他模块将简略讲解。

  • 首先我们选择构建一个自由风格的软件项目,然后输入任务名称为mall-admin,配置其Git仓库地址,这里我直接使用了Gitee上面的地址:

指定代码仓库

点击添加,创建gitee登录凭据

  • 之后我们创建一个构建,构建mall-swarm项目中的依赖模块,否则当构建可运行的服务模块时会因为无法找到这些模块而构建失败;
1
2
# 只install mall-common,mall-mbg,mall-security三个模块
clean install -pl mall-common,mall-mbg,mall-security -am
  • 依赖项目构建示意图:

  • 再创建一个构建,单独构建并打包${WORKSPACE}/mall-registry/pom.xml

  • 添加一个构建来通过SSH去执行远程任务,用于执行mall-registry的运行脚本:

  • 点击保存,完成mall-registry的执行任务创建

mall-admin

mall-admin和其他模块与mall-registry创建任务方式基本一致,只需修改构建模块时的pom.xml文件位置和执行脚本位置即可。

  • 我们可以直接从mall-registry模块的任务复制一个过来创建:

  • 修改第二个构建中的pom.xml文件位置,改为:${WORKSPACE}/mall-admin/pom.xml

  • 修改第三个构建中的SSH执行脚本文件位置,改为:/malldata/sh/mall-registry.sh

  • 点击保存,完成mall-admin的执行任务创建。
  • 尝试构建 mall-admin 模块,如果构建成功,再创建其他模块的构建任务

其他模块

其他模块的执行任务创建,参考mall-registry和mall-admin的创建即可。

模块启动顺序问题

关于各个模块的启动顺序问题,mall-registry模块必须第一个启动,mall-config模块必须第二个启动,其他模块没有启动顺序限制。

推荐启动顺序:

  • mall-registry
  • mall-config
  • mall-monitor
  • mall-gateway
  • mall-admin
  • mall-portal
  • mall-search
  • mall-demo
1
2
3
4
5
6
7
8
docker start mall-registry
docker start mall-config
docker start mall-monitor
docker start mall-gateway
docker start mall-admin
docker start mall-portal
docker start mall-search
docker start mall-demo

4.5、使用jenkins编译

4.6、容器网络问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
docker network create -d bridge mall-network

docker network disconnect data_default mysql
docker network disconnect data_default redis
docker network disconnect data_default nginx
docker network disconnect data_default rabbitmq
docker network disconnect data_default elasticsearch
docker network disconnect data_default kibana
docker network disconnect data_default mongo

docker network inspect data_default


docker network disconnect bridge mall-registry
docker network disconnect bridge mall-config
docker network disconnect bridge mall-monitor
docker network disconnect bridge mall-gateway
docker network disconnect bridge mall-admin
docker network disconnect bridge mall-portal
docker network disconnect bridge mall-search
docker network disconnect bridge mall-demo

docker network inspect bridge

docker network connect mall-network mysql
docker network connect mall-network redis
docker network connect mall-network nginx
docker network connect mall-network rabbitmq
docker network connect mall-network elasticsearch
docker network connect mall-network kibana
docker network connect mall-network mongo
docker network connect mall-network mall-registry
docker network connect mall-network mall-config
docker network connect mall-network mall-monitor
docker network connect mall-network mall-gateway
docker network connect mall-network mall-admin
docker network connect mall-network mall-portal
docker network connect mall-network mall-search
docker network connect mall-network mall-demo


docker network ls
docker network inspect mall-network
docker inspect mysql | grep Network
docker inspect mall-registry | grep Network
docker inspect mall-admin | grep Network

5、mall-admin-web前端

http://www.macrozheng.com/#/deploy/mall_deploy_web

1
2
3
4
5
6
7
git clone https://gitee.com/carloz/mall-admin-web.git

$ npm config set registry http://registry.npm.taobao.org/
$ npm info underscore
$ rm -rf node_modules
$ npm install
$ npm run dev

http://localhost:8090/

1
$ npm run build