K8s CoreDNS落地實踐

DNS 服務是 Kubernetes 內置的服務發現組件,它方便容器服務可以通過發佈的唯一 App 名字找到對方的端口服務,再也不需要維護服務對應的 IP 關係。這個對傳統企業內部的運維習慣也是有一些變革的。一般傳統企業內部都會維護一套 CMDB 系統,專門來維護服務器和 IP 地址的對應關係,方便規劃管理好應用服務集羣。當落地 K8s 集羣之後,因爲應用容器的 IP 生命週期短暫,通過 App 名字來識別服務其實對運維和開發都會更方便。所以本篇就是結合實際的需求場景給大家詳細介紹 DNS 的使用實踐。

CoreDNS 介紹

Kubernetes 早期的 DNS 組件叫 KubeDNS。CNCF 社區後來引入了更加成熟的開源項目 CoreDNS 替換了 KubeDNS。所以我們現在提到 KubeDNS,其實默認指代的是 CoreDNS 項目。在 Kubernetes 中部署 CoreDNS 作爲集羣內的 DNS 服務有很多種方式,例如可以使用官方 Helm Chart 庫中的 Helm Chart 部署,具體可查看 CoreDNS Helm Chart。

$ helm install --name coredns --namespace=kube-system stable/coredns

查看 coredns 的 Pod,確認所有 Pod 都處於 Running 狀態:

kubectl get pods -n kube-system -l k8s-app=kube-dns
NAME                       READY     STATUS    RESTARTS   AGE
coredns-699477c54d-9fsl2   1/1       Running   0          5m
coredns-699477c54d-d6tb2   1/1       Running   0          5m
coredns-699477c54d-qh54v   1/1       Running   0          5m
coredns-699477c54d-vvqj9   1/1       Running   0          5m
coredns-699477c54d-xcv8h   1/1       Running   0          6m

測試一下 DNS 功能是否好用:

kubectl run curl --image=radial/busyboxplus:curl -i --tty

nslookup kubernetes.default
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local

服務發現規則

DNS 支持的服務發現是支持 Service 和 Pod 的。它的規則如下。

Services

A 記錄:

  • Service(headless Service 除外)將被分配一個 DNS A 記錄,格式爲 my-svc.my-namespace.svc.cluster.local。該 DNS 記錄解析到 Service 的 ClusterIP。

  • Headless Service(沒有 ClusterIP)也將被分配一個 DNS A 記錄,格式爲 my-svc.my-namespace.svc.cluster.local。該 DNS 記錄解析到 Service 所選中的一組 Pod 的 IP 地址的集合。調用者應該使用該 IP 地址集合,或者按照輪詢(round-robin)的方式從集合中選擇一個 IP 地址使用。SRV 記錄:Service(含 headless Service)的命名端口(有 name 的端口)將被分配一個 SRV 記錄,其格式爲 _my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local。

  • 對於一個普通 Service(非 headless Service),該 SRV 記錄解析到其端口號和域名 my-svc.my-namespace.svc.cluster.local。

  • 對於一個 Headless Service,該 SRV 記錄解析到多個結果:每一個結果都對應該 Service 的一個後端 Pod,包含其端口號和 Pod 的域名 auto-generated-pod-name.my-svc.my-namespace.svc.cluster.local。

Pods

Kubernetes 在創建 Pod 時,將 Pod 定義中的 metadata.name 的值作爲 Pod 實例的 hostname。

  • Pod 定義中有一個可選字段 spec.hostname 可用來直接指定 Pod 的 hostname。例如,某 Pod 的 spec.hostname 字段被設置爲 my-host,則該 Pod 創建後 hostname 將被設爲 my-host。
  • Pod 定義中還有一個可選字段 spec.subdomain 可用來指定 Pod 的 subdomain。例如,名稱空間 my-namespace 中,某 Pod 的 hostname 爲 foo,並且 subdomain 爲 bar,則該 Pod 的完整域名(FQDN)爲 foo.bar.my-namespace.svc.cluster.local。

備註:A 記錄不是根據 Pod name 創建的,而是根據 hostname 創建的。如果一個 Pod 沒有 hostname 只有 subdomain,則 Kubernetes 將只爲其 headless Service 創建一個 A 記錄 default-subdomain.my-namespace.svc.cluster-domain.example,該記錄指向 Pod 的 IP 地址。

DNS 優化

社區根據壓測數據,對 CoreDNS 需要的內存提供了一個計算公式:

MB required (default settings) = (Pods + Services) / 1000 + 54

註解:

  • 30 MB 留給緩存,默認緩存大小爲 1 萬條記錄。
  • 5 MB 留給應用查詢操作使用,默認壓測單例 CoreDNS 支持大約 30K QPS。

集成外部 DNS 服務

我們在使用 Kubernetes 的場景中,企業經常已經默認有了自己的 DNS 服務,在部署容器集羣的時候,肯定期望和外置的 DNS 服務做一些集成,方便企業內部的使用。

默認 DNS 查詢策略是 ClusterFirst,也就是查詢應用名字首先是讓集羣內部的 CoreDNS 提供名字服務。而我們需要解決的是讓指定的別名訪問外部的服務,這個時候就需要做如下配置:

apiVersion: v1

kind: ConfigMap

metadata:

  name: kube-dns

  namespace: kube-system

data:

  stubDomains: |

    {"consul.local": ["10.150.0.1"]}

  upstreamNameservers: |

    ["8.8.8.8""8.8.4.4"]

上面這個例子很好的解釋了外置 Consul 服務,也可以很好地集成到 Kubernetes 服務中。如果是正式的域名,直接轉向查詢 8.8.8.8 上游 DNS 服務器了。

總結

CoreDNS 是 Kubernetes 集羣中最核心,也是最容易理解的一個組件,它的功能單一,很容易上手。但是名字解析的規則還是需要大家熟悉,避免一些不必要的認知錯誤。

參考:

https://github.com/coredns/deployment/blob/master/kubernetes/Scaling_CoreDNS.md

https://kuboard.cn/learning/k8s-intermediate/service/dns.html

本文分享自微信公衆號 - 雲原生技術愛好者社區(programmer_java)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章