Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support configuring the order of the upstream dns service discovery resolve #7935

Merged
6 changes: 5 additions & 1 deletion apisix/discovery/dns/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ function _M.init_worker()
local local_conf = config_local.local_conf()
local servers = local_conf.discovery.dns.servers

local default_order = {"last", "SRV", "A", "AAAA", "CNAME"}
local order = core.table.try_read_attr(local_conf, "discovery", "dns", "order")
order = order or default_order

local opts = {
hosts = {},
resolvConf = {},
nameservers = servers,
order = {"last", "SRV", "A", "AAAA", "CNAME"},
order = order,
}

local client, err = core.dns_client.new(opts)
Expand Down
9 changes: 9 additions & 0 deletions apisix/discovery/dns/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ return {
type = "string",
},
},
order = {
type = "array",
minItems = 1,
maxItems = 5,
uniqueItems = true,
items = {
enum = {"last", "SRV", "A", "AAAA", "CNAME"}
},
},
},
required = {"servers"}
}
6 changes: 6 additions & 0 deletions conf/config-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ nginx_config: # config for render the template to generate n
# dns:
# servers:
# - "127.0.0.1:8600" # use the real address of your dns server
# order: # order in which to try different dns record types when resolving
# - last # "last" will try the last previously successful type for a hostname.
# - SRV
# - A
# - AAAA
# - CNAME
# eureka:
# host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster.
# - "http://127.0.0.1:8761"
Expand Down
17 changes: 16 additions & 1 deletion docs/en/latest/discovery/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,23 @@ and `test.consul.service` be resolved as `1.1.1.1` and `1.1.1.2`, this result wi
Note that all the IPs from `test.consul.service` share the same weight.

The resolved records will be cached according to their TTL.
For service whose record is not in the cache, we will query it in the order of `SRV -> A -> AAAA -> CNAME`.
For service whose record is not in the cache, we will query it in the order of `SRV -> A -> AAAA -> CNAME` by default.
When we refresh the cache record, we will try from the last previously successful type.
We can also customize the order by modifying the configuration file.

```yaml
# add this to config.yaml
discovery:
dns:
servers:
- "127.0.0.1:8600" # use the real address of your dns server
order: # order in which to try different dns record types when resolving
- last # "last" will try the last previously successful type for a hostname.
- SRV
- A
- AAAA
- CNAME
```

If you want to specify the port for the upstream server, you can add it to the `service_name`:

Expand Down
19 changes: 16 additions & 3 deletions docs/zh/latest/discovery/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,22 @@ discovery:

注意所有来自 `test.consul.service` 的 IP 都有相同的权重。

解析的记录将根据它们的 TTL 来进行缓存。
对于记录不在缓存中的服务,我们将按照 `SRV -> A -> AAAA -> CNAME` 的顺序进行查询。
刷新缓存记录时,我们将从上次成功的类型开始尝试。
解析的记录将根据它们的 TTL 来进行缓存。对于记录不在缓存中的服务,我们将默认按照 `SRV -> A -> AAAA -> CNAME` 的顺序进行查询,刷新缓存记录时,我们将从上次成功的类型开始尝试。也可以通过修改配置文件来自定义 DNS 的解析顺序。

```yaml
# 添加到 config.yaml
discovery:
dns:
servers:
- "127.0.0.1:8600" # 使用 DNS 服务器的真实地址
order: # DNS 解析的顺序
- last # "last" 表示从上次成功的类型开始
- SRV
- A
- AAAA
- CNAME

```

如果你想指定 upstream 服务器的端口,可以把以下内容添加到 `service_name`:

Expand Down
120 changes: 120 additions & 0 deletions t/discovery/dns/sanity.t
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ upstreams:
id: 1
--- response_body
hello world
--- grep_error_log eval
qr/proxy request to \S+/
--- grep_error_log_out
proxy request to [0:0:0:0:0:0:0:1]:1980



Expand All @@ -133,6 +137,10 @@ upstreams:
id: 1
--- response_body
hello world
--- grep_error_log eval
qr/proxy request to \S+/
--- grep_error_log_out
proxy request to 127.0.0.1:1980



Expand Down Expand Up @@ -318,3 +326,115 @@ qr/upstream nodes: \{[^}]+\}/
qr/upstream nodes: \{("127.0.0.1:1980":60,"127.0.0.2:1980":20|"127.0.0.2:1980":20,"127.0.0.1:1980":60)\}/
--- response_body
hello world



=== TEST 16: prefer A than SRV when A is ahead of SRV in config.yaml
--- yaml_config
apisix:
node_listen: 1984
enable_admin: false
deployment:
role: data_plane
role_data_plane:
config_provider: yaml
discovery:
dns:
servers:
- "127.0.0.1:1053"
order:
- A
- SRV
--- apisix_yaml
upstreams:
- service_name: "srv-a.test.local"
discovery_type: dns
type: roundrobin
id: 1
--- error_code: 502
--- error_log
proxy request to 127.0.0.1:80



=== TEST 17: Invalid order type in config.yaml
--- yaml_config
apisix:
node_listen: 1984
enable_admin: false
deployment:
role: data_plane
role_data_plane:
config_provider: yaml
discovery:
dns:
servers:
- "127.0.0.1:1053"
order:
- B
- SRV
--- apisix_yaml
upstreams:
- service_name: "srv-a.test.local"
discovery_type: dns
type: roundrobin
id: 1
--- must_die
--- error_log
matches none of the enum values



=== TEST 18: Multiple order type in config.yaml
--- yaml_config
apisix:
node_listen: 1984
enable_admin: false
deployment:
role: data_plane
role_data_plane:
config_provider: yaml
discovery:
dns:
servers:
- "127.0.0.1:1053"
order:
- SRV
- SRV
--- apisix_yaml
upstreams:
- service_name: "srv-a.test.local"
discovery_type: dns
type: roundrobin
id: 1
--- must_die
--- error_log
expected unique items but items 1 and 2 are equal



=== TEST 19: invalid order type in config.yaml
--- yaml_config
apisix:
node_listen: 1984
enable_admin: false
deployment:
role: data_plane
role_data_plane:
config_provider: yaml
discovery:
dns:
servers:
- "127.0.0.1:1053"
order:
- a
- SRV
--- apisix_yaml
upstreams:
- service_name: "srv-a.test.local"
discovery_type: dns
type: roundrobin
id: 1
--- must_die
--- error_log
matches none of the enum values
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a test case: DNS Server returns SRV records first for the same domain name, and the next query returns A records?