如何在 Docker Swarm 中正确配置 HAProxy 以自动将流量路由到复制服务(通过 SSL)?
How to properly configure HAProxy in Docker Swarm to automatically route traffic to replicated services (via SSL)?
我正在尝试部署一个 Docker 具有单个复制服务的三个主机节点的 Swarm,并在其前面放置一个 HAProxy。我希望客户端能够通过 SSL 连接。
我的docker-compose.yml
:
version: '3.9'
services:
proxy:
image: haproxy
ports:
- 443:8080
volumes:
- haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
deploy:
placement:
constraints: [node.role == manager]
networks:
- servers-network
node-server:
image: glusk/hackathon-2021:latest
ports:
- 8080:8080
command: npm run server
deploy:
mode: replicated
replicas: 2
networks:
- servers-network
networks:
servers-network:
driver: overlay
我的haproxy.cfg
(基于official example):
# Simple configuration for an HTTP proxy listening on port 80 on all
# interfaces and forwarding requests to a single backend "servers" with a
# single server "server1" listening on 127.0.0.1:8000
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend servers
backend servers
server server1 127.0.0.1:8000 maxconn 32
我的主机是 Lightsail VPS Ubuntu 个实例并且共享同一个私有网络。
node-service
运行s 每个 https 服务器任务在其自己的容器内:0.0.0.0:8080
。
我现在尝试使这项工作的方式是 ssh
进入 manager 节点(它也有一个静态和 public IP),从上面复制我的配置文件,然后 运行:
docker stack deploy --compose-file=docker-compose.yml hackathon-2021
但是没用。
嗯,首先关于 SSL(因为这是你提到的第一件事)你需要使用证书配置它并监听端口 443
, 不是端口 80
.
通过该修改,您的代理配置已经更改为:
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend servers
frontend https-in
bind *:443 ssl crt /etc/ssl/certs/hackaton2021.pem
default_backend servers
这将是允许 SSL 连接的真正简化的配置。
现在,我们来访问不同的服务。
首先,您无法访问 localhost
上的服务,实际上您甚至不应该向主机公开您拥有的服务端口。原因?您已经在与 haproxy
相同的网络中拥有这些应用程序,因此理想的做法是利用 Docker DNS 直接访问它们
为此,首先我们需要能够解析服务名称。为此,您需要将以下部分添加到您的配置中:
resolvers docker
nameserver dns1 127.0.0.11:53
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold other 10s
hold refused 10s
hold nx 10s
hold timeout 10s
hold valid 10s
hold obsolete 10s
Docker Swarm DNS 服务 始终 在 127.0.0.11
.
可用
现在对于您之前存在的配置,我们必须添加服务器但使用服务名称发现:
backend servers
balance roundrobin
server-template node- 2 node-server:8080 check resolvers docker init-addr libc,none
如果您检查我们在做什么,我们正在 node-server
服务中为 Swarm 中的每个发现的容器创建一个服务器(因此是副本),我们将创建那些添加前缀 node-
给他们每个人。
基本上,这相当于获取每个副本的实际 IP 并将它们添加为基本 server
配置。
对于部署,您也有一些错误,因为我们对实际向主机公开 node-server
端口不感兴趣,而是创建两个副本并使用 HAProxy 进行网络连接。
为此,我们应该使用以下 Docker 撰写:
version: '3.9'
services:
proxy:
image: haproxy
ports:
- 80:80
- 443:443
volumes:
- hackaton2021.pem:/etc/ssl/certs/hackaton2021.pem
- haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
deploy:
placement:
constraints: [node.role == manager]
node-server:
image: glusk/hackathon-2021:latest
command: npm run server
deploy:
mode: replicated
replicas: 2
记得在部署 Stack 之前将您的 haproxy.cfg
和应用程序的自签名(或真实)证书复制到实例。
此外,当您创建该堆栈时,它会自动创建一个名为 <STACK_NAME>-default
的网络,因此您不需要定义一个网络来连接这两个服务。
我正在尝试部署一个 Docker 具有单个复制服务的三个主机节点的 Swarm,并在其前面放置一个 HAProxy。我希望客户端能够通过 SSL 连接。
我的docker-compose.yml
:
version: '3.9'
services:
proxy:
image: haproxy
ports:
- 443:8080
volumes:
- haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
deploy:
placement:
constraints: [node.role == manager]
networks:
- servers-network
node-server:
image: glusk/hackathon-2021:latest
ports:
- 8080:8080
command: npm run server
deploy:
mode: replicated
replicas: 2
networks:
- servers-network
networks:
servers-network:
driver: overlay
我的haproxy.cfg
(基于official example):
# Simple configuration for an HTTP proxy listening on port 80 on all
# interfaces and forwarding requests to a single backend "servers" with a
# single server "server1" listening on 127.0.0.1:8000
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend servers
backend servers
server server1 127.0.0.1:8000 maxconn 32
我的主机是 Lightsail VPS Ubuntu 个实例并且共享同一个私有网络。
node-service
运行s 每个 https 服务器任务在其自己的容器内:0.0.0.0:8080
。
我现在尝试使这项工作的方式是 ssh
进入 manager 节点(它也有一个静态和 public IP),从上面复制我的配置文件,然后 运行:
docker stack deploy --compose-file=docker-compose.yml hackathon-2021
但是没用。
嗯,首先关于 SSL(因为这是你提到的第一件事)你需要使用证书配置它并监听端口 443
, 不是端口 80
.
通过该修改,您的代理配置已经更改为:
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend servers
frontend https-in
bind *:443 ssl crt /etc/ssl/certs/hackaton2021.pem
default_backend servers
这将是允许 SSL 连接的真正简化的配置。
现在,我们来访问不同的服务。
首先,您无法访问 localhost
上的服务,实际上您甚至不应该向主机公开您拥有的服务端口。原因?您已经在与 haproxy
相同的网络中拥有这些应用程序,因此理想的做法是利用 Docker DNS 直接访问它们
为此,首先我们需要能够解析服务名称。为此,您需要将以下部分添加到您的配置中:
resolvers docker
nameserver dns1 127.0.0.11:53
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold other 10s
hold refused 10s
hold nx 10s
hold timeout 10s
hold valid 10s
hold obsolete 10s
Docker Swarm DNS 服务 始终 在 127.0.0.11
.
现在对于您之前存在的配置,我们必须添加服务器但使用服务名称发现:
backend servers
balance roundrobin
server-template node- 2 node-server:8080 check resolvers docker init-addr libc,none
如果您检查我们在做什么,我们正在 node-server
服务中为 Swarm 中的每个发现的容器创建一个服务器(因此是副本),我们将创建那些添加前缀 node-
给他们每个人。
基本上,这相当于获取每个副本的实际 IP 并将它们添加为基本 server
配置。
对于部署,您也有一些错误,因为我们对实际向主机公开 node-server
端口不感兴趣,而是创建两个副本并使用 HAProxy 进行网络连接。
为此,我们应该使用以下 Docker 撰写:
version: '3.9'
services:
proxy:
image: haproxy
ports:
- 80:80
- 443:443
volumes:
- hackaton2021.pem:/etc/ssl/certs/hackaton2021.pem
- haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
deploy:
placement:
constraints: [node.role == manager]
node-server:
image: glusk/hackathon-2021:latest
command: npm run server
deploy:
mode: replicated
replicas: 2
记得在部署 Stack 之前将您的 haproxy.cfg
和应用程序的自签名(或真实)证书复制到实例。
此外,当您创建该堆栈时,它会自动创建一个名为 <STACK_NAME>-default
的网络,因此您不需要定义一个网络来连接这两个服务。