如何在进行DNS解析时使用服务端口

时间:2018-05-04 11:47:34

标签: docker dns registration consul

我正在运行consulregistrator。我可以在docker容器中启动服务:

docker run -d -P --name=redis redis

正如预期的那样,registrator能够在consul中注册服务:

http http://localhost:8500/v1/catalog/service/redis

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 308
Content-Type: application/json
Date: Fri, 04 May 2018 11:33:50 GMT
Vary: Accept-Encoding
X-Consul-Effective-Consistency: leader
X-Consul-Index: 34
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0

[
    {
        "Address": "127.0.0.1", 
        "CreateIndex": 34, 
        "Datacenter": "dc1", 
        "ID": "48b6c821-3b93-dbf4-394e-5024123ea7df", 
        "ModifyIndex": 34, 
        "Node": "863e97e527c3", 
        "NodeMeta": {
            "consul-network-segment": ""
        }, 
        "ServiceAddress": "", 
        "ServiceEnableTagOverride": false, 
        "ServiceID": "polyphemus.wavilon.net:redis:6379", 
        "ServiceMeta": {}, 
        "ServiceName": "redis", 
        "ServicePort": 32769, 
        "ServiceTags": [], 
        "TaggedAddresses": {
            "lan": "127.0.0.1", 
            "wan": "127.0.0.1"
        }
    }
]

然后我可以使用consul DNS服务:

» dig @127.0.0.1 -p 8600 redis.service.consul

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @127.0.0.1 -p 8600 redis.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62382
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;redis.service.consul.          IN      A

;; ANSWER SECTION:
redis.service.consul.   0       IN      A       127.0.0.1

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri May 04 13:31:21 CEST 2018
;; MSG SIZE  rcvd: 65

这一切都很好。这基本上意味着我可以开始使用consul来定位我的服务,所以这样的事情:

curl -X GET http://myservice.service.consul

可以在我的容器内工作。但是......这里缺少一件:registrator知道IP 运行服务的端口。我可以通过特殊的dns SRV请求来检查:

» dig @127.0.0.1 -p 8600 redis.service.consul SRV

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @127.0.0.1 -p 8600 redis.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52758
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;redis.service.consul.          IN      SRV

;; ANSWER SECTION:
redis.service.consul.   0       IN      SRV     1 1 32769 863e97e527c3.node.dc1.consul.

;; ADDITIONAL SECTION:
863e97e527c3.node.dc1.consul. 0 IN      A       127.0.0.1
863e97e527c3.node.dc1.consul. 0 IN      TXT     "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri May 04 13:36:02 CEST 2018
;; MSG SIZE  rcvd: 149

我的问题是:如何在我的应用程序中集成它?我们假设我正在使用python编写requests个应用程序。 DNS解析如何定位和使用服务公开的端口?

要明确:信息已在consul中正确注册,如何使用应用程序中的此信息?

我看到了不同的选择:

  • 实施&#34;领事DNS解析&#34;我的应用程序中的一个层(作为一个库),它使SRV DNS(或API)请求被查询以便定位IP和端口。
  • 强制容器始终公开端口80(我正在做http REST服务),因此DNS解析不需要关心端口。

第一个选项意味着应用程序的一些重构,我想避免。第二种选择意味着我需要摆弄所有服务配置。

有更好的选择吗?在进行名称解析时是否有透明的方法来集成SRV DNS请求,并自动使用端口而不是使用端口80(或443)?

我看不出这对python requestscurl或任何其他工具的可行性如何:我们总是需要在使用时手动指定端口那些图书馆/工具。

还有一个相关问题:何时/如何使用SRV DNS请求?似乎那些提供了我需要的信息,但正常的DNS解析并没有使用它:客户端总是假设服务运行的端口(80http,{{ 1}}用于443等等,而不是询问具有该信息的DNS服务器。

2 个答案:

答案 0 :(得分:0)

在DNS的限制范围内或直接使用Consul API,没有其他选择,正如您已经在上面提到过的那样;正如它所说here

  

...在这种模式下,应用程序和服务每次想要在数据中心找到其他服务时都直接与Consul交谈.... [缺点]需要在应用程序中直接使用HTTP API或制作DNS   查询并假设端口或进行两次DNS查询以查找   地址和端口

然而,相同的链接确实提供了一些替代方案,这些方案总是涉及中间人。在 Fabio 的情况下,使用有效的直接DNS,通过consul服务标签从应用程序到端口的关联,而不是从应用程序到[服务]端口的任何直接引用。

答案 1 :(得分:0)

我们处理此问题的几种方法:

  • 使用docker overlay网络进行容器到容器的通信。在这种情况下,您的端口可以是静态的(在容器级别),并且可以在建立连接时假定端口号
  • 使用“ consul-template”生成具有从consul读取的IP和端口信息的配置文件。此consul-template命令通常将作为您的docker入口点运行,并依次启动您的实际应用。每当领事发生变化时,领事模板将重新生成文件,并可将其配置为重新加载/重新启动您的应用

谢谢, 阿鲁尔