Docker高级之——Docker Compose、Docker Swarm、Jakins持续集成、Rancher持续部署
1 容器编排概述
Docker只是一个对项目做打包和运行的小工具,如果止步于此,那么充其量就是一个开发者手里的小玩具
。
因为真实的项目都是要集群部署的,还要考虑负载均衡、水平扩展、动态伸缩、集群容错等问题,而Docker并不具备这样的功能。
而要想让Docker在集群中的部署如同单机部署一样的方便,那就需要用到容器编排技术了。
“编排”(Orchestration)在云计算行业里不算是新词汇,它主要是指用户如何通过某些工具或者配置来完成一组虚拟机以及关联资源的定义、配置、创建、删除等工作,然后由云计算平台按照这些指定的逻辑来完成的过程。
而容器时代,“编排”显然就是对 Docker 容器的一系列定义、配置和创建动作的管理。目前容器编排技术比较知名的包括:
- Docker公司自己的:docker-compose + swarm组合
- Google牵头的Kubernetes技术,简称为k8s
2 Docker Compose,配合swarm集群使用时坑,BUG多,运行的服务不稳定,写脚本一个个加服务,别用它
Docker Compose
是 Docker 官方编排(Orchestration)项目之一,负责快速的部署分布式应用,官网地址: https://github.com/docker/compose ,其前身是开源项目 Fig。
本节将介绍 Compose
项目情况以及安装和使用。
网址:https://docs.docker.com/compose/compose-file/
2.1 为什么要用Docker Compose
通过Dockerfile我们可以将一个项目很方便的打包为一个Docker镜像。但是在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
那么如何定义各个容器的依赖关系,这就需要用到docker-compose了。
Compose
恰好满足了Docker集群化的需求。它允许用户通过一个单独的 ==docker-compose.yml== 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
2.2 Docker Compose安装
MAC下或者Windows下的Docker自带Compose功能,无需安装。
Linux下需要通过命令安装:
1 | # 安装 |
2.3 Docker Compose快速入门
假设我们要部署一个SpringBoot项目,并且依赖于Redis。
2.3.1 导入微服务工程
工程的基本功能就是统计用户的访问量,代码在资料
中docker-demo,直接解压到没有中文的目录下,使用Idea导入即可。
打包项目,获得app.jar
2.3.2 编写Dockerfile
(1)在任意位置创建一个新目录,docker-compose,将app.jar复制到该目录
(2)在该目录中,新建一个==Dockerfile==文件,并编写下面的内容:
1 | FROM java:8-alpine |
2.3.3 编写docker-compose
在刚才的目录中,创建一个==docker-compose.yml==文件并填写内容:
1 | version: '3' |
此时的结构如下:
命令解读:
- version:compose的版本
- services:服务列表,包括两个服务:
- web:自己写的Java项目
- build:这个服务镜像是临时构建的,构建目录是当前目录,会利用当前目录的Dockerfile来完成构建。
- ports:端口映射,对外开放8080端口
- redis:redis服务
- web:自己写的Java项目
2.3.4 启动测试
将刚刚准备好的文件夹docker-compose上传到Linux的/opt
目录:
进入docker-compose目录然后执行命令:
1 | docker-compose up |
构建完成后,可以看到项目运行的日志信息:
此时,访问浏览器 http://192.168.80.151:9090/hello,可以看到下面的结果:
如果多次访问,这个次数会累加。
按CTRL+C
后可以停止运行程序,并且Docker运行的容器中也会关闭。
通过docker-compose up -d
命令,可以后台启动,这样就不会显示日志:
通过docker-compose stop
关闭容器
通过docker-compose down
关闭容器并删除
2.4 Docker Compose 相关命令
docker-compose的相关命令参数:
通过:docker-compose --help
查看
1 | [root@localhost docker-demo]# docker-compose --help |
2.5 Docker Compose常用语法
Compose模板文件是Compose的核心,包括有多种版本的Compose文件格式–:1,2,2.x和3.x。对应的Docker版本也不一样,对照表:
Compose file format | Docker Engine release |
---|---|
3.8 | 19.03.0+ |
3.7 | 18.06.0+ |
3.6 | 18.02.0+ |
3.5 | 17.12.0+ |
3.4 | 17.09.0+ |
3.3 | 17.06.0+ |
3.2 | 17.04.0+ |
3.1 | 1.13.1+ |
3.0 | 1.13.0+ |
2.4 | 17.12.0+ |
2.3 | 17.06.0+ |
2.2 | 1.13.0+ |
2.1 | 1.12.0+ |
2.0 | 1.10.0+ |
1.0 | 1.9.1.+ |
编写时,需要根据自己的docker版本来选择指定的Compose版本。
详细语法参考文档:https://docs.docker.com/compose/compose-file/
概念
Compose
中有两个重要的概念:
- 项目 (
project
):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml
文件中定义。 - 服务 (
service
):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
Compose
的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。
Compose文件是一个YAML文件,定义 一个或多个服务(service),网络(network)和 卷(volume)。撰写文件的默认路径为./docker-compose.yml
。
提示:您可以为此文件使用
.yml
或.yaml
扩展名。他们俩都工作。
简单来说,一个project
包含多个service
,每个service
都是一个组件。例如入门案例中的Java项目和Redis都是service
。部署时,可能每个service都会有多个容器去运行,形成负载均衡的集群。
因此,我们定义service,就是在定义这个service在容器运行时的规则参数,就像是给docker run
命令设置参数一样。
我们定义network和volume类似于 docker network create
和docker volume create
这两个命令的效果。
只不过,我们定义规则,执行命令则由docker compose来完成。
参考我们之前的Demo,我们来学习下Compose的模板文件语法:
1 | version: '3' |
version
版本信息,详见上面提到的Compose版本与Docker的对应关系。
build
指定 Dockerfile
所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml
文件的路径)。 Compose
将会利用它自动构建这个镜像,然后使用这个镜像。
在入门案例中,因为Dockerfile
和docker-compose.yml
是在一个目录,因此build值指定为.
1 | version: '3' |
另外,你也可以先制定目录,然后在指定Dockerfile文件,例如:
1 | version: '3' |
说明:
- build:Dockerfile配置
- context:用来指定Compose的工作环境目录,如果不指定或使用了相对路径则默认为
docker-compose.yml
所在目录。 - dockerfile:指定Dockerfile的文件名称
- context:用来指定Compose的工作环境目录,如果不指定或使用了相对路径则默认为
command
覆盖容器运行时的默认命令。
1 | version: '3' |
depends_on
解决容器的依赖、启动先后的问题。以下例子中会先启动 redis
db
再启动 web
:
1 | version: '3' |
depends_on踩坑,巨坑!!!
1、就算配置了也不一定按照既定顺序走。。。BUG没办法
2、depends_on可以解决容器的运行顺序先后的问题,但它只是检测服务是否在running阶段,而这时启动慢的服务其实还没真正启动,比如Nacos依赖的Mysql,而要解决这个问题,需要使用一个脚本:wait-for
Github地址:https://github.com/Eficode/wait-for
首先下载wait-for脚本:
1 | !/bin/sh |
docker-conpose.xml文件:
1 | version: '3' |
ENTRYPOINT
指定服务容器启动后执行的入口文件或者启动命令,例如:
1 | entrypoint: /code/entrypoint.sh |
或者:
1 | entrypoint: ["php", "-d", "memory_limit=-1", "vendor/bin/phpunit"] |
environment
添加环境变量。您可以使用数组或字典。任何布尔值(true,false,yes,no)都需要用引号引起来,以确保YML解析器不会将其转换为True或False。
仅具有键的环境变量在运行Compose的计算机上解析为它们的值,这对于秘密或特定于主机的值很有用。
1 | environment: |
或:
1 | environment: |
expose
指定内部端口,不将其发布到宿主机上,只有链接的其它服务才能访问它们。
1 | expose: |
extra_hosts
类似 Docker 中的 --add-host
参数,指定额外的 host 名称映射信息。
1 | extra_hosts: |
会在启动后的服务容器中 /etc/hosts
文件中添加如下两条条目。
1 | 8.8.8.8 googledns |
image
指定用于启动容器的图像。可以是镜像名称(仓库:tag)或镜像ID,例如:
1 | image: redis |
如果镜像在本地不存在,而且你没有指定build参数,那么Compose会尝试docker pull
来拉取镜像
logging
配置日志选项。
1 | logging: |
目前支持三种日志驱动类型。
1 | driver: "json-file" # 记录为json文件 |
默认采用json-file
的日志方式,可以通过options
配置日志文件的限制参数。
1 | options: |
network_mode
网络模式。使用与docker --network
参数相同的值:
1 | network_mode: "bridge" |
networks
要加入的网络,引用Compose文件中的顶级项目networks下的定义的网络名称 。
要通过容器名称互相访问,则,各个容器必须处于同一个网络中。
1 | version: "3.8" |
另外,在定义网络时可以指定ip
网段,而加入网络的容器则需要在网段中选择一个固定ip地址:
1 | version: "3.8" |
ports
暴露的端口信息,会映射到宿主机端口,另外为了避免语法出错,所有端口配置都必须使用字符串格式:
1 | ports: |
如果仅指定了容器端口,则会随机选择一个宿主机端口。
restart
指定容器退出后的重启策略。包括下面的几种选项:
1 | restart: "no" # 在任何情况下都不会重新启动容器 |
生产环境建议配置为:always
或者unless-stopped
volumes
指定要挂载的数据卷或目录。数据卷可以是某个service的局部数据卷,也可以是提前定义的全局数据卷(通过顶级参数volumes来指定)。
例如:
1 | version: "3.8" |
其他swarm配置,上面只是讲解了Compose的部分模板语法。有关swarm下的一些配置并未说明,在swarm部分继续讲解。
3 Docker Swarm
Docker-Compose负责定义Project和Service(服务)。但是服务具体运行在哪个服务节点?需要多少个Docker容器来部署?这就要靠Docker Swarm来管理了。
Swarm
是使用 SwarmKit
构建的 Docker 引擎内置(原生)的集群管理和编排工具。
网址:https://docs.docker.com/engine/swarm/
3.1 Docker Swarm相关概念
Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。
使用 Swarm
集群之前需要了解以下几个概念:
3.1.1 Node节点
什么是节点?
运行 Docker 的主机可以主动初始化一个 Swarm
集群或者加入一个已存在的 Swarm
集群,这样这个运行 Docker 的主机就成为一个 Swarm
集群的节点 (node
) 。
节点的分类:
节点分为管理 (manager
) 节点和工作 (worker
) 节点。
管理节点:用于 Swarm
集群的管理,docker swarm
命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave
可以在工作节点执行)。一个 Swarm
集群可以有多个管理节点(高可用),但只有一个管理节点可以成为 leader
,leader
通过 raft
协议实现。
工作节点:是任务执行节点,管理节点将服务 (service
) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。
Docker-Swarm的官方架构图:
3.1.2 Service服务和Task任务
任务 (Task
):是 Swarm
中的最小的调度单位,可以理解为一个单一的容器。
服务 (Services
): 是指一组任务的集合,服务定义了任务的属性。服务有两种模式:
replicated services
按照一定规则在各个工作节点上运行指定个数的任务。global services
每个工作节点上运行一个任务
两种模式通过 docker service create
的 --mode
参数指定。
容器、任务、服务的关系图:
常用命令:
1 | docker service ls 发布服务列表 |
3.2 创建Swarm集群
我们知道 Swarm
集群由 管理节点 和 工作节点 组成。本节我们来创建一个包含一个管理节点和两个工作节点的最小 Swarm
集群。
我会启动3台虚拟机,计划如下:
虚拟机IP | 节点角色 |
---|---|
192.168.80.151 | 管理节点 |
192.168.80.152 | 工作节点 |
192.168.80.153 | 工作节点 |
注意:节点的IP请定义为自己的虚拟机IP。
虚拟机克隆
结果:
分别先后开启f1,f2,修改ip分别为100,101,切记,此时不能同时开任何两个虚拟机
分别在三台机器执行命令:
99机器
1 | echo '192.168.80.151 master' >> /etc/hosts |
100机器
1 | echo '192.168.80.152 slaver1' >> /etc/hosts |
101机器
1 | echo '192.168.80.153 slaver2' >> /etc/hosts |
一定要重启机器
一定要重启机器
一定要重启机器
3.2.1 创建管理节点
我们在节点192.168.200.99上运行一个命令:
1 | docker swarm init --advertise-addr 192.168.80.151 |
因为我们的虚拟机可能有多个IP地址,这里通过--advertise-addr
指定一个IP地址,这里我选择的是我的NAT网卡的地址。
执行命令效果如下:
3.2.2 创建工作节点
通过上面执行的结果可以看到这样的提示:
1 | To add a worker to this swarm, run the following command: |
所以,我们需要在另外两台机器
:192.168.80.152和192.168.80.153上执行命令,不要复制笔记,要复制自己的内容:
1 | docker swarm join --token SWMTKN-1-40jgt6v1n59mb7aaw41yg10coxo2524tdgw2t6g2sorbiuflhj-5rymf91h0w2l9ic3adbkik39y 192.168.80.151:2377 |
效果:
踩坑:manage节点需要防火墙开放端口
1 | firewall-cmd --zone=public --add-port=2377/tcp --permanent # 开放端口 |
3.2.3.查看swarm集群
在管理节点:192.168.80.151上执行命令,查看swarm集群信息:
1 | docker node ls |
结果:
此时,我们已经创建了一个最小的 Swarm
集群,包含一个管理节点和两个工作节点。
3.2.4.删除swarm集群中的某个节点
管理节点上对节点进行“离开”操作:
1 | docker node update --availability drain 6whtoqrhkzv3ax4xy9ab20gmy |
在节点中自己退出集群
1 | docker swarm leave |
删除节点
1 | docker node rm 6whtoqrhkzv3ax4xy9ab20gmy |
3.2.5.查看加入集群的Token等命令
1 | docker swarm join-token worker:查看加入woker的命令。 |
3.3 部署单个服务
通过docker service create
命令,可以创建一个service,并在swarm集群中运行。
3.3.1.创建服务
在管理节点:192.168.80.151上运行代码:
1 | docker service create --replicas 3 -p 80:80 --name nginx nginx |
解读:
--replicas 3
:代表这个服务要创建3个副本,也就是启动3个容器来运行nginx
如图:
3.3.2 查看服务
通过docker service ls
可以查看服务状态:
通过docker service ps nginx
命令可以查看nginx服务的运行节点信息:
此时,我们通过浏览器访问:http://192.168.80.151或者http://192.168.80.152或者http://192.168.80.153都可以看到一样的效果:
其它命令:
我们可以使用 docker service scale
对一个服务运行的容器数量进行伸缩。
当业务处于高峰期时,我们需要扩展服务运行的容器数量。
1 | docker service scale nginx=5 |
当业务平稳时,我们需要减少服务运行的容器数量。
1 | docker service scale nginx=2 |
使用 docker service rm
来从 Swarm
集群移除某个服务。
1 | docker service rm nginx |
3.4 部署多个服务
使用 docker service create
一次只能部署一个服务,使用 docker-compose.yml
我们可以一次启动多个关联的服务并部署到swarm集群中。
接下来,我们就来搭建一个多服务的集群,包括下面的服务:
- web:就是之前在docker-compose案例中的Java项目,依赖于redis进行计数。部署3个
- redis:redis数据库,记录某个IP的访问次数,部署1个,在管理节点。
- nginx:nginx服务,对3个web服务反向代理,部署1个,在管理节点
部署计划表:
服务名称 | 部署数量 | 节点IP |
---|---|---|
web | 3 | 192.168.80.151, 192.168.80.152, 192.168.80.153 |
redis | 1 | 192.168.80.151 |
nginx | 1 | 192.168.80.151 |
结构如下:
3.4.1 准备镜像
首先,我们需要在3个docker节点上都准备java项目的镜像。
1)上传
找到之前准备的docker-compose
这个文件夹:
分别上传到3个docker节点的 `/opt 目录:
2)构建镜像
然后分别在3个docker节点中运行下面的命令:
进入: /opt/docker-compose ,执行如下命令
1 | docker build -t web:latest . |
通过docker images
查看镜像:
3.4.2 编写nginx配置
我们需要用nginx反向代理3个web节点,因此需要编写一个nginx的配置文件。
nginx部署在管理节点:192.168.80.151
,所以进入这个节点的/opt/docker-compose/swarm
目录下,创建一个nginx.conf
文件,内容如下:
/opt/docker-compose/swarm
1 | worker_processes 1; |
注意:
proxy_pass http://web:9090
:会把请求代理到web服务的9090端口。Docker-Swarm会自动对3个docker节点的web服务负载均衡
3.4.3 编写docker-compose
swarm下的docke-swarm会有一些变化,我们修改管理节点(192.168.80.151)下的docker-compose.yml
文件,内容如下:
1 | version: '3' |
解读:
- service:服务,包括3个
- web:java项目
- image:指定web服务的镜像,就是刚刚自己打包的
web:latest
- networks: 网络配置,这里是用了默认的overlay格式,是swarm模式的固定格式
- deploy:swarm下的部署配置
- mode:replicated代表在多个节点上做备份
- replicas: 3 ,备份数量为3,即web服务会部署到swarm集群的随机3个节点
- image:指定web服务的镜像,就是刚刚自己打包的
- redis:redis数据库
- image: “redis:latest”,指定用到的镜像是redis最新镜像
- deploy:swarm下的部署配置
- placement: 指定部署位置
- constraints: [node.role == manager] 部署到manager节点
- placement: 指定部署位置
- nginx:nginx服务
- image: “nginx:latest”,指定镜像名称
- networks: 指定网络,这里是用了默认的overlay格式,是swarm模式的固定格式
- ports: 对外暴露的端口为80
- volumes: 数据卷,指定目录下的nginx.conf文件挂载到容器中
- deploy: 部署,指定部署位置到manager节点
- web:java项目
3.4.4 部署运行
多服务运行与单个服务命令不同,在管理节点(192.168.80.151)运行下面的命令:
1 | docker stack deploy -c docker-compose.yml counter |
说明:
docker stack
:就是通过docker-compose部署的命令-c docker-compose.yml
:指定docker-compose文件位置counter
:给部署的集群起个名字
运行过程如图:
通过docker stack ls
可以查看到当前集群信息:
通过docker stack ps [集群名]
可以查看集群中的服务信息:
1 | docker stack ps counter |
此时,访问浏览器:http://192.168.80.151/hello即可:
此时,通过命令:
1 | docker service logs -f counter_web |
可以查看运行日志:
多次访问99主节点,可以看到,Docker-Swarm会自己对3个web服务做负载均衡:
4 持续集成&持续部署
4.1 理解什么是持续集成&持续部署
随着软件开发复杂度的不断提高,团队开发成员间如何更好地协同工作以确保软件
开发的质量已经慢慢成为开发过程中不可回避的问题。互联网软件的开发和发布,已经形成了一套标准流程。
如: 在互联网企业中,每时每刻都有需求的变更,bug的修复, 为了将改动及时更新到生产服务器上,下面的图片我们需要每天执行N多次,开发人员完成代码自测后提交到git,然后需要将git中最新的代码生成镜像并部署到测试服务器,如果测试通过了还需要将最新代码部署到生产服务器。如果采用手动方式操作,那将会浪费大量的时间浪费在运维部署方面。
现在的互联网企业,基本都会采用以下方案解决:
持续集成(Continuous integration,简称 CI)。
持续部署(continuous deployment, 简称 CD)
4.1.1 持续集成
持续集成 (Continuous integration,简称 CI) 指的是,频繁地(一天多次)将代码集成到主干。
它的好处主要有两个。
快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。
防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
Martin Fowler 说过,”持续集成并不能消除 Bug,而是让它们非常容易发现和改正。”
与持续集成相关的,还有两个概念,分别是持续交付和持续部署。
4.1.2 持续交付
持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。
持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。
4.1.3 持续部署
持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。
持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。
持续部署的前提是能自动化完成测试、构建、部署等步骤。
4.1.4 演示流程说明
为了保证团队开发人员提交代码的质量,减轻软件发布时的压力;
持续集成中的任何一个环节都是自动完成的,无需太多的人工干预,有利于减少重复
过程以节省时间、费用和工作量;接下来我们会演示一套基本的自动化持续集成和持续部署方案,来帮助大家理解互联网企业的软件部署方案。
流程如下:
实现流程:
- 开发人员将代码提交到 git 指定分支 如: dev
- git仓库触发push事件,发送webhooks通知到持续集成软件
- 持续集成软件触发构建任务,对dev分支的代码进行构建、编译、单元测试
- 如果构建失败,发送邮件提醒代码提交人员或管理员
- 如果构建成功,最新代码将会被构建Docker镜像并上传到注册中心
- 构建成功触发webhooks通知容器编排软件,进行服务升级
- 容器编排软件,触发对应的服务升级任务, 将创建对应服务的新容器替换之前的容器
- 完成最新代码的自动构建与自动部署,全程无工作人员干预
要实现上面流程,我们需要了解两款新的软件 jenkins
和 rancher
4.2 CI&CD jenkins
4.2.1 jenkins介绍
Jenkins,原名Hudson,2011年改为现在的名字,它 是一个开源的实现持续集成的
软件工具。官方网站:http://jenkins-ci.org/ 。
Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图
表的形式形象地展示项目构建的趋势和稳定性。
特点:
- 易配置:提供友好的GUI配置界面;
- 变更支持:Jenkins能从代码仓库(Subversion/CVS)中获取并产生代码更新列表并
输出到编译输出信息中;
支持永久链接:用户是通过web来访问Jenkins的,而这些web页面的链接地址都是
永久链接地址,因此,你可以在各种文档中直接使用该链接; - 集成E-Mail/RSS/IM:当完成一次集成时,可通过这些工具实时告诉你集成结果(据
我所知,构建一次集成需要花费一定时间,有了这个功能,你就可以在等待结果过程
中,干别的事情); - JUnit/TestNG测试报告:也就是用以图表等形式提供详细的测试报表功能;
- 支持分布式构建:Jenkins可以把集成构建等工作分发到多台计算机中完成;
文件指纹信息:Jenkins会保存哪次集成构建产生了哪些jars文件,哪一次集成构建使
用了哪个版本的jars文件等构建记录; - 支持第三方插件:使得 Jenkins 变得越来越强大
4.2.2 安装配置jenkins
jenkins的官方文档中提供了多种安装方式,本文选择docker的安装方式来学习jenkins
4.2.2.1 安装jenkins
强烈建议虚拟机内存升级到4G,CPU给4核心
强烈建议虚拟机内存升级到4G,CPU给4核心
强烈建议虚拟机内存升级到4G,CPU给4核心
下载jenkins
1 | docker pull jenkins/jenkins:lts-centos7 |
创建jenkins容器
1 | docker run -d --name myjenkins -p 8888:8080 --restart=always jenkins/jenkins:lts-centos7 |
查看jenkins启动日志
1 | docker logs -f myjenkins |
启动成功后 访问:
4.2.2.2 解锁jenkins
第一次运行时,需要先解锁jenkins
具体步骤:
- 去容器中 指定文件查看管理员密码
- 将密码拷贝到文本框
- 点击继续即可
密码在日志文件中已经打印,也可以根据提示在容器中获取
具体解锁的管理员密码,在jenkins的安装目录中,因为我们是采用的容器安装,所以需要进入到容器中查看,命令如下:
1 | 进入到jenkins容器 |
4.2.2.3 安装推荐插件
jenkins的各项功能,依赖各种插件,可以手工选择安装也可以按照推荐安装
我们课程主要使用git 和 chinese中文插件,所以搜索安装
创建管理员用户
插件安装完毕后,会进入到设置管理员用户页面,按自己需求设置就好,后续登录可以使用
设置完毕后点击保存并完成则进入到jenkins欢迎页
接下来,jenkins会让我们确认jenkins服务端的地址,直接下一步就好,
然后点击开始使用jenkins进入到jenkins页面
进入到jenkins页面, 如果这个时候你的页面都是英文的话,重启下就好
(因为上面安装默认插件中已经安装了 中文插件)
4.2.2.4 jenkins插件下载镜像加速
更新地址:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
4.2.2.4 配置maven环境
对于git中项目的构建我们要使用到maven命令,那么在jenkins中需要下载对应的maven插件,以及jenkins所在的容器也要有maven环境
(1) 下载maven插件:
点击系统管理 –> 点击插件管理 –> 进入到插件管理页面
点击可选插件 –> 输入maven –> 勾选Maven Integration –> 下载待重启安装
等待下载完成后,重启jenkins容器即可
(2) 安装maven环境
将资源中的maven安装包,拷贝到容器中解压即可,再配置好华为云镜像
将maven压缩包拷贝容器解压
1 | 目录根据自己实际情况来 |
配置maven镜像
上传资料中的settings.xml文件到宿主机中并复制配置文件到容器中
1 | docker cp settings.xml myjenkins:/var/jenkins_home/apache-maven-3.6.3/conf/settings.xml |
(3) jenkins中配置maven环境
系统管理中点击全局工具配置
- 新增maven
- name随意,MAVEN_HOME: /var/jenkins_home/apache-maven-3.6.3
- 取消勾选自动安装
- 保存即可
完成后,我们就可以通过jenkins创建构建任务啦
Docker私有Registry
(1)拉取私有仓库镜像(此步可省略)
1 | docker pull registry |
(2)启动私有仓库容器
1 | docker run -id -p 5000:5000 --name myregistry --restart=always registry |
修改开机自启动
(3)查看检验是否安装启动成功。
打开浏览器 输入地址
1 | http://192.168.80.151:5000/v2/_catalog |
看到 {“repositories”:[]} ,表示私有仓库搭建成功并且内容为空
设置当前docker信任私有注册中心(所有容器都要添加,否则Docker会拉取不到本地镜像仓库的镜像)
(1)修改daemon.json,让 docker信任私有仓库地址
修改文件:
1 | vim /etc/docker/daemon.json |
添加如下内容,保存退出。
1 | { |
注意:该文件中如有多个内容,比如有之前配置的私服镜像地址,用英文逗号隔开,参考如下:
1 | { |
(2)重启docker 服务和私服
1 | systemctl restart docker |
4.2.3 jenkins快速入门
4.2.3.1 准备要部署的工程
准备工作,导入资源中的docker-demo工程, 在pom中添加docker-maven插件配置,
注意将IP部分变成自己虚拟机的IP
1 |
|
将项目上传到码云(gitee.com)中
Git中的地址: git@gitee.com:taft31/docker-demo.git
4.2.3.2 创建maven构建任务
(1) 新建jenkins任务
在jenkins的首页的第一个页签就是用于构建任务,点击新建任务:
定义任务名名称,勾选构建模板 保存任务
(2) 设置任务的构建信息:
描述信息设置
**源码设置 ***
jenkins可以根据配置的源码地址获取源码,来用于构建,配置如下:
选择git仓库
设置git仓库地址
如果是私有仓库需要添加凭证
选择仓库分支
构建触发器:
什么情况可以触发此任务,或者定时触发此任务,暂不设置
构建设置
- Pre Steps 构建的前置任务,可以在构建执行前触发一些通知或脚本的执行
- build 要执行的构建任务
- PostSteps 构建的后置任务,可以在完成构建后触发的一些通知或脚本的执行
构建任务配置如下:
Root POM
: 本次构建要使用的git仓库中的pom文件
Goals and options
: 要执行的mvn命令 不用写前面的mvn
1 | maven命令 |
构建结果通知
可以将构建结果,通知给配置的管理员或触发此任务的代码上传人员,本文不配置
保存任务
点击保存即可
构建前要确认docker的2375端口是开放
1 | # 编辑此文件 |
4.2.3.3 执行maven构建任务
(1)执行构建任务
当我们保存完毕任务之后,会进入到任务的详情页面, 点击立即构建即可执行该构建任务
或者返回首页面板,也能看到任务列表,列表后面的图标也可以用于构建
(2) 查看任务执行日志
点击构建后,在页面左下会出现任务的执行状态,点击进度条进入到任务构建详情中
可以通过控制台输出页面,查看控制台信息,和我们在idea控制中看到的信息类似
第一次执行会下载很多maven依赖
实际上,jenkins是从我们配置的git中拉取了源码信息,在使用maven的命令进行构建
(3) 查看任务构建结果
控制台出现 BUILD SUCCESS
代表构建成功啦
对应的虚拟机中已经有了这个镜像
对应的注册中心中也上传了此镜像
OK 那么接下来基于这个镜像构建出容器,我们就完成了部署。
4.3 容器编排平台 Rancher
4.3.1 Rancher介绍
前面我们了解了容器编排的概念,如: docker 的Swarm以及 google的k8s, 但是这些软件的入门门槛很高,需要我们记住很多命令,那么下面我们介绍一款软件 Rancher,它可以基于上面的容器编排软件,提供可视化的操作页面 实现容器的编排和管理。
Rancher是一个开源的企业级全栈化容器部署及管理平台。Rancher为容器提供一揽
子基础架构服务:CNI兼容的网络服务、存储服务、主机管理、负载均衡、防护墙……
Rancher让上述服务跨越公有云、私有云、虚拟机、物理机环境运行,真正实现一键式应
用部署和管理。
https://www.cnrancher.com/
4.3.1 Rancher快速入门
4.3.1.1 安装Rancher
下载rancher
1 | docker pull rancher/server |
创建rancher容器
1 | docker run -d --name=myrancher -p 9099:8080 rancher/server |
查看rancher启动日志
1 | docker logs -f myrancher |
开启2049端口
1 | # 开启2049端口 |
访问Rancher: http://192.168.80.151:9099/
页面右下角 点击下拉框 选择简体中文
4.3.1.2 配置环境
在互联网项目中,可能会有多套部署环境 如: 测试环境 、 生产环境,不同的环境下会有不同的服务器 Rancher支持多环境多服务器管理
默认 我们处于default的默认环境中,点击环境管理可以创建环境
点击添加环境可以定义一个环境
构建环境时,需要设置环境的名称、环境描述、及环境模板
可以看到 环境模板支持多套,所谓的环境模板就是底层使用哪种编排工具
rancher支持 cattle、swarm、k8s、mesos等,默认使用cattle
入门案例我们使用内置的Cattle模板即可,添加后列表出现刚创建的环境
切换到prod环境中
4.3.1.3 配置主机
在不同的环境中可以会有不同的服务器,要想让我们的rancher能够管理这些服务器,需要在基础架构中添加主机
(1) 添加主机
点击基础架构下拉框中的主机
–> 在点击添加主机
(2) 复制脚本
确认站点地址是否正确,然后点击保存(端口9099)
复制脚本:
- 要管理的主机IP 如: 要管理 192.168.80.151的虚拟机
- 复制脚本,将脚本复制到192.168.80.151的机器上执行
- 执行完毕后关闭此页面,等待主机连接
(3) 到主机中执行脚本
如: 到我的192.168.80.151的虚拟机中 执行如下命令:
运行完毕后,在rancher的页面上,关闭窗口 可以在主机列表中看到对应服务器信息
(需要等待主机中下载镜像及启动相关容器)
显示active
代表服务器当前状态可用, 如果报红 或显示reconnecting
则为重连状态,等待一会即可
4.3.1.4 管理容器
连接成功后,我们可以点击基础架构
下的容器
进行容器的管理
说明:
(1)页面提供了对应主机上的容器管理功能,额外创建的容器都是系统容器,用于rancher的管理,可以通过 取消勾选显示系统容器进行过滤
(2)点击添加容器,可以通过简单配置构建一个容器
如: 构建一个redis容器
- 点击添加容器
- 配置容器名称、描述、镜像、端口映射即可
(3)容器列表结尾提供了容器的 重启、删除、查看日志等功能
4.3.3 Rancher中的应用与服务
4.3.3.1 应用与服务的概念
上面的容器管理,仅仅是提供了容器的管理页面,但对于企业级的项目部署 会涉及到集群扩容缩容、服务升级、负载均衡等等高可用的管理。需要在Rancher中通过定义应用与服务的设置来管理。
应用(Project): 代表一个项目 如: 电商项目
服务(Service):代表一个服务 如: 电商项目下的订单微服务
4.3.3.2 创建应用与服务
和我们学习的swarm类似,我们可以创建一个应用project
一个应用下可以包含多个服务
service
, 一个服务下可以运行多个相同的容器container
创建应用
点击到环境首页,创建应用 : 应用名称、描述 点击创建
添加服务
在刚创建好的myPro应用中添加服务
设置服务信息:
- 容器名称(rancher中显示的名称)
- 描述
- 构建创建前拉取最新镜像
- 镜像的名称
点击创建,可以看到容器已经运行
在docker中也有对应的服务
4.3.3.3 演示服务扩容
点击左侧的 数量加减 会自动对服务进行扩容 缩容
4.3.3.4 演示服务负载均衡
不过我们当前服务集群 并没有配置端口映射,因此外部无法访问,需要配置负载均衡
回到服务列表,添加负载均衡
配置负载均衡
1.负载均衡名称 : lbdockerDemo
2.负载均衡描述 : dockerDemo的负载均衡
3.访问端口: 9001
4.目标服务: myPro/dockerDemo
5.映射服务容器端口: 9090
访问测试: http://192.168.80.151:9001/hello 多次点击
依次查看3个容器的日志
已经实现了负载均衡效果
4.3.3.5 演示服务升级
访问当前服务 http://192.168.206.66:9001/hello
变更当前代码
push提交到git
执行jenkins构建任务,将最新的代码打包成新镜像,并上传到注册中心
构建成功后,在rancher中进行服务升级 在详情页面或列表页面都有向上的箭头代表服务升级
填写升级信息, 启动行为勾选:
这样会先根据最新镜像创建容器,创建完毕后,在将之前的容器删除,来完成服务的更新
点击升级
最后,点击完成升级 旧的容器将被删除掉
刷新页面,可以看到服务已经升级完毕
也就意味着完成服务的一键部署
搭建NFS服务挂载数据卷
1、安装NFS服务
1 | #安装nfs服务 |
2、创建目录和赋予权限:
1 | #创建文件夹 |
3、启动rpcbind和nfs服务:
1 | systemctl start rpcbind && systemctl enable rpcbind |
注意:需要设置固定端口,并且放行
1 | vim /etc/sysconfig/nfs |
放行端口:
1 | # tcp/udp:111、2049、30003、30004 |
5、每个node查询NFS服务器
1 | showmount -e 192.168.3.99 |
6、在Rancher中的应用商店添加NFS应用
7、设置NFS服务器的IP地址以及挂载目录
因为以及设置过了,所以这里只展示参数
注意:ON_REMOVE
参数设置为retain
,如果设置成purge
那么在删除卷的时候会清除底层数据,这样会造成数据丢失
8、进入“存储”页面,添加卷
使用时直接添加卷就行了卷名称:容器内路径
4.4 自动集成及自动部署
上面的演示中,当我们把idea上的代码提交到git中之后, 手动的点击了jenkins中的构建任务,完成镜像的构建和上传注册中心。 然后,在到rancher软件中,根据最新的镜像完成一键升级。 那么自动化的流程就是让这两部也变成自动的,我们只需要将代码上传到指定分支将会自动化的完成构建与升级部署。
4.4.1 自动通知jenkins触发任务
主流的git软件都提供了webhooks功能(web钩子), 通俗点说就是git在发生某些事件的时候可以通过POST请求调用我们指定的URL路径,那在这个案例中,我们可以在push事件上指定jenkins的任务通知路径。
4.4.1.1 jenkins配置Gitee插件
jenkins下载webhooks插件
gitee插件介绍: https://gitee.com/help/articles/4193#article-header0
jenkins也支持通过url路径来启动任务,具体设置方法:
jenkins的默认下载中仅下载了github的通知触发,我们需要先下载一个插件
(1) 下载gitee插件
系统管理–>插件管理–>可选插件–>搜索 Gitee
下载–>重启jenkins
(2) gitee生成访问令牌
首先,去下面网址生成gitee访问令牌
https://gitee.com/profile/personal_access_tokens
添加令牌描述,提交,弹出框输入密码
复制令牌
(3) jenkins中配置Gitee
系统管理 –> 系统配置 –> Gitee配置
- 链接名: gitee
- 域名: https://gitee.com
- 令牌: Gitee Api 令牌 (需要点击添加按下图配置)
- 配置好后测试连接
- 测试成功后保存配置
令牌配置:
- 类型选择Gitee API令牌
- 私人令牌: 将码云中生成的令牌复制过来
- 点击添加
4.4.1.2 修改jenkins构建任务
修改配置接收webhooks通知
任务详情中点击配置来修改任务
点击构建触发器页签,勾选Gitee webhook
生成Gitee Webhook密码
保存好触发路径和webhook密码,到gitee中配置webhook通知
如:
触发路径: http://192.168.80.151:8888/gitee-project/dockerDemo
触发密码: a591baa17f90e094500e0a11b831af9c
4.4.1.3 Gitee添加webhooks通知
gitee仓库配置webhooks通知
点击仓库页面的管理
添加webhook
- 点击webhooks菜单,然后点击添加
- 配置jenkins通知地址
- 填写密码
- 点击添加
但在点击添加时,提示失败 gitee中需要配置一个公有IP或域名,这里我们可以通过内网穿透来解决
4.4.1.4 配置内网穿透
内网穿透的小工具很多,这里面我们使用 natapp提供的内网穿透功能
在资料中找到natapp,上传整个目录到linux,
并进入natapp,执行命令
授权
1 | chmod a+x natapp |
运行
1 | ./natapp |
在gitee中将上面的外网地址替换之前的ip和端口部分,再次添加,
如:http://hgyyd3.natappfree.cc/gitee-project/dockerDemo
添加成功
4.4.1.5 测试自动构建
添加完毕后测试一下:
点击webhooks,发送测试请求
点击查看更多结果,200代表请求成功
不过这个时候jenkins中的任务是没被触发的,我们尝试从idea中上传代码,看看任务是否自动构建
上传代码
代码上传到git后,自动触发了jenkins中的构建任务
4.4.2 Jenkiens自动通知Rancher触发升级
4.4.2.1 Rancher配置接收器
在rancher中,配置接收器来接收webhooks通知
在api下拉菜单下,点击webhooks添加接收器
名称:自定义即可
类型:支持扩容,缩容,和服务升级 我们演示服务升级
参数格式: Docker Hub即可
镜像标签: 对应镜像的标签
服务选择器: 我们的服务也可以设置标签, 如: 当前标签service=demo
当这个接收器被触发时,所有服务包含此标签的 service=demo 则会触发服务升级
- 后面参数的概念:
先启动一个新容器, 启动成功后停止老容器,最后删除老容器完成升级
保存,复制触发url路径
触发路径:
4.4.2.2 服务添加标签
最后,给我们的服务设置标签,删除之前的服务,重新添加服务 ,以及负载均衡器
注意在下面标签下的内容,一致要和接收器设置的标签和值一致此服务才会触发升级
标签: service docker
4.4.2.3 测试服务升级
通过POSTMAN进行测试
在触发请求时还需要携带一些必要的参数:
- 镜像的标签 tag: 这个标签的值要和上面接收器中的标签值一致才可以触发
- 仓库的名称 repo_name: 镜像的仓库名称
1 | { |
点击完毕后观察rancher中服务列表变化,会发现服务将自动完成升级
4.4.2.4 配置jenkins的后置处理
最后,让jenkins来触发rancher,修改jenkins中的配置
- 在构建完毕的后置处理步骤中添加 执行Shell脚本
- 选择Run only if build succeeds 仅在构建成功时运行下面脚本
- 执行脚本
注意: 调用的路径是我们接收器所生成的路径
tag: 是镜像的tag标签
repo_name: 是对应镜像的仓库名称
要根据自己的实际情况修改哦~~~~~
1 | curl "http://192.168.80.151:9099/v1-webhooks/endpoint?key=KoA2vrxiAycydPNDwlb3DLkZ5Kghdshs58lN2lia&projectId=1a13" \ |
4.4.3 自动集成&自动部署演示
操作步骤:
- 变更代码并上传到git
- 注意jenkins任务是否被触发
- 注意rancher自动升级是否被触发
- 访问项目查看变更是否生效
OK,如果成功了,说明你只需要提交代码就可以了, 和部署相关 编译,测试,构建,上传镜像,服务升级,扩容缩容全部交给工具吧~~~