當前位置:
首頁 > 知識 > Linux DNS 查詢剖析(第四部分)

Linux DNS 查詢剖析(第四部分)

Linux DNS 查詢剖析(第四部分)


編譯自: https://zwischenzugs.com/2018/08/06/anatomy-of-a-linux-dns-lookup-part-iv/

作者: Zwischenzugs

譯者: Andy Song

在 Linux DNS 查詢剖析(第一部分) , Linux DNS 查詢剖析(第二部分) 和 Linux DNS 查詢剖析(第三部分) 中,我們已經介紹了以下內容:

  • nsswitch
  • /etc/hosts
  • /etc/resolv.conf
  • ping 與 host 查詢方式的對比
  • systemd 和對應的 networking 服務
  • ifup 和 ifdown
  • dhclient
  • resolvconf
  • NetworkManager
  • dnsmasq

在第四部分中,我將介紹容器如何完成 DNS 查詢。你想的沒錯,也不是那麼簡單。


1) Docker 和 DNS

在 Linux DNS 查詢剖析(第三部分) 中,我們介紹了 dnsmasq,其工作方式如下:將 DNS 查詢指向到 localhost 地址 127.0.0.1,同時啟動一個進程監聽 53 埠並處理查詢請求。

在按上述方式配置 DNS 的主機上,如果運行了一個 Docker 容器,容器內的 /etc/resolv.conf 文件會是怎樣的呢?

我們來動手試驗一下吧。

按照默認 Docker 創建流程,可以看到如下的默認輸出:


$ docker run ubuntu cat /etc/resolv.conf

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)

# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN

# 127.0.0.53 is the systemd-resolved stub resolver.

# run "systemd-resolve --status" to see details about the actual nameservers.

search home

nameserver 8.8.8.8

nameserver 8.8.4.4

奇怪!


地址 8.8.8.8 和 8.8.4.4 從何而來呢?

當我思考容器內的 /etc/resolv.conf 配置時,我的第一反應是繼承主機的 /etc/resolv.conf。但只要稍微進一步分析,就會發現這樣並不總是有效的。

如果在主機上配置了 dnsmasq,那麼 /etc/resolv.conf 文件總會指向 127.0.0.1 這個 迴環地址(loopback address)。如果這個地址被容器繼承,容器會在其本身的 網路上下文(networking context)中使用;由於容器內並沒有運行(在 127.0.0.1 地址的)DNS 伺服器,因此 DNS 查詢都會失敗。

「有了!」你可能有了新主意:將 主機的 的 IP 地址用作 DNS 伺服器地址,其中這個 IP 地址可以從容器的 默認路由(default route)中獲取:


root@79a95170e679:/# ip route

default via 172.17.0.1 dev eth0

172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2

使用主機 IP 地址真的可行嗎?

從默認路由中,我們可以找到主機的 IP 地址 172.17.0.1,進而可以通過手動指定 DNS 伺服器的方式進行測試(你也可以更新 /etc/resolv.conf 文件並使用 ping 進行測試;但我覺得這裡很適合介紹新的 dig 工具及其 @ 參數,後者用於指定需要查詢的 DNS 伺服器地址):


root@79a95170e679:/# dig @172.17.0.1 google.com | grep -A1 ANSWER.SECTION

;; ANSWER SECTION:

google.com. 112 IN A 172.217.23.14

但是還有一個問題,這種方式僅適用於主機配置了 dnsmasq 的情況;如果主機沒有配置 dnsmasq,主機上並不存在用於查詢的 DNS 伺服器。

在這個問題上,Docker 的解決方案是忽略所有可能的複雜情況,即無論主機中使用什麼 DNS 伺服器,容器內都使用 Google 的 DNS 伺服器 8.8.8.8 和 8.8.4.4 完成 DNS 查詢。

我的經歷:在 2013 年,我遇到了使用 Docker 以來的第一個問題,與 Docker 的這種 DNS 解決方案密切相關。我們公司的網路屏蔽了 8.8.8.8 和 8.8.4.4,導致容器無法解析域名。

這就是 Docker 容器的情況,但對於包括 Kubernetes 在內的容器 編排引擎(orchestrators),情況又有些不同。


2) Kubernetes 和 DNS

在 Kubernetes 中,最小部署單元是 pod;它是一組相互協作的容器,共享 IP 地址(和其它資源)。

Kubernetes 面臨的一個額外的挑戰是,將 Kubernetes 服務請求(例如,myservice.kubernetes.io)通過對應的 解析器(resolver),轉發到具體服務地址對應的 內網地址(private network)。這裡提到的服務地址被稱為歸屬於「 集群域(cluster domain)」。集群域可由管理員配置,根據配置可以是 cluster.local 或 myorg.badger 等。

在 Kubernetes 中,你可以為 pod 指定如下四種 pod 內 DNS 查詢的方式。

Default

在這種(名稱容易讓人誤解)的方式中,pod 與其所在的主機採用相同的 DNS 查詢路徑,與前面介紹的主機 DNS 查詢一致。我們說這種方式的名稱容易讓人誤解,因為該方式並不是默認選項!ClusterFirst 才是默認選項。

如果你希望覆蓋 /etc/resolv.conf 中的條目,你可以添加到 kubelet 的配置中。

ClusterFirst

在 ClusterFirst 方式中,遇到 DNS 查詢請求會做有選擇的轉發。根據配置的不同,有以下兩種方式:

第一種方式配置相對古老但更簡明,即採用一個規則:如果請求的域名不是集群域的子域,那麼將其轉發到 pod 所在的主機。

第二種方式相對新一些,你可以在內部 DNS 中配置選擇性轉發。

下面給出示例配置並從 Kubernetes 文檔 中選取一張圖說明流程:


apiVersion: v1

kind: ConfigMap

metadata:

name: kube-dns

namespace: kube-system

data:

stubDomains: |

{"acme.local": ["1.2.3.4"]}

upstreamNameservers: |

["8.8.8.8", "8.8.4.4"]

在 stubDomains 條目中,可以為特定域名指定特定的 DNS 伺服器;而 upstreamNameservers 條目則給出,待查詢域名不是集群域子域情況下用到的 DNS 伺服器。

這是通過在一個 pod 中運行我們熟知的 dnsmasq 實現的。


Linux DNS 查詢剖析(第四部分)


kubedns

剩下兩種選項都比較小眾:

ClusterFirstWithHostNet

適用於 pod 使用主機網路的情況,例如繞開 Docker 網路配置,直接使用與 pod 對應主機相同的網路。

None

None 意味著不改變 DNS,但強制要求你在 pod 規範文件(specification)的 dnsConfig 條目中指定 DNS 配置。

CoreDNS 即將到來

除了上面提到的那些,一旦 CoreDNS 取代 Kubernetes 中的 kube-dns,情況還會發生變化。CoreDNS 相比 kube-dns 具有可配置性更高、效率更高等優勢。

如果想了解更多,參考 這裡 。

如果你對 OpenShift 的網路感興趣,我曾寫過一篇 文章 可供你參考。但文章中 OpenShift 的版本是 3.6,可能有些過時。


第四部分總結

第四部分到此結束,其中我們介紹了:

  • Docker DNS 查詢
  • Kubernetes DNS 查詢
  • 選擇性轉發(子域不轉發)
  • kube-dns

via: https://zwischenzugs.com/2018/08/06/anatomy-of-a-linux-dns-lookup-part-iv/

作者: zwischenzugs 譯者: pinewall 校對: wxy

本文由 LCTT 原創編譯, Linux中國 榮譽推出

點擊「了解更多」可訪問文內鏈接

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Linux技術 的精彩文章:

日常 Python 編程優雅之道

TAG:Linux技術 |