1.简介
Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。支持的工具包括但不限于以下各项:
- Dokku
- Docker Compose
- Docker Machine
- Jenkins
原理如下图所示,swarm 集群由管理节点(manager)和工作节点(work node)构成。
- swarm manager:负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作。
- work node:即图中的 available node,主要负责运行相应的服务来执行任务(task)。
2.使用
当前的系统和Docker版本,以下测试均基于此环境:
# 系统版本 [root@tcloud ~]# cat /etc/centos-release CentOS Linux release 7.9.2009 (Core) # Docker版本 [root@tcloud ~]# docker --version Docker version 20.10.13, build a224086
2.1 初始化
首先,您需要在 Docker 主机上初始化 Swarm。可以通过以下命令完成:
# 初始化命令 docker swarm init # 实测 [root@tcloud ~]# docker swarm init Swarm initialized: current node (xab6g9fgtm86u830xc6y0ydib) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-46uvq1siqzb59k6gs0hfhmq02ndemtuze3obv0z7rm0wt7ca6l-56ubevf6f4pmlytic9170fywj xxx.xx.x.x:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
执行此命令后,Docker 将当前节点设置为 Swarm 的管理节点,并生成一个加入 Swarm 的token令牌。这个令牌用于将其他节点加入 Swarm。
# 查看Docker信息 [root@tcloud ~]# docker info # Swarm相关信息 Server: Swarm: active NodeID: xab6g9fgtm86u830xc6y0ydib Is Manager: true ClusterID: d62ha22wptcgugdzlg8zn8892 Managers: 1 Nodes: 1 Default Address Pool: 10.0.0.0/8 SubnetSize: 24 Data Path Port: 4789 Orchestration: Task History Retention Limit: 5 Raft: Snapshot Interval: 10000 Number of Old Snapshots to Retain: 0 Heartbeat Tick: 1 Election Tick: 10 Dispatcher: Heartbeat Period: 5 seconds CA Configuration: Expiry Duration: 3 months Force Rotate: 0 Autolock Managers: false Root Rotation In Progress: false Node Address: xxx.xx.x.x Manager Addresses: xxx.xx.x.x:2377
忘记令牌可以在Manager节点进行查询:
# 查询命令【To add a manager to this swarm】 docker swarm join-token manager # 实测 [root@tcloud ~]# docker swarm join-token manager To add a manager to this swarm, run the following command: docker swarm join --token SWMTKN-1-46uvq1siqzb59k6gs0hfhmq02ndemtuze3obv0z7rm0wt7ca6l-b1wor0jtm59dgkbj87y3vo6pa xxx.xx.x.x:2377
# 查询命令【To add a worker to this swarm】 docker swarm join-token worker # 实测 [root@tcloud ~]# docker swarm join-token worker To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-46uvq1siqzb59k6gs0hfhmq02ndemtuze3obv0z7rm0wt7ca6l-56ubevf6f4pmlytic9170fywj xxx.xx.x.x:2377
2.2 添加节点
节点的系统和Docker版本【与Manager的系统和Docker版本都不一致】:
# 系统版本 CentOS Linux release 7.7.1908 (Core) # Docker版本 Docker version 17.06.2-ce, build cec0b72
在节点上,使用之前生成的令牌将它们加入到 Swarm。例如:
# 添加命令 docker swarm join --token <TOKEN> <MANAGER-IP>:<PORT> # 实例 [root@localhost deepface]# docker swarm join --token SWMTKN-1-46uvq1siqzb59k6gs0hfhmq02ndemtuze3obv0z7rm0wt7ca6l-56ubevf6f4pmlytic9170fywj xxx.xx.x.x:2377 This node joined a swarm as a worker.
添加节点后在Manager上查询数据如下:
# 可以看到节点数变为2了 Server: Swarm: active Managers: 1 Nodes: 2
使用node
命令查看信息如下:
# 查询命令 docker node ls # 查询结果 ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION j3ey43drdbcndd5o6ondp3r9g localhost.localdomain Ready Active 17.06.2-ce lvrjegiuhr6tllt8hr3ls50v3 * nodexxx Ready Active Leader 20.10.13 # 删除节点命令 docker node rm <node-id> # 排查节点命令 docker node update --availability drain <node-id> # 重新启用节点 docker node update --availability active <node-id> # 排除节点后 ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION j3ey43drdbcndd5o6ondp3r9g localhost.localdomain Ready Drain 17.06.2-ce lvrjegiuhr6tllt8hr3ls50v3 * nodexxx Ready Active Leader 20.10.13 ahgt6tmv8d9o6vp0i0c20nxed nodexxx Ready Active 20.10.13
2.3 创建服务
创建一个 Docker 服务,定义容器的规模、镜像、端口映射等。例如:
docker service create --replicas 3 -p 80:80 --name web nginx:latest
此命令创建一个名为 “web” 的服务,使用 Nginx 镜像,在集群中运行 3 个副本,并将主机的端口 80 映射到服务的端口 80。以下为实例:
# 单机版的服务启动命令 docker run --name deepface --privileged --restart=always --net="host" -v /root/.deepface/weights/:/root/.deepface/weights/ -d deepface_image # 集群版启动 docker service create --replicas 4 --name deepface_cluster --publish 5000:5000 --mount type=bind,source=/root/.deepface/weights/,target=/root/.deepface/weights/ -d deepface_image docker service create --replicas 2 --name deepface_cluster --network host --mount type=bind,source=/root/.deepface/weights/,target=/root/.deepface/weights/ -d deepface_image
注意:如果副本数大于节点数不可使用--network host
会因为端口占用而无法启动节点。
--replicas
的值和节点数并不需要严格一样。在 Docker Swarm 中,--replicas
参数用于指定服务的副本数量,而不是节点数。副本是指服务在整个 Swarm 集群中运行的实例数量。当您创建一个服务时,可以指定 --replicas
参数来定义服务的规模,但这并不要求集群中的每个节点都会运行一个副本。Swarm 将会在可用的节点上自动进行副本的调度,以满足指定的数量。例如,如果您有一个包含 3 个节点的 Swarm 集群,并且执行以下命令:
docker service create --replicas 5 --name my-service my-image
这将在集群的某些节点上调度 5 个副本,而不是每个节点上都运行一个。Swarm 会在集群中选择可用的节点,并在这些节点上启动服务的副本,以实现规模为 5。
2.4 查看服务状态
可以使用以下命令来查看 Swarm 集群中的服务状态:
# 查询命令 docker service ls # 查询结果 ID NAME MODE REPLICAS IMAGE PORTS kjbpehilmg98 deepface_cluster replicated 4/4 deepface_image:latest
这会列出所有运行的服务以及它们的状态和规模。
2.5 扩展或缩减服务
可以通过以下命令来扩展或缩减服务的规模:
docker service scale web=5
这将将 “web” 服务的规模扩展到 5 个副本。以下为实践内容:
2.6 更新服务
需要更新服务,例如更改容器使用的镜像,可以使用以下命令:
# 此命令未进行测试 docker service update --image new-image:tag web
2.6 删除服务和停止 Swarm
最后,要删除服务,可以使用以下命令:
# 删除服务命令 docker service rm web # 测试 [root@node178 /root]$ docker service rm deepface_cluster deepface_cluster # 查询并删除全部服务 docker service rm $(docker service ls -q)
要停止 Swarm,可以在管理节点上运行以下命令:
# 停止Swarm命令 docker swarm leave --force
3.报错
3.1 OpenBLAS blas_thread_init: pthread_create failed for thread x of xx: Operation not permitted
deepface_cluster.1.wtmx0mm6vu2f@localhost.localdomain | OpenBLAS blas_thread_init: pthread_create failed for thread x of xx: Operation not permitted deepface_cluster.1.wtmx0mm6vu2f@localhost.localdomain | OpenBLAS blas_thread_init: RLIMIT_NPROC -1 current, -1 max
由于节点的Docker版本为17.06.2-ce, build cec0b72
在执行以下命令启动容器时:
docker run --name deepface --privileged --restart=always --net="host" -v /root/.deepface/weights/:/root/.deepface/weights/ -d deepface_image
两个版本的容器均运行正常,但使用下边的命令启动容器时,去掉了--privileged
:
docker run --name deepface --restart=always --net="host" -v /root/.deepface/weights/:/root/.deepface/weights/ -d deepface_image
此时,较低版本的会有如下报错:
OpenBLAS blas_thread_init: pthread_create failed for thread x of xx: Operation not permitted OpenBLAS blas_thread_init: RLIMIT_NPROC -1 current, -1 max
3.2 节点的服务未被调用
docker swarm cluster 各结点间通信依赖于三个端口2377,7946,4789
其中:
- tcp端口2377:为集群管理端口
- tcp与udp端口7946:为节点之间通讯端口
- tcp与udp端口4789:为overlay网络通讯端口(overlay网络为二层与三层之间新型通讯技术)
iptables -A INPUT -p tcp --dport 2377 -j ACCEPT iptables -A INPUT -p tcp --dport 7946 -j ACCEPT iptables -A INPUT -p udp --dport 7946 -j ACCEPT iptables -A INPUT -p tcp --dport 4789 -j ACCEPT iptables -A INPUT -p udp --dport 4789 -j ACCEPT
放开端口后未解决问题。可能是启动服务时的参数--network host
导致的,进行以下尝试:
# 1.创建专用网络 docker network create -d overlay deepface_network # 查询网络 docker network ls # 2.重新启动服务 docker service create --replicas 2 --name deepface_cluster --network deepface_network --publish 5000:5000 --mount type=bind,source=/root/.deepface/weights/,target=/root/.deepface/weights/ -d deepface_image
Manager
启动失败:
# 通过以下命令查看 journalctl -u docker.service # 报错信息 level=error msg="Failed creating ingressingress network: error creating external connectivity network: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i docker_gwbridge -j RETURN: iptables: No chain/target/match by that name.\n (exit status 1))" level=error msg="Failed creating ingress network: error creating external connectivity network: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i docker_gwbridge -j RETURN: iptables: No chain/target/match by that name.\n (exit status 1))" level=error msg="failed removing container name resolution for c09097de449b90705f7022e7a9ece84d535fcd955a0858817e4892d429ac0182 epRec:{ingress-endpoint <nil> 10.0.0.34 [] [] [] false} err:network w8w5u3v5ny4cirzk5hfkvfu5q not found" level=error msg="Not continuing with pull after error: errors:\ndenied: requested access to the resource is denied\nunauthorized: authentication required\n" level=info msg="Ignoring extra error returned from registry: unauthorized: authentication required" level=error msg="pulling image failed" error="pull access denied for deepface_image, repository does not exist or may require 'docker login': denied: requested access to the resource is denied" module=node/agent/taskmanager node.id=lvrjegiuhr6tllt8hr3ls50v3 service.id=xh66bfakl21z8rxb1oof0pdp2 task.id=oj16bpvpxgdzxmpo6jf8we117 level=warning msg="IPv4 forwarding is disabled. Networking will not work." level=warning msg="IPv4 forwarding is disabled. Networking will not work." level=error msg="1aab2faa1bbe2b0857062a4c211d4abc308338f1a367936665b266c3d44d5d69 cleanup: failed to delete container from containerd: no such container" level=error msg="fatal task error" error="starting container failed: error creating external connectivity network: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i docker_gwbridge -j RETURN: iptables: No chain/target/match by that name.\n (exit status 1))" module=node/agent/taskmanager node.id=l level=warning msg="Error (Unable to complete atomic operation, key modified) deleting object [endpoint icoywtf0kcknyw0og5samm59j 90904c66a7adb5751ace11266f6482fe47b1e8f813cd89085f1843b44153371c], retrying...." level=warning msg="rmServiceBinding handleEpTableEvent deepface_cluster abc833b8b12d6c3b23ec293eb24f8750c2ca14d9f4a1d8da4f52b8f6a3145d07 aborted s.loadBalancers[nid] !ok"
解决:
# 重启docker systemctl restart docker # 重新启动服务 docker service create --replicas 2 --name deepface_cluster --network deepface_network --publish 5000:5000 --mount type=bind,source=/root/.deepface/weights/,target=/root/.deepface/weights/ -d deepface_image
成功!