我在AWS上有一个由2个节点组成的Docker Swarm集群。我先停止了这两个实例,然后首先启动了Swarm管理器,接着再启动Worker。在停止实例之前,我有一个运行中的服务,其中4个副本分布在管理器和Worker之间。
当我首先启动Swarm管理器节点时,所有副本容器都在管理器本身上启动,并且没有转移到Worker上。
请告诉我如何进行负载均衡?
当Worker启动时,Swarm管理器不负责执行此操作吗?
我在AWS上有一个由2个节点组成的Docker Swarm集群。我先停止了这两个实例,然后首先启动了Swarm管理器,接着再启动Worker。在停止实例之前,我有一个运行中的服务,其中4个副本分布在管理器和Worker之间。
当我首先启动Swarm管理器节点时,所有副本容器都在管理器本身上启动,并且没有转移到Worker上。
请告诉我如何进行负载均衡?
当Worker启动时,Swarm管理器不负责执行此操作吗?
目前(18.03),如果服务处于默认的“复制模式”,则Swarm不会在启动新节点时移动或替换容器。这是设计上的考虑。如果我要添加一个新节点,我不一定想停止一堆其他容器并在我的新节点上创建新的容器。当Swarm必须(在复制模式下)“移动”副本时,它才会停止容器。
docker service update --force <servicename>
将重新平衡满足其要求和约束条件的所有节点上的服务。
进一步建议:与其他容器编排器一样,您需要在节点上提供容量,以处理任何服务副本在故障期间移动的工作负载。你的备用容量应该匹配你计划支持的冗余级别。例如,如果你想同时处理2个节点失败的容量,你需要在所有节点上拥有最低百分比的资源,以便这些工作负载转移到其他节点。
这是我用来重新平衡的Bash脚本:
#!/usr/bin/env bash
set -e
EXCLUDE_LIST="(_db|portainer|broker|traefik|prune|logspout|NAME)"
for service in $(docker service ls | egrep -v $EXCLUDE_LIST |
awk '{print $2}'); do
docker service update --force $service
done
添加新节点存在“被抢”的问题。我们还避免了对健康任务的抢占。重新平衡是随着时间而进行的,而不是杀死正在工作的进程。预占在未来可能会被考虑。
作为解决方法,将服务进行扩展和收缩应该可以重新平衡任务。您也可以触发滚动更新,因为这将重新安排新任务。
version: "3"
services:
app:
image: repository/user/app:latest
networks:
- net
ports:
- 80
deploy:
restart_policy:
condition: any
mode: replicated
replicas: 5
placement:
constraints: [node.role == worker]
update_config:
delay: 2s
备注:约束条件为节点角色为worker
使用标志“--replicas”意味着我们不关心它们被放置在哪个节点上,如果我们想要每个节点一个服务,可以使用“--mode=global”。
在Docker 1.13及更高版本中,您可以使用docker服务更新命令的--force或-f标志,强制服务在可用的工作节点之间重新分配其任务。