我正在尝试使用 consul DNS 来实现服务发现。我已经设置了一个带有 consul 集群的 docker swarm,该集群充当 swarm 所需的键/值对后端,并充当其他容器的服务发现后端。
我首先从安装了 docker 引擎的 3 个裸服务器开始。我使用 ansible 配置集群。
到目前为止设置该集群的过程如下:
- 安装docker时,
--cluster-store=consul://127.0.0.1:8500
在docker daemon opts中设置 - 在“主”集群节点上,以“-bootstrap-expect 3”模式启动 consul 服务器容器
- 在“辅助”集群节点上,以“-join”模式启动 consul 服务器容器
- 在每个集群节点上启动一个 swarm master 和 swarm agent 容器,指向同一主机上的本地 consul 服务器
当启动 consul 服务器时,我将所有 consul 端口映射到主机,如下所示:
version: '2'
services:
consul:
image: progrium/consul
hostname: "{{ ansible_hostname }}"
ports:
# Explanation of ports needed: http://stackoverflow.com/a/30692226/1514089
- "8300:8300" # This is used by servers to handle incoming requests from other agents
- "8301:8301/tcp" # This is used to handle gossip in the LAN. Required by all agents
- "8301:8301/udp" # This is used to handle gossip in the LAN. Required by all agents
- "8302:8302/tcp" # This is used by servers to gossip over the WAN to other servers
- "8302:8302/udp" # This is used by servers to gossip over the WAN to other servers
- "8400:8400" # This is used by all agents to handle RPC from the CLI
- "8500:8500" # This is used by clients to talk to the HTTP API
- "8600:8600" # Used to resolve DNS queries
restart: always
command: "{{ consul_command }}"
这让我得到了一个可以工作的docker swarm。我可以登录任何一个集群节点并使用docker compose来启动一个应用程序,swarm会透明地在服务器之间平衡。
但是现在,我想开始使用 consuls DNS 功能来解析群集中每个容器内部的服务,我希望能够执行以下操作:
$ docker run -it ubuntu dig consul.service.consul
我尝试了一些方法,但都没有成功,我怀疑这与 docker 网络有关。让我解释一下...
当我启动 consul 服务器时,它们会连接到自己的 docker-compose 网络,因为我使用 docker-compose 启动它们。但是由于 swarm 尚未运行,显然尚未设置多主机覆盖网络。因此,每个 consul 容器最终都会位于自己的主机专用桥接网络上。我只创建我的 docker 网络后集群已启动。集群启动后,我无法将 consul 容器添加到覆盖网络,我得到
Error response from daemon: No such container: swarm-node-1/swarmconsul_consul_1
如何使基于 DNS 的服务发现在我的容器内发挥作用?
答案1
最后我终于让它工作了。我做错了几件事。
最大的错误是我没有将主机上的端口 53 映射到 consul 容器内的端口 53/udp。完整的端口映射现在如下所示:
services:
consul:
image: progrium/consul
hostname: "{{ ansible_hostname }}"
ports:
# Explanation of ports needed: http://stackoverflow.com/a/30692226/1514089
- "8300:8300" # This is used by servers to handle incoming requests from other agents
- "8301:8301/tcp" # This is used to handle gossip in the LAN. Required by all agents
- "8301:8301/udp" # This is used to handle gossip in the LAN. Required by all agents
- "8302:8302/tcp" # This is used by servers to gossip over the WAN to other servers
- "8302:8302/udp" # This is used by servers to gossip over the WAN to other servers
- "8400:8400" # This is used by all agents to handle RPC from the CLI
- "8500:8500" # This is used by clients to talk to the HTTP API
- "8600:8600" # Used to resolve DNS queries
- "172.17.0.1:53:53/udp"
restart: always
command: "{{ consul_command }}"
这里我们绑定到 docker0 接口上的端口 53。但是,我了解到 docker0 网桥的 IP 可以更改,因此我对其进行了一些硬编码,并通过在--bip=172.17.0.1
docker 守护进程选项中指定来告诉 docker 始终将此 IP 用于 docker0 网桥。下一步是将 docker 守护进程的默认 dns 设置为相同的 IP。我的完整 docker 守护进程选项如下所示:
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon \
-H tcp://0.0.0.0:2375 \
-H unix:///var/run/docker.sock \
--bip=172.17.0.1/16 \
--dns=172.17.0.1 \
--dns-search=service.consul \
--storage-driver=overlay \
--cluster-store=consul://127.0.0.1:8500
现在我可以这样做:
$ sudo docker -H :4000 run -it joffotron/docker-net-tools
/ # dig +short consul.service.consul
10.0.0.93
10.0.0.95
10.0.0.94
伟大的!