Kubernetes之无头服务(headless)
己經(jīng)看到如何使用服務(wù)來提供穩(wěn)定的ip地址,從而允許客戶端連接到支持服務(wù)的每個pod (或其他端點)。到服務(wù)的每個連接都被轉(zhuǎn)發(fā)到一個隨機選擇的pod上。但是如果客戶端需要鏈接到所有的pod呢?如果后端的pod都需要連接到所有其他 pod呢?通過服務(wù)連接顯然不是這樣的,那是怎樣的呢?
要讓客戶端連接到所有pod,需要找出每個pod的IP。一種選擇是讓客戶端調(diào)用Kubernetes API服務(wù)器并通過API調(diào)用獲取pod及其IP地址列表,但由于應(yīng)始終努力保持應(yīng)用程序與Kubernetes無關(guān),因此使用API服務(wù)器并不理想。
幸運的是,Kubernetes允許客戶通過DNS查找發(fā)現(xiàn)pod IP。通常,當(dāng)執(zhí)行服務(wù)的DNS查找時,DNS服務(wù)器會返回單個IP——服務(wù)的集群IP。但是,如果告訴 Kubernetes,不需要為服務(wù)提供集群IP (通過在服務(wù)spec中將clusterIP字段設(shè)置為None來完成此操作),則DNS服務(wù)器將返回podIP而不是單個服務(wù)IP。
DNS服務(wù)器不會返回單個DNS A記錄,而是會為該服務(wù)返回多個A記錄,每個記錄指向當(dāng)時支持該服務(wù)的單個pod的IP??蛻舳艘虼丝梢宰鲆粋€簡單的DNS A 記錄查找并獲取屬于該服務(wù)一部分的所有pod的IP。客戶端可以使用該信息連接到其中的一個、多個或全部。
1.創(chuàng)建headless服務(wù)
將服務(wù)spec中的clusterIP字段設(shè)置為None會使服務(wù)成為headless服務(wù),因為Kubernetes不會為其分配集群IP,客戶端可通過該IP將其連接到支持它的pod。
現(xiàn)在將創(chuàng)建一個名為kubia-headless的headless服務(wù)。以下代碼清單顯示了它的定義。
apiVersion: v1
kind: Service
metadata:
name: kubia-headless
spec:
clusterIP: None #這使得服務(wù)成為headless
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
在使用kubectlcreate創(chuàng)建服務(wù)之后,可以通過kubectlget和kubectl describe來查看服務(wù),你會發(fā)現(xiàn)它沒有集群IP,并且它的后端包含與pod選擇器匹配的(部分)pod。“部分”是因為pod包含就緒探針,所以只有準(zhǔn)備就緒的pod會被列出作為服務(wù)的后端文件來確保至少有兩個pod報告己準(zhǔn)備就緒。
2.通過DNS發(fā)現(xiàn)pod
準(zhǔn)備好pod后,現(xiàn)在可以嘗試執(zhí)行DNS查找以查看是否獲得了實際的podIP。需要從其中一個pod中執(zhí)行查找。不幸的是,kubia容器鏡像不包含nslookup(或dig)二進制文件,因此無法使它執(zhí)行DNS查找。
所要做的就是在集群中運行的一個pod中執(zhí)行DNS查詢。為什么不尋找一個包含所需二進制文件的鏡像來運行新的容器?要執(zhí)行與DNS相關(guān)的操作,可以使用DockerHub上提供的tutum/dnsutils容器鏡像,它包含nslookup和dig二進制文件。要運行pod,可以完成創(chuàng)建YAML清單并將其傳給kubectlcreate的整個過程。但是太煩瑣了,對嗎?幸運的是,有一個更快的方法。
不通過YAML文件運行pod
使用kubectlrun是這次只想創(chuàng)建一個pod,不需要創(chuàng)建一個ReplicationController來管理pod??梢赃@樣做:
$ kubectl run dnsutils --image=tutum/dnsutils --generator=run-pod/v1 --command -- sleep infinity pod "dnsutils" created
訣竅在--generator=run-pod/vl選項中,該選項讓kubectl直接創(chuàng)建pod,而不需要通過ReplicationController之類的資源來創(chuàng)建。
理解headless服務(wù)的DNSA記錄解析
使用新創(chuàng)建的pod執(zhí)行DNS查找:
$ kubectl exec dnsutils nslookup kubia-headless Name: kubia-headless.default.svc.cluster.local Address: 10.108.1.4 Name: kubia-headless.default.svc.cluster.local Address: 10.108.2.5
DNS服務(wù)器為kubia-headless.default.svc.cluster.localFQDN返回兩個不同的IP。這些是報告準(zhǔn)備就緒的兩個pod的IP??梢酝ㄟ^使用kubectlgetpods-owide列出pod來確認(rèn)此問題,該清單顯示了pod的IP。
這與常規(guī)(非headless服務(wù))服務(wù)返回的DNS不同,比如kubia服務(wù),返回的IP是服務(wù)的集群IP。(這里就不做代碼演示了)
盡管headless服務(wù)看起來可能與常規(guī)服務(wù)不同,但在客戶的視角上它們并無不同。即使使用headless服務(wù),客戶也可以通過連接到服務(wù)的DNS名稱來連接到pod上,就像使用常規(guī)服務(wù)一樣。但是對于headless服務(wù),由于DNS返回了pod的IP,客戶端直接連接到該pod,而不是通過服務(wù)代理。
注意:headless服務(wù)仍然提供跨pod的負(fù)載平衡,但是通過DNS輪詢機制不是
3.發(fā)現(xiàn)所有的pod--包括未就緒的pod
只有準(zhǔn)備就緒的pod能夠作為服務(wù)的后端。但有時希望即使pod沒有準(zhǔn)備就緒,服務(wù)發(fā)現(xiàn)機制也能夠發(fā)現(xiàn)所有匹配服務(wù)標(biāo)簽選擇器的pod。
幸運的是,不必通過查詢KubernetesAPI服務(wù)器,可以使用DNS查找機制來查找那些未準(zhǔn)備好的pod。要告訴Kubernetes無論pod的準(zhǔn)備狀態(tài)如何,希望將所有pod添加到服務(wù)中。必須將以下注解添加到服務(wù)中:
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
警告: 就像說的那樣,注解名稱表明了這是一個alpha功能。KubernetesService API己經(jīng)支持一個名為publishNotReadyAddresses的新服務(wù)規(guī)范字段,它將替換tolerate-unready-endpoints注解。在Kubernetes1.9.0版本中,這個字段還沒有實現(xiàn)(這個注解決定了未準(zhǔn)備好的endpoints是否在DNS的記錄中)。檢查文檔以查看是否己更改。
作者:小家電維修
相見有時,后會無期。
總結(jié)
以上是生活随笔為你收集整理的Kubernetes之无头服务(headless)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 向量、矩阵的范数/模(norm)
- 下一篇: 电信网关怎样连接路由器如何连接网关上的路