一 Pod和SVC網(wǎng)絡(luò)1.1 實(shí)踐準(zhǔn)備及原理Docker實(shí)現(xiàn)了不同的網(wǎng)絡(luò)模式,Kubernetes也以一種不同的方式來解決這些網(wǎng)絡(luò)模式的挑戰(zhàn)。本完整實(shí)驗(yàn)深入剖析Kubernetes在網(wǎng)絡(luò)層是如何實(shí)現(xiàn)及工作的。
實(shí)驗(yàn)節(jié)點(diǎn)架構(gòu):
如上圖所示,Kubernetes的網(wǎng)絡(luò)模型要求每個(gè)Node上的容器都可以相互訪問。默認(rèn)的Docker網(wǎng)絡(luò)模型提供了一個(gè)IP地址段是172.17.0.0/16的docker0網(wǎng)橋。每個(gè)容器都會在這個(gè)子網(wǎng)內(nèi)獲得IP地址,并且將docker0網(wǎng)橋的IP地址(172.17.42.1)作為其默認(rèn)網(wǎng)關(guān)。需要注意的是,Docker宿主機(jī)外面的網(wǎng)絡(luò)不需要知道任何關(guān)于這個(gè)172.17.0.0/16的信息或者知道如何連接到其內(nèi)部,因?yàn)镈ocker的宿主機(jī)針對容器發(fā)出的數(shù)據(jù),在物理網(wǎng)卡地址后面都做了IP偽裝MASQUERADE(隱含NAT)。也就是說,在網(wǎng)絡(luò)上看到的任何容器數(shù)據(jù)流都來源于那臺Docker節(jié)點(diǎn)的物理IP地址。這里所說的網(wǎng)絡(luò)都指連接這些主機(jī)的物理網(wǎng)絡(luò)。
默認(rèn)的Docker網(wǎng)絡(luò)模型簡單便捷,但需要依賴端口映射的機(jī)制。在Kubernetes的網(wǎng)絡(luò)模型中,每臺主機(jī)上的docker0網(wǎng)橋都是可以被路由到的。也就是說,在部署了一個(gè)Pod時(shí),在同一個(gè)集群內(nèi),各主機(jī)都可以訪問其他主機(jī)上的Pod IP,并不需要在主機(jī)上做端口映射。
因此,可以在網(wǎng)絡(luò)層將Kubernetes的節(jié)點(diǎn)看作一個(gè)路由器,其網(wǎng)絡(luò)架構(gòu)如下:
二 Pod和SVC實(shí)驗(yàn)2.1 檢查環(huán)境[root@k8smaster02 ~]# ifconfig #node1上檢查網(wǎng)絡(luò)地址
由上可知,有一個(gè)docker0網(wǎng)橋和一個(gè)本地eth0地址的網(wǎng)絡(luò)端口。
2.2 創(chuàng)建RC[root@k8smaster01 study]# vi frontend-controller.yaml
1 apiVersion: v1 2 kind: ReplicationController 3 metadata: 4 name: frontend 5 labels: 6 name: frontend 7 spec: 8 replicas: 1 9 selector: 10 name: frontend 11 template: 12 metadata: 13 labels: 14 name: frontend 15 spec: 16 containers: 17 - name: php-redis 18 image: kubeguide/guestbook-php-frontend 19 env: 20 - name: GET_HOSTS_FROM 21 value: env 22 ports: 23 - containerPort: 80 24 hostPort: 80 [root@k8smaster01 study]# kubectl create -f frontend-controller.yaml
2.3 再次檢查網(wǎng)絡(luò)[root@k8smaster01 study]# kubectl get pods -o wide
Kubernetes為這個(gè)Pod找了一個(gè)主機(jī)172.24.8.71(k8smaster01) 來運(yùn)行它。另外,這個(gè)Pod獲得了一個(gè)在k8smaster01的docker0網(wǎng)橋上的IP地址。
[root@k8smaster01 study]# docker ps #k8smaster01上查看正在運(yùn)行的容器
第2個(gè)運(yùn)行的是一個(gè)google_containers/pause:latest的鏡像,而且這個(gè)容器已經(jīng)做了端口映射。
[root@k8smaster01 study]# docker inspect c6578085541b | grep NetworkMode #查看容器的網(wǎng)絡(luò)模型
"NetworkMode": "default",
[root@k8smaster01 study]# docker inspect da8251102c93 | grep NetworkMode
"NetworkMode": "container:c6578085541b6f47ab624134d0ed0be352b30b42379493a71a8fc913d829989c",
解釋:第1個(gè)容器是運(yùn)行了“google_containers/pause:latest”鏡像的容器,它使用了Docker默認(rèn)的網(wǎng)絡(luò)模型bridge(默認(rèn)網(wǎng)絡(luò)模型即為橋接);
第2個(gè)容器,也就是在RC/Pod中定義運(yùn)行的php-redis容器,使用了非默認(rèn)的網(wǎng)絡(luò)配置和映射容器的模型,指定了映射目標(biāo)容器為“google_containers/pause:latest”。
2.4 網(wǎng)絡(luò)模型釋義首先,一個(gè)Pod內(nèi)的所有容器都需要共用同一個(gè)IP地址,這就意味著一定要使用網(wǎng)絡(luò)的容器映射模式。然而,為什么不能只啟動第1個(gè)Pod中的容器,而將第2個(gè)Pod中的容器關(guān)聯(lián)到第1個(gè)容器呢?
Kubernetes主要基于如下兩個(gè)覺得考慮:
首先,如果在Pod內(nèi)有多個(gè)容器的話,則可能很難連接這些容器;
其次,后面的容器還要依賴第1個(gè)被關(guān)聯(lián)的容器,如果第2個(gè)容器關(guān)聯(lián)到第1個(gè)容器,且第1個(gè)容器異常的話,第2個(gè)容器也將異常。
啟動一個(gè)基礎(chǔ)容器,然后將Pod內(nèi)的所有容器都連接到基礎(chǔ)容器相對容易。因?yàn)橹恍枰獮榛A(chǔ)的這個(gè)Google_containers/pause容器執(zhí)行端口映射規(guī)則,這也簡化了端口映射的過程。所以啟動Pod后的網(wǎng)絡(luò)模型類似下圖:
實(shí)際上,應(yīng)用容器直接監(jiān)聽了這些端口,和google_containers/pause容器共享了同一個(gè)網(wǎng)絡(luò)堆棧。這就是為什么在Pod內(nèi)部實(shí)際容器的端口映射都顯示到google_containers/pause容器上了。
[root@k8smaster01 study]# docker port c6578085541b #通過dockerport命令來檢驗(yàn)端口轉(zhuǎn)發(fā)
80/tcp -> 0.0.0.0:80
綜上所述,google_containers/pause容器實(shí)際上只是負(fù)責(zé)接管這個(gè)Pod的Endpoint。
2.5 發(fā)布SVCService允許我們在多個(gè)Pod之間抽象一些服務(wù),而且服務(wù)可以通過提供在同一個(gè)Service的多個(gè)Pod之間的負(fù)載均衡機(jī)制來支持水平擴(kuò)展。
[root@k8smaster01 study]# vi frontend-service.yaml
1 apiVersion: v1 2 kind: Service 3 metadata: 4 name: frontend 5 labels: 6 name: frontend 7 spec: 8 ports: 9 - port: 80 10 selector: 11 name: frontend [root@k8smaster01 study]# kubectl create -f frontend-service.yaml
[root@k8smaster01 study]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.254.176.53 <none> 80/TCP 45s
釋義:如上可知Kubernetes集群已經(jīng)為這個(gè)服務(wù)分配了一個(gè)虛擬IP地址10.254.176.53,這個(gè)IP地址是在Kubernetes的Portal Network中分配的。 而這個(gè)Portal Network的地址范圍是我們在Kubmaster上啟動API服務(wù)進(jìn)程時(shí),使用--service-cluster-ip-range=xx命令行參數(shù)指定:
[root@k8smaster01 study]# cat /etc/systemd/system/kube-apiserver.service | grep 10.254
--service-cluster-ip-range=10.254.0.0/16 \
注意:這個(gè)IP段可以是任何段,只要不和docker0或者物理網(wǎng)絡(luò)的子網(wǎng)沖突即可。選擇任意其他網(wǎng)段的原因是這個(gè)網(wǎng)段將不會在物理網(wǎng)絡(luò)和docker0網(wǎng)絡(luò)上進(jìn)行路由。這個(gè)Portal Network針對每一個(gè)Node都有局部的特殊性,實(shí)際上它存在的意義是讓容器的流量都指向默認(rèn)網(wǎng)關(guān)(也就是docker0網(wǎng)橋)。
2.6 確認(rèn)驗(yàn)證當(dāng)所有的Pod都運(yùn)行起來,Service將會把客戶端請求負(fù)載分發(fā)到包含“name=frontend”標(biāo)簽的所有Pod上。
注意:本實(shí)驗(yàn)更詳細(xì)的步驟參考:https://blog.csdn.net/qq_31136839/article/details/99778434。
|
|