全部產品
Search
文件中心

Container Service for Kubernetes:DNS解析及緩衝策略說明

更新時間:Jul 09, 2024

本文介紹Kubernetes叢集中容器Pod在網域名稱解析過程中的解析策略和緩衝策略。

DNS解析鏈路全景

以下介紹三種應用部署形式下應用解析網域名稱的鏈路:

說明

關於圖中的timeout、attempts等術語的含義,請參考下文解析策略和緩衝策略。

  • 非容器化應用直接運行於ECS之上。

    樣本:App運行於ECS上。

    DNS解析鏈路1.png

  • 容器化應用運行於Kubernetes中,DNSPolicy注入ClusterFirst的Pod裡。

    樣本:App運行於Kubernetes容器Pod中。

    DNS解析鏈路2.png

  • 容器化應用運行於Kubernetes中,DNSPolicy注入了NodeLocal DNSCache的Pod裡。

    樣本:App運行於Kubernetes容器Pod中,同時部署了NodeLocal DNSCache。

    DNS解析鏈路3.png

解析策略

用戶端側

一般情況下,應用解析網域名稱是通過Glibc提供的介面完成的,下表參數為/etc/resolv.conf中暴露的網域名稱解析參數,即Glibc解析網域名稱時的可配置參數。

參數

說明

Glibc中預設值

ECS

DNSPolicy為ClusterFirst的Pod

DNSPolicy為Default的Pod

注入了NodeLocal DNSCache的Pod

DNSPolicy為Default且採用主機網路的Pod

nameserver

解析網域名稱時使用的DNS伺服器

VPC DNS伺服器

CoreDNS ClusterIP

VPC DNS伺服器

  • NodeLocal DNSCache IP

  • CoreDNS ClusterIP

VPC DNS伺服器

search

請求非完整網域名稱(非FQDN)時,網域名稱會被拼接上search組成FQDN再進行請求

<ns>.svc.cluster.cloal svc.cluster.local cluster.local

<ns>.svc.cluster.cloal svc.cluster.local cluster.local

ndots:n

訪問的網域名稱字串內的點字元數量超過ndots值,則認為是完整網域名稱(FQDN),並被直接解析;如果不足ndots值,則追加search段尾碼再進行查詢。

1

1

5

1

3

1

timeout:n

對於單個網域名稱解析請求的逾時時間,單位為秒

5

2

5

5

1

2

attempts:n

解析網域名稱失敗時重試的次數

2

3

2

2

2

3

rotate

以Round Robin的形式輪詢DNS伺服器

關閉

開啟

關閉

關閉

關閉

開啟

single-request-reopen

開啟該配置後,一旦需要處理同一Socket發送的兩次請求時,解析端會在發送第一次請求後關閉Socket,並在發送第二次請求前開啟新的socket。

關閉

開啟

關閉

關閉

關閉

開啟

attempts參數僅在部分情境下起到重試的效果,例如服務端返回SERVFAIL、NOTIMP、REFUSED時,或服務端返回NOERROR,但沒有解析結果時。更多資訊,請參見attempts參數解析請求說明

VPC DNS伺服器是指ECS上預設配置的DNS伺服器,IP為100.100.2.136和100.100.2.138,負責PrivateZone和權威網域名稱的解析。

CoreDNS ClusterIP是指Kubernetes叢集內預設部署的CoreDNS在kube-system命名空間下提供的kube-dns服務的IP地址,負責叢集內部服務網域名稱的解析,以及PrivateZone、權威網域名稱的解析轉寄。

NodeLocal DNSCache IP是指部署了NodeLocal DNSCache組件後,組件在每個節點上監聽的169.254.20.10的IP地址。

說明

關於resolv.conf配置的更多資訊,請參見resolv.conf

部分情況下,用戶端側的網域名稱解析策略可能與上述配置不同:

  • 當採用Alpine作為容器鏡像時,其內建了Musl庫代替Glibc實現,解析行為會有較大不同,例如:

    • Alpine不遵循/etc/resolv.conf裡面的single-request和single-request-reopen。

    • 3.3及更早版本Alpine不支援search參數,不支援搜尋域,無法完成服務發現。

    • 並發請求/etc/resolv.conf中配置的多個DNS伺服器,導致NodeLocal DNSCache最佳化失效。

    • 並發使用同一Socket請求A和AAAA記錄,在舊版本核心上觸發Conntrack源連接埠衝突導致丟包問題。

    說明

    關於解析行為的更多資訊,請參見musl libc

  • 當使用Golang、NodeJS等程式設計語言時,應用可能會採用語言內建的網域名稱解析器,其行為也存在較大區別。

叢集內DNS伺服器

CoreDNS的/etc/resolv.conf預設沿用ECS的配置,但在實際轉寄DNS請求時,會使用內建的Forward外掛程式完成。

NodeLocal DNSCache內建了CoreDNS實現DNS服務轉寄,與CoreDNS配置方式一致。

Forward外掛程式的解析策略控制的參數如下表所示。關於CoreDNS Forward外掛程式的更多配置,請參見Forward

參數

說明

CoreDNS預設值

NodeLocal DNSCache預設值

prefer_udp

優先使用UDP協議與上遊通訊

開啟

關閉

force_tcp

強制使用TCP協議與上遊通訊

關閉

開啟

max_fails

連續多少次健全狀態檢查失敗就認為upstream不健康

2

2

expire

與upstream的連結保持10秒

10s

10s

policy

選擇upstream的策略

random

random

health_check

健全狀態檢查時間間隔

0.5s

0.5s

max_concurrent

最大請求upstream的連結並發數

dial timeout

串連upstream的逾時

30s,根據實際耗時動態減小

30s,根據實際耗時動態減小

read timeout

從upstream等待資料的逾時

2s

2s

緩衝策略

用戶端側

用戶端側的緩衝策略是因容器和應用而異的,實際的緩衝策略取決於您的配置。

叢集內DNS伺服器

參數

說明

CoreDNS社區預設配置

NodeLocal DNSCache ACK預設配置

CoreDNS ACK預設配置

success Max TTL

成功的網域名稱解析結果緩衝最大TTL

3600s

30s

30s

success Min TTL

成功的網域名稱解析結果緩衝最小TTL

5s

5s

5s

success Capacity

成功的網域名稱解析結果緩衝數目

9984

9984

9984

denial Max TTL

失敗的網域名稱解析結果緩衝最大TTL

1800s

5s

30s

denial Min TTL

失敗的網域名稱解析結果緩衝最小TTL

5s

5s

5s

denial Capacity

失敗的網域名稱解析結果緩衝數目

9984

9984

9984

ServerError TTL

上遊DNS伺服器異常時解析結果TTL

5s

0s(NodeLocal DNSCache Helm Chart版本低於1.5.0時,預設為5s)

0s(CoreDNS低於1.8.4.2版本時預設為5s)

serve_stale

允許無法串連上遊DNS伺服器時使用已到期的本機快取

關閉

開啟(NodeLocal DNSCache Helm Chart版本低於1.5.0時,預設關閉)

關閉

說明

實際生效的緩衝時間TTL由網域名稱解析結果自身TTL、最大TTL、最小TTL共同決定,規則如下:

  • 解析結果TTL>Max TTL時,實際生效的TTL為Max TTL。

  • 解析結果TTL<Min TTL時,實際生效的TTL為Min TTL。

  • Min TTL<解析結果TTL<Max TTL時,實際生效的TTL為解析結果TTL。

最佳化建議

本文介紹了Kubernetes叢集的解析路徑及各環節參數配置,您可以通過修改Pod Yaml、CoreDNS ConfigMap、NodeLocal DNSCache ConfigMap等方式來修改參數,樣本如下。

當用戶端Pod配置dnsPolicy:Default時,ECS上VPC DNS伺服器會被拷貝至容器內/etc/resolv.conf設定檔中。

apiVersion: v1
kind: Pod
metadata:
  name: example
  namespace: default
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/example-ns/example:v1
    name: example
  #Pod YAML中dnsPolicy值為Default。
  dnsPolicy: Default

# 此時容器內/etc/resolv.conf。
# cat /etc/resolv.conf
nameserver 100.100.2.136
nameserver 100.100.2.138

容器內對比ECS上,缺少了rotate single-request-reopen timeout:2 attempts:3的options參數,可能會使一個偶發的網路鏈路抖動導致業務側網域名稱解析異常,需要補充這些參數以提升容錯能力。調整Pod YAML如下:

apiVersion: v1
kind: Pod
metadata:
  name: example
  namespace: default
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/example-ns/example:v1
    name: example
  # Pod YAML中dnsPolicy值為Default。
  dnsPolicy: Default
  # 增加以下容錯配置。
  dnsConfig:
    options:
    - name: timeout
      value: "2"
    - name: attempts
      value: "3"
    - name: rotate
    - name: single-request-reopen

# 修改後重新部署Pod,容器內/etc/resolv.conf新增了options參數。
# cat /etc/resolv.conf
nameserver 100.100.2.136
nameserver 100.100.2.138
options rotate single-request-reopen timeout:2 attempts:3