我们在 Swarm 集群中有 3 个主机,并且我们在这个集群中部署了一个 Web 应用程序。该 Web 应用程序在任何时候都只能在 1 个主机上运行。如果一个主机死机,该 Web 应用程序将被转移到另一个主机。
无论您的请求命中哪个主机,Docker 都会负责将您的请求路由到 Web 应用程序。
为了确保我们始终能够访问正常运行的主机,我们考虑使用 Nginx 作为前端。我们将在 Nginx 上创建一个虚拟主机,它将代理对 Docker 群的请求。
对此我们有两种方法。
答:我们只是在主机之间“循环”处理请求。
这是一种简单的方法。当服务发生故障时,我们将使用 Nginx 来移除服务。但是,即使 Nginx 从主机 1 收到 500 错误,也可能是 Web 应用程序从主机 3 返回了该 500 错误。Nginx 会错误地认为主机 1 上的服务发生故障,并移除该主机上的服务。
B. 我们会将所有请求发送给群组领导者。
我们不使用 Nginx 在主机之间进行负载平衡。我们只是将所有请求发送到 Docker Swarm 领导者(通过各种脚本,我们配置 Nginx 来执行此操作)。这样,我们就不会进行“双重”负载平衡(Nginx 和 Docker Swarm),但所有流量都只通过 Docker Swarm 领导者。
一方面,解决方案 A 简单易懂,但在双负载平衡方面也可能会增加复杂性。第二种解决方案可能更复杂,因为它不太标准,但也可能使事情更容易理解。
从纯技术角度来看,我们应该选择哪种方法?
答案1
我认为这是对选项 1 的评论。
我也在研究这个问题,从 Docker Swarm > 1.12 中我所知道的,你所要做的就是创建一个到服务/网站的反向代理。我在概念验证中所做的是:1) 创建两个覆盖网络,一个用于代理网络,它将面向外部,另一个用于我的服务网络,它只用于内部;然后 2) 部署 3 个服务副本,将其附加到服务覆盖和代理覆盖网络 (--network proxy --network my-service)。最后,我建立了一个绑定到我公司别名的 nginx 反向代理,它将接受端口 80 和 443 上的传入连接。
sudo docker service create --name proxy \
-p 80:80 \
-p 443:443 \
--network proxy \
--mount type=volume,source=reverse-proxy,target=/etc/nginx/conf.d,volume-driver=azurefile \
--mount type=volume,source=ssl,target=/etc/nginx/ssl,volume-driver=azurefile \
nginx
挂载点就在那里,所以我不必将文件复制到每个主机。此挂载指向 Azure 文件存储帐户,这使得启动更多容器更加易于维护。
反向代理如下所示:
location /my-service/ {
proxy_read_timeout 900;
proxy_pass http://my-service/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
http://我的服务是 Swarm 内部的 DNS 记录,它始终指向托管我服务的 VIP,无论是 1 个节点还是 1,000 个节点。据我所知,您部署的每项服务都有自己的子网范围,主节点会跟踪容器的运行位置并为您处理路由。
目前,我们有多个指向不同主机 IP 的 A 记录,并使用循环调度,但我们可能会将其从 Windows Server 管理的 DNS 移至 Azure Traffic Manager,以获得更好的控制。