這篇文章主要講解了“怎么理解Kubernetes容器網(wǎng)絡(luò)模型”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么理解Kubernetes容器網(wǎng)絡(luò)模型”吧!
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、網(wǎng)站制作、梅列網(wǎng)絡(luò)推廣、重慶小程序開發(fā)、梅列網(wǎng)絡(luò)營(yíng)銷、梅列企業(yè)策劃、梅列品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供梅列建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:www.cdcxhl.com
計(jì)算、存儲(chǔ)和網(wǎng)絡(luò)是云時(shí)代的三大基礎(chǔ)服務(wù),作為新一代基礎(chǔ)架構(gòu)的 Kubernetes 也不例外。而這三者之中,網(wǎng)絡(luò)又是一個(gè)最難掌握和最容易出問題的服務(wù);本文通過對(duì)Kubernetes網(wǎng)絡(luò)流量模型進(jìn)行簡(jiǎn)單梳理,希望對(duì)初學(xué)者能夠提供一定思路。先看一下kubernetes 總體模型:
容器網(wǎng)絡(luò)中涉及的幾個(gè)地址:
Node Ip:物理機(jī)地址。
POD Ip:Kubernetes的最小部署單元是Pod,一個(gè)pod 可能包含一個(gè)或多個(gè)容器,簡(jiǎn)單來講容器沒有自己?jiǎn)为?dú)的地址,他們共享POD 的地址和端口區(qū)間。
ClusterIp:Service的Ip地址,外部網(wǎng)絡(luò)無法ping通改地址,因?yàn)樗翘摂MIP地址,沒有網(wǎng)絡(luò)設(shè)備為這個(gè)地址負(fù)責(zé),內(nèi)部實(shí)現(xiàn)是使用Iptables規(guī)則重新定向到其本地端口,再均衡到后端Pod;只有Kubernetes集群內(nèi)部訪問使用。
Public Ip :Service對(duì)象在Cluster IP range池中分配到的IP只能在內(nèi)部訪問,適合作為一個(gè)應(yīng)用程序內(nèi)部的層次。如果這個(gè)Service作為前端服務(wù),準(zhǔn)備為集群外的客戶提供業(yè)務(wù),我們就需要給這個(gè)服務(wù)提供公共IP。
容器網(wǎng)絡(luò)至少需要解決如下幾種場(chǎng)景的通信:①POD內(nèi)容器間通信
②同主機(jī)POD間 通信
③跨主機(jī)POD間 通信
④集群內(nèi)Service Cluster Ip和外部訪問下面具體介紹實(shí)現(xiàn)方式
Pod中的容器可以通過“l(fā)ocalhost”來互相通信,他們使用同一個(gè)網(wǎng)絡(luò)命名空間,對(duì)容器來說,hostname就是Pod的名稱。Pod中的所有容器共享同一個(gè)IP地址和端口空間,你需要為每個(gè)需要接收連接的容器分配不同的端口。也就是說,Pod中的應(yīng)用需要自己協(xié)調(diào)端口的使用。實(shí)驗(yàn)如下:首先我們創(chuàng)建一個(gè)Pod ,包含兩個(gè)容器,容器參數(shù)如下:
查看:
可以看到容器共享Pod 的地址,那么他們是否使用同一端口資源呢,我們可以簡(jiǎn)單實(shí)驗(yàn)一下:首先在容器1監(jiān)聽一個(gè)端口:
然后在容器2查看該端口是否被占用:
可見端口也是共享的;所以簡(jiǎn)單理解,可以把Pod看做一個(gè)小系統(tǒng),容器當(dāng)做系統(tǒng)中的不同進(jìn)程;內(nèi)部實(shí)現(xiàn):同POD 內(nèi)的容器實(shí)際共享同一個(gè)Namespace,因此使用相同的Ip和Port空間,該Namespace 是由一個(gè)叫Pause的小容器來實(shí)現(xiàn),每當(dāng)一個(gè)Pod被創(chuàng)建,那么首先創(chuàng)建一個(gè)pause容器, 之后這個(gè)pod里面的其他容器通過共享這個(gè)pause容器的網(wǎng)絡(luò)棧,實(shí)現(xiàn)外部pod進(jìn)行通信,因此對(duì)于同Pod里面的所有容器來說,他們看到的網(wǎng)絡(luò)視圖是一樣的,我們?cè)谌萜髦锌吹牡刂?,也就是Pod地址實(shí)際是Pause容器的IP地址??傮w模型如下:
我們?cè)趎ode 節(jié)點(diǎn)查看之前創(chuàng)建的POD,可以看到該pause容器 :
這種新創(chuàng)建的容器和已經(jīng)存在的一個(gè)容器(pause)共享一個(gè) Network Namespace(而不是和宿主機(jī)共享) 就是我們常說的container 模式。
每個(gè)節(jié)點(diǎn)上的每個(gè)Pod都有自己的namespace,同主機(jī)上的POD之間怎么通信呢?我們可以在兩個(gè)POD之間建立Vet Pair進(jìn)行通信,但如果有多個(gè)容器,兩兩建立Veth 就會(huì)非常麻煩,假如有N 個(gè)POD ,那么我們需要?jiǎng)?chuàng)建n(n-1)/2個(gè)Veth Pair,擴(kuò)展性非常差,如果我們可以將這些Veth Pair 連接到一個(gè)集中的轉(zhuǎn)發(fā)點(diǎn),由它來統(tǒng)一轉(zhuǎn)發(fā)就就會(huì)非常便捷,這個(gè)集中轉(zhuǎn)發(fā)點(diǎn)就是我們常說的bridge;如下所示(簡(jiǎn)單起見,這里把pause忽略):
仍然以我們的測(cè)試環(huán)境為例,創(chuàng)建pod1 和pod2地址分別為:10.244.1.16、10.244.1.18,位于node1 節(jié)點(diǎn)
查看節(jié)點(diǎn)下的namespace:
這兩個(gè)NS就是上述兩個(gè)POD 對(duì)應(yīng)的namespace,查詢對(duì)應(yīng)namespace 下的接口:
可以看到標(biāo)紅處的地址,實(shí)際就是POD 的ip地址;NS 和對(duì)應(yīng)的POD 地址都找到了,那么如何確認(rèn)這兩個(gè)ns 下的虛接口的另一端呢? 比較直觀的確認(rèn)方式為:上述接口如 3: eth0@if7,表示本端接口id 為3 ,對(duì)端接口id是7,我們看下default namespace(我們平時(shí)看的默認(rèn)都在default下) 的veth口:
7: veth4b416eb5@if3 ,該接口的id 正是我們要找的id 為7的接口 ,是veth pair的另一端;
簡(jiǎn)單來看,對(duì)于網(wǎng)絡(luò)上兩個(gè)端點(diǎn)之間的互通無非兩種方案,一種是underlay 直接互通,那么就需要雙方有彼此的路由信息并且該路由信息在underlay的路徑上存在,一種是overlay 方案,通過隧道實(shí)現(xiàn)互通,underlay 層面保證主機(jī)可達(dá)即可,前者代表方案有 Calico(direct模式)和Macvlan,后者有Overlay,OVS,F(xiàn)lannel和Weave。我們?nèi)〈硇缘腇lannel 和calico 插件進(jìn)行介紹;
2.3.1 Flannel
總體通信流程如下:
通信過程
2.3.1.1地址分配
flanneld第一次啟動(dòng)時(shí),從 etcd 獲取配置的 Pod 網(wǎng)段信息,為本節(jié)點(diǎn)分配一個(gè)未使用的地址段,然后創(chuàng)建 flannedl.1 網(wǎng)絡(luò)接口(也可能是其它名稱,如 flannel1 等),flannel 將分配給自己的 Pod 網(wǎng)段信息寫入 /run/flannel/docker 文件(不同k8s版本文件名存在差異),docker 后續(xù)使用這個(gè)文件中的環(huán)境變量設(shè)置 docker0 網(wǎng)橋,從而使這個(gè)地址段為本節(jié)點(diǎn)的所有;
查看flannel 為docker 分配的地址段:
表示該節(jié)點(diǎn)創(chuàng)建的POD 地址都從10.244.1.1/24中分配,比如node1 節(jié)點(diǎn)的如下2個(gè)pod。
2.3.1.2路由下發(fā)
每臺(tái)主機(jī)上,flannel 運(yùn)行一個(gè)daemon 進(jìn)程叫flanneld,它可以在內(nèi)核中創(chuàng)建路由表,查看node1節(jié)點(diǎn)的路由表如下:
可以看到node2 節(jié)點(diǎn)的路由match 10.244.2.0 一行規(guī)則,出接口為flannel.1 口(接口名flannel后數(shù)字可能不一樣) flannel.1 是flanneld程序創(chuàng)建的一個(gè)隧道口;這里有一個(gè)問題,就是如何判斷隧道打到那里呢,很顯然,flannld存儲(chǔ)了類似容器-物理節(jié)點(diǎn)之間的映射關(guān)系,這種信息存放在etcd里面,flannld進(jìn)程通過讀取etcd中的映射關(guān)系信息,決定隧道外層封裝。
2.3.1.3數(shù)據(jù)面封裝
Flannel 知道外層封裝地址后,對(duì)報(bào)文進(jìn)行封裝,源采用自己的物理ip 地址,目的采用對(duì)端的,vxlan 外層的udp port 8472(如果是UDP封裝使用8285作為默認(rèn)目的端口,下文會(huì)提到),對(duì)端只需監(jiān)控port 即可,當(dāng)改端口收到報(bào)文后將報(bào)文送到flannedld 進(jìn)程,進(jìn)程將報(bào)文送到flanned 接口接封裝,然后查詢本地路由表:
可以看到目的地址為cni0 ;Flannel功能內(nèi)部支持三種不同后端實(shí)現(xiàn),分別是:
Host-gw:需要兩臺(tái)host 在同一網(wǎng)段,不支持跨網(wǎng),因此不適合大規(guī)模部署
UDP:不建議使用,除非內(nèi)核不支持vxlan 或者debugg時(shí)候使用,當(dāng)前也已經(jīng)廢棄;
Vxlan : vxlan 封裝,flannel 使用 vxlan 技術(shù)為各節(jié)點(diǎn)創(chuàng)建一個(gè)可以互通的 Pod 網(wǎng)絡(luò),使用的端口為 UDP 8472(需要開放該端口,如公有云 AWS 等)。
我們?cè)趎ode 節(jié)點(diǎn)進(jìn)行抓包驗(yàn)證一下:
(注:因?yàn)樵趌inux 環(huán)境中,F(xiàn)lannel的vxlan 封裝中UDP 目的port 是 8472 ,標(biāo)準(zhǔn)Vxlan 報(bào)文的識(shí)別依據(jù)是目的端口4789,因此需要手動(dòng)指定按照vxlan 來解析,否則無法識(shí)別內(nèi)層信息)
2.3.2 CalicoCalico支持3種路由模式:
Direct: 路由轉(zhuǎn)發(fā),報(bào)文不做封裝;
Ip-In-Ip:Calico 默認(rèn)的路由模式,數(shù)據(jù)面采用ipip封裝;
Vxlan:vxlan 封裝;
這里主要介紹Direct模式,采用軟路由建立BGP 宣告容器網(wǎng)段,使得全網(wǎng)所有的Node和網(wǎng)絡(luò)設(shè)備都有到彼此的路由的信息,然后直接通過underlay 轉(zhuǎn)發(fā)。Calico實(shí)現(xiàn)的總體結(jié)構(gòu)如下:
組件包含:
Felix:Calico agent:運(yùn)行在每臺(tái)node上,為容器設(shè)置網(wǎng)絡(luò)信息:IP,路由規(guī)則,iptable規(guī)則等BIRD:
BGP Client:監(jiān)聽 Host上由 Felix 注入的路由信息,然后通過 BGP 協(xié)議廣播告訴其他Host節(jié)點(diǎn),從而實(shí)現(xiàn)網(wǎng)絡(luò)互通
BGP Route Reflector: BGP peer建立方式多樣,可以在node 之間兩兩建立bgp peer(默認(rèn)模式),和傳統(tǒng)ibgp peer問題類似,這會(huì)帶來n*(n-1)/2 的鄰居量,因此也可以自建RR 反射器(上圖中結(jié)構(gòu)),node 節(jié)點(diǎn)和RR 建立peer,當(dāng)然node也可以和Tor 建peer,詳細(xì)的組網(wǎng)討論可以參考官網(wǎng):
https://docs.projectcalico.org/reference/architecture/design/l3-interconnect-fabric
Calicoctl: calico命令行管理工具。
具體選擇哪種peer方式?jīng)]有固定標(biāo)準(zhǔn),要適配總體網(wǎng)絡(luò)規(guī)劃,只要最終保證容器網(wǎng)絡(luò)可正確發(fā)布到物理網(wǎng)絡(luò)即可;
數(shù)據(jù)通信的流程為:數(shù)據(jù)包先從veth設(shè)備對(duì)另一口發(fā)出,到達(dá)宿主機(jī)上的Cali開頭的虛擬網(wǎng)卡上,到達(dá)這一頭也就到達(dá)了宿主機(jī)上的網(wǎng)絡(luò)協(xié)議棧,然后查詢路由表轉(zhuǎn)發(fā);因?yàn)楸緳C(jī)通過bird 和RR 建立bgp 鄰居關(guān)系,會(huì)將本地的容器地址發(fā)送到RR 從而反射到網(wǎng)絡(luò)其它節(jié)點(diǎn),同樣,其它節(jié)點(diǎn)的網(wǎng)絡(luò)地址也會(huì)傳送到本地,然后由Felix 進(jìn)程進(jìn)行管理并下發(fā)到路由表中,報(bào)文匹配路由規(guī)則后正常進(jìn)行轉(zhuǎn)發(fā)即可(實(shí)際還有復(fù)雜的iptables 規(guī)則,這里不做展開)
下面通過簡(jiǎn)單實(shí)驗(yàn)學(xué)習(xí)下:
具體安裝過程不再討論,可參考官網(wǎng):https://www.projectcalico.org/進(jìn)行安裝部署;
Node節(jié)點(diǎn)bgp配置如下:
為了簡(jiǎn)化實(shí)驗(yàn),我們?cè)賳⒂靡慌_(tái)機(jī)器運(yùn)行FRR 來充當(dāng)RR(關(guān)于Frr參考官網(wǎng)https://frrouting.org/) ,RR配置如下:
這樣所有節(jié)點(diǎn)都和RR 建立了bgp 鄰居,通過如下方式檢查鄰居狀態(tài):
我們新建兩個(gè)pod ,分別位于兩個(gè)node節(jié)點(diǎn):
默認(rèn)情況下,當(dāng)網(wǎng)絡(luò)中出現(xiàn)第一個(gè)容器,calico會(huì)為容器分配一段子網(wǎng)(子網(wǎng)掩碼/26),后續(xù)出現(xiàn)該節(jié)點(diǎn)上的pod都從這個(gè)子網(wǎng)中分配ip地址,這樣做的好處是能夠縮減節(jié)點(diǎn)上的路由表的規(guī)模.進(jìn)入容器查看路由我們發(fā)現(xiàn)網(wǎng)關(guān)地址為169.254.1.1
實(shí)際上在calico 網(wǎng)絡(luò)中,容器網(wǎng)關(guān)始終是169.254.1.1,該地址在實(shí)際網(wǎng)絡(luò)中不存在的,是直接進(jìn)行的ARP 代理(ee:ee:ee:ee:ee:ee),我們?cè)趧?chuàng)建Pod的時(shí)候系統(tǒng)會(huì)在對(duì)應(yīng)的node 上新增一個(gè)cali開頭的虛擬網(wǎng)卡,它就是veth Pair的另一端(本端是容器本地eth0口),它的mac 就是上面的169.254.1.1 對(duì)應(yīng)的mac地址
此時(shí)的報(bào)文已經(jīng)進(jìn)入default namespace ,這里開始查看路由表:
其中192.168.23.128/26 是node2上的地址空間,該路由由node2 節(jié)點(diǎn)bird發(fā)送到RR,RR 反射到node1節(jié)點(diǎn)的bird ,然后由felix來進(jìn)行管理和下發(fā)到路由表中,我們可以在node1節(jié)點(diǎn)抓包進(jìn)一步確認(rèn):
同時(shí)因?yàn)閏alico 的代理方式,使得同node的不同POD通信也比較特殊,它也是通過三層轉(zhuǎn)發(fā)來實(shí)現(xiàn),比如node2 節(jié)點(diǎn)的2個(gè)地址,在路由表中都是/32位存在,下一跳接口為veth-pair的一端,另一端就是對(duì)應(yīng)的pod內(nèi)接口;
這和flannel 經(jīng)過bridge 方式實(shí)現(xiàn)是不一樣的;
2.3.3 總結(jié)
這里我們從網(wǎng)絡(luò)角度對(duì)flannel 和calico 進(jìn)行簡(jiǎn)單對(duì)比:
總體來看,對(duì)性能敏感、策略需求較高時(shí)偏向于Calio方案,否則的話,采用Flannel會(huì)是更好的選擇;
Serice 和外部通信場(chǎng)景實(shí)現(xiàn)涉及較多iptables 轉(zhuǎn)發(fā)原理,限于篇幅這里不再展開,簡(jiǎn)單介紹如下:
Pod與service通信: Pod間可以直接通過IP地址通信,但前提是Pod知道對(duì)方的IP。在 Kubernetes集群中,Pod可能會(huì)頻繁地銷毀和創(chuàng)建,也就是說Pod的IP 不是固定的。為了解決這個(gè)問題,Service提供了訪問Pod的抽象層。 無論后端的Pod如何變化,Service都作為穩(wěn)定的前端對(duì)外提供服務(wù)。 同時(shí),Service還提供了高可用和負(fù)載均衡功能,Service負(fù)責(zé)將請(qǐng)求轉(zhuǎn) 給正確的Pod;
外部通信:無論是Pod的IP還是Service的Cluster IP,它們只能在Kubernetes集群中可見,對(duì)集群之外的世界,這些IP都是私有的Kubernetes提供了兩種方式讓外界能夠與Pod通信:
NodePort:Service通過Cluster節(jié)點(diǎn)的靜態(tài)端口對(duì)外提供服務(wù), 外部可以通過:訪問Service。
LoadBalancer:Service利用cloud provider提供的load balancer對(duì)外提供服務(wù),cloud provider負(fù)責(zé)將load balancer 的流量導(dǎo)向Service。目前支持的cloud provider有GCP、AWS、 Azur等。
感謝各位的閱讀,以上就是“怎么理解Kubernetes容器網(wǎng)絡(luò)模型”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)怎么理解Kubernetes容器網(wǎng)絡(luò)模型這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!