了解 DNS
Istio 以不同的方式与 DNS 交互,这可能会让人难以理解。本文深入探讨了 Istio 和 DNS 如何协同工作。
请求的生命周期
在这些示例中,我们将逐步介绍应用程序运行 curl example.com
时会发生的情况。虽然这里使用了 curl
,但几乎所有客户端都适用相同的原理。
当您向某个域名发送请求时,客户端会进行 DNS 解析以将其解析为 IP 地址。无论 Istio 设置如何,这都会发生,因为 Istio 仅拦截网络流量;它无法更改应用程序的行为或发送 DNS 请求的决定。在下面的示例中,example.com
解析为 192.0.2.0
。
$ curl example.com -v
* Trying 192.0.2.0:80...
接下来,请求将被 Istio 拦截。此时,Istio 将同时看到主机名(来自 Host: example.com
标头)和目标地址(192.0.2.0:80
)。Istio 使用这些信息来确定目标地址。 了解流量路由 深入探讨了此行为的工作原理。
如果客户端无法解析 DNS 请求,则请求将在 Istio 接收它之前终止。这意味着,如果向 Istio 已知的主机名(例如,通过 ServiceEntry
)但 DNS 服务器不知道的主机名发送请求,则请求将失败。Istio DNS 代理 可以更改此行为。
一旦 Istio 确定了目标地址,它就必须选择要发送到的地址。由于 Istio 的高级 负载均衡功能,这通常不是客户端发送的原始 IP 地址。根据服务配置,Istio 可以通过以下几种不同的方式来实现这一点。
- 使用客户端的原始 IP 地址(如上例中的
192.0.2.0
)。这是ServiceEntry
类型为resolution: NONE
(默认值)和 无头Services
的情况。 - 在静态 IP 地址集中进行负载均衡。这是
ServiceEntry
类型为resolution: STATIC
的情况,其中所有spec.endpoints
都将使用,或者对于标准Services
,其中所有Endpoints
都将使用。 - 定期使用 DNS 解析地址,并在所有结果中进行负载均衡。这是
ServiceEntry
类型为resolution: DNS
的情况。
请注意,在所有情况下,Istio 代理中的 DNS 解析与用户应用程序中的 DNS 解析是正交的。即使客户端进行 DNS 解析,代理也可能忽略已解析的 IP 地址并使用自己的 IP 地址,这可能是来自静态 IP 地址列表或通过执行自己的 DNS 解析(可能是相同的主机名或不同的主机名)。
代理 DNS 解析
与大多数在请求时按需进行 DNS 请求(然后通常缓存结果)的客户端不同,Istio 代理从不执行同步 DNS 请求。当配置了 resolution: DNS
类型的 ServiceEntry
时,代理将定期解析配置的主机名,并将它们用于所有请求。此间隔由 DNS 响应的 TTL 决定。即使代理从未向这些应用程序发送任何请求,也会发生这种情况。
对于具有许多代理或许多 resolution: DNS
类型的 ServiceEntries
的网格,特别是当使用低 TTL
时,这可能会导致 DNS 服务器负载过高。在这些情况下,以下方法可以帮助减少负载
- 切换到
resolution: NONE
以完全避免代理 DNS 查询。这适用于许多用例。 - 如果您控制要解析的域名,请增加其 TTL。
- 如果您的
ServiceEntry
仅被少数工作负载需要,请使用exportTo
或Sidecar
限制其范围。
DNS 代理
Istio 提供了一个功能来 代理 DNS 请求。这使 Istio 可以捕获客户端发送的 DNS 请求,并直接返回响应。这可以提高 DNS 延迟、减少负载,并允许 ServiceEntries
(否则 kube-dns
无法识别)得以解析。
请注意,此代理仅适用于用户应用程序发送的 DNS 请求;当使用 resolution: DNS
类型的 ServiceEntries
时,代理不会影响 Istio 代理的 DNS 解析。