Docker系列文章
第三章 docker swarm
文章目录
- 前言
- 一、Docker Swarm 简介
- 二、常用命令
- 三、集群实践
前言
这里是在前两章 Docker 与 Docker Compose 基础上拓展的,如果还未了解可以按顺序先行了解再来看该章节。原理会比较枯燥,但是基础理论是实践的基础,只有了解了才能知道其中奥义。
一、Docker Swarm 简介
1.1. Docker Swarm 是什么?
Docker Swarm 是 Docker 的集群管理工具,几乎全部使用 Go 语言来完成开发。它将若干台 Docker 主机池抽象为单一的虚拟主机。 Docker Swarm 提供了标准的 Docker API 来管理 Docker 主机上的各种 Docker 资源,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。
1.2. 为何选择 Docker Swarm
不管是单个服务的 Docker 容器化部署,还是使用 Docker Compose 编排多个服务,都是局限在一台宿主机上操作。但是在实际工作中,我们服务的部署往往都是集群模式,分布式模式的,单台宿主机无法支撑起整个分布式集群,更无法避免单点故障问题,并且即使是多台服务器部署,跨主机的容器也无法进行通讯。为此 Docker Swarm 就提供了这一系列问题的解决方案。
1.3. Docker Swarm 特性
-
集群管理集成进Docker Engine
使用内置集群管理功能,可以直接使用 Docker CLI 来创建和管理 Swarm 集群,无需在依赖其它外部软件工具。 -
去中心化设计
Node 表示加入Swarm 集群中的一个 Docker Engine 实例,Node 又分为 Manager 和 Worke 两类。在 Swarm 集群运行期间,可以对集群进行扩容缩容等操作而不需要暂停或重启集群服务,如添加 Manager Node,删除 Worker Node。 -
声明式服务模型(Declarative Service Model)
Docker Engine 使用声明式方法让您定义应用程序堆栈中各种服务的所需状态。例如,您可能会描述一个应用程序,该应用程序由具有消息队列服务和数据库后端的 Web 前端服务组成。 -
服务扩容缩容
对于每个服务,您可以声明要运行的任务数量。当您扩大或缩小规模时,群管理器会通过添加或删除任务来自动适应以保持所需的状态。 -
协调预期状态与实际状态的一致性
集群中 Swarm Manager Node 会持续不断的监控和协调集群状态,并调整当前状态与期望状态之间的差异,使得预期状态与实际状态保持一致。如设置一个服务运行10个副本容器,如果2个副本的服务器节点崩溃,Manager将创建两个新的副本替代崩溃的副本。并将新的副本分配到可用的 Worker 节点预期数量一致。 -
多主机网络
可以对待部署服务指定一个 Overlay 网络,当服务初始化或更新时,Swarm Manager 在指定的 Overlay 网络中为容器自动分配 IP 地址(虚拟 IP ) -
服务发现
Swarm Manager 通过给集群中个每个服务分配唯一的 DNS 名称来对运行中的容器进行负载均衡。通过这个 DNS 我们可以查询到集群运行中容器的状态。 -
负载均衡
在 Swarm 内部可以指定如何在各个 Node 间分发服务容器(Service Container)实现负载均衡。而如果想使用集群外部的负载均衡器,可以将服务容器端口暴露。 -
安全策略
Swarm 集群内部的 Node 强制使用基于 TLS 的双向认证,并且在单个 Node 及集群中多个 Node 间都进行了安全的加密通信。我们可以选择使用自签名的根证书,或者使用自定义的根 CA(Root CA)证书。 -
滚动更新
对于服务更新,可以在多个 Node 上进行增量部署更新,此外 Swarm Manager 支持通过使用 Docker CLI 设置 delay 指定时间间隔,实现多个服务在多个Node 上依次部署。该方式可以灵活控制更新,如有一个服务更新失败,则可以暂停后续更新操作,重新回滚到上一个版本。
1.4. Swarm 关键概念
-
Swarm
一组 Docker Engine 集群。集群的管理和编排是使用嵌入 Docker Engine 的 SwarmKit,可以在 Docker 初始化时启动 Swarm 模式或加入已存在的 Swarm。 -
Node
单个 Docker Engine 实例。或视为 Docker 节点。可以在单个物理机或云服务器上运行一个或多个节点,也可以运行在多个物理机和云服务器上。基于 Docker Engine 可以创建和管理多个 Docker 容器。集群初建时 Swarm Manager 即为集群中的第一个 Node,Node又根据职能划分为 Manager Node 和 Worker Node。 -
Manager Node
管理节点。一个集群需要至少一个 Manager Node。负责整个集群的管理工作包括维护集群状态、调度服务、为群模式HTTP API 端点提供服务。如负责调度 Task,一个 Task 表示要在 Swarm 集群中的某个 Node 上启动 Docker容器,及一个或多个 Docker 容器运行在集群中的某个 Worker Node 上。同时,Manager Node 还负责编排容器和集群管理功能,维护集群状态。默认情况下 Manager Node 也作为一个 Worker Node 来执行 Task 。Swarm 支持配置 Manager 坐座位一个专用的管理 Node。 -
Worker Node
工作节点。接收由 Manager Node 调度指派的 Task,启动一个 Docker 容器来运行指定的服务,并且 Worker Node 需要向 Manger Node 汇报被指派的 Task 的执行状态。 -
Service
Service是一个抽象的概念,它只是一个对运行在swarm集群上的应用服务,所期望状态的描述。它就像一个清单列表一样,描述了具体服务名称、使用哪些镜像、运行多少副本、容器连接的网络、映射的端口等。一个 Service 是工作节点上执行任务的定义。创建一个服务时,需要指定使用的容器镜像。一个 Service 只能运行一个镜像,但可以运行来自同一个镜像的多个容器。 -
Stack
stack是一组 Service,和 docker-compose 类似。我们通过在一个 YAML 文件中来定义一个stack。 默认情况下一个Stack共用一个Network,可互相访问,与其它Stack网络隔绝。 statck 只是为了编排的方便, docker stack命令可以方便地操作一个 Stack,而无需一个个地操作 Service。 -
Task
Task 是集群内调度的原子单元,对应运行在一个 Service 中的单个 Docker 容器。每个 Task 在 Service中被分配一个唯一的数字 ID,从1到 Service 设置的 replicas 值,每个 Task 中有一个对应的容器。一个 Task 即一个 Docker 容器。
1.5. Stacks、Services、Tasks 之间关系
1.6. Docker Swarm 与 Docker Compose 区别
Docker Swarm 和 Docker Compose 一样都是 Docker 官方容器编排工具,不同的是 Docker Compose 只能在单个服务器或主机上进行多容器的创建和管理,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务。这对于微服务部署 Docker Swarm 会是个更好的选择。
1.7. Docker Stack 与 Docker Compose 对比
1.7.1.简介
Docker引擎在1.12 版本集成了Docker Swarm,带来了新的容器编排工具 Docker Stack 。即无需安装 Docker Compose 就可以使用 docker stack 命令利用 docker-compose.yml 文件创建 Docker 容器堆栈。
1.7.2.相同点
两者使用方式基本相同,都使用 yml 文件定义容器编排。此外两者都能操纵 yml 文件中定义的 service、volumes、networks等。
# compose
docker-compose -f docker-compose up
# stack
docker stack deploy -c docker-compose.yml <stackname>
1.7.3.差异性
- 支持 compose 版本差异
docker stack 不支持 v2 规范编写的compose.yml文件,必须使用最新的V3 版本。docker-compose工具依然可以处理 v2,v3
工具 | Compose v1 | Compose v2 | Compose v3 |
---|---|---|---|
docker-compose | √ | √ | √ |
docker stack | × | × | √ |
-
指令差异
docker stack 不支持 compose file中的构建指令(build)即不可在stack 命令中创建镜像,docker stack 需要已经存在的镜像, 因此相比之下docker-compose 可现场创建镜像,更适合迭代开发、测试和 快速验证原型。两者都各自会忽律 yml 文件的部分指令,具体可以参考官方文档https://docs.docker.com/compose/compose-file/compose-file-v3/中指令下的注意事项。 -
诞生差异
docker-compose 是一个Python 项目。 起初有一个名为 fig 的 Python 项目能够解析 fig.yml 启动docker 容器堆栈。 这个工具慢慢产品化并被改名为docker-compose,但这始终是一个Python工具,作用在Docker引擎的顶层。在内部,它使用 Docker API 根据规范启动容器,所以仍然必须单独安装 docker-compose 才能与 Docker 一起使用。而 docker stack 的来源自 docker引擎原生支持,无需安装额外工具去启动docker 容器堆栈。
1.8. Swarm 基本架构
Docker Engine 1.12 引入了 swarm 模式,使您能够创建一个由一个或多个 Docker 引擎组成的集群,称为 swarm。swarm 由一个或多个节点组成:在 swarm 模式下运行 Docker Engine 1.12 或更高版本的物理或虚拟机。
-
Manager nodes(管理节点)
manager节点采用 Raft 协议来保证分布式场景下的数据一致性。通常为了保证 manager 节点的高可用,Docker 建议采用奇数个 Manager 节点,这样便可以在不关机的情况下恢复故障的管理器节点。N个 manager 节点最多可以同时容忍 (N-1)/2 个 manager 节点失效的情况下保证高可用,如3 个 manager 节点最多可以同时容忍 1 个 manager 节点失效的情况下保证高可用,当然并不意味着添加更多的管理节点可扩展性更高或性能更高,一般而言情况正好相反。官方建议一个集群下最多不超过7个 manager 节点。 -
Worker nodes(工作节点)
worker 节点不参与 Raft 分布式状态,不做出调度决策,也不为 swarm 模式 HTTP API 提供服务,其唯一目的是执行容器。worker节点之间,通过control plane 进行通信,这种通信使用gossip协议,并且是异步的。
1.8. Swarm 网络通讯
Swarm 管理的集群, 内部建立一个统一的网络层,你绑定的端口, 并非是直接绑定到宿主机, 而是绑在这个 overlay 网络。 对于集群来说, 相当于都绑在网络的一个端口上, 启用负载策略来转发请求。
二、常用命令
2.1.管理配置文件
docker config
# 查看已创建配置文件
docker config ls
# 将已有配置文件添加到 docker 配置文件中
docker config create docker <配置文件名> <本地配置文件>
2.2.管理 Swarm 节点
docker node
# 查看集群中的节点
docker node ls
# 将manager角色降级为worker
docker node demote <主机名>
# 将worker角色升级为manager
docker node promote <主机名>
# 查看节点的详细信息,默认json格式
docker node inspect <主机名>
# 查看节点信息平铺格式
docker node inspect --pretty <主机名>
# 查看运行的一个或多个及节点任务数,默认当前节点
docker node ps
# 从swarm中删除一个节点
docker node rm <主机名>
# 更新一个节点
docker node update
# 对节点设置状态(“active”正常|“pause”暂停|“drain”排除自身work任务)
docker node update --availability
2.3.管理敏感数据存储
# 管理敏感数据存储
docker secret
2.4.管理服务栈
docker stack
# 服务栈,栈的形式,一般作为编排使用,格式与docker compose相同
docker stack
# 通过.yml文件指令部署
docker stack deploy -c <文件名>.yml <编排服务名>
# 查看编排服务
docker stack ls
2.5.管理集群
docker swarm
# 初始化一个swarm
docker swarm init
# 指定初始化ip地址节点
docker swarm init --advertise-addr <管理端IP地址>
# 去除本地之外的所有管理器身份
docker swarm init --force-new-cluster
# 将节点加入swarm集群,两种加入模式manager与worker
docker swarm join
# 工作节点加入管理节点需要通过join-token认证
docker swarm join-token
# 重新获取docker获取初始化命令
docker swarm join-token worker
# 离开swarm
docker swarm leave
# 对swarm集群更新配置
docker swarm update
2.6.管理服务
docker service
# 创建一个服务
docker service create
# 创建的副本数
docker service create --replicas <副本数>
# 指定容器名称
docker service create --name <名字>
# 每次容器与容器之间的更新时间间隔。
docker service create --update-delay <秒>
# 更新时同时并行更新数量,默认1
docker service create --update-parallelism <个数>
# 任务容器更新失败时的模式,(“pause”停止|”continue“继续),默认pause。
docker service create --update-failure-action <类型>
# 每次容器与容器之间的回滚时间间隔。
docker service create --rollback-monitor 20s
# 回滚故障率如果小于百分比允许运行
docker service create --rollback-max-failure-ratio .<数值>(例 .2 为%20)
# 添加网络
docker service create --network <网络名>
# 创建volume类型数据卷
docker service create --mount type=volume,src=volume<名称>,dst=<容器目录>
# 创建bind读写目录挂载
docker service create --mount type=bind,src=<宿主目>录,dst=<容器目录>
# 创建bind只读目录挂载
docker service create --mount type=bind,src=<宿主目录>,dst=<容器目录>,readonly
# 创建dnsrr负载均衡模式
docker service create --endpoint-mode dnsrr <服务名>
# 创建docker配置文件到容器本地目录
docker service create --config source=<docker配置文件>,target=<配置文件路径>
# 创建添加端口
docker service create --publish <暴露端口>:<容器端口> <服务名>
# 查看服务详细信息,默认json格式
docker service inspect
# 查看服务信息平铺形式
docker service inspect --pretty <服务名>
# 查看服务内输出
docker service logs
# 列出服务
docker service ls
# 列出服务任务信息
docker service ps
# 查看服务启动信息
docker service ps <服务名>
# 过滤只运行的任务信息
docker service ps -f "desired-state=running" <服务名>
# 删除服务
docker service rm
# 缩容扩容服务
docker service scale
# 扩展服务容器副本数量
docker service scale <服务名>=<副本数>
# 更新服务相关配置
docker service update
# 容器加入指令
docker service update --args <指令> <服务名>
# 更新服务容器版本
docker service update --image <更新版本> <服务名 >
# 回滚服务容器版本
docker service update --rollback <回滚服务名>
# 添加容器网络
docker service update --network-add <网络名> <服务名>
# 删除容器网络
docker service update --network-rm <网络名> <服务名>
# 服务添加暴露端口
docker service update --publish-add <暴露端口>:<容器端口> <服务名>
# 移除暴露端口
docker service update --publish-rm <暴露端口>:<容器端口> <服务名>
# 修改负载均衡模式为dnsrr
docker service update --endpoint-mode dnsrr <服务名>
三、集群实践
3.1.准备工作
3.1.1.准备机器
准备3台网络互通的机器(没条件就2台,有条件还可以更多)
IP | 角色 |
---|---|
192.168.61.129 | manager |
192.168.61.130 | worker |
192.168.61.131 | worker |
3.1.2.开放端口
创建集群前以下端口需要打开,如果测试环境关闭防火墙可以忽略,如果正式环境开启了防火墙就需要打开相应端口。
端口 | 用途 |
---|---|
2377 | TCP端口2377用于集群管理通信 |
7946 | TCP和UDP端口7946用于节点之间的通信 |
4789 | TCP和UDP端口4789用于覆盖网络流量 |
附:关闭防火墙
# 关闭防火墙,立即生效
systemctl stop firewalld
# 设置重启生效
systemctl disable firewalld
3.2.创建管理节点
创建节点
# 运行以下命令来创建一个节点,首次创建的节点即为 管理节点
docker swarm init --advertise-addr 192.168.61.129
记住执行成功后的 token 信息,此 token 作为其它节点加入集群的凭证。
3.3.查看节点信息
查看节点信息命令只能在管理节点上执行
# 方式一
docker node list
# 方式二
docker node ls
3.4.添加工作节点
# 分别在工作节点机器上执行以下命令,这里 token 为上一步创建管理节点生成的值
docker swarm join --token SWMTKN-1-0a6fjic9st893u2ajmtkyjf2kxz882t2ti3f3r2vgjn87pbvrc-7l5k7wjkoahclx8zf55g0we27 192.168.61.129:2377
加入工作节点成功
查看节点列表信息,发现已经有3台机器了
3.5.添加更多管理节点
集群需要多个管理节点时,可在管理节点上执行以下命令(工作节点无法执行该命令),拷贝加入管理节点的命令,在需要加入管理节点的新的机器上执行命令就可以
# 管理节点上执行以下命令,获取加入管理节点的token信息
docker swarm join-token manager
可以看到加入管理节点的相关命令,拷贝去新的机器上执行即可
3.6.退出节点
# 如果你想退出节点,可在要退出的机器上执行以下命令即可
docker swarm leave
在管理节点上查看节点列表信息,发现状态为 Down 则退出成功,如需在加入,执行一开始的加入工作节点命令即可
3.7.Docker Service 实践
3.7.1部署服务
这里在3台机器上部署一个 nginx 集群,3个副本
# 在管理节点上执行以下命令(本地没有镜像的自己拉取)
docker service create --name nginx --replicas 3 -p 80:80 nginx:1.7.9
3.7.2查看服务
# 查看服务列表(管理节点上执行)
docker service ls
# 查看服务详情(管理节点上执行)
docker service ps nginx
在工作节点上查看服务,可以看到有个正在运行的 nginx 容器
在任意一台节点机器 ip 上都可以访问 nginx 服务
3.7.3.服务协调
服务集群运行后, 会以期望的状态方式管理整个集群。 如刚刚创建的 3台 nginx 组成的集群。 如果其中一台宕机, swarm 会自动新建一台, 来补足 task 数量。
模拟宕机,在一个几点机器上删除一个容器 docker rm -fv
在管理节点上查询 nginx 服务又可以看到新起的服务了
3.7.4.滚动升级
无需关闭服务即可对正在运行的 nginx 服务版本进行滚动升级,将原来版本 1.9.7 升级为稳定版本 stable(或者其它指定版本如 1.9.7)
# 在管理节点上执行滚动升级
docker service update --image nginx:stable nginx
查看服务,可以看到 nginx 版本已经升级为 stable
3.7.5.动态扩容
可以在服务运行期间,动态的在节点集群上进行扩容,如扩容 nginx 服务为 4
# 管理节点上进行动态扩容
docker service scale nginx=4
再次查看运行服务,可以看到在运行 nginx 服务已经扩容为4个
3.8.Docker Stack 实践
大规模场景下的多服务部署和管理是一件困难的事情,而 Docker Stack 可以方便的解决该问题。其与 Docker Compose 是类似的,通过 .yml 配置文件提供期望状态、滚动升级、扩缩容、健康检查。
3.8.1.Docker Stack部署web应用
3.8.1.1.Compose 和 Docker 兼容性
Compose 配置文件版本与 docker 版本对应规范可以通过官方文档查看:
https://docs.docker.com/compose/compose-file/
编写文件格式 | Docker 引擎发布 |
---|---|
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+ |
3.8.1.2.创建docker-stack.yml
# file: docker-compose.yml
version: "3.7"
services:
aloneService: # 服务名
image: alonedockerhub/alone:1.0 #镜像名 这里自己使用公共仓库确保每个节点机器都能拉取到镜像
networks: # 网络设置
overlay:
ports: # 端口映射 [宿主机:容器]
- "8088:8082"
deploy: # 部署设置
mode: replicated
replicas: 3
restart_policy: # 重启策略 [条件,延时,最大次数,检测时间]
condition: on-failure
delay: 5s
max_attempts: 3
window: 30s
update_config: # 升级配置 [并发数,延时,失败处理,监听时间,更新规则]
parallelism: 1
delay: 5s
failure_action: rollback
monitor: 5s
order: start-first
resources: # 资源控制 [cpu,mem]
limits:
cpus: '0.2'
memory: 1024M
networks: # 定义网络
overlay:
3.8.1.2.docker stack 部署服务
注意:镜像地址要注意,如果所有节点都拉取不到会创建不成功,如果某个节点机器拉取不到该镜像(比如该镜像在其中一个节点机器本地仓库中)则拉取不到的节点机器就无法运行,会使得多个副本都在能拉取到镜像的节点上运行导致分布不均。所以上一步配置文件中的镜像地址(镜像名)需要公共仓库保证每个节点机器能拉取到镜像。
# 在管理节点机器上执行部署
docker stack deploy -c <FILE_NAME>.yml <STACK_NAME>
3.8.1.3.查看 stack 启动的服务
(1)查看服务
# 管理节点上执行查看
docker service ls
(2)查看启动服务
# 管理节点机器上查看
docker service ps <SERVICE_NAME>
(3)查看 stack 服务
# 管理节点机器上查看
docker stack ls
(4)查看启动的服务
# 在管理节点机器上执行查看
docker stack ps <STACK_NAME>
(5)查看其它节点机器上服务
# 其它节点机器查看
docker ps
其它节点可以看到成功运行
(6)访问服务
各个节点*问启动的服务,都可以访问成功
3.8.1.3.移除 stack
# 在管理节点上执行移除
docker stack rm <STACK_NAME>
下一章发布 docker + k8s