Kubernetes DNS


DNS介紹

介紹

kubernets的所有資源.包括Service,Pod都有生命周期,會頻繁的銷毀和創建.這些資源的IP地址也會隨之動態變化.所以Kubernetes使用DNS實現通過資源名解析IP地址.

DNS服務器

Kubernetes集群安裝了默認的Core-dns組件(通過Pod方式運行).以及kube-dns的service.

1
2
3
4
5
6
7
[root@k8s-master ~]$kubectl get pods -n kube-system | grep dns
coredns-7f9c544f75-9sh28 1/1 Running 2 324d
coredns-7f9c544f75-jgmqq 1/1 Running 2 324d

#下方這個10.96.0.10就是kubernetes集群的內部DNS服務器
[root@k8s-master ~]$kubectl get svc -n kube-system | grep dns
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 324d

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
2
3
4
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5

resolv.conf 配置文件說明

nameserver:指明DNS服務器地址.也就是上文提到的kube-dns 的service

search:當原始域名不能被DNS解析時,resolver會將該域名加上search指定的參數,重新請求DNS,直到被正確解析或試完search指定的列表為止 options:dns配置

ndots:5:所有DNS查詢中,如果“.”的個數少於5個,則會根據search中配置的列表依次在對應域中先進行搜索,如果沒有返回,則最后再直接查詢域名本身

為了了解searchndots 的概念,我們先要了解FQDN的概念.FQDN(Fully qualified domain name)即完整域名。一般來說如果一個域名以.結束,就表示一個完整域名。比如www.abc.xyz.就是一個FQDN,而www.abc.xyz則不是FQDN。了解了這個概念之后我們就來看searchoptions ndots

如果一個域名是FQDN,那么這個域名會被轉發給DNS服務器進行解析。如果域名不是FQDN,那么這個域名會到search搜索解析,還是通過一個例子說明,比如訪問abc.xyz這個域名,因為它並不是一個FQDN,所以它會和search域中的值進行組合而變成一個FQDN,以上文的resolv.conf為例,這域名會這樣組合:

1
2
3
abx.xyz.default.svc.cluster.local.
abc.xyz.svc.cluster.local.
abc.xyz.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.confjplat、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
2
3
4
5
6
/ # nslookup my-svc
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: my-svc
Address 1: 10.96.51.58 my-svc.default.svc.cluster.local

上面的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
2
3
4
5
6
/ # nslookup kube-dns.kube-system
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: kube-dns.kube-system
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

實際上DNS解析的是完全FQDN域名,只不過后面一部分內容default.svc.cluster.local 可以省略罷了.默認就是解析當前名稱空間下的資源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/ # nslookup my-svc
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: my-svc
Address 1: 10.96.51.58 my-svc.default.svc.cluster.local

#等同於:
/ # nslookup my-svc.default.svc.cluster.local
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: my-svc.default.svc.cluster.local
Address 1: 10.96.51.58 my-svc.default.svc.cluster.local

在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-svc10.96.51.58這個IP地址.

如果是對於無頭服務(headless service).這種service沒有IP.但是也會以上面的形式被指派一個DNS的A記錄.只不過這種記錄和普通Service不同,而是被解析成對應服務的POD集合的Pod的IP.客戶端使用標准的負載均衡策略從這組Pod中進行選擇.

例如下面創建一個headless的svc.和普通svc的區別在於clusterIP的值為None.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[root@k8s-master ~]$cat deployment-kubia-v1.yaml
apiVersion: v1
kind: Pod
metadata:
name: hsq1
labels:
app: hsq-openapi
spec:
containers:
- name: nginx
image: nginx

---
apiVersion: v1
kind: Pod
metadata:
name: hsq2
labels:
app: hsq-openapi
spec:
containers:
- name: nginx
image: nginx
---
#一個yaml文件可以定義多種資源,中間用---隔開

apiVersion: v1
kind: Service
metadata:
name: hsq-openapi
spec:
selector:
app: hsq-openapi
clusterIP: None
ports:
- port: 80
targetPort: 80

headless服務一般用於statefulset資源.不能用於deployment控制器

創建該文件后查看hsq-openapiservice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8s-master ~]$kubectl describe svc hsq-openapi
Name: hsq-openapi
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"hsq-openapi","namespace":"default"},"spec":{"clusterIP":"None","p...
Selector: app=hsq-openapi
Type: ClusterIP
IP: None
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.100.36.66:80,10.100.36.69:80 #這里是后端pod列表
Session Affinity: None
Events: <none>

headless類型服務的DNS解析

仍然使用上文中的busybox測試容器.解析hsq-openapi service 的A記錄.可以看到解析的結果返回了2個pod的IP地址列表.對於這種類型的service.和普通的service不同.他解析出來的是POD的ip地址列表

1
2
3
4
5
6
7
8
/ # nslookup hsq-openapi
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: hsq-openapi
Address 1: 10.100.36.69 10-100-36-69.hsq-openapi.default.svc.cluster.local
Address 2: 10.100.36.66 10-100-36-66.hsq-openapi.default.svc.cluster.local
/ # ???

Pod的A記錄

一般而言,Pod會對應如下DNS名字解析: pod-ip-address.<namespace-name>.pod.cluster.local 例如對於上面例子中的iP為10.100.36.69 的Pod.對應的DNS名稱為:

1
2
3
4
5
6
/ # nslookup 10-100-36-69.default.pod.cluster.local  #DNS名稱
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: 10-100-36-69.default.pod.cluster.local
Address 1: 10.100.36.69 10-100-36-69.hsq-openapi.default.svc.cluster.local

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進行解析。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM