如何給 Pod 添加 DNS 記錄?

來(lái)源:https://unsplash.com/photos/f77dx5VnBKc
我們都知道 StatefulSet 中的 Pod 是擁有單獨(dú)的 DNS 記錄的,比如一個(gè) StatefulSet 名稱為 etcd,而它關(guān)聯(lián)的 Headless SVC 名稱為 etcd-headless,那么 CoreDNS 就會(huì)為它的每個(gè) Pod 解析如下的記錄:
etcd-0.etcd-headless.default.svc.cluster.localetcd-1.etcd-headless.default.svc.cluster.local......
那么除了 StatefulSet 管理的 Pod 之外,其他的 Pod 是否也可以生成 DNS 記錄呢?
如下所示,我們這里只有一個(gè) Headless 的 SVC,并沒(méi)有 StatefulSet 管理的 Pod,而是 ReplicaSet 管理的 Pod,我們可以看到貌似也生成了類似于 StatefulSet 中的解析記錄。
這是怎么做到的呢?按照我們常規(guī)的理解會(huì)認(rèn)為這是一個(gè) StatefulSet 管理的 Pod,但其實(shí)這里是不同的 ReplicaSet 而已。這里的實(shí)現(xiàn)其實(shí)是因?yàn)?Pod 自己本身也是可以有自己的 DNS 記錄的,所以我們是可以去實(shí)現(xiàn)一個(gè)類似于 StatefulSet 的 Pod 那樣的解析記錄的。
首先我們來(lái)部署一個(gè) Deployment 管理的普通應(yīng)用,其定義如下:
#?nginx.yaml
apiVersion:?apps/v1?
kind:?Deployment
metadata:
??name:?nginx
spec:
??selector:
????matchLabels:
??????app:?nginx
??replicas:?2
??template:
????metadata:
??????labels:
????????app:?nginx
????spec:
??????containers:
??????-?name:?nginx
????????image:?nginx:1.7.9
????????ports:
????????-?containerPort:?80
部署后創(chuàng)建了兩個(gè) Pod:
$?kubectl?apply?-f?nginx.yaml
deployment.apps/nginx?created
$?kubectl?get?pod?-l?app=nginx?-o?wide
NAME?????????????????????READY???STATUS????RESTARTS???AGE???IP?????????????NODE????NOMINATED?NODE???READINESS?GATES
nginx-5d59d67564-2cwdz???1/1?????Running???0??????????19s???10.244.1.68????node1??????????????
nginx-5d59d67564-bp5br???1/1?????Running???0??????????19s???10.244.2.209???node2??????????????
然后定義如下的 Headless Service:
#?service.yaml
apiVersion:?v1
kind:?Service
metadata:
??name:?nginx
spec:
??clusterIP:?None
??ports:
??-?name:?http
????port:?80
????protocol:?TCP
??selector:
????app:?nginx
??type:?ClusterIP
創(chuàng)建該 service,并嘗試解析 service DNS:
$?kubectl?apply?-f?ervice.yaml
service/nginx?created
$?kubectl?get?svc
NAME???????????????????????TYPE????????CLUSTER-IP???????EXTERNAL-IP???PORT(S)??????????????????????AGE
kubernetes?????????????????ClusterIP???10.96.0.1????????????????443/TCP??????????????????????38d
nginx??????????????????????ClusterIP???None?????????????????????80/TCP???????????????????????7s
[email protected]?nginx.default.svc.cluster.local
;?<<>>?DiG?9.9.4-RedHat-9.9.4-73.el7_6?<<>>[email protected]?nginx.default.svc.cluster.local
;?(1?server?found)
;;?global?options:?+cmd
;;?Got?answer:
;;?->>HEADER<<-?opcode:?QUERY,?status:?NOERROR,?id:?2573
;;?flags:?qr?aa?rd;?QUERY:?1,?ANSWER:?2,?AUTHORITY:?0,?ADDITIONAL:?1
;;?WARNING:?recursion?requested?but?not?available
;;?OPT?PSEUDOSECTION:
;?EDNS:?version:?0,?flags:;?udp:?4096
;;?QUESTION?SECTION:
;nginx.default.svc.cluster.local.?IN?A
;;?ANSWER?SECTION:
nginx.default.svc.cluster.local.?30?IN?A?10.244.2.209
nginx.default.svc.cluster.local.?30?IN?A?10.244.1.68
;;?Query?time:?19?msec
;;?SERVER:?10.96.0.10#53(10.96.0.10)
;;?WHEN:?Wed?Nov?25?11:44:41?CST?2020
;;?MSG?SIZE??rcvd:?154
然后我們對(duì) nginx 的 FQDN 域名進(jìn)行 dig 操作,可以看到返回了多條 A 記錄,每一條對(duì)應(yīng)一個(gè) Pod。上面 dig 命令中使用的 10.96.0.10 就是 kube-dns 的 cluster IP,可以在 kube-system namespace 中查看:
$?kubectl?-n?kube-system?get?svc
NAME???????????????????TYPE????????CLUSTER-IP?????EXTERNAL-IP???PORT(S)?????????AGE
kube-dns???????????????ClusterIP???10.96.0.10?????????????53/UDP,53/TCP???52m
接下來(lái)我們?cè)囋囋?service 名字前面加上 Pod 名字交給 kube-dns 做解析:
[email protected]?nginx-5d59d67564-bp5br.nginx.default.svc.cluster.local
;?<<>>?DiG?9.9.4-RedHat-9.9.4-73.el7_6?<<>>[email protected]?nginx-5d59d67564-bp5br.nginx.default.svc.cluster.local
;?(1?server?found)
;;?global?options:?+cmd
;;?Got?answer:
;;?->>HEADER<<-?opcode:?QUERY,?status:?NXDOMAIN,?id:?10485
;;?flags:?qr?aa?rd;?QUERY:?1,?ANSWER:?0,?AUTHORITY:?1,?ADDITIONAL:?1
;;?WARNING:?recursion?requested?but?not?available
;;?OPT?PSEUDOSECTION:
;?EDNS:?version:?0,?flags:;?udp:?4096
;;?QUESTION?SECTION:
;nginx-5d59d67564-bp5br.nginx.default.svc.cluster.local.?IN?A
;;?AUTHORITY?SECTION:
cluster.local.??30?IN?SOA?ns.dns.cluster.local.?hostmaster.cluster.local.?1606275807?7200?1800?86400?30
;;?Query?time:?4?msec
;;?SERVER:?10.96.0.10#53(10.96.0.10)
;;?WHEN:?Wed?Nov?25?11:47:31?CST?2020
;;?MSG?SIZE??rcvd:?176
可以看到并沒(méi)有得到解析結(jié)果。官方文檔中有一段 Pod’s hostname and subdomain fields 說(shuō)明:
“Pod 規(guī)范中包含一個(gè)可選的 hostname 字段,可以用來(lái)指定 Pod 的主機(jī)名。當(dāng)這個(gè)字段被設(shè)置時(shí),它將優(yōu)先于 Pod 的名字成為該 Pod 的主機(jī)名。舉個(gè)例子,給定一個(gè) hostname 設(shè)置為 "my-host" 的 Pod, 該 Pod 的主機(jī)名將被設(shè)置為 "my-host"。Pod 規(guī)約還有一個(gè)可選的 subdomain 字段,可以用來(lái)指定 Pod 的子域名。舉個(gè)例子,某 Pod 的 hostname 設(shè)置為
”“foo”,subdomain 設(shè)置為“bar”, 在名字空間“my-namespace”中對(duì)應(yīng)的完全限定域名為“foo.bar.my-namespace.svc.cluster-domain.example”。
nginx.yaml 加上 subdomain 測(cè)試下看看:
apiVersion:?apps/v1?
kind:?Deployment
metadata:
??name:?nginx
spec:
??selector:
????matchLabels:
??????app:?nginx
??replicas:?2
??template:
????metadata:
??????labels:
????????app:?nginx
????spec:
??????subdomain:?nginx
??????containers:
??????-?name:?nginx
????????image:?nginx:1.7.9
????????ports:
????????-?containerPort:?80
更新部署再嘗試解析 Pod DNS:
$?kubectl?apply?-f?nginx.yaml
$?kubectl?get?pod?-l?app=nginx?-o?wide
NAME?????????????????????READY???STATUS????????RESTARTS???AGE?????IP?????????????NODE????NOMINATED?NODE???READINESS?GATES
nginx-78f58d8bcb-6kctm???1/1?????Running???????0??????????8s??????10.244.2.210???node2??????????????
nginx-78f58d8bcb-6tbnv???1/1?????Running???????0??????????15s?????10.244.1.69????node1??????????????
[email protected]?nginx-78f58d8bcb-6kctm.nginx.default.svc.cluster.local
;?<<>>?DiG?9.9.4-RedHat-9.9.4-73.el7_6?<<>>[email protected]?nginx-78f58d8bcb-6kctm.nginx.default.svc.cluster.local
;?(1?server?found)
;;?global?options:?+cmd
;;?Got?answer:
;;?->>HEADER<<-?opcode:?QUERY,?status:?NXDOMAIN,?id:?34172
;;?flags:?qr?aa?rd;?QUERY:?1,?ANSWER:?0,?AUTHORITY:?1,?ADDITIONAL:?1
;;?WARNING:?recursion?requested?but?not?available
;;?OPT?PSEUDOSECTION:
;?EDNS:?version:?0,?flags:;?udp:?4096
;;?QUESTION?SECTION:
;nginx-78f58d8bcb-6kctm.nginx.default.svc.cluster.local.?IN?A
;;?AUTHORITY?SECTION:
cluster.local.??30?IN?SOA?ns.dns.cluster.local.?hostmaster.cluster.local.?1606276303?7200?1800?86400?30
;;?Query?time:?2?msec
;;?SERVER:?10.96.0.10#53(10.96.0.10)
;;?WHEN:?Wed?Nov?25?11:52:18?CST?2020
;;?MSG?SIZE??rcvd:?176
可以看到依然不能解析,那就試試官方文檔中的例子 ,不用 Deployment 直接創(chuàng)建 Pod 吧。第一步先將 hostname 和 subdomain 注釋掉:
#?individual-pods-example.yaml
apiVersion:?v1
kind:?Service
metadata:
??name:?default-subdomain
spec:
??selector:
????name:?busybox
??clusterIP:?None
??ports:
??-?name:?foo?#?Actually,?no?port?is?needed.
????port:?1234
????targetPort:?1234
---
apiVersion:?v1
kind:?Pod
metadata:
??name:?busybox1
??labels:
????name:?busybox
spec:
??hostname:?busybox-1
??subdomain:?default-subdomain
??containers:
??-?image:?busybox:1.28
????command:
??????-?sleep
??????-?"3600"
????name:?busybox
---
apiVersion:?v1
kind:?Pod
metadata:
??name:?busybox2
??labels:
????name:?busybox
spec:
??hostname:?busybox-2
??subdomain:?default-subdomain
??containers:
??-?image:?busybox:1.28
????command:
??????-?sleep
??????-?"3600"
????name:?busybox
部署然后嘗試解析 Pod DNS (注意這里 hostname 和 pod 的名字有區(qū)別,中間多了減號(hào)):
$?kubectl?apply?-f?individual-pods-example.yaml
[email protected]?busybox-1.default-subdomain.default.svc.cluster.local
;?<<>>?DiG?9.11.3-1ubuntu1.5-Ubuntu?<<>>[email protected]?busybox-1.default-subdomain.default.svc.cluster.local
;?(1?server?found)
;;?global?options:?+cmd
;;?Got?answer:
;;?WARNING:?.local?is?reserved?for?Multicast?DNS
;;?You?are?currently?testing?what?happens?when?an?mDNS?query?is?leaked?to?DNS
;;?->>HEADER<<-?opcode:?QUERY,?status:?NOERROR,?id:?12636
;;?flags:?qr?aa?rd?ra;?QUERY:?1,?ANSWER:?1,?AUTHORITY:?0,?ADDITIONAL:?1
;;?OPT?PSEUDOSECTION:
;?EDNS:?version:?0,?flags:;?udp:?4096
;?COOKIE:?5499ded915cf1ff2?(echoed)
;;?QUESTION?SECTION:
;busybox-1.default-subdomain.default.svc.cluster.local.?IN?A
;;?ANSWER?SECTION:
busybox-1.default-subdomain.default.svc.cluster.local.?5?IN?A?10.44.0.6
;;?Query?time:?0?msec
;;?SERVER:?10.96.0.10#53(10.96.0.10)
;;?WHEN:?Fri?Apr?19?15:27:38?CST?2019
;;?MSG?SIZE??rcvd:?163
現(xiàn)在我們看到有 ANSWER 記錄回來(lái)了,hostname 和 subdomain 二者都必須顯式指定,缺一不可。一開(kāi)始我們的截圖中的實(shí)現(xiàn)方式其實(shí)也是這種方式。
現(xiàn)在我們修改一下之前的 nginx deployment 加上 hostname,重新解析:
[email protected]?nginx.nginx.default.svc.cluster.local
;?<<>>?DiG?9.9.4-RedHat-9.9.4-73.el7_6?<<>>[email protected]?nginx.nginx.default.svc.cluster.local
;?(1?server?found)
;;?global?options:?+cmd
;;?Got?answer:
;;?->>HEADER<<-?opcode:?QUERY,?status:?NOERROR,?id:?21127
;;?flags:?qr?aa?rd;?QUERY:?1,?ANSWER:?2,?AUTHORITY:?0,?ADDITIONAL:?1
;;?WARNING:?recursion?requested?but?not?available
;;?OPT?PSEUDOSECTION:
;?EDNS:?version:?0,?flags:;?udp:?4096
;;?QUESTION?SECTION:
;nginx.nginx.default.svc.cluster.local.?IN?A
;;?ANSWER?SECTION:
nginx.nginx.default.svc.cluster.local.?30?IN?A?10.244.2.211
nginx.nginx.default.svc.cluster.local.?30?IN?A?10.244.1.70
;;?Query?time:?1?msec
;;?SERVER:?10.96.0.10#53(10.96.0.10)
;;?WHEN:?Wed?Nov?25?11:55:37?CST?2020
;;?MSG?SIZE??rcvd:?172
可以看到解析成功了,但是因?yàn)?Deployment 中無(wú)法給每個(gè) Pod 指定不同的 hostname,所以兩個(gè) Pod 有同樣的 hostname,解析出來(lái)兩個(gè) IP,跟我們的本意就不符合了。
不過(guò)知道了這種方式過(guò)后我們就可以自己去寫(xiě)一個(gè) Operator 去直接管理 Pod 了,給每個(gè) Pod 設(shè)置不同的 hostname 和一個(gè) Headless SVC 名稱的 subdomain,這樣就相當(dāng)于實(shí)現(xiàn)了 StatefulSet 中的 Pod 解析。
訓(xùn)練營(yíng)推薦

?點(diǎn)擊屏末?|?閱讀原文?|?即刻學(xué)習(xí)

