解密K8S DNS:揭開內部服務查詢的生命循環

更新 發佈閱讀 18 分鐘

先前我們說明了在K8S內部基本網路溝通的基本原則,本篇我們再針對應用服務的查詢與發現,這個部分將會依賴K8S內部的DNS元件來實現。

raw-image

同時也將說明內部服務查詢的整個生命循環,我們可以透過了解DNS的工作原理,可以在應用服務的問題處理可以更有效率。

本篇將不會說明安裝的做法,只針對DNS服務查詢的流程進行討論。我們接著將說明以下內容:

  1. Pod在K8S內部的溝通
  2. Kubernetes DNS是什麼
  3. DNS record長什麼樣子
  4. 要如何利用DNS來找到服務
  5. 基本測試
  6. 結論

1. Pod在K8S內部的溝通

一般來說,K8S內部使用Pod IP進行溝通會有以下問題:

  1. 動態IP指派:Pod在建立、重啟、擴展都會被指派新的IP位址,以IP來追蹤的話會常常出現問題。
  2. 外部存取限制:Pod IP無法從外部存取,因為K8S是沒有路由能力的。所以外部要存取到Pod,需要透過Service type。

所謂的Service type就是透過建立一個持久性的名稱來讓後端的Pod群組可以被外界存取到,並且提供以下優點:

  • Stable Communication:當Pod要連線到其他的Pod時,直接參照Service name,並且service可以很有效的將流量路由到其他的Pod
  • Load Balancing : 透過負載平衡的特性,將流量分散到所有的Pod可以強化應用服務的效能
  • High Availability : Service設定可以確保流量的重導到特定的Pod,就算失敗也不會干擾應用服務的可用性。
  • DNS Resolution : Service可以向Kubernetes DNS進行註冊,讓Pod-to-Pod的溝通可以很容易建立,而且不需要知道個別的IP位址。

2. Kubernetes DNS是什麼

用一句話來說明:將服務發現的工作簡單化

當我們建立Service建立之後,K8S DNS就會自動產生一個對應的A record 將service dns name與IP位址配對。之後,Pod就可以透過DNS名稱來進行連線。而DNS負責動態更新所有的A record來反應Service IP的改變。

K8S核心元件預設將與內部的DNS進行溝通來確保每個Pod與Service建立、移動、移除時相關記錄的正確。

目前K8S預設的DNS已從kube-dns移動到CoreDNS。二者所實作的功能相同的部分如下:

  • kube-dns service將建立一個以上的pod
  • kube-dns service針對service與endpoint相關事件並且修改成合適的DNS記錄
  • kubelet會對kube-dns的service指派對應的cluster ip,並且在每個pod內部的/etc/resolv.conf加入nameserver的字串如下:
nameserver 10.10.23.1
search namespace.svc.cluster.local svc.cluster.local cluster.local
  • 應用程式可以將 test-service.namespace 等主機名稱解析為適當的叢集 IP 位址
raw-image

3. DNS record長什麼樣子

一個完整的k8s service的A record如下:

service.namespace.svc.cluster.local

對應於上述的記錄,對於實際上的real IP後呈現如下:

10-32-0-125.namespace.pod.cluster.local

同時,針對k8s service 特定port的SRV記錄將用以下格式建立:

_port-name._protocol.service.namespace.svc.cluster.local

最後,應用程式可透過簡單且一致的主機名稱來存取叢集上的其他服務或 Pod。

通常不會使用完整的hostname來取用其他的服務,因為會在resolv.conf會設定好domain suffixes,如果要與同一個namespace內的服務溝通的話,只要用以下方式即可:

other-service

如果要到其他的namespace的話,加上:

other-service.other-namespace

如果要直接對應到Pod的話,則是:

pod-ip.other-namespace.pod

一個標準的service的定義如下:

apiVersion: v1
kind: Service
metadata:
name: foo
namespace: bar
spec:
ports:
- port: 80
name: http

建立之後,A record, SRV record就會用以下方式產生:

foo.bar.svc.cluster.local                     30 A X.X.X.X
_http._tcp.nginx.default.svc.cluster.local 3600 SRV 0 100 80 X-X-X-X.foo.bar.svc.cluster.local.

※ Cluster domain: cluster.local

當記錄建立完成後,在cluster內就可以使用DNS name去解析Service IP。


4. 要如何利用DNS來找到服務

情況1:不同節點

raw-image

流程:

Step1. Pod發動一個DNS查詢,會先查自已內部的resolv.conf

Step2. 內部的resolv.conf會設定一個預設的dns,這個dns帶有快取的含義

Step3. 如果這個local dns沒有相關的記錄,就會透過resolv.conf的內容,指向CoreDNS

Step4. CoreDNS透過向Kubernetes API(service registry)進行查詢,這個registry就會包含service name與ip的對應

Step5. 當查詢到了之後就會將正確的值回傳給Pod

Step6. 如果在Service registry也沒有的記錄就會再往更上游的DNS進行查詢。

以下簡單說明:

※ Pod發起查詢

Pod發送一個API需求來查詢service時,先詢問自已/etc/resolv.conf的內容。這個檔案是由kubelet所自動為每個pod所產生的。預設內容如下:

# cat /etc/resolv.conf

search namespace.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.101.101.11
options ndots:5

※ ndots 選項決定何時直接進行絕對網域查詢,而不是先附加搜尋網域。

※ Local dns

DNS查詢在網路溝通的過程是很普遍發生的,因為頻率很高,所以必須要很快速地處理來避免造成效能問題並且不容易除錯。

如果在k8s cluster內要強化DNS查詢效率,可以在每個節點再加入一個nodelocaldns元件來做決DNS快取。

如果在快取層沒有找到記錄,就會將查詢向上到CoreDNS,這種方式可以大大減少不斷的往CoreDNS查詢的頻率。

※ K8S 記錄的TTL

預設CoreDNS的DNS記錄的TTL是30秒。並且可以在CoreDNS的設定檔內變更這個值。

TTL會決定在必須進行新查詢之前多久的回應將被視為有效。如果把這個TTL變的更短,反而有可能增加DNS server的負載。但是更長也可能導致DNS回應的過期或回應的值不正確的問題。

※ SRV

K8S也會使用SRV來解析服務Port號。這也允許客戶端可以透過查詢DNS來發現服務的Port號。例如:

apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: test
spec:
ports:
- port: 80
name: http

[note]
(1) nginx容器會以http的名稱,暴露80port給外界,而k8s將會自動產生一個SRV的記錄如下:
_http._tcp.nginx.tet.svc.cluster.local

(2)用指令直接查詢:
[root]# dig SRV _http._tcp.nginx.tet.svc.cluster.local +short
=> 會回傳對應的SRV記錄

5. 基本測試

#--------------------------------------------------
# S5-1. create dnsutils pod
#--------------------------------------------------
[root]# vim dnsutils.yaml
apiVersion: v1
kind: Pod
metadata:
name: dnsutils
namespace: default
spec:
containers:
- name: dnsutils
image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
command:
- sleep
- "infinity"
imagePullPolicy: IfNotPresent
restartPolicy: Always

[root]# kubectl apply -f dnsutils.yaml
[root]# kubectl get pod
#--------------------------------------------------
# S5-2. confirm pod dns
#--------------------------------------------------
[root]# kubectl exec -i -t dnsutils -- nslookup kubernetes.default
Server: 10.96.0.10
Address: 10.96.0.10#53

Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1
#--------------------------------------------------
# S5-3. confirm dns resolv.conf
#--------------------------------------------------
[root]# kubectl exec -ti dnsutils -- cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local test.example.poc
nameserver 10.96.0.10
options ndots:5
#--------------------------------------------------
# S5-4. confirm coredns running
#--------------------------------------------------
[root]# kubectl get pods --namespace=kube-system -l k8s-app=kube-dns
NAME READY STATUS RESTARTS AGE
coredns-5d78c9869d-n5jwk 1/1 Running 2 90d
coredns-5d78c9869d-s2kf8 1/1 Running 2 90d
#--------------------------------------------------
# S5-5. confirm pod's log
#--------------------------------------------------
[root]# kubectl logs --namespace=kube-system -l k8s-app=kube-dns
raw-image
#--------------------------------------------------
# S5-6. confirm dns service is running
# "kube-dns"名稱是coredns & kubedns都用同一個名字
#--------------------------------------------------
[root]# kubectl get svc --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 90d
metrics-server ClusterIP 10.103.38.187 <none> 443/TCP
#--------------------------------------------------
# S5-7. DNS endpoint是否有暴露出來
#--------------------------------------------------
[root]# kubectl get endpoints kube-dns --namespace=kube-system
NAME ENDPOINTS AGE
kube-dns 192.168.101.133:53,192.168.101.134:53,192.168.101.133:53 + 3 more..
#--------------------------------------------------
# S5-8. 確認DNS查詢是否有接收並處理
# 透過在coredns設定檔內加入log
#--------------------------------------------------
[root]# kubectl edit configmap coredns -n kube-system
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
log <<<
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}

[root]# kubectl logs -f coredns-5d78c9869d-n5jwk -n kube-system
raw-image

6.結論

所有Pod一建立起來就會被指派IP。Pod之間就可以使用這些IP相互溝通。

問題是如果Pod有任何重建或是刪除的異動的話,原本的IP也會被異動。如果要避免這種情況就必須要改用Service這種資源類型。

當建立service之後,apiserver就會儲存相關的資料到controller-manager並且會帶跟另外二個資源類型:EndpointsEndpointSlices

此時,CoreDNS就會利用這些資源去識別如何將service name轉換成service ip。同時,每個節點上的kube-proxy就會去更新節點內的iptables rules。這些規則就會讓需求可以正確定位到正確的Pod。

最後,當Pod產生查詢需求,就會執行一個DNS查詢給CoreDNS來取得service ip,取得service ip之後,就會套用節點上由kube-proxy所建立的規則來將流量導至實際的Pod IP。


本篇說明到這邊,感謝大家觀看,下期再見~~~


※ References:

留言
avatar-img
超健忘閒人的沙龍
15會員
40內容數
記錄IT社畜的自我學習筆記,如同專題名稱,主要是怕自已忘記自已做過什麼、學到什麼。索性就分享我自已在學習Kubernetes這條路上的各種測試、學習心得。
2024/05/08
本文將介紹如何在Gitlab上部署和註冊runner,以進行CI/CD測試。透過Docker-compose方式進行部署,同時注意安裝時的一些注意事項。建議學習者至少掌握一種以上的Pipeline工具,以滿足實務上的需求。
Thumbnail
2024/05/08
本文將介紹如何在Gitlab上部署和註冊runner,以進行CI/CD測試。透過Docker-compose方式進行部署,同時注意安裝時的一些注意事項。建議學習者至少掌握一種以上的Pipeline工具,以滿足實務上的需求。
Thumbnail
2024/04/19
上一篇說明了如何在Kubernetes上建立基本的MySQL standalone,並加入phpmyadmin(PMA)來進行圖形化的管理,本篇就再進階一步,實作MySQL replication架構(master-salve),並進行驗證是否成功。
Thumbnail
2024/04/19
上一篇說明了如何在Kubernetes上建立基本的MySQL standalone,並加入phpmyadmin(PMA)來進行圖形化的管理,本篇就再進階一步,實作MySQL replication架構(master-salve),並進行驗證是否成功。
Thumbnail
2024/04/09
本文記錄如何在Kubernetes環境下,部署Standalone架構的MySQL Database,並透過phpmyadmin進行管理。這篇文章將分成MySQL部署在K8S內的優勢、部署MySQL DB standalone、部署PhpMyAdmin (PMA)、結論四個部分進行說明與實作的流程。
Thumbnail
2024/04/09
本文記錄如何在Kubernetes環境下,部署Standalone架構的MySQL Database,並透過phpmyadmin進行管理。這篇文章將分成MySQL部署在K8S內的優勢、部署MySQL DB standalone、部署PhpMyAdmin (PMA)、結論四個部分進行說明與實作的流程。
Thumbnail
看更多
你可能也想看
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
安裝環境需求 64位元Linux,核心版本為3.1以上,且能滿足Ducker安裝環境。 機器之間要能夠互通。 外部存取權限。 硬體資源:兩核心CPU、8G記憶體、硬碟30GB以上。 安裝Kubeadm與Ducker Kubeadm是Kubernetes的一鍵部署工具。 增加Kube
Thumbnail
安裝環境需求 64位元Linux,核心版本為3.1以上,且能滿足Ducker安裝環境。 機器之間要能夠互通。 外部存取權限。 硬體資源:兩核心CPU、8G記憶體、硬碟30GB以上。 安裝Kubeadm與Ducker Kubeadm是Kubernetes的一鍵部署工具。 增加Kube
Thumbnail
在實際生產中,容器化技術開始走向「容器編排技術」,如:Kubernetes。因為Docker無法獨立支撐大規模容器化部署。 Kubernetes起源於Borg系統,所以在大規模的叢集管理,優於其他容器編排技術。它提供拉取映像檔、拉取執行容器、路由閘道、水平擴充、監控和備份等,除外還可以自動化處理容
Thumbnail
在實際生產中,容器化技術開始走向「容器編排技術」,如:Kubernetes。因為Docker無法獨立支撐大規模容器化部署。 Kubernetes起源於Borg系統,所以在大規模的叢集管理,優於其他容器編排技術。它提供拉取映像檔、拉取執行容器、路由閘道、水平擴充、監控和備份等,除外還可以自動化處理容
Thumbnail
本文介紹如何在GCP上使用Terraform建立CloudFlare DNS解析和模組化。通過閱讀本文,可以瞭解如何設置Terraform建立CloudFlare DNS解析以及取得GCS上的Terraform state file並透過Terraform建立CloudFlare DNS解析的步驟。
Thumbnail
本文介紹如何在GCP上使用Terraform建立CloudFlare DNS解析和模組化。通過閱讀本文,可以瞭解如何設置Terraform建立CloudFlare DNS解析以及取得GCS上的Terraform state file並透過Terraform建立CloudFlare DNS解析的步驟。
Thumbnail
本文將探討Kubernetes內部DNS解析的相關流程,並介紹如何利用DNS來找到服務。透過瞭解DNS的工作原理,可以讓應用服務的問題處理更有效率,並提供基本測試與結論。
Thumbnail
本文將探討Kubernetes內部DNS解析的相關流程,並介紹如何利用DNS來找到服務。透過瞭解DNS的工作原理,可以讓應用服務的問題處理更有效率,並提供基本測試與結論。
Thumbnail
本篇說明如何利用Kubernetes特色,將PostgreSQL DB以HA的架構來提供服務,並說明相關的實作流程與說明。
Thumbnail
本篇說明如何利用Kubernetes特色,將PostgreSQL DB以HA的架構來提供服務,並說明相關的實作流程與說明。
Thumbnail
引言 在當今的技術世界中,Kubernetes 已成為容器化應用的領導平台。作為一個高效的容器編排系統,它不僅管理著容器的部署和擴展,還提供了必要的自動化支持,以保證應用的高可用性和性能。在這個框架中,自動擴展功能起著至關重要的作用,特別是在面對不斷變化的負載和需求時。
Thumbnail
引言 在當今的技術世界中,Kubernetes 已成為容器化應用的領導平台。作為一個高效的容器編排系統,它不僅管理著容器的部署和擴展,還提供了必要的自動化支持,以保證應用的高可用性和性能。在這個框架中,自動擴展功能起著至關重要的作用,特別是在面對不斷變化的負載和需求時。
Thumbnail
本文將演示在安裝完 Kubernetes Cluster 後的基本元件安裝,包括 Calico/Calicoctl、Metric Server 和 Dashboard UI 的安裝方法以及相關問題與解決方式。
Thumbnail
本文將演示在安裝完 Kubernetes Cluster 後的基本元件安裝,包括 Calico/Calicoctl、Metric Server 和 Dashboard UI 的安裝方法以及相關問題與解決方式。
Thumbnail
這篇文章教你如何搭建Kubernetes Cluster,包括節點安裝前設定、軟體套件安裝、Control-Plane部署和加入運算節點等步驟。在建置之後,作者會分享一些基礎服務的安裝。希望這篇文章對你有所幫助。
Thumbnail
這篇文章教你如何搭建Kubernetes Cluster,包括節點安裝前設定、軟體套件安裝、Control-Plane部署和加入運算節點等步驟。在建置之後,作者會分享一些基礎服務的安裝。希望這篇文章對你有所幫助。
Thumbnail
本文章將說明如果您想要從頭建置一組具有Loadbalancer HA架構的Kubernetes Cluster時,你可能會需要做的事前準備工作。
Thumbnail
本文章將說明如果您想要從頭建置一組具有Loadbalancer HA架構的Kubernetes Cluster時,你可能會需要做的事前準備工作。
Thumbnail
最近在部署一些解決方案時,碰到了關於名稱解析上的一些問題,雖然有時候不難解決,但我發現如果清楚K8S有關於名稱解析的概念,會對除錯的時間與過程有很大的幫助。 透過本篇文章,除了幫自已留下問題查找的過程,同時也希望利用文章來整理自已對CoreDNS元件的一些觀念,同時也可以分享給大家參考。
Thumbnail
最近在部署一些解決方案時,碰到了關於名稱解析上的一些問題,雖然有時候不難解決,但我發現如果清楚K8S有關於名稱解析的概念,會對除錯的時間與過程有很大的幫助。 透過本篇文章,除了幫自已留下問題查找的過程,同時也希望利用文章來整理自已對CoreDNS元件的一些觀念,同時也可以分享給大家參考。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News