計算機間的信息和數據在網絡中必須按照數據傳輸的順序、數據的格式內容等方面的約定或規則進行傳輸,這種約定或規則稱作協議。各類網絡協議分佈於不一樣的網絡分層中,網絡分層分爲OSI七層模型和TCP/IP五層模型兩種。TCP/IP五層模型分別是應用層、傳輸層、網絡層、鏈路層和物理層,與OSI七層模型的區別是在TCP/IP五層模型中,OSI七層模型中的會話層、表示層、應用層統一被稱爲應用層。計算機網絡數據是按照協議規範採用分層的結構由發送端自上而下流動到物理層,再從物理層在網絡分層中自下而上的流動到接收端的應用層,完成數據通訊。網絡分層中,高層級的應用模塊僅利用低層級應用模塊提供的接口和功能,低層級應用模塊也僅是使用高層級應用模塊傳來的參數響應相關的操做,層次間每一個應用模塊都是可被能提供相同功能的應用模塊替代。 node
Kubernetes的網絡通訊也遵照TCP/IP五層模型的定義,經過不一樣的資源對象在相應的層級提供相應的模塊功能。Kubernetes資源對象在相應的網絡層級與傳統網絡設備模塊的對照表如表12-2所示。nginx
表 12-2 設備模塊對照表web
網絡分層 | 設備模塊 | Kubernetes資源對象 |
---|---|---|
應用層 | F五、Haproxy、Nginx | Ingress |
傳輸層 | 四層交換、路由 | Service |
網絡層 | 路由器、三層交換機 | flannel、calico、Pod(容器間通訊) |
鏈路層 | 網橋、二層交換機、網卡 | vnet、bridge |
物理層 | 中繼器、集線器、網線 |
Kubernetes是基於容器的管理系統,其使用Docker容器版本的Pod是由多個Docker容器組成的,爲方便理解Pod的網絡通訊方式,先了解下Docker自有的網絡模式,Docker容器有以下4種常見的網絡模式。算法
主機模式(host),容器與宿主機共享網絡命名空間(netns,network namespace),在容器中能夠查看到宿主機的全部網卡,能夠經過訪問宿主機IP,訪問到容器中運行應用的全部網絡端口。主機模式下網絡傳輸效率最高,但宿主機上已經存在的網絡端口將沒法被該模式下的容器使用。docker
無網卡模式(none),容器中只有環回(lo,Lookback)接口,運行在容器內的應用僅能使用環回接口實現網絡層的數據傳輸。shell
橋接模式(bridge), 容器內會被建立veth(Virtual ETHernet)設備並接入宿主機的橋接網絡,經過宿主機的橋接網絡,可與宿主機及宿主機中接入同一橋設備的其它容器進行通訊。apache
Docker容器間能夠經過IP網絡、容器名解析、joined容器三種方式實現通訊。IP網絡是在網絡聯通的基礎上經過IP地址實現互訪通訊。容器名解析是在網絡聯通的基礎上,由Docker內嵌的DNS進行容器名解析實現的互訪通訊方式,同一主機橋接模式的容器間須要啓動時使用「--link」參數啓用這一功能。joined 容器方式可使多個容器共享一個網絡命名空間,多個容器間經過環回接口直接通訊,這種方式容器間傳輸效率最高。後端
Kubernetes的Pod網絡通訊包括以下幾種方式:api
Pod是由多個Docker容器以joined容器方式構成的,多個容器共享由名爲pause的容器建立的網絡命名空間(netns,network namespace),容器內的進程彼此間經過環回(lo,Lookback)接口實現數據通訊。環回接口不依賴鏈路層和物理層協議,一旦傳輸層檢測到目的端地址是環回接口地址時,數據報文離開網絡層時會把它返回給本身。這種模式傳輸效率較高,很是適用於容器間進程的頻繁通訊。緩存
每一個Pod擁有惟一的IP和彼此隔離的網絡命名空間,在Linux系統中,Pod間跨網絡命名空間的數據通訊是經過Veth(Virtual ETHernet)設備實現的。Veth設備工做在鏈路層,老是成對出現也被稱爲Veth-pair設備。在網絡插件是Flannel的虛擬網絡結構中,Flannel被Kubernetes觸發並收到相關Pod參數時,會爲Pod建立Veth設備並分配IP,Veth設備一端是Pod的eth0接口,一端是Node節點中網絡空間名爲default的Veth虛擬接口。Flannel在初始安裝時,建立了網橋設備cni0,網絡空間default中被建立的Veth虛擬接口都被加入到網橋設備cni0中,至關於全部的Pod都被接入到這個虛擬交換機中,在同一虛擬交換機中的Pod實現了鏈路層的互聯並進行網絡通訊。工做原理如圖12-5所示。
圖 12-5 同節點的Pod間數據通訊
可用以下命令查看當前節點服務器的網絡命名空間和網橋信息。
# 查看系統中的網絡命名空間 ls /var/run/docker/netns # 查看每一個命名空間的網絡接口信息 nsenter --net=/var/run/docker/netns/default ifconfig -a # 查看網橋信息 brctl show
Flannel是由CoreOS使用Go語言開發的,Flannel實現了一種基於Vxlan(Virtual eXtensible Local Area Network)封裝的覆蓋網絡(overlay network),其將TCP數據封裝在另外一種網絡包中進行路由轉發和通訊。
Vxlan協議是一種隧道協議,基於UDP協議傳輸數據。Flannel的Vxlan虛擬網絡是比較簡單的,在每一個Kubernetes節點上只有1個Vxlan網絡和1個Vxlan接口(默認爲flannel.1)。Vxlan接口叫作VTEP(Vxlan tunnel endpoint)設備,VTEP設備的MAC地址由Flannel被Kubernetes觸發並同步緩存在本地的fdb(forwarding database)中。Kubernetes集羣中整個flannel網絡默認配置網段爲10.244.0.0/16,每一個節點都分配了惟一的24位的子網,Flannel在Kubernetes集羣中相似一個傳統網絡中的三層交換設備,每一個Node節點的橋設備經過VTEP設備接口互聯,使運行在不一樣Node節點中不一樣子網IP的容器實現跨主機互通。
可用以下命令查看當前節點服務器的arp信息。
# 本地橋 arp表 bridge fdb bridge fdb show dev flannel.1
Kubernetes 經過副本集控制器可以動態地建立和銷燬 Pod,每一個Pod可被動態的建立或銷燬於集羣中的任意一個節點,所以Pod IP也將隨之變化。Flannel構建的虛擬網絡使得集羣中的每一個Pod在網絡上已經實現互聯互通,因爲Pod IP變化的不肯定性,使得運行在Pod中的應用服務沒法被其餘應用固定訪問。爲使動態變化IP的Pod應用能夠被其餘應用訪問,Kubernetes經過標籤篩選的形式對具備相同指定標籤的一組Pod定義爲Service,每一個Service的Pod成員信息經過端點控制器在etcd中保存及更新。Service爲應用Pod提供了固定的虛擬IP和端口用以提供固定的訪問,讓集羣內其餘Pod應用能夠訪問這個服務。
Service 是 「4層」(TCP/UDP over IP)概念,其構建了一個有固定ClusterIP(集羣虛擬IP,Virtual IP) 和 Port 的虛擬集羣,每一個節點上運行的kube-proxy 進程經過主節點的接口服務監控資源對象Service和 Endpoints內Pod列表的變化,kube-proxy 默認使用iptables 代理模式,其經過對每一個Service配置對應的iptables 規則捕獲到達該 Service 的 ClusterIP和 Port 的請求,當捕獲到請求時,會將訪問請求按比例隨機分配給Service 中的一個Pod,若是被選擇的Pod沒有響應(依賴「readiness probes」的配置),則自動重試另外一個Pod。Service訪問邏輯如圖12-6 所示。
圖 12-6 Service訪問邏輯
kube-proxy 在集羣中的每一個節點都會配置集羣中全部Service 的iptables規則,iptables規則設置以下。
Service的負載均衡是由iptables的statistic模塊實現的,statistic模塊的random模式能夠將被設定目標的請求數在參數probability設定的機率範圍內分配,參數設定的值在0.0至1.0之間,當參數設定值爲0.5時,表示該目標有50%機率分配到請求。kube-proxy 遍歷Service中的Pod列表時,按照公式1.0/float64(n-i)爲每一個Pod計算機率值,n是Pod的總數量,i是當前計數。當有3個Pod時,計算值分別爲33%、50%、100%,3個Pod的總流量負載分配分別爲33%,35%,32%。
Service也支持會話保持功能,是應用iptables的recent模塊實現的。recent容許動態的建立源地址列表,並對源地址列表中匹配的來源IP執行相應的Iptables動做。recent模塊參數如表12-3所示。
表 12-3 模塊參數
參數 | 參數說明 |
---|---|
set | 把匹配動做的源IP添加到地址列表 |
name | 源地址列表名稱 |
mask | 源地址列表中IP的掩碼 |
rsource | 設置源地址列中保存數據包的源IP地址 |
rcheck | 檢查當前數據包源IP是否在源地址列表中 |
seconds | 與rcheck配合使用,設置對指定時間內更新的IP地址與數據包源IP進行匹配檢查,單位爲秒 |
reap | 與seconds配合使用,將清除源地址列表中指定時間內沒被更新的IP地址 |
配置Service 會話保持,只需在Service 中作以下配置便可。
spec: sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 10800
kube-proxy 實現Service的方法有四種,分別是userspace、iptables、ipvs和winuserspace,iptables只是默認配置,因kube-proxy的其餘將在其餘章節進行深刻探討。
Service 實現了Pod訪問的固定IP和端口,但ClusterIP並非綁定在網絡設備上的,其只是kube-proxy 進程設定的iptables本地監聽轉發規則,只能在K8集羣內的節點上進行訪問。Kubernetes系統同默認提供兩種方式實現Pod應用在集羣外發布服務,一種是基於資源對象Pod的hostPort和hostNetwork方式,另外一種是基於資源對象Service的NodePort、LoadBalancer和externalIPs方式。
hostPort方式至關於建立Docker容器時使用"-p"參數提供容器的端口映射,只能經過運行容器的節點IP進行訪問,其屬於資源對象Pod的運行方式,不支持多個Pod的Service負載均衡等功能。資源配置以下所示。
apiVersion: v1 kind: Pod metadata: name: apps labels: app: web spec: containers: - name: apps image: apache ports: - containerPort: 80 hostPort: 8080
hostNetwork方式至關於建立Docker容器時以主機模式爲網絡模式的Pod運行方式,該方式運行的容器與所在節點共享網絡命名空間,屬於資源對象Pod的運行方式,不支持多個Pod的Service負載均衡等功能。資源配置以下所示。
apiVersion: v1 kind: Pod metadata: name: nginx-web namespace: default labels: run: nginx-web spec: hostNetwork: true containers: - name: nginx-web image: nginx ports: - containerPort: 80
NodePort方式是在集羣中每一個節點監聽固定端口(nodePort)的訪問,外部用戶對任意節點IP和nodePort的訪問,都會被Service負載到後端的Pod,全局nodePort的默承認用範圍爲30000-32767。NodePort方式訪問邏輯如圖12-7所示。
圖 12-7 NodePort方式訪問邏輯
kube-proxy 初始化時,會對NodePort方式的Service 在Iptables nat表中建立規則鏈 KUBE-NODEPORTS,用於監聽本機nodePort的請求。
外部請求訪問節點IP和端口(nodePort)後,被Iptables 規則KUBE-NODEPORTS 匹配後跳轉給對應的KUBE-SVC規則鏈執行負載均衡等操做。
選定Pod後,請求被轉發到選定的Pod IP 和目標端口(targetPod)。
NodePort方式資源配置以下所示。
apiVersion: v1 kind: Service metadata: name: nginx-web namespace: default labels: run: nginx-web spec: type: NodePort ports: - nodePort: 31804 port: 8080 protocol: TCP targetPort: 8080
LoadBalancer 方式是一種經過Kubernetes自動對外發布的解決方案,該方案是將外部負載均衡器做爲上層負載,在建立Service時自動與外部負載均衡器互動,完成對Kubernetes Service負載均衡建立的操做,將Service按照外部負載均衡器的負載策略對外提供服務。該方案依賴外部負載均衡器的支持,一般如阿里雲、騰訊雲的容器雲都提供了這個方案的支持。資源配置以下所示。
apiVersion: v1 kind: Service metadata: name: nginx-web namespace: default labels: run: nginx-web spec: type: LoadBalancer ports: - port: 8080 protocol: TCP targetPort: 8080
不一樣的外部負載均衡器須要有對應的負載均衡控制器(Loadbalancer Controller)。
負載均衡控制器實時經過接口服務監聽資源對象Service的變化。
LoadBalancer類型的Service被建立時,Kubernetes會爲該Service自動分配nodePort。
當監聽到LoadBalancer類型的Service 建立時,負載均衡控制器將觸發外部負載均衡器(LoadBalancer)建立外部VIP、分配外部IP或將現有節點IP綁定nodePort端口添加到外部負載均衡器的負載均衡池,完成負載均衡的配置。
當外部用戶訪問負載均衡器的外部VIP時,外部負載均衡器會將流量負載到Kubernetes節點或Kubernetes集羣中的Pod(視外部負載均衡器的功能而定)。
不能與NodePort方式同時使用。
External IPs方式提供了一種指定外部IP綁定Service端口的方法,該方法能夠指定節點內某幾個節點IP地址或綁定外部路由到節點網絡的非節點IP對外提供訪問。Kubernetes經過externalIPs參數將被指定的IP與Service 端口經過Iptables監聽,其使用與Service 一致的端口,相對NodePort方式配置更加簡單靈活。因爲是直接將Service端口綁定被路由的IP對外暴露服務,使用者須要對整個集羣對外服務的端口作好相應的規劃,避免端口衝突。資源配置以下所示。
spec: externalIPs: - 192.168.1.101 - 192.168.1.102 ports: - name: http port: 80 targetPort: 80 protocol: TCP - name: https port: 443 targetPort: 443 protocol: TCP
externalIPs設置的IP能夠爲集羣中現有的節點IP,也能夠是上層網絡設備路由過來的IP。kube-proxy 初始化時,會對externalIPs方式的Service 在Iptables nat表中建立規則鏈 KUBE-SERVICES,用於訪問到externalIPs列表中IP及Service port請求的監聽。
外部或本地訪問externalIPs列表中IP及port的請求被匹配後,跳轉給對應的KUBE-SVC規則鏈執行負載均衡等操做。
Kubernetes系統中,Pod的部署是隨機的,使用者也可經過不一樣的調度策略進行調整,Pod的調度策略一樣對Pod通訊存在必定的影響,相關的調度策略有以下兩種。
Kubernetes集羣中的Pod 是被隨機調度,並建立在集羣中的節點上的,在實際使用中,有時須要考慮節點資源的有效利用及不一樣應用間的訪問效率等因素,也須要對這種調度設置相關指望的策略。主要體如今節點與Pod間的關係、同Service下的Pod間關係、不一樣Service的Pod間關係這3個方面。節點與Pod間關係可使用「nodeAffinity」 在資源配置文件中設置,其能夠在設置Pod資源對象時,將Pod部署到具備指定標籤的集羣節點上。Pod間關係可經過「podAntiAffinity」的配置儘可能把同一Service下的Pod分配到不一樣的節點,提升自身的高可用性,也能夠把互相影響的不一樣Service的Pod分散到不一樣的集羣節點上。對於Pod間訪問比較頻繁的應用可使用「podAffinity」配置,儘可能把被配置的Pod部署到同一節點服務器上。
Service的流量調度策略(externalTrafficPolicy)有兩種Pod調度策略,分別是Cluster和Local。Cluster是默認調度策略,其會依據iptables的隨機負載算法,將用戶請求負載均衡分配給Pod,但該方式會隱藏客戶端的源IP。Local策略則會將請求只分配給請求節點IP的Pod,而不會轉發給其餘節點的Pod,這樣就保留了最初的源 IP 地址。但該方式不會對Service的Pod進行負載均衡,同時被訪問IP的節點上若是沒有該應用的Pod,則會報錯。Local策略僅適用於NodePort和LoadBalancer類型的Service。
Kubernetes中Service的Pod是經過Service實現Pod應用訪問的,在流量調度策略的Cluster調度策略下,對一個Service的訪問請求會被隨機分配到Service中的任意Pod,即使該Service與發出請求的Pod在同一節點有可提供服務的Pod,也不必定會被選中。在Kubernetes 計劃的1.16版本中增長了服務拓撲感知的流量管理功能,設計了新的Pod定位器(PodLocator)實現了服務的拓撲感知服務路由機制,使Pod總能優先使用「本地訪問」的策略找到最近的服務後端,這種拓撲感知服務使「本地訪問」具備更普遍的意義,包括節點主機、機架、網絡、機房等,這樣能夠有效的減小網絡延遲,提升訪問效率及安全性,更加節約成本。
Ingress 已經屬於七層範圍,其涵蓋的內容也較多,將會另起一章進行分析。