了解 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
)。對於類型為resolution: NONE
(預設值)的ServiceEntry
和無頭Services
,情況就是如此。 - 在一組靜態 IP 位址上進行負載平衡。對於類型為
resolution: STATIC
的ServiceEntry
,將使用所有spec.endpoints
,或者對於標準Services
,將使用所有Endpoints
,情況就是如此。 - 定期使用 DNS 解析位址,並在所有結果之間進行負載平衡。對於類型為
resolution: DNS
的ServiceEntry
,情況就是如此。
請注意,在所有情況下,Istio 代理中的 DNS 解析與使用者應用程式中的 DNS 解析是正交的。即使用戶端進行 DNS 解析,代理也可能會忽略解析的 IP 位址,並使用自己的位址,這可能是來自靜態 IP 清單或通過執行自己的 DNS 解析(可能是相同的 hostname 或不同的 hostname)獲得的。
Proxy 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
不會知道這些 ServiceEntries
。
請注意,此代理僅適用於用戶端應用程式傳送的 DNS 請求;當使用 resolution: DNS
類型的 ServiceEntries
時,代理對 Istio 代理的 DNS 解析沒有任何影響。