您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Kubernetes DNS的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
$ sudo lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.2 LTS Release: 16.04 Codename: xenial $ kubectl version Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:53:09Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:34:32Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
從Kubernetes 1.3開始,DNS通過使用插件管理系統cluster add-on
,成為了一個內建的自啟動服務。
Kubernetes DNS在Kubernetes集群上調度了一個DNS Pod和Service,并配置kubelet,使其告訴每個容器使用DNS Service的Ip來解析DNS名稱。
集群中定義的每個Service(包括DNS Service它自己)都被分配了一個DNS名稱。默認的,Pod的DNS搜索列表中會包含Pod自己的命名空間和集群的默認域,下面我們用示例來解釋以下。
假設有一個名為foo
的Service,位于命名空間bar
中。運行在bar
命名空間中的Pod可以通過DNS查找foo
關鍵字來查找到這個服務,而運行在命名空間quux
中的Pod可以通過關鍵字foo.bar
來查找到這個服務。
下面的章節詳細的描述了支持的記錄(record)類型和layout。
普通(非headless)的Service都被分配了一個DNS記錄,該記錄的名稱格式為my-svc.my-namespace.svc.cluster.local
,通過該記錄可以解析出服務的集群IP。
Headless(沒有集群IP)的Service也被分配了一個DNS記錄,名稱格式為my-svc.my-namespace.svc.cluster.local
。與普通Service不同的是,它會解析出Service選擇的Pod的IP列表。
SRV records用于為命名端口服務,這些端口是headless或者普通Service的一部分。對于每個命名端口,SRV record的格式為:_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local
。對于普通服務來說,這會解析出端口號和CNAMEmy-svc.my-namespace.svc.cluster.local
。對于headless服務來說,這會解析出多個結果,一個是service后端的每個pod,一個是包含端口號,和格式為auto-generated-name.my-svc.my-namespace.svc.cluster.local
的pod的CNAME。
kube-dns的之前版本,使用了格式為my-svc.my-namespace.cluster.local
(svc這一層是后面加上的)的名稱。但這種格式不再被支持了。
pod會被分配一個DNS記錄,名稱格式為pod-ip-address.my-namespace.pod.cluster.local
。
比如,一個pod,它的IP地址為1.2.3.4
,命名空間為default
,DNS名稱為cluster.local,那么它的記錄就是:1-2-3-4.default.pod.cluster.local
。
當pod被創建時,它的hostname設置在Pod的metadata.name
中(寫yaml的時候應該很清楚這點)。
在v1.2版本中,用戶可以指定一個Pod注解,pod.beta.kubernetes.io/hostname
,用于指定Pod的hostname。這個Pod注解,一旦被指定,就將優先于Pod的名稱,成為pod的hostname。比如,一個Pod,其注解為pod.beta.kubernetes.io/hostname: my-pod-name
,那么該Pod的hostname會被設置為my-pod-name。
v1.2中還引入了一個beta特性,用戶指定Pod注解,pod.beta.kubernetes.io/subdomain
,來指定Pod的subdomain。比如,一個Pod,其hostname注解設置為“foo”
,subdomain注解為“bar”
,命名空間為“my-namespace”
,那么它最終的FQDN就是“foo.bar.my-namespace.svc.cluster.local”
。
在v1.3版本中,PodSpec有了hostname
和subdomain
字段,用于指定Pod的hostname和subdomain。它的優先級則高于上面提到的pod.beta.kubernetes.io/hostname
和pod.beta.kubernetes.io/subdomain
。
示例:
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 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 command: - sleep - "3600" name: busybox
如果一個headless service中,多個pod都在同一個命名空間里,并且subdomain名稱也相同,集群的KubeDNS還是會為每個Pod返回完整而合格的hostname。給定一個Pod,其hostname設置為busybox-1
,subdomain設置為default-subdomain
,同一個命名空間中的headless Service名為default-subdomain
,那么pod自己的FQDN就是“busybox-1.default-subdomain.my-namespace.svc.cluster.local”
。
在Kubernetes v1.2里,Endpoint對象還使用了注解endpoints.beta.kubernetes.io/hostnames-map
。它的值就是json格式中的map[string(IP)][endpoints.HostRecord]
, 比如 ‘{“10.245.1.6”:{HostName: “my-webserver”}}’。如果Endpoint是用于headless service的,就會為其創建一個格式為...svc的記錄。以json格式為例,如果Endpoint用于名為“bar”的headless service,其中一個Endpoint的ip為“10.245.1.6”,就會創建一個名為“my-webserver.bar.my-namespace.svc.cluster.local”
的記錄,查詢該記錄就會得到“10.245.1.6”。這個Endpoint注解一般不需要終端用戶來指定,但可以被內部服務控制器使用,來實現上面的特性。
在v1.3中,Endpoint對象可以為任何一個Endpoint指定hostname和IP。hostname字段會覆蓋endpoints.beta.kubernetes.io/hostnames-map
注解的值。
在v1.3中,以下注解被棄用了:pod.beta.kubernetes.io/hostname
,pod.beta.kubernetes.io/subdomain
, endpoints.beta.kubernetes.io/hostnames-map
。
創建一個名為busybox.yaml文件,使用下面的內容:
apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - image: busybox command: - sleep - "3600" imagePullPolicy: IfNotPresent name: busybox restartPolicy: Always
使用該文件創建pod:
kubectl create -f busybox.yaml
獲取pod狀態:
$ kubectl get pods busybox
你會看到:
NAME READY STATUS RESTARTS AGE busybox 1/1 Running 0 7m
一旦pod處于running
狀態時,可以使用exec nslookup
來查詢狀態:
$ kubectl exec -ti busybox -- nslookup kubernetes.default
你應該看到類似的結果:
Server: 10.0.0.10 Address 1: 10.0.0.10 Name: kubernetes.default Address 1: 10.0.0.1
如果出現上述結果,則說明DNS正常工作。
如果nslookup
失敗,檢查以下選項:
檢查pod的resolv.conf
文件。
$ kubectl exec busybox cat /etc/resolv.conf
確認搜索路徑和name sever被設置成類似下面的樣子(注意搜索路徑可能因云提供商不同而有所差異):
search default.svc.cluster.local svc.cluster.local cluster.local google.internal c.gce_project_id.internal nameserver 10.0.0.10 options ndots:5
如下的錯誤表明kube-dns add-on或者相關服務有問題:
$ kubectl exec -ti busybox -- nslookup kubernetes.default Server: 10.0.0.10 Address 1: 10.0.0.10 nslookup: can't resolve 'kubernetes.default'
或者
$ kubectl exec -ti busybox -- nslookup kubernetes.default Server: 10.0.0.10 Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local nslookup: can't resolve 'kubernetes.default'
使用kubectl get pods
命令來確認DNS pod是否正在運行。
$ kubectl get pods --namespace=kube-system -l k8s-app=kube-dns
應該會有如下的結果:
NAME READY STATUS RESTARTS AGE ... kube-dns-v19-ezo1y 3/3 Running 0 1h ...
如果沒有相關的pod運行,或者pod狀態為failed/completed,那么就說明你的環境下,沒有默認部署DNS add-on,你需要手動部署它。
使用kubectl log
命令來查看DNS守護程序的日志。
$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c kubedns $ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c dnsmasq $ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c healthz
如果有任何可疑的日志,每一行開頭的W,E,F字母分別表示警告、錯誤和故障。請搜索這些錯誤日志的條目,或者通過kubernetes issues頁面來報錯非預期的錯誤。
使用kubectl get service
命令來查看DNS服務是否已經啟動。
$ kubectl get svc --namespace=kube-system
你會看到:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE ... kube-dns 10.0.0.10 <none> 53/UDP,53/TCP 1h ...
該服務會默認地被創建,或者如果你手動創建了該服務,但是該服務卻并沒有在上述命令中出現,請查看 debugging services page頁面獲取更多信息。
可通過kubectl get endpoints
命令來確認是否暴露了DNS Endpoint。
$ kubectl get ep kube-dns --namespace=kube-system
你應該會看到下面的結果:
NAME ENDPOINTS AGE kube-dns 10.180.3.17:53,10.180.3.17:53 1h
如果沒有看到Endpoint,那么請查看debugging services page頁面。
若要查看更多的Kubernetes DNS示例,請在Kubernetes Github倉庫中查看cluster-dns examples。
運行的Kubernetes DNS pod包含3個容器——kubedns、dnsmasq和一個叫做healthz的健康檢查容器。kubedns進程監視Kubernetes master上Service和Endpoint的改變,并在內存中維護lookup 結構用于服務DNS請求。dnsmasq容器增加DNS緩存,從而提升性能。healthz容器提供一個單點的健康檢查Endpoint,檢查dnsmasq和kubedns的健康程度。
DNS pod以服務的形式暴露出來,它擁有一個靜態IP。一旦被創建,kubelet就使用--cluster-dns=10.0.0.10
標識,將DNS配置信息傳遞給每個容器。
DNS名稱也需要域。本地域是可以配置的,在kubelet中,使用--cluster-domain=<default local domain>
參數。
Kubernetes集群的DNS服務(基于SkyDNS庫)支持forward lookup(A recoreds),service lookup(SRV records)和反向IP地址查找(PTR recoreds)。
當運行pod時,kubelet會預先考慮集群的DNS服務,并在node本地的DNS設置中搜索路徑。如果node能夠解析DNS名稱,那么pod也可以做到。
如果你希望在pod中使用不同的DNS,那么你可以使用kubelet的--resolv-conf
參數。該設置意味著pod不會從node繼承DNS。設置該值為其他的文件路徑,意味著會使用該文件來配置DNS,而不是/etc/resolv.conf
。
Kubernetes安裝默認并不會使用集群的DNS配置來設置Kubernetes node的resolv.conf
文件,因為該進程依賴于發行版的配置。
Linux的libc有著3個DNS nameserver
和6個DNS搜索記錄的限制,Kubernetes需要消耗一個nameserver和3個搜索記錄。這意味著如果一個本地配置已經使用了3個nameserver或者使用了3個以上的搜索記錄,那么這些配置可能會丟失。有一個臨時方案,node可以運行dnsmasq
,它可以提供更多的nameserver選項,但不能提供更多的搜索選項。你也可以使用kubelet的--resolv-conf
選項。
如果你使用的是Alpine 3.3或更早的版本,DNS可能不能正常的工作,這是已知的問題。
感謝各位的閱讀!關于“Kubernetes DNS的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。