DNS介紹
介紹
kubernets的所有資源.包括Service,Pod都有生命周期,會頻繁的銷毀和創建.這些資源的IP地址也會隨之動態變化.所以Kubernetes使用DNS實現通過資源名解析IP地址.
DNS服務器
Kubernetes集群安裝了默認的Core-dns組件(通過Pod方式運行).以及kube-dns的service.
1 |
[root@k8s-master ~]$kubectl get pods -n kube-system | grep dns |
pod容器內部dns解析
創建一個臨時的pod容器,測試DNS解析效果.下面的命令臨時運行了一個busybox的鏡像
1 |
[root@k8s-master ~]$kubectl run -it dns-test --rm --image=busybox:1.28.4 -- sh |
不要使用latest版本的鏡像,其dns解析有問題.最好使用1.28.4版本的
下方是Pod容器的內部dns服務器信息
1 |
/ # cat /etc/resolv.conf |
resolv.conf
配置文件說明
nameserver:指明DNS服務器地址.也就是上文提到的kube-dns
的service
search:當原始域名不能被DNS解析時,resolver會將該域名加上search指定的參數,重新請求DNS,直到被正確解析或試完search指定的列表為止 options:dns配置
ndots:5:所有DNS查詢中,如果“.”的個數少於5個,則會根據search中配置的列表依次在對應域中先進行搜索,如果沒有返回,則最后再直接查詢域名本身
為了了解search
和ndots
的概念,我們先要了解FQDN的概念.FQDN(Fully qualified domain name)
即完整域名。一般來說如果一個域名以.
結束,就表示一個完整域名。比如www.abc.xyz.
就是一個FQDN
,而www.abc.xyz
則不是FQDN
。了解了這個概念之后我們就來看search
和options ndots
。
如果一個域名是FQDN
,那么這個域名會被轉發給DNS服務器進行解析。如果域名不是FQDN
,那么這個域名會到search
搜索解析,還是通過一個例子說明,比如訪問abc.xyz
這個域名,因為它並不是一個FQDN
,所以它會和search
域中的值進行組合而變成一個FQDN
,以上文的resolv.conf
為例,這域名會這樣組合:
1 |
abx.xyz.default.svc.cluster.local. |
然后這些域名先被kube-DNS
解析,如果沒有解析成功再由宿主機的DNS
服務器進行解析。
而ndots
是用來表示一個域名中.
的個數在不小於該值的情況下會被認為是一個FQDN
。簡單說這個屬性用來判斷一個不是以.
結束的域名在什么條件下會被認定為是一個FQDN
.上面的示例中ndots為5,也就是說如果一個域名中.
的數量大於等於5,即使域名不是以.
結尾,也會被認定為是一個FQDN
。比如:域名是abc.xyz.xxx.yyy.zzz.aaa
這個域名就是FQDN
.
之所以會有search
域主要還是為了方便k8s內部服務之間的訪問。比如:k8s在同一個namespace
下是可以直接通過服務名稱進行訪問的,其原理就是會在search
域查找,比如上面的resolv.conf
中jplat、oms-dev
着兩個其實都是這兩個pod所在的namespace
的名稱。所以通過服務名稱訪問的時候,會和search
域進行組合,這樣最終域名會組合成servicename.namespace.svc.cluster.local
。而如果是跨namespace
訪問,則可以通過servicename.namespace
這樣的形式,在通過和search
域組合,依然可以得到servicename.namespace.svc.cluster.local
。
DNS解析
解析對象
Kubernetes集群中的每個Service資源都會被指派一個DNS名稱.客戶端Pod的DNS搜索列表默認是搜索自己的namespace
名稱空間內的資源.
例如上文的resolv.conf
文件內的search搜索列表為search default.svc.cluster.local svc.cluster.local cluster.local localdomain
.此時Pod可以直接搜索default
名稱空間下的所有Service:
例如.使用上面的臨時busybox容器解析my-svc
的Service
1 |
/ # nslookup my-svc |
上面的IP地址10.96.51.58
表示成功解析到該Service的IP.my-svc.default.svc.cluster.local
這個就是該Service的FQDN完全限定域名.
其中:
default
—表示名稱空間,我們的名稱空間名字就是默認的default
svc
—————-表示資源類型,這里是Service
cluster.local
–k8s集群域名
也可以解析其他名稱空間內的資源,比如解析kube-system
名稱空間下的DNS服務器的Service.(DNS服務器本身也會被指定一個DNS名稱).就可以通過<svc-name>.<namespace-name>
實現.比如下面解析kube-system
名稱空間下的kube-dns
的Service
1 |
/ # nslookup kube-dns.kube-system |
實際上DNS解析的是完全FQDN域名,只不過后面一部分內容default.svc.cluster.local
可以省略罷了.默認就是解析當前名稱空間下的資源
1 |
/ # nslookup my-svc |
在kubernetes官網中也提到:
假設在 Kubernetes 集群的名字空間 bar
中,定義了一個服務 foo
。 運行在名字空間 bar
中的 Pod 可以簡單地通過 DNS 查詢 foo
來找到該服務。 運行在名字空間 quux
中的 Pod 可以通過 DNS 查詢 foo.bar
找到該服務。
Service A記錄
對於普通的Service資源.會以<service-name>.<namespace-name>.svc.cluster.local
這種形式被分配一個DNS A記錄.也就是上文中的my-svc
的10.96.51.58
這個IP地址.
如果是對於無頭服務(headless service).這種service沒有IP.但是也會以上面的形式被指派一個DNS的A記錄.只不過這種記錄和普通Service不同,而是被解析成對應服務的POD集合的Pod的IP.客戶端使用標准的負載均衡策略從這組Pod中進行選擇.
例如下面創建一個headless的svc.和普通svc的區別在於clusterIP的值為None
.
1 |
[root@k8s-master ~]$cat deployment-kubia-v1.yaml |
headless服務一般用於statefulset資源.不能用於deployment控制器
創建該文件后查看hsq-openapi
service:
1 |
[root@k8s-master ~]$kubectl describe svc hsq-openapi |
headless類型服務的DNS解析
仍然使用上文中的busybox測試容器.解析hsq-openapi
service 的A記錄.可以看到解析的結果返回了2個pod的IP地址列表.對於這種類型的service.和普通的service不同.他解析出來的是POD的ip地址列表
1 |
/ # nslookup hsq-openapi |
Pod的A記錄
一般而言,Pod會對應如下DNS名字解析: pod-ip-address.<namespace-name>.pod.cluster.local
例如對於上面例子中的iP為10.100.36.69
的Pod.對應的DNS名稱為:
1 |
/ # nslookup 10-100-36-69.default.pod.cluster.local #DNS名稱 |
k8s默認的DNS策略
k8s提供了5種DNS策略,如下:
Default
: Pod 從運行所在的節點繼承名稱解析配置。ClusterFirst
: 與配置的集群域后綴不匹配的任何 DNS 查詢(例如 “www.kubernetes.io”) 都將轉發到從節點繼承的上游名稱服務器。集群管理員可能配置了額外的存根域和上游 DNS 服務器。ClusterFirstWithHostNet
:對於以 hostNetwork 方式運行的 Pod,應顯式設置其 DNS 策略ClusterFirstWithHostNet
。None
: 此設置允許 Pod 忽略 Kubernetes 環境中的 DNS 設置。Pod 會使用其dnsConfig
字段 所提供的 DNS 設置。
k8s默認使用的DNS策略是ClusterFirst
,這點需要注意,也就是說域名解析會優先使用集群的DNS(kube-DNS
)進行查詢,如果k8s的DNS解析失敗,會轉發到宿主機的DNS進行解析。