一, 简介
1. 什么是 docker swarm?
Swarm 在 Docker 1.12 版本之前属于一个独立的项目, 在 Docker 1.12 版本发布之后, 该项目合并到了 Docker 中, 成为 Docker 的一个子命令. 目前, Swarm 是 Docker 社区提供的唯一一个原生支持 Docker 集群管理的工具. 它可以把多个 Docker 主机组成的系统转换为单一的虚拟 Docker 主机, 使得容器可以组成跨主机的子网网络.
Docker Swarm 是一个为 IT 运维团队提供集群和调度能力的编排工具. 用户可以把集群中所有 Docker Engine 整合进一个「虚拟 Engine」的资源池, 通过执行命令与单一的主 Swarm 进行沟通, 而不必分别和每个 Docker Engine 沟通. 在灵活的调度策略下, IT 团队可以更好地管理可用的主机资源, 保证应用容器的高效运行.
Swarm 的基本架构如下图所示:
2. Docker Swarm 优点
任何规模都有高性能表现
对于企业级的 Docker Engine 集群和容器调度而言, 可拓展性是关键. 任何规模的公司 -- 不论是拥有五个还是上千个服务器 -- 都能在其环境下有效使用 Swarm.
经过测试, Swarm 可拓展性的极限是在 1000 个节点上运行 50000 个部署容器, 每个容器的启动时间为亚秒级, 同时性能无减损.
灵活的容器调度
Swarm 帮助 IT 运维团队在有限条件下将性能表现和资源利用最优化. Swarm 的内置调度器 (scheduler) 支持多种过滤器, 包括: 节点标签, 亲和性和多种容器部策略如 binpack,spread,random 等等.
服务的持续可用性
Docker Swarm 由 Swarm Manager 提供高可用性, 通过创建多个 Swarm master 节点和制定主 master 节点宕机时的备选策略. 如果一个 master 节点宕机, 那么一个 slave 节点就会被升格为 master 节点, 直到原来的 master 节点恢复正常.
此外, 如果某个节点无法加入集群, Swarm 会继续尝试加入, 并提供错误警报和日志. 在节点出错时, Swarm 现在可以尝试把容器重新调度到正常的节点上去.
和 Docker API 及整合支持的兼容性
Swarm 对 Docker API 完全支持, 这意味着它能为使用不同 Docker 工具 (如 Docker CLI,Compose,Trusted Registry,Hub 和 UCP) 的用户提供无缝衔接的使用体验.
Docker Swarm 为 Docker 化应用的核心功能 (诸如多主机网络和存储卷管理) 提供原生支持
开发的 Compose 文件能 (通过 docker-compose up ) 轻易地部署到测试服务器或 Swarm 集群上. Docker Swarm 还可以从 Docker Trusted Registry 或 Hub 里 pull 并 run 镜像.
二, 相关概念
1. 节点
有两种类型的节点: managers 和 workers.
管理节点(managers)
管理节点用于 Swarm 集群的管理, docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行). 一个 Swarm 集群可以有多个管理节点, 但只有一个管理节点可以成为 leader,leader 通过 raft 协议实现.
为了利用 swarm 模式的容错功能, Docker 建议您根据组织的高可用性要求实现奇数个节点. 当您拥有多个管理器时, 您可以从管理器节点的故障中恢复而无需停机.
N 个管理节点的集群容忍最多损失 (N-1)/2 个管理节点.
Docker 建议一个集群最多 7 个管理器节点.
重要说明: 添加更多管理节点并不意味着可扩展性更高或性能更高. 一般而言, 情况正好相反.
工作节点(workers)
工作节点是任务执行节点, 管理节点将服务 (service) 下发至工作节点执行. 管理节点默认也作为工作节点. 你也可以通过配置让服务只运行在管理节点. 下图展示了集群中管理节点与工作节点的关系.
2. 服务和任务
任务 (Task)是 Swarm 中的最小的调度单位, 目前来说就是一个单一的容器.
服务 (Services) 是指一组任务的集合, 服务定义了任务的属性. 服务有两种模式:
replicated services (复制服务)按照一定规则在各个工作节点上运行指定个数的任务.
global services (全局服务)每个工作节点上运行一个任务.
两种模式通过 docker service create 的 --mode 参数指定. 下图展示了容器, 任务, 服务的关系.
三, Swarm 集群
准备工作
三个可以通过网络进行通信的 Linux 主机或虚拟机, 并安装了 Docker, 或者使用 docker-machine 创建三台虚拟机.
已安装 Docker Engine 1.12 或更高版本
在主机之间打开端口(2377,7946,4789)
创建一个集群
1. 创建虚拟机(已经有 Linux 主机或虚拟机的跳过此步)
本文通过 docker-machine 使用 VirtualBox 驱动程序创建 3 个 VM (已经有 Linux 主机或虚拟机的跳过此步):
- docker-machine create --driver VirtualBox myvm-1
- docker-machine create --driver VirtualBox myvm-2
- docker-machine create --driver VirtualBox myvm-3
列出虚拟机并获取其 IP 地址:
docker-machine ls
以下是此命令的示例输出:
- $docker-machine ls
- NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
- myvm-1 - VirtualBox Running tcp://192.168.99.100:2376 v18.09.1-beta2
- myvm-2 - VirtualBox Running tcp://192.168.99.101:2376 v18.09.1-beta2
- myvm-3 - VirtualBox Running tcp://192.168.99.102:2376 v18.09.1-beta2
2. 初始化 swarm
把第一台机器 myvm-1 充当管理节点, 第二台 myvm-2 , 第三台 myvm-3 为工作节点.
使用 docker-machine SSH 连接 myvm-1,Linux 主机直接 SSH 连接就行.
docker-machine SSH myvm-1
初始化 swarm
- docker swarm init --advertise-addr 192.168.99.100
- Swarm initialized: current node (4a8mo8cekpe0vpk0ze963avw9) is now a manager.
- To add a worker to this swarm, run the following command:
- docker swarm join --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u 192.168.99.100:2377
- To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
上面输出的这一段就是工作节点加入集群的命令:
docker swarm join --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u 192.168.99.100:2377
如果你的 Docker 主机有多个网卡, 拥有多个 IP, 必须使用 --advertise-addr 指定 IP.
执行 docker swarm init 命令的节点自动成为管理节点.
命令 docker info 可以查看 swarm 集群状态:
- Server Version: 18.09.1-beta2
- Storage Driver: overlay2
- Backing Filesystem: extfs
- Supports d_type: true
- Native Overlay Diff: true
- Logging Driver: JSON-file
- Cgroup Driver: cgroupfs
- Plugins:
- Volume: local
- Network: bridge host macvlan null overlay
- Log: awslogs Fluentd gcplogs gelf journald JSON-file local logentries splunk syslog
- Swarm: active
- NodeID: ib1498ex2q18i7gznb2zgicqq
- Is Manager: true
- ClusterID: fbyxxjzrtcxc53op35jnyzl7t
- Managers: 3
- Nodes: 3
- Default Address Pool: 10.0.0.0/8
命令 docker node ls 可以查看集群节点信息:
- $docker node ls
- ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
- ib1498ex2q18i7gznb2zgicqq * myvm-1 Ready Active Leader 18.09.1-beta2
3. 工作节点加入 swarm 集群
连接机器 myvm-2
docker-machine SSH myvm-2
加入 swarm 集群
- $docker swarm join \
- --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u \
- 192.168.99.100:2377
- This node joined a swarm as a worker.
节点 myvm-3, 执行 myvm-2 相同的操作加入集群.
集群的大部分命令需要在管理节点中才能运行
我们进入管理节点 myvm-1 , 查看集群的节点信息.
- docker node ls
- ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
- ib1498ex2q18i7gznb2zgicqq * myvm-1 Ready Active Leader 18.09.1-beta2
- vels0fe3eh5s5cxj1s573v9wx myvm-2 Ready Active 18.09.1-beta2
- obxnnqelh4p16wajrwvyn6j8v myvm-3 Ready Active 18.09.1-beta2
为了高可用, 我们升级工作节点为管理节点.
- docker node promote myvm-2
- docker node promote myvm-3
这时我们再看集群的节点信息
- $ docker node ls
- ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
- ib1498ex2q18i7gznb2zgicqq * myvm-1 Ready Active Leader 18.09.1-beta2
- vels0fe3eh5s5cxj1s573v9wx myvm-2 Ready Active Reachable 18.09.1-beta2
- obxnnqelh4p16wajrwvyn6j8v myvm-3 Ready Active Reachable 18.09.1-beta2
myvm-2,myvm-3 的 集群状态变为 Reachable(选举者), 因为集群中节点 Leader 只能有一个, 这个类似 zookeeper, 只不过 zookeepers 用的算法是 paxos,Swarm 用的算法是 raft.
4. 退出 Swarm 集群
如果 Manager 想要退出 Swarm 集群, 在 Manager Node 上执行如下命令:
docker swarm leave
如果集群中还存在其它的 Worker Node, 还希望 Manager 退出集群, 则加上一个强制选项, 命令行如下所示:
docker swarm leave --force
工作节点进行退出集群, 需要在工作节点上执行命令:
docker swarm leave
退出后的节点, 依然可以使用 上面的 docker swarm join --token 重新加入集群.
集群上部署应用
命令
$ docker service create --replicas 1 --name 别名 镜像 ID
replicas 指定运行服务的数量.
实例 1
创建一个 alpine 服务(alpine 是一个小型 liunx 系统)
- # 运行一个 alpine 镜像, 并执行 ping 命令
- docker service create --replicas 1 --name test1 alpine ping docker.com
查看集群上的服务
- $docker service ls
- ID NAME MODE REPLICAS IMAGE PORTS
- rnu10rprrwzv test1 replicated 1/1 alpine:latest
实例 2
以下命令将 nginx 容器中的端口 80 发布到群集中任何节点的端口 8080
- docker service create \
- --name my-web \
- --publish published=8080,target=80 \
- --replicas 2 \
- nginx
查看集群上的服务
- $ docker service ls
- ID NAME MODE REPLICAS IMAGE PORTS
- q6wfiizzosmd nginx replicated 3/3 nginx:latest *:8080->80/tcp
- rnu10rprrwzv test1 replicated 1/1 alpine:latest
service 通过 ingress load balancing 来发布服务, 且 swarm 集群中所有 node 都参与到 ingress 路由网格(ingress routing mesh) 中, 访问任意一个 node+PublishedPort 即可访问到服务.
当访问任何节点上的端口 8080 时, Docker 将您的请求路由到活动容器. 在群节点本身, 端口 8080 可能并不实际绑定, 但路由网格知道如何路由流量, 并防止任何端口冲突的发生.
路由网格在发布的端口上监听分配给节点的任何 IP 地址. 对于外部可路由的 IP 地址, 该端口可从主机外部获得. 对于所有其他 IP 地址, 只能从主机内部访问.
所以访问 192.169.99.100:8080,192.169.99.101:8080,192.169.99.102:8080 , 都可以访问到 nginx, 这样就实现了负载均衡. 因为我们指定 --replicas 3 启动了 3 个运行 nginx 的容器 , 所以三个节点 myvm-1,myvm-2,myvm-3 上都运行了一个 nginx 的容器, 可以通过改其中一个节点上的 nginx 的欢迎页 , 然后再访问, 来检查是否实现了负载均衡.
可以通过 scale 来指定运行容器的数量.
docker service scale nginx=2
我通过 docker service ls 可以看出 nginx 的副本变成了 2 个
- $docker service ls
- ID NAME MODE REPLICAS IMAGE PORTS
- q6wfiizzosmd nginx replicated 2/2 nginx:latest *:8080->80/tcp
overlay 网络
1. 概述
初始化 swarm 或将 Docker 主机加入现有 swarm 时, 会在该 Docker 主机上创建两个新网络:
ingress: 称为覆盖网络 ingress, 处理与群集服务相关的控制和数据流量. 创建群组服务并且不将其连接到用户定义的覆盖网络时, ingress 是默认连接的网络.
docker_gwbridge: 称为桥接网络 docker_gwbridge, 它将各个 Docker 守护程序连接到参与该群集的其他守护进程.
在管理节点上查看网络
- $ docker network ls
- NETWORK ID NAME DRIVER SCOPE
- cb0ccb89a988 bridge bridge local
- 0174fb113496 docker_gwbridge bridge local
- 541b62778c0e host host local
- 8n7xppn5z4j2 ingress overlay swarm
- 369d459f340d none null local
overlay 网络驱动程序会创建多个 Docker 守护主机之间的分布式网络. 该网络位于 (覆盖) 特定于主机的网络之上, 允许连接到它的容器 (包括群集服务容器) 安全地进行通信. Docker 透明地处理每个数据包与正确的 Docker 守护程序主机和正确的目标容器的路由.
2. 自定义 overlay 网络
创建用于 swarm 服务的 overlay 网络, 使用如下命令:
docker network create -d overlay my-overlay
我们再次查看网络, 发现可以看到自定义 overlay 了.
- $docker network ls
- NETWORK ID NAME DRIVER SCOPE
- cb0ccb89a988 bridge bridge local
- 0174fb113496 docker_gwbridge bridge local
- 541b62778c0e host host local
- 8n7xppn5z4j2 ingress overlay swarm
- a23htz7n0pvp my-overlay overlay swarm
- 369d459f340d none null local
集群中部署了两个服务 nginx,alpine, 现在我们进入 alpine, 去访问 nginx.
- docker exec -it test1.1.oonwl8c5g4u3p17x8anifeubi bash
- / # ping nginx
- ping: bad address 'nginx'
- wget 192.168.99.100:8080
- Connecting to 192.168.99.100:8080 (192.168.99.100:8080)
- index.html 100% |*************************************************************************************************************| 612 0:00:00 ETA
我们发现集群中的各个服务不能用名称访问的, 只能用集群服务发现的路由网络访问, 那么集群中的服务怎么能通过名称进行访问呢, 这就需要用到上面自定义的 overlay 网络.
删除我们启动的服务, 重新创建指定使用自定义网络的服务.
- docker service rm nginx test1
- docker service create --name nginx -p 8080:80 --network my-overlay --replicas 3 nginx
- docker service create --name test1 --network my-overlay alpine ping www.baidu.com
进入 test1 容器中, 重新测试下:
- / # ping nginx
- PING nginx (10.0.0.2): 56 data bytes
- 64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.120 ms
- 64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.094 ms
- 64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.108 ms
- / # wget nginx
- Connecting to nginx (10.0.0.2:80)
- index.HTML 100% |*************************************************************************************************************| 612 0:00:00 ETA
发现可以通过名称进行集群中的容器间的访问了.
欢迎扫码或微信搜索公众号《程序员果果》关注我, 关注有惊喜~
来源: https://www.cnblogs.com/huanchupkblog/p/10851195.html