Docker Swarm中的RabbitMQ:按主机名发现任务示例

tzcvj98z  于 2023-03-30  发布在  RabbitMQ
关注(0)|答案(1)|浏览(169)

我在Swarm中运行了一个RabbitMQ集群,配置为全局服务,其主机名设置为主机名:

services:
  rabbitmq:
    image: "rabbitmq:3-management"
    hostname: "rabbitmq-{{.Node.Hostname}}"
    networks:
      - rabbitmq
    configs:
      - source: rabbitmq_config
        target: /etc/rabbitmq/rabbitmq.conf
    secrets:
      - source: rabbitmq_erlang_cookie
        target: /var/lib/rabbitmq/.erlang.cookie
    environment:
      RABBITMQ_NODENAME: "rabbit@rabbitmq-{{.Node.Hostname}}"
    deploy:
      mode: global

所有节点都会收到一个动态生成的配置文件,其中包含所有节点,因此它们可以形成集群:

docker_hosts=$(docker node ls --format '{{.Hostname}}')
count=0
for host in ${docker_hosts}; do
  count=$((count+1))
  echo "cluster_formation.classic_config.nodes.${count} = rabbit@rabbitmq-${host}" >> rabbitmq.conf
done

我想用DNS对等发现后端替换这个经典的发现配置,以自动发现其他任务,但遇到了一些障碍。
内置的Docker DNS守护进程允许通过查询tasks.<service name>来发现任务。对于RabbitMQ,这会产生如下输出:

root@rabbitmq-foo-1:/# nslookup tasks.rabbitmq
Server:     127.0.0.11
Address:    127.0.0.11#53

Non-authoritative answer:
Name:   tasks.rabbitmq
Address: 10.100.8.158
Name:   tasks.rabbitmq
Address: 10.100.8.162
Name:   tasks.rabbitmq
Address: 10.100.8.163

这意味着我们可以将种子主机名tasks.rabbitmq传递给RabbitMQ,它将在启动期间执行A查找。根据文档,此查询的结果将 “将当前节点的前缀(例如rabbit在rabbit@hostname1.example.local中)附加到每个主机名并返回结果。"
执行手动反向查找,我们得到如下结果:

root@rabbitmq-foo-1:/# nslookup 10.100.8.158
158.8.100.10.in-addr.arpa   name = foo_rabbitmq.tjqxe6kpe5g4mnmgwoiuink16.xhosndlwm3eaoldu36udvjfi9.rabbitmq-net.

这意味着Docker DNS服务将反向记录构建为:

<Project Name>_<Task Name>.<Task ID>.< Container ID>.<Network Name>.

不幸的是,RabbitMQ不能很好地使用这个名称:即使配置为使用节点的FQDN,RabbitMQ也会根据节点的主机名检查解析的RR记录,并且只有在它们匹配时才加入集群。
因此,它需要rabbitmq-foo-1.whatever.而不是foo_rabbitmq.tjqxe6kpe5g4mnmgwoiuink16.xhosndlwm3eaoldu36udvjfi9.rabbitmq-net.(其中主机名为foo-1)。
有没有办法解析任务示例的给定主机名?或者一个DNS端点来获取所有Swarm节点?

biswetbf

biswetbf1#

上周我将RabbitMQ迁移到Docker Swarm集群,遇到了完全相同的问题。
以下是关键属性:

  • 创建具有自定义名称的自定义内部网络以获得确定性网络名称
  • 将容器主机名设置为“{{.Task.Name}}.$NETWORK_NAME”(请参阅docker-composite.yml)-这将修复反向DNS名称匹配问题
  • 设置env var RABBITMQ_USE_LONGNAME=true
  • 将deploy-〉endpoint_mode设置为“dnsrr”,以允许通过服务名称对所有副本进行DNS发现
  • 在RabbitMQ配置文件中配置DNS集群形成

以下是我在Docker Swarm中对RabbitMQ的DNS发现的完整解决方案:

docker-compose.yml

version: '3.7'

services:
    # utilize HAProxy as proxy server in front of all rabbits
    rabbit-haproxy:
        image: haproxy
        ports:
            - 5672:5672
            - 7000:7000
            - 8071:8071
        networks:
            - external-rabbit
            - rabbit-internal
        configs:
            - source: haproxy-config
              target: /usr/local/etc/haproxy/haproxy.cfg

    rabbit:
        image: rabbitmq:3.11-management-alpine
        # set hostname to the final combination of reverse DNS name
        hostname: '{{.Task.Name}}.rabbits'
        environment:
            - RABBITMQ_USE_LONGNAME=true
            - RABBITMQ_CONFIG_FILE=/config/rabbitmq
        configs:
            - source: rabbit-config
              target: /config/rabbitmq
        secrets:
            - source: rabbit-erlang-cookie
              target: /var/lib/rabbitmq/.erlang.cookie
              mode: 0600
              gid: "101"
              uid: "100"
        networks:
            - rabbit-internal
        deploy:
            endpoint_mode: dnsrr

configs:
    haproxy-config:
        file: config/haproxy.cfg
    rabbit-config:
        file: config/rabbit

secrets:
    rabbit-erlang-cookie:
        file: config/rabbit-erlang-cookie

networks:
    rabbit-internal:
        name: rabbits
        driver: overlay
    external-rabbit:
    external: true

RabbitMQ配置文件(“config/rabbit”)

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_dns
cluster_formation.dns.hostname = rabbit
cluster_formation.discovery_retry_limit = 10
cluster_formation.discovery_retry_interval = 1000

HAProxy摘录(“配置/haproxy. cfg”)

listen rabbitmq
bind 0.0.0.0:5672
mode tcp
option tcpka
balance roundrobin
server-template rabbit- 1-9 rabbit:5672 check resolvers docker init-addr libc,none

RabbitMQ Erlang Cookie文件(“config/rabbit-erlang-cookie”)

mysupersecreterlangcookie---changeme

注意事项:

当RabbitMQ处于自动发现模式时,它会尝试发现一个 * 已经在运行 * 的RabbitMQ集群。当一只兔子认为他是孤独的,需要启动一个独立的集群时,集群就会形成。
因此,当第一次初始化时,将没有集群存在。启动2个或更多的兔子副本将导致它们试图找到彼此,最终由于并行性而失败,从而创建它们单独的集群。
从一个副本开始,然后根据需要扩展集群。这样可以确保存在可以被新对等节点发现的集群。

相关问题