幾張圖就把 Kubernetes Service 掰扯清楚了

在 Kubernetes 中 Service 主要有4種不同的類型,其中的 ClusterIP 是最基礎(chǔ)的,如下圖所示:

當(dāng)我們創(chuàng)建一個(gè) NodePort 的 Service 時(shí),它也會創(chuàng)建一個(gè) ClusterIP,而如果你創(chuàng)建一個(gè) LoadBalancer,它就會創(chuàng)建一個(gè) NodePort,然后創(chuàng)建一個(gè) ClusterIP
此外我們還需要明白 Service 是指向 pods 的,Service 不是直接指向 Deployments 或 ReplicaSets,而是直接使用 labels 標(biāo)簽指向 Pod,這種方式就提供了極大的靈活性,因?yàn)橥ㄟ^什么方式創(chuàng)建的 Pod 其實(shí)并不重要。接下來我們通過一個(gè)簡單的例子開始,我們用不同的 Service 類型來逐步擴(kuò)展,看看這些 Service 是如何建立的。
No Services
最開始我們沒有任何的 Services。

我們有兩個(gè)節(jié)點(diǎn),一個(gè) Pod,節(jié)點(diǎn)有外網(wǎng)(4.4.4.1、4.4.4.2)和內(nèi)網(wǎng)(1.1.1.1、1.1.1.2)的 IP 地址,pod-python 這個(gè) Pod 只有一個(gè)內(nèi)部的 IP 地址。

現(xiàn)在我們添加第二個(gè)名為 pod-nginx 的 Pod,它被調(diào)度在 node-1 節(jié)點(diǎn)上。在 Kubernetes 中,所有的 Pod 之間都可以通過 Pod 的 IP 進(jìn)行通信,不管它們運(yùn)行在哪個(gè)節(jié)點(diǎn)上。這意味著 pod-nginx 可以使用其內(nèi)部IP 1.1.1.3 來 ping 和連接 pod-python 這個(gè) Pod。

現(xiàn)在如果 pod-python 掛掉了重新創(chuàng)建了一個(gè)新的 pod-python 出來(本文不涉及如何管理和控制 pods),重新分配了一個(gè)新的 1.1.1.5 的 Pod IP 地址,這個(gè)時(shí)候 pod-nginx 就無法再達(dá)到 1.1.1.3 這個(gè)之前的地址了,為了防止這種情況發(fā)生,我們就需要?jiǎng)?chuàng)建一個(gè) Service 服務(wù)了!
ClusterIP

和上面同樣的場景,但是我們創(chuàng)建了一個(gè)名為 service-python 類型為 ClusterIP 的 Service 服務(wù),一個(gè) Service 并不像 Pod 那樣運(yùn)行在一個(gè)特定的節(jié)點(diǎn)上,這里我們可以假設(shè)一個(gè) Service 只是在整個(gè)集群內(nèi)部的內(nèi)存中可用就可以了。
pod-nginx 可以安全地連接到 1.1.10.1 這個(gè) ClusterIP 或直接通過 dns 名service-python 進(jìn)行通信,并被重定向到后面一個(gè)可用的 Pod 上去。

現(xiàn)在我們來稍微擴(kuò)展下這個(gè)示例,啟動3個(gè) python 實(shí)例,現(xiàn)在我們來顯示所有 Pod 和 Service 內(nèi)部 IP 地址的端口。
集群內(nèi)部的所有 Pods 都可以通過 http://1.1.10.1:3000 或者 http://service-python:3000 來訪問到后面的 python pods 的443端口。
service-python 這個(gè) Service ?是隨機(jī)或輪詢的方式來轉(zhuǎn)發(fā)請求的,這個(gè)就是 ClusterIP Service 的作用,它通過一個(gè)名稱和一個(gè) IP 讓集群內(nèi)部的 Pods 可用。
上圖中的 service-python 這個(gè) Service 可以用下面的 yaml 文件來創(chuàng)建:
apiVersion:?v1
kind:?Service
metadata:
??name:?service-python
spec:
??ports:
??-?port:?3000
????protocol:?TCP
????targetPort:?443
??selector:
????run:?pod-python
??type:?ClusterIP
創(chuàng)建后,可以用 kubectl get svc 命令來查看:

NodePort
現(xiàn)在我們想讓 ClusterIP Service 可以從集群外部進(jìn)行訪問,為此我們需要把它轉(zhuǎn)換成 NodePort 類型的 Service,在我們的例子中,我們只需要簡單修改上面的 service-python 這個(gè) Service 服務(wù)即可:
apiVersion:?v1
kind:?Service
metadata:
??name:?service-python
spec:
??ports:
??-?port:?3000
????protocol:?TCP
????targetPort:?443
????nodePort:?30080
??selector:
????run:?pod-python
??type:?NodePort
更新完成后,如下圖所示:

這意味著我們的內(nèi)部的 service-python 這個(gè) Service 現(xiàn)在也可以通過30080 端口從每個(gè)節(jié)點(diǎn)的內(nèi)部和外部 IP 地址進(jìn)行訪問了。

集群內(nèi)部的 Pod 也可以通過內(nèi)網(wǎng)節(jié)點(diǎn) IP 連接到 30080 端口。

運(yùn)行 kubectl get svc 命令來查看這個(gè) NodePort 的 Service,可以看到同樣有一個(gè) ClusterIP,只是類型和額外的節(jié)點(diǎn)端口不同。在內(nèi)部,NodePort 服務(wù)仍然像之前的 ClusterIP 服務(wù)一樣。

LoadBalancer
如果我們希望有一個(gè)單獨(dú)的 IP 地址,將請求分配給所有的外部節(jié)點(diǎn)IP(比如使用 round robin),我們就可以使用 LoadBalancer 服務(wù),所以它是建立在 NodePort 服務(wù)之上的。

一個(gè) LoadBalancer 服務(wù)創(chuàng)建了一個(gè) NodePort 服務(wù),NodePort 服務(wù)創(chuàng)建了一個(gè) ClusterIP 服務(wù)。我們也只需要將服務(wù)類型更改為 LoadBalancer 即可。
apiVersion:?v1
kind:?Service
metadata:
??name:?service-python
spec:
??ports:
??-?port:?3000
????protocol:?TCP
????targetPort:?443
????nodePort:?30080
??selector:
????run:?pod-python
??type:?LoadBalancer
LoadBalancer 服務(wù)所做的就是創(chuàng)建一個(gè) NodePort 服務(wù),此外,它還會向托管 Kubernetes 集群的提供商發(fā)送一條消息,要求設(shè)置一個(gè)指向所有外部節(jié)點(diǎn) IP 和特定 nodePort 端口的負(fù)載均衡器,當(dāng)然前提條件是要提供商支持。
現(xiàn)在運(yùn)行 kubectl get svc 可以看到新增了 external-IP 和 LoadBalancer 的類型。

LoadBalancer 服務(wù)仍然像和以前一樣在節(jié)點(diǎn)內(nèi)部和外部 IP 上打開 30080 端口。
ExternalName
最后是 ExternalName 服務(wù),這個(gè)服務(wù)和前面的幾種類型的服務(wù)有點(diǎn)分離。它創(chuàng)建一個(gè)內(nèi)部服務(wù),其端點(diǎn)指向一個(gè) DNS 名。
我們假設(shè) pod-nginx 運(yùn)行在 Kubernetes 集群中,但是 python api 服務(wù)在集群外部。

這里 pod-nginx 這個(gè) Pod 可以直接通過 http://remote.server.url.com 連接到外部的 python api 服務(wù)上去,但是如果我們考慮到以后某個(gè)時(shí)間節(jié)點(diǎn)希望把這個(gè) python api 服務(wù)集成到 Kubernetes 集群中去,還不希望去更改連接的地址,這個(gè)時(shí)候我們就可以創(chuàng)建一個(gè) ExternalName 類型的 Service 服務(wù)了。

對應(yīng)的 YAML 資源清單文件如下所示:
kind:?Service
apiVersion:?v1
metadata:
??name:?service-python
spec:
??ports:
??-?port:?3000
????protocol:?TCP
????targetPort:?443
??type:?ExternalName
??externalName:?remote.server.url.com
現(xiàn)在 pod-nginx 就可以很方便地通過 http://service-python:3000 進(jìn)行通信了,就像使用 ClusterIP 服務(wù)一樣,當(dāng)我們決定將 python api 這個(gè)服務(wù)也遷移到我們 Kubernetes 集群中時(shí),我們只需要將服務(wù)改為 ClusterIP 服務(wù),并設(shè)置正確的標(biāo)簽即可,其他都不需要更改了。

到這里我們就用幾張圖將 Kubernetes 中的 Service 解釋得明明白白清清楚楚真真切切了~~~
原文鏈接:https://medium.com/swlh/kubernetes-services-simply-visually-explained-2d84e58d70e5
訓(xùn)練營推薦


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