對(duì)于新安裝的 Kubernetes憔儿,經(jīng)常出現(xiàn)的一個(gè)問題是 Service
沒有正常工作泪勒。如果您已經(jīng)運(yùn)行了 Deployment
并創(chuàng)建了一個(gè) Service
,但是當(dāng)您嘗試訪問它時(shí)沒有得到響應(yīng),希望這份文檔能幫助您找出問題所在违寞。
先來熟悉下Service工作邏輯:
為了完成本次演練的目的,我們先運(yùn)行幾個(gè) Pod
偶房。
$ kubectl run hostnames --image=k8s.gcr.io/serve_hostname \
確認(rèn)您的 Pods
是運(yùn)行狀態(tài):
$ kubectl get pods -l app=hostnames
問題1:Service 存在嗎趁曼?
細(xì)心的讀者會(huì)注意到我們還沒有真正創(chuàng)建一個(gè) Service
- 其實(shí)這是我們有意的。這是一個(gè)有時(shí)會(huì)被遺忘的步驟蝴悉,也是第一件要檢查的事情彰阴。
那么,如果我試圖訪問一個(gè)不存在的 Service
拍冠,會(huì)發(fā)生什么呢尿这?假設(shè)您有另一個(gè) Pod
,想通過名稱使用這個(gè) Service
庆杜,您將得到如下內(nèi)容:
u@pod$ wget -O- hostnames
因此射众,首先要檢查的是 Service
是否確實(shí)存在:
$ kubectl get svc hostnames
我們已經(jīng)有一個(gè)罪魁禍?zhǔn)琢耍屛覀儊韯?chuàng)建 Service
晃财。就像前面一樣叨橱,這里的內(nèi)容僅僅是為了步驟的執(zhí)行 - 在這里您可以使用自己的 Service
細(xì)節(jié)。
$ kubectl expose deployment hostnames --port=80 --target-port=9376
再查詢一遍断盛,確定一下:
$ kubectl get svc hostnames
與前面相同罗洗,這與您使用 YAML 啟動(dòng)的 Service
一樣:
apiVersion: v1
現(xiàn)在您可以確認(rèn) Service
存在。
問題2:Service 是否通過 DNS 工作钢猛?
從相同 Namespace
下的 Pod
中運(yùn)行:
u@pod$ nslookup hostnames
如果失敗伙菜,那么您的 Pod
和 Service
可能位于不同的 Namespace
中,請(qǐng)嘗試使用限定命名空間的名稱:
u@pod$ nslookup hostnames.default
如果成功命迈,那么需要調(diào)整您的應(yīng)用贩绕,使用跨命名空間的名稱去訪問服務(wù)火的,或者,在相同的 Namespace
中運(yùn)行應(yīng)用和 Service
淑倾。如果仍然失敗馏鹤,請(qǐng)嘗試一個(gè)完全限定的名稱:
u@pod$ nslookup hostnames.default.svc.cluster.local
注意這里的后綴:”default.svc.cluster.local”〗慷撸”default” 是我們正在操作的 Namespace
湃累。”svc” 表示這是一個(gè) Service
迂尝⊥衍裕”cluster.local” 是您的集群域,在您自己的集群中可能會(huì)有所不同垄开。
您也可以在集群中的 Node 上嘗試此操作:
注意: 10.0.0.10 是我的 DNS
Service
琴许,您的可能不同)
u@node$ nslookup hostnames.default.svc.cluster.local 10.0.0.10
如果您能夠使用完全限定的名稱查找,但不能使用相對(duì)名稱溉躲,則需要檢查 /etc/resolv.conf
文件是否正確榜田。
u@pod$ cat /etc/resolv.conf
nameserver
行必須指示您的集群的 DNS Service
,它通過 --cluster-dns
標(biāo)志傳遞到 kubelet
锻梳。
search
行必須包含一個(gè)適當(dāng)?shù)暮缶Y箭券,以便查找 Service
名稱。在本例中疑枯,它在本地 Namespace
(default.svc.cluster.local
)辩块、所有 Namespace
中的 Service
(svc.cluster.local
)以及集群(cluster.local
)中查找服務(wù)。根據(jù)您自己的安裝情況荆永,可能會(huì)有額外的記錄(最多 6 條)废亭。集群后綴通過 --cluster-domain
標(biāo)志傳遞給 kubelet
。本文檔中具钥,我們假定它是 “cluster.local”豆村,但是您的可能不同,這種情況下骂删,您應(yīng)該在上面的所有命令中更改它掌动。
options
行必須設(shè)置足夠高的 ndots
,以便 DNS 客戶端庫(kù)考慮搜索路徑宁玫。在默認(rèn)情況下粗恢,Kubernetes 將這個(gè)值設(shè)置為 5,這個(gè)值足夠高欧瘪,足以覆蓋它生成的所有 DNS 名稱适滓。
問題3:DNS 是否可以解析默認(rèn)服務(wù)?
如果上面仍然失敗 - DNS 查找不到您需要的 Service
- 我們可以后退一步,看看還有什么不起作用凭迹。Kubernetes 主 Service
應(yīng)該一直是工作的:
u@pod$ nslookup kubernetes.default
如果失敗,您可能需要轉(zhuǎn)到這個(gè)文檔的 kube-proxy 部分苦囱,或者甚至回到文檔的頂部重新開始嗅绸,但不是調(diào)試您自己的 Service
,而是調(diào)試 DNS撕彤。
問題4:Service 能夠通過 IP 訪問么鱼鸠?
假設(shè)我們可以確認(rèn) DNS 工作正常,那么接下來要測(cè)試的是您的 Service
是否工作正常羹铅。從集群中的一個(gè)節(jié)點(diǎn)蚀狰,訪問 Service
的 IP(從上面的 kubectl get
命令獲取)职员。
u@node$ curl 10.0.1.175:80
如果 Service
是正常的麻蹋,您應(yīng)該得到正確的響應(yīng)。如果沒有焊切,有很多可能出錯(cuò)的地方扮授,請(qǐng)繼續(xù)。
問題5:Service 是對(duì)的嗎专肪?
這聽起來可能很愚蠢刹勃,但您應(yīng)該加倍甚至三倍檢查 Service
是否正確,并且與您的 Pod
匹配嚎尤。查看 Service
并驗(yàn)證它:
$ kubectl get service hostnames -o json
spec.ports[]
中描述的是您想要嘗試訪問的端口嗎荔仁?targetPort
對(duì)您的 Pod
來說正確嗎(許多 Pod
選擇使用與 Service
不同的端口)?如果您想把它變成一個(gè)數(shù)字端口芽死,那么它是一個(gè)數(shù)字(9376)還是字符串 “9376”乏梁?如果您想把它當(dāng)作一個(gè)指定的端口,那么您的 Pod
是否公開了一個(gè)同名端口收奔?端口的 protocol
和 Pod
的一樣嗎掌呜?
問題6:Service 有端點(diǎn)嗎?
如果您已經(jīng)走到了這一步坪哄,我們假設(shè)您已經(jīng)確認(rèn) Service
存在质蕉,并能通過 DNS 解析。現(xiàn)在翩肌,讓我們檢查一下模暗,您運(yùn)行的 Pod
確實(shí)是由 Service
選擇的。
早些時(shí)候念祭,我們已經(jīng)看到 Pod
是運(yùn)行狀態(tài)兑宇。我們可以再檢查一下:
$ kubectl get pods -l app=hostnames
“AGE” 列表明這些 Pod
已經(jīng)啟動(dòng)一個(gè)小時(shí)了,這意味著它們運(yùn)行良好粱坤,而不是崩潰隶糕。
-l app=hostnames
參數(shù)是一個(gè)標(biāo)簽選擇器 - 就像我們的 Service
一樣瓷产。在 Kubernetes 系統(tǒng)中有一個(gè)控制循環(huán),它評(píng)估每個(gè) Service
的選擇器枚驻,并將結(jié)果保存到 Endpoints
對(duì)象中濒旦。
$ kubectl get endpoints hostnames
這證實(shí) endpoints 控制器已經(jīng)為您的 Service
找到了正確的 Pods
。如果 hostnames
行為空再登,則應(yīng)檢查 Service
的 spec.selector
字段尔邓,以及您實(shí)際想選擇的 Pods
的 metadata.labels
的值。常見的錯(cuò)誤是輸入錯(cuò)誤或其他錯(cuò)誤锉矢,例如 Service
想選擇 run=hostnames
梯嗽,但是 Deployment
指定的是 app=hostnames
。
問題8:Pod 正常工作嗎沽损?
到了這步灯节,我們知道您的 Service
存在并選擇了 Pods
。讓我們檢查一下 Pod
是否真的在工作 - 我們可以繞過 Service
機(jī)制缠俺,直接進(jìn)入 Pod
显晶。
注意: 這些命令使用的是
Pod
端口(9376),而不是Service
端口(80)壹士。
u@pod$ wget -qO- 10.244.0.5:9376
我們期望的是 Endpoints
列表中的每個(gè) Pod
返回自己的主機(jī)名磷雇。如果這沒有發(fā)生(或者您自己的 Pod
的正確行為沒有發(fā)生),您應(yīng)該調(diào)查發(fā)生了什么躏救。您會(huì)發(fā)現(xiàn) kubectl logs
這個(gè)時(shí)候非常有用唯笙,或者使用 kubectl exec
直接進(jìn)入到您的 Pod
,并從那里檢查服務(wù)盒使。
另一件要檢查的事情是崩掘,您的 Pod 沒有崩潰或正在重新啟動(dòng)。頻繁的重新啟動(dòng)可能會(huì)導(dǎo)致斷斷續(xù)續(xù)的連接問題少办。
$ kubectl get pods -l app=hostnames
如果重新啟動(dòng)計(jì)數(shù)很高苞慢,請(qǐng)查閱有關(guān)如何調(diào)試 pods 獲取更多信息。
問題9:kube-proxy 正常工作嗎英妓?
如果您到了這里挽放,那么 Service
正在運(yùn)行,也有 Endpoints
蔓纠,而您的 Pod
實(shí)際上也正在服務(wù)辑畦。在這一點(diǎn)上,整個(gè) Service
代理機(jī)制是否正常就是可疑的了腿倚。我們來確認(rèn)一下纯出,一部分一部分來。
確認(rèn) kube-proxy
正在您的 Nodes
上運(yùn)行。您應(yīng)該得到如下內(nèi)容:
u@node$ ps auxw | grep kube-proxy
下一步暂筝,確認(rèn)它并沒有出現(xiàn)明顯的失敗箩言,比如連接主節(jié)點(diǎn)失敗。要做到這一點(diǎn)焕襟,您必須查看日志分扎。訪問日志取決于您的 Node
操作系統(tǒng)。在某些操作系統(tǒng)是一個(gè)文件胧洒,如 /var/log/messages kube-proxy.log,而其他操作系統(tǒng)使用 journalctl
訪問日志墨状。您應(yīng)該看到類似的東西:
I1027 22:14:53.995134 5063 server.go:200] Running in resource-only container "/kube-proxy"
如果您看到有關(guān)無法連接主節(jié)點(diǎn)的錯(cuò)誤消息卫漫,則應(yīng)再次檢查節(jié)點(diǎn)配置和安裝步驟。
kube-proxy
無法正確運(yùn)行的可能原因之一是找不到所需的 conntrack
二進(jìn)制文件肾砂。在一些 Linux 系統(tǒng)上列赎,這也是可能發(fā)生的,這取決于您如何安裝集群镐确,例如包吝,您正在從頭開始安裝 Kubernetes。如果是這樣的話源葫,您需要手動(dòng)安裝 conntrack
包(例如诗越,在 Ubuntu 上使用 sudo apt install conntrack
),然后重試息堂。
問題10:kube-proxy 是否在寫 iptables 規(guī)則嚷狞?
kube-proxy
的主要職責(zé)之一是寫實(shí)現(xiàn) Services
的 iptables
規(guī)則。讓我們檢查一下這些規(guī)則是否已經(jīng)被寫好了荣堰。
kube-proxy 可以在 “userspace” 模式床未、 “iptables” 模式或者 “ipvs” 模式下運(yùn)行。如果您正在使用 “iptables” 模式或者 “ipvs” 模式振坚。您應(yīng)該看到以下情況之一薇搁。
Iptables
u@node$ iptables-save | grep hostnames
KUBE-SERVICES
中應(yīng)該有 1 條規(guī)則,KUBE-SVC-(hash)
中每個(gè)端點(diǎn)有 1 或 2 條規(guī)則(取決于 SessionAffinity
)渡八,每個(gè)端點(diǎn)中應(yīng)有 1 條 KUBE-SEP-(hash)
鏈啃洋。準(zhǔn)確的規(guī)則將根據(jù)您的確切配置(包括節(jié)點(diǎn)、端口組合以及負(fù)載均衡器設(shè)置)而有所不同呀狼。
IPVS
u@node$ ipvsadm -ln
IPVS 代理將為每個(gè)服務(wù)器地址(例如集群 IP裂允、外部 IP、節(jié)點(diǎn)端口 IP哥艇、負(fù)載均衡 IP等)創(chuàng)建虛擬服務(wù)器绝编,并為服務(wù)的端點(diǎn)創(chuàng)建一些相應(yīng)的真實(shí)服務(wù)器(如果有)。在這個(gè)例子中,服務(wù)器主機(jī)(10.0.1.175:80
)有 3 個(gè)端點(diǎn)(10.244.0.5:9376
, 10.244.0.6:9376
, 10.244.0.7:9376
)十饥,你會(huì)得到類似上面的結(jié)果窟勃。
如果走到這一步還沒解決!那只有燒香拜佛了逗堵!