【问题标题】:How to properly configure HAProxy in Docker Swarm to automatically route traffic to replicated services (via SSL)?如何在 Docker Swarm 中正确配置 HAProxy 以自动将流量路由到复制服务(通过 SSL)?
【发布时间】:2021-11-02 13:56:29
【问题描述】:

我正在尝试使用单个复制服务部署一个由三个主机节点组成的 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 在其自己的容器中运行每个 https 服务器任务:0.0.0.0:8080

我目前尝试完成这项工作的方法是将ssh 放入 manager 节点(它也有一个静态和公共 IP),从上面复制我的配置文件,然后运行:

docker stack deploy --compose-file=docker-compose.yml hackathon-2021

但它不起作用。

【问题讨论】:

标签: docker docker-compose docker-swarm haproxy


【解决方案1】:

首先,关于 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 Compose:

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 的网络,因此您无需定义一个仅用于连接这两个服务的网络。

【讨论】:

  • 精彩的解释,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 2017-11-05
  • 1970-01-01
  • 2021-07-26
  • 2021-03-06
  • 2018-02-24
  • 2021-09-30
相关资源
最近更新 更多