目錄
* 什么是服務(wù)發(fā)現(xiàn)? <https://www.cnblogs.com/lshare/p/11361687.html#什么是服務(wù)發(fā)現(xiàn)>
* 環(huán)境變量 <https://www.cnblogs.com/lshare/p/11361687.html#環(huán)境變量>
* DNS 服務(wù) <https://www.cnblogs.com/lshare/p/11361687.html#dns-服務(wù)>
* Linux 中 DNS 查詢?cè)?
<https://www.cnblogs.com/lshare/p/11361687.html#linux-中-dns-查詢?cè)?gt;
* Kubernetes 中 DNS 查詢?cè)?
<https://www.cnblogs.com/lshare/p/11361687.html#kubernetes-中-dns-查詢?cè)?gt;
* 調(diào)試 DNS 服務(wù) <https://www.cnblogs.com/lshare/p/11361687.html#調(diào)試-dns-服務(wù)>
* 存根域及上游 DNS <https://www.cnblogs.com/lshare/p/11361687.html#存根域及上游-dns>
什么是服務(wù)發(fā)現(xiàn)?
服務(wù)發(fā)現(xiàn)就是一種提供服務(wù)發(fā)布和查找的服務(wù),是基于服務(wù)架構(gòu)(SOA)應(yīng)用的核心服務(wù),需具備以下關(guān)鍵特性:
* 注冊(cè)(Registration),新增服務(wù)到服務(wù)列表;
* 目錄(Directory),即服務(wù)列表;
* 查找(Lookup),通過服務(wù)名找到服務(wù)。
服務(wù)發(fā)現(xiàn)的關(guān)鍵在于服務(wù)元數(shù)據(jù)(metadata)的存儲(chǔ),包括服務(wù)名、服務(wù) IP、服務(wù)端口等信息。
Kubernetes 支持兩種服務(wù)發(fā)現(xiàn)方式,環(huán)境變量和 DNS。
環(huán)境變量
當(dāng) Pod 創(chuàng)建時(shí),Kubernetes 會(huì)將每個(gè)活躍的 Service 的相關(guān)環(huán)境變量設(shè)置到 Pod 中。值得注意的是,這些環(huán)境變量不會(huì)因?yàn)橄嚓P(guān)
Service 改變而改變(筆者親手試驗(yàn)過)。
Kubernetes 會(huì)設(shè)置兩類環(huán)境變量,分別是:
* Kubernetes Service 環(huán)境變量
* Docker Link 環(huán)境變量
Kubernetes Service 環(huán)境變量形如(假定服務(wù)名為 latte,且訪問端口為 8080):
LATTE_SERVICE_HOST=10.100.251.57 LATTE_SERVICE_PORT=8080
Docker Link 環(huán)境變量形如(假定服務(wù)名為 latte,且訪問端口為 8080):
LATTE_PORT_8080_TCP_ADDR=10.100.251.57 LATTE_PORT_8080_TCP_PORT=8080
LATTE_PORT_8080_TCP_PROTO=tcp LATTE_PORT=tcp://10.100.251.57:8080
LATTE_PORT_8080_TCP=tcp://10.100.251.57:8080
可以通過進(jìn)入 Pod 的終端,執(zhí)行 env 命令查看設(shè)置的環(huán)境變量驗(yàn)證。
kubectl exec -ti <pod-name> env --namespace=<my-namespace>
此種方式的服務(wù)發(fā)現(xiàn)缺點(diǎn)很明顯:
* 依賴的服務(wù)必須先運(yùn)行起來,否則 Pod 無法發(fā)現(xiàn);
* 如依賴的服務(wù)宕機(jī)或綁定新地址,Pod 無法發(fā)現(xiàn),仍然持有舊的地址。
幸好,我們還有另一種服務(wù)發(fā)現(xiàn)機(jī)制。
DNS 服務(wù)
在講述 Kubernetes 中使用 DNS 進(jìn)行服務(wù)發(fā)現(xiàn)之前,我們不得不先了解下 Linux 中是如何進(jìn)行 DNS 查詢的。
Linux 中 DNS 查詢?cè)?br>
在 Linux 的 /etc/ 目錄中,存在 3
個(gè)我們需要關(guān)注的文件,分別是(參考:http://man7.org/linux/man-pages/man5/host.conf.5.html):
* /etc/host.conf:DNS 解析器配置,包含 trim、multi、order、reorder 和 nospoof 等等配置。
* /etc/hosts:本地 hosts 數(shù)據(jù)庫,存放本地的域名到 IP 的配置。
* /etc/resolv.conf:DNS 解析器配置,包含 nameserver、domain、search、sortlist 和 options
等配置。
下面是一臺(tái) Linux 服務(wù)器中 3 個(gè)相關(guān)文件的內(nèi)容:
# /etc/host.conf multi on # /etc/hosts 127.0.0.1 localhost
localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost6
localhost6.localdomain6 # /etc/resolv.conf ; generated by
/usr/sbin/dhclient-script search us-west-2.compute.internal options timeout:2
attempts:5 nameserver 192.168.0.2
/etc/resolv.conf 配置 <http://man7.org/linux/man-pages/man5/resolv.conf.5.html>
解釋如下:
配置項(xiàng) 功能 備注
nameserver DNS 服務(wù)器 值必須是 IP 地址
domain 本地域名 域中的查詢可以使用相對(duì)于本地域名的短名稱
search 主機(jī)名查詢列表 默認(rèn)只包含本地域名。閾值為 6 個(gè)域名,256 個(gè)字符。
options 選項(xiàng) 修改內(nèi)部 DNS 解析器變量值。
options 中常見的配置項(xiàng)有:
配置項(xiàng) 功能
ndots 所有查詢中,如果.的個(gè)數(shù)少于給定的數(shù)值,則會(huì)根據(jù)search中配置的列表依次在對(duì)應(yīng)域中先進(jìn)行搜索,如果沒有返回,則最后再直接查詢域名本身。閾值為
15。
timeout 等待 DNS 服務(wù)器響應(yīng)的超時(shí)時(shí)間,單位為秒。閾值為 30 s。
attempts 向同一個(gè) DNS 服務(wù)器發(fā)起重試的次數(shù),單位為次。閾值為 5。
筆者在本地試驗(yàn)時(shí)發(fā)現(xiàn),文件 /etc/resolv.conf 是網(wǎng)絡(luò)連接時(shí)自動(dòng)生成的,依據(jù)是:
* 當(dāng)本機(jī)處以斷網(wǎng)狀態(tài)時(shí),cat /etc/resolv.conf 返回空文本;
* 當(dāng)本機(jī)連上網(wǎng)絡(luò)時(shí),cat /etc/resolv.conf 返回以下內(nèi)容: # # macOS Notice # # This file is not
consulted for DNS hostname resolution, address # resolution, or the DNS query
routing mechanism used by most # processes on this system. # # To view the DNS
configuration used by this system, use: # scutil --dns # # SEE ALSO #
dns-sd(1), scutil(8) # # This file is automatically generated. # nameserver
58.250.162.58 nameserver 8.8.8.8
第一個(gè) DNS 服務(wù)器是中國(guó)聯(lián)通的,通過訪問 https://whois.domaintools.com/58.250.162.58 可知;
第二個(gè) DNS服務(wù)器是 Google 的,通過 nslookup 8.8.8.8 或者訪問
https://whois.domaintools.com/8.8.8.8 可知。
Kubernetes 中 DNS 查詢?cè)?br>
Kubernetes 中有兩個(gè)可選的 DNS 服務(wù)插件(處在 kube-system 命名空間):
插件 說明
kube-dns 其代碼已經(jīng)從 kubernetes 庫中分離到單獨(dú)的倉庫維護(hù),見 https://github.com/kubernetes/dns
CoreDNS 支持 Kubernetes v1.9 及以上;Kubernetes v1.12 起,官方推薦使用來替換
kube-dns;Kubernetes v1.13 起,成為默認(rèn) DNS 服務(wù);占用內(nèi)存小,查詢速度快。
注意:kube-dns 在 Kubernetes 中有多重含義,要注意區(qū)別。
* 與 CoreDNS 對(duì)比時(shí),使用狹義,表示名為 kube-dns 的 DNS 服務(wù);
* 當(dāng)泛指時(shí),表示 Kubernetes 中的 DNS 服務(wù)。
使用 kubeadm 創(chuàng)建 v1.11 及以后的 Kubernetes 集群,默認(rèn)啟用 CoreDNS(處于 GA 狀態(tài),見 Software
release life cycle <https://en.wikipedia.org/wiki/Software_release_life_cycle>
)。(來源
<https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/>)
筆者通過 aws 提供的 eksctl 工具創(chuàng)建的 v1.15 的集群默認(rèn)也是啟用了 CoreDNS,查閱 eksctl 源碼
<https://github.com/weaveworks/eksctl/tree/master/pkg/addons/default>
可以獲取其默認(rèn)啟用的插件。
Kubernetes 通過修改每個(gè) Pod 中每個(gè)容器的域名解析配置文件 /etc/resolv.conf 來達(dá)到服務(wù)發(fā)現(xiàn)的目的
。在筆者創(chuàng)建的集群中獲取其中一個(gè)容器的域名解析配置文件如下:
# /etc/resolv.conf nameserver 10.100.0.10 search cafe.svc.cluster.local
svc.cluster.local cluster.local us-west-2.compute.internal options ndots:5
其含義是:DNS 服務(wù)器為 10.100.0.10,當(dāng)查詢關(guān)鍵詞中 . 的數(shù)量少于 5 個(gè),則根據(jù) search
中配置的域名進(jìn)行查詢,當(dāng)查詢都沒有返回正確響應(yīng)時(shí)再嘗試直接查詢關(guān)鍵詞本身。
例如,執(zhí)行 host -v cn.bing.com 后我們將會(huì)看到:
Trying "cn.bing.com.cafe.svc.cluster.local" Trying
"cn.bing.com.svc.cluster.local" Trying "cn.bing.com.cluster.local" Trying
"cn.bing.com.us-west-2.compute.internal" Trying "cn.bing.com" ...
解析過程是如此緩慢,當(dāng)對(duì)某些服務(wù)訪問頻繁時(shí)建議額外配置 DNS 記錄。
注:獲取過程如下
# 1) 查詢指定命名空間中的所有 pod kubectl get pods --namespace=cafe # 2) 進(jìn)入其中一個(gè) pod 的交互終端
kubectl exec -ti macchiato-6746674bdd-5hmtw sh --namespace=cafe # 3) 查看
/etc/resolv.conf cat /etc/resolv.conf
DNS 服務(wù)器會(huì)監(jiān)聽著集群內(nèi)所有 Service API,以在服務(wù)不可用時(shí)移除記錄,在新服務(wù)創(chuàng)建時(shí)插入新記錄。
這些記錄存放在哪里呢?
答案是:存儲(chǔ)在 kube-dns 插件中的 cache 也可配置到 etcd。
存儲(chǔ)的 DNS 記錄有哪些種類呢?
我們過去或多或少了解到的 DNS 記錄 <https://en.wikipedia.org/wiki/List_of_DNS_record_types>
有以下幾種:
類別 作用
A Address record,域名到 IP 地址的記錄
CNAME Canonical name record,別名記錄,設(shè)置域名的別名
NS Name server record,域名服務(wù)器記錄
MX Mail exchange record,郵件服務(wù)記錄
TXT Text record,為某條記錄設(shè)置說明
AAAA IPv6 address record,域名到 IPv6 地址 ( 128 = 32 * 4 )的記錄
這次我們要多認(rèn)識(shí)一個(gè)稱之為 SRV(Service locator)的 DNS 記錄,用來通用化地定位服務(wù)。
Kubernetes 的 DNS 服務(wù)(簡(jiǎn)稱為 kube-dns)支持 Service 的 A 記錄、 SRV 記錄和 CNAME 記錄。
我們知道 Kubernetes 中的 Service 是 Pod 的邏輯分組,有 Cluster IP 和 Label Selector 有無之別。沒有設(shè)置
Cluster IP 的我們稱之為 Headless Service,否則稱之為 Normal Service。設(shè)置了 Label Selector
的會(huì)同時(shí)產(chǎn)生一個(gè) Endpoints 對(duì)象,聲明集群內(nèi)部 Service 的訪問端點(diǎn)。
假定有一個(gè) cafe 命名空間下名為 latte 的 Normal Service,開放了名為 http 的 TCP 端口 8080,kube-dns
會(huì)為其生成以下的 A 記錄和 SRV 記錄:
latte.cafe.svc.cluster.local. 5 IN A 10.100.71.56
_http._tcp.latte.cafe.svc.cluster.local. 30 IN SRV 10 100 443
latte.cafe.svc.cluster.local.
注:查詢 DNS 記錄的方法
(1)安裝 dig 工具
將下面的部署配置保存到文件 dnsutils.yaml,然后執(zhí)行 kubectl apply -f dnsutils.yaml 部署。
apiVersion: v1 kind: Pod metadata: name: dnsutils namespace: default spec:
containers: - name: dnsutils image: tutum/dnsutils command: - sleep - "3600"
imagePullPolicy: IfNotPresent restartPolicy: Always
(2)使用 dig 工具獲取 DNS 記錄
# 用法 dig @<DNS服務(wù)器> <記錄類型> <域名> <可選值> # 示例 ## 1)獲取 DNS 服務(wù)地址 kubectl get svc
kube-dns -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns
ClusterIP 10.100.0.10 <none> 53/UDP,53/TCP 8d ## 2)進(jìn)入 dnsutils 的 shell 終端
kubectl exec -ti dnsutils sh ## 3)查詢 latte 服務(wù)的 A 記錄 dig @10.100.0.10 A
latte.cafe.svc.cluster.local +noall +answer
假如有一個(gè) cafe 命名空間下名為 mocha 的 Headless Service,kube-dns 會(huì)為其生成以下的 A 記錄集(域名到 Pod
IPs 的映射):
mocha.cafe.svc.cluster.local. 5 IN A 192.168.62.111
mocha.cafe.svc.cluster.local. 5 IN A 192.168.62.112
mocha.cafe.svc.cluster.local. 5 IN A 192.168.62.113
如若有一個(gè) cafe 命名空間下名為 macchiato 的 Headless 但設(shè)置了以下 Endpoints 的 Service:
kind: Endpoints apiVersion: v1 metadata: name: macchiato namespace: cafe
subsets: - addresses: - ip: 1.2.3.4 ports: - port: 9376
kube-dns 會(huì)為其生成以下的 A 記錄:
macchiato.cafe.svc.cluster.local. 4 IN A 1.2.3.4
如果有一個(gè) cafe 命名空間下名為 cappuccino 的 Headless 但設(shè)置了以下 ExternalName 的 Service:
kind: Service apiVersion: v1 metadata: name: cappuccino namespace: cafe spec:
type: ExternalName externalName: cappuccino.cafe.com
kube-dns 會(huì)為其生成以下的 CNAME 記錄:
cappuccino.cafe.svc.cluster.local. 10 IN CNAME cappuccino.cafe.com.
Kubernetes 的 DNS 服務(wù)除了支持 Service 的 DNS 記錄外,還支持 Pod 的 A 記錄,使用 hostname +
subdomain 方式實(shí)現(xiàn)。仔細(xì)閱讀以下部署配置。
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
我們發(fā)現(xiàn)其創(chuàng)建了:
* name 為 busybox1,hostname 為 busybox-1,subdomain 為 default-subdomain 的 Pod;
* name 為 busybox2,hostname 為 busybox-2,subdomain 為 default-subdomain 的 Pod;
* name 為 default-subdomain 的 Headless Service。
產(chǎn)生以下 A 記錄:
busybox-1.default-subdomain.svc.cluster.local. 4 IN A 192.168.51.119
busybox-2.default-subdomain.svc.cluster.local. IN A
busybox-2.default-subdomain.svc.cluster.local. 4 IN A 192.168.36.188
default-subdomain.svc.cluster.local. 4 IN A 192.168.62.187
default-subdomain.svc.cluster.local. 4 IN A 192.168.62.188
這些記錄是怎樣的一種格式呢?
參見:https://github.com/kubernetes/dns/blob/master/docs/specification.md
調(diào)試 DNS 服務(wù)
使用 busybox 調(diào)試 DNS 服務(wù)
<https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/>
,因?yàn)?busybox 中有 nslookup 工具可以使用。
(1)保存以下文本到文件 busybox.yaml(此處使用命名空間為 cafe )
apiVersion: v1 kind: Pod metadata: name: busybox namespace: cafe spec:
containers: - name: busybox image: busybox:1.28 command: - sleep - "3600"
imagePullPolicy: IfNotPresent restartPolicy: Always
(2)應(yīng)用 busybox.yaml,并查看狀態(tài)
kubectl apply -f busybox.yaml --namespace=cafe kubectl get pods busybox
--namespace=cafe
(3)進(jìn)入終端交互界面并支持 nslookup 查詢服務(wù) latte
kubectl exec -ti busybox sh --namespace=cafe nslookup latte
存根域及上游 DNS
<https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#effects-on-pods>
當(dāng)無自定義配置時(shí),不匹配的 DNS 查詢(比如上文說的cn.bing.com)會(huì)使用從 Node 中繼承的 nameserver 進(jìn)行解析。
當(dāng)有自定義的配置時(shí),會(huì)在 DNS 緩存層查詢無果后,根據(jù)查詢名稱后綴決定去往的 DNS 解析器:
* 查詢名稱帶有集群后綴的(比如 ".cluster.local"),轉(zhuǎn)發(fā)到 kube-dns。
* 查詢名稱帶有存根域名后綴的(比如 ".acme.local"),轉(zhuǎn)發(fā)到 custom DNS。
* 查詢名稱不匹配的(比如 "widget.com"),轉(zhuǎn)發(fā)到 upstream DNS。
以上配置使用 Kubernetes 的ConfigMap 插件,配置如下:
apiVersion: v1 kind: ConfigMap metadata: name: kube-dns namespace: kube-system
data: stubDomains: | {"acme.local": ["1.2.3.4"]} upstreamNameservers: |
["8.8.8.8","8.8.4.4"]
熱門工具 換一換