如何使用 traefik 路由到一个 docker 群服务暴露两个端口?
How to route with traefik to one docker swarm service exposing two ports?
RabbitMq 在端口 15672 提供管理 GUI,客户端在端口 5672 连接到消息代理
我的环境:
docker群服务器版本:19.03.5
图片:"traefik:v2.0.2"
图片:rabbitmq:management-高山
我可以在 https://mq.mydom.comexample 浏览 Rabbit MQ 管理页面
下面是我的 compose.yml for docker stack deploy
的一部分
mq:
deploy:
labels:
- "traefik.enable=true"
- "traefik.http.routers.mq-service.rule=Host(`mq.mydom.comexample`)"
- "traefik.http.services.mq-service.loadbalancer.server.port=15672"
- "traefik.http.routers.mq-service.entrypoints=websecure"
- "traefik.http.routers.mq-service.tls.certresolver=mytlschallenge"
现在我也想在同一服务中连接到 RabbitMq 消息代理
但我不明白 traefik 语法。尝试变体没有成功。
以下是其中一种变体,可能会显示我希望实现的目标:
mq:
deploy:
labels:
- "traefik.enable=true"
- "traefik.http.routers.mq-service.rule=Host(`mq.mydom.comexample`)"
- "traefik.http.services.mq-service.loadbalancer.server.port=15672"
- "traefik.http.routers.mq-service.entrypoints=websecure"
- "traefik.http.routers.mq-service.tls.certresolver=mytlschallenge"
# so far same as above
- "traefik.http.routers.mq-connect.rule=Host(`mq-connect.mydom.comexample`)"
- "traefik.http.services.mq-connect.loadbalancer.server.port=5672"
正在浏览 https://mq.mydom.comexample 或 https://mq-connect.mydom.comexample
两者都响应 404 页面未找到
远程登录 mq.mydom.comexample 443
telnet mq-connect.mydom.comexample 443
两者都连接:转义字符是'^]'。
如何告诉 traefik 路由我想要什么?
我对 Traefik V2 做了更多的研究。多个端点的解决方案是明确命名您的服务。
这是一个例子:
whoami:
image: "containous/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.docker`)"
- "traefik.http.routers.whoami.entrypoints=web"
- "traefik.http.routers.whoami.service=whoami"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
- "traefik.http.routers.altwhoami.rule=Host(`alt.docker`)"
- "traefik.http.routers.altwhoami.entrypoints=web"
- "traefik.http.routers.altwhoami.service=altwhoami"
- "traefik.http.services.altwhoami.loadbalancer.server.port=80"
因此,为了修复您的 traefik 实现,您需要添加 traefik.http.routers.whoami.service=service-name 标签。
希望对您有所帮助。
编辑:
为了通过 traefik 路由 AMQP,您需要一个 TCP 路由器。我为 rabbitmq 创建了一个小的工作示例:
version: "3.3"
services:
traefik:
image: "traefik"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.rabbitmq.address=:5672"
ports:
- "80:80"
- "8080:8080"
- "5672:5672"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
rabbitmq:
image: "rabbitmq:management-alpine"
labels:
- "traefik.enable=true"
- "traefik.http.routers.rabbitmq.rule=Host(`rabbitmq.docker`)"
- "traefik.http.routers.rabbitmq.entrypoints=web"
- "traefik.http.routers.rabbitmq.service=rabbitmq"
- "traefik.http.services.rabbitmq.loadbalancer.server.port=15672"
- "traefik.tcp.routers.ingress.rule=HostSNI(`*`)"
#- "traefik.tcp.routers.ingress.rule=HostSNI(`ingress.docker`)"
- "traefik.tcp.routers.ingress.entrypoints=rabbitmq"
#- "traefik.tcp.routers.ingress.tls=true"
#- "traefik.tcp.routers.ingress.tls.passthrough=true"
- "traefik.tcp.services.ingress.loadbalancer.server.port=5672"
这会将端口 5672 上的 TCP 流量通过 traefik 路由到您的容器(确保相应地调整您的 traefik 配置)。
您可能会注意到相当开放的 HostSNI(*)
规则。如果您想将此规则限制为单个 host/domain,则必须在 rabbitmq 中启用 TLS support 以便 traefik 正确过滤这些请求。
查看有关将 traefik 转换为支持 tls 的信息的注释行。您可以让 traefik 处理 TLS 或直接将其传递给 rabbitmq。
总而言之,这对我有用(非常感谢)。
version: "3.7"
traefik:
image: "traefik:v2.0.2"
command:
- "--api.insecure=true"
- "--providers.docker.swarmMode=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.rabbitmq.address=:5672"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
# testing: Letsencrypt would close us out for 24hrs if too many bad requests are made!
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.mytlschallenge.acme.email=postmaster@mydomain"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
- "--log=true"
- "--log.filepath=/var/log/traefik.log"
ports:
# https
- "443:443"
# traefik dash
- "8080:8080"
# rabbit mq message broker
- "5672:5672"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
mq:
hostname: xyz_mq
image: rabbitmq:3.8.2-alpine
environment:
- RABBITMQ_DEFAULT_VHOST=prod_vhost
- RABBITMQ_DEFAULT_USER=prod_user
- RABBITMQ_DEFAULT_PASS=abcdef123
deploy:
labels:
- "traefik.enable=true"
# web browser access to RabbitMq management GUI
- "traefik.http.routers.mq.rule=Host(`mq.mydomain`)"
- "traefik.http.services.mq.loadbalancer.server.port=15672"
- "traefik.http.routers.mq.entrypoints=websecure"
- "traefik.http.routers.mq.tls.certresolver=mytlschallenge"
- "traefik.http.routers.mq.service=mq"
# AMQPS - SSL terminated by traefik
- "traefik.tcp.routers.mq-connect.rule=HostSNI(`mq-connect.mydomain`)"
- "traefik.tcp.services.mq-connect.loadbalancer.server.port=5672"
- "traefik.tcp.routers.mq-connect.entrypoints=rabbitmq"
- "traefik.tcp.routers.mq-connect.tls.certresolver=mytlschallenge"
- "traefik.tcp.routers.mq-connect.service=mq-connect"
volumes:
- rabbitmq:/var/lib/rabbitmq
- ./rabbitmq_plugins:/etc/rabbitmq/enabled_plugins
stop_grace_period: 5m
volumes:
rabbitmq:
我在尝试让 RabbitMQ 落后于 Traefik 运行 时偶然发现了这个答案。在为在我的 EC2 实例上获得 运行 这些解决方案而奋斗了几天之后,我终于意识到这些示例(它们完美运行)与我在云上 运行 部署它们的方式之间的唯一区别是docker 资源限制(我总是将其应用于云服务)。
我不知道最小约束是什么(或者这些约束如何严重干扰 RabbitMQ),但我可以说这些资源限制会导致问题并会创建一个 semi-functional RMQ 实例(我经常可以连接到它,但无法成功地从中提取任务)。我认为这是因为我搞砸了一些 Traefik 路由,但这是此处提到的 docker 资源限制。希望这能让其他人头疼!
resources:
limits:
cpus: "0.25"
memory: 128M
从 Rabbit's Production Checklist 看来至少需要 256MB 的内存。将此限制提高到 256MB 并没有解决问题,但仔细阅读本文档可能会发现导致创建不稳定实例的资源限制。
从 Rabbit's Docker Hub Page 看来,由于 Rabbit 明确跟踪和管理内存使用情况,因此需要了解 cgroup-imposed 限制。有问题!您必须让 Rabbit 知道任何 docker 强加给内存的资源限制。
RabbitMq 在端口 15672 提供管理 GUI,客户端在端口 5672 连接到消息代理
我的环境:
docker群服务器版本:19.03.5
图片:"traefik:v2.0.2"
图片:rabbitmq:management-高山
我可以在 https://mq.mydom.comexample 浏览 Rabbit MQ 管理页面 下面是我的 compose.yml for docker stack deploy
的一部分 mq:
deploy:
labels:
- "traefik.enable=true"
- "traefik.http.routers.mq-service.rule=Host(`mq.mydom.comexample`)"
- "traefik.http.services.mq-service.loadbalancer.server.port=15672"
- "traefik.http.routers.mq-service.entrypoints=websecure"
- "traefik.http.routers.mq-service.tls.certresolver=mytlschallenge"
现在我也想在同一服务中连接到 RabbitMq 消息代理 但我不明白 traefik 语法。尝试变体没有成功。 以下是其中一种变体,可能会显示我希望实现的目标:
mq:
deploy:
labels:
- "traefik.enable=true"
- "traefik.http.routers.mq-service.rule=Host(`mq.mydom.comexample`)"
- "traefik.http.services.mq-service.loadbalancer.server.port=15672"
- "traefik.http.routers.mq-service.entrypoints=websecure"
- "traefik.http.routers.mq-service.tls.certresolver=mytlschallenge"
# so far same as above
- "traefik.http.routers.mq-connect.rule=Host(`mq-connect.mydom.comexample`)"
- "traefik.http.services.mq-connect.loadbalancer.server.port=5672"
正在浏览 https://mq.mydom.comexample 或 https://mq-connect.mydom.comexample 两者都响应 404 页面未找到
远程登录 mq.mydom.comexample 443
telnet mq-connect.mydom.comexample 443
两者都连接:转义字符是'^]'。
如何告诉 traefik 路由我想要什么?
我对 Traefik V2 做了更多的研究。多个端点的解决方案是明确命名您的服务。 这是一个例子:
whoami:
image: "containous/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.docker`)"
- "traefik.http.routers.whoami.entrypoints=web"
- "traefik.http.routers.whoami.service=whoami"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
- "traefik.http.routers.altwhoami.rule=Host(`alt.docker`)"
- "traefik.http.routers.altwhoami.entrypoints=web"
- "traefik.http.routers.altwhoami.service=altwhoami"
- "traefik.http.services.altwhoami.loadbalancer.server.port=80"
因此,为了修复您的 traefik 实现,您需要添加 traefik.http.routers.whoami.service=service-name 标签。
希望对您有所帮助。
编辑:
为了通过 traefik 路由 AMQP,您需要一个 TCP 路由器。我为 rabbitmq 创建了一个小的工作示例:
version: "3.3"
services:
traefik:
image: "traefik"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.rabbitmq.address=:5672"
ports:
- "80:80"
- "8080:8080"
- "5672:5672"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
rabbitmq:
image: "rabbitmq:management-alpine"
labels:
- "traefik.enable=true"
- "traefik.http.routers.rabbitmq.rule=Host(`rabbitmq.docker`)"
- "traefik.http.routers.rabbitmq.entrypoints=web"
- "traefik.http.routers.rabbitmq.service=rabbitmq"
- "traefik.http.services.rabbitmq.loadbalancer.server.port=15672"
- "traefik.tcp.routers.ingress.rule=HostSNI(`*`)"
#- "traefik.tcp.routers.ingress.rule=HostSNI(`ingress.docker`)"
- "traefik.tcp.routers.ingress.entrypoints=rabbitmq"
#- "traefik.tcp.routers.ingress.tls=true"
#- "traefik.tcp.routers.ingress.tls.passthrough=true"
- "traefik.tcp.services.ingress.loadbalancer.server.port=5672"
这会将端口 5672 上的 TCP 流量通过 traefik 路由到您的容器(确保相应地调整您的 traefik 配置)。
您可能会注意到相当开放的 HostSNI(*)
规则。如果您想将此规则限制为单个 host/domain,则必须在 rabbitmq 中启用 TLS support 以便 traefik 正确过滤这些请求。
查看有关将 traefik 转换为支持 tls 的信息的注释行。您可以让 traefik 处理 TLS 或直接将其传递给 rabbitmq。
总而言之,这对我有用(非常感谢)。
version: "3.7"
traefik:
image: "traefik:v2.0.2"
command:
- "--api.insecure=true"
- "--providers.docker.swarmMode=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.rabbitmq.address=:5672"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
# testing: Letsencrypt would close us out for 24hrs if too many bad requests are made!
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.mytlschallenge.acme.email=postmaster@mydomain"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
- "--log=true"
- "--log.filepath=/var/log/traefik.log"
ports:
# https
- "443:443"
# traefik dash
- "8080:8080"
# rabbit mq message broker
- "5672:5672"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
mq:
hostname: xyz_mq
image: rabbitmq:3.8.2-alpine
environment:
- RABBITMQ_DEFAULT_VHOST=prod_vhost
- RABBITMQ_DEFAULT_USER=prod_user
- RABBITMQ_DEFAULT_PASS=abcdef123
deploy:
labels:
- "traefik.enable=true"
# web browser access to RabbitMq management GUI
- "traefik.http.routers.mq.rule=Host(`mq.mydomain`)"
- "traefik.http.services.mq.loadbalancer.server.port=15672"
- "traefik.http.routers.mq.entrypoints=websecure"
- "traefik.http.routers.mq.tls.certresolver=mytlschallenge"
- "traefik.http.routers.mq.service=mq"
# AMQPS - SSL terminated by traefik
- "traefik.tcp.routers.mq-connect.rule=HostSNI(`mq-connect.mydomain`)"
- "traefik.tcp.services.mq-connect.loadbalancer.server.port=5672"
- "traefik.tcp.routers.mq-connect.entrypoints=rabbitmq"
- "traefik.tcp.routers.mq-connect.tls.certresolver=mytlschallenge"
- "traefik.tcp.routers.mq-connect.service=mq-connect"
volumes:
- rabbitmq:/var/lib/rabbitmq
- ./rabbitmq_plugins:/etc/rabbitmq/enabled_plugins
stop_grace_period: 5m
volumes:
rabbitmq:
我在尝试让 RabbitMQ 落后于 Traefik 运行 时偶然发现了这个答案。在为在我的 EC2 实例上获得 运行 这些解决方案而奋斗了几天之后,我终于意识到这些示例(它们完美运行)与我在云上 运行 部署它们的方式之间的唯一区别是docker 资源限制(我总是将其应用于云服务)。
我不知道最小约束是什么(或者这些约束如何严重干扰 RabbitMQ),但我可以说这些资源限制会导致问题并会创建一个 semi-functional RMQ 实例(我经常可以连接到它,但无法成功地从中提取任务)。我认为这是因为我搞砸了一些 Traefik 路由,但这是此处提到的 docker 资源限制。希望这能让其他人头疼!
resources:
limits:
cpus: "0.25"
memory: 128M
从 Rabbit's Production Checklist 看来至少需要 256MB 的内存。将此限制提高到 256MB 并没有解决问题,但仔细阅读本文档可能会发现导致创建不稳定实例的资源限制。
从 Rabbit's Docker Hub Page 看来,由于 Rabbit 明确跟踪和管理内存使用情况,因此需要了解 cgroup-imposed 限制。有问题!您必须让 Rabbit 知道任何 docker 强加给内存的资源限制。