Kubernetes网络一年发展动态与未来趋势
Kubernetes網絡模型
談到Kubernetes的網絡模型,就不能不提它著名的“單Pod單IP”模型,即每個Pod都有一個獨立的IP,Pod內所有容器共享網絡namespace(同一個網絡協議棧和IP)。“單Pod單IP”網絡模型為我們勾勒了一個Kubernetes扁平網絡的藍圖,在這個網絡世界里:容器之間直接通信,不需要額外的NAT(網絡地址轉換);Node與容器之間,同樣不需要額外的NAT;在其他容器和容器自身看到的IP也一樣的。扁平化網絡的優點在于:沒有NAT的性能損耗,可追溯源地址進而為后面的網絡策略做鋪墊,易排錯等。總體而言,如果集群內要訪問Pod,走Service,至于集群外要訪問Pod,走的是Ingress。Service和Ingress是Kubernetes專門的抽象出來的和服務發現相關的概念,后面會做詳細討論。
類似于CRI之于Kubernetes的Runtime,Kubernetes使用CNI(Container Network Interface)作為Pod網絡配置的標準接口。需要注意的是,CNI并不支持Docker網絡,也就是說docker0網橋會被CNI的各類插件“視而不見”。
上圖描繪了當用戶在Kubernetes里創建了一個Pod后,CRI和CNI協同創建所有容器并為他們初始化網絡棧的全過程。
具體過程如下:當用戶在Kubernetes的Master那邊創建了一個Pod后,Kubelet觀察到新Pod的創建,于是首先調用CRI(后面的Runtime實現,比如:dockershim,containerd等)創建Pod內的若干個容器。在這些容器里面,第一個被創建的Pause容器是比較特殊的,這是Kubernetes系統“贈送”的容器,里面跑著一個功能十分簡單的Go語言程序,具體邏輯是一啟動就去select一個空的Go語言channel,自然就永遠阻塞在那里了。一個永遠阻塞而且沒有實際業務邏輯的pause容器到底有什么用呢?用處大了。我們知道容器的隔離功能利用的是Linux內核的namespace機制,而只要是一個進程,不管這個進程是否處于運行狀態(掛起亦可),它都能“占”著一個namespace。因此,每個Pod內的第一個系統容器Pause的作用就是為占用一個Linux的network namespace,而Pod內其他用戶容器通過加入到這個network namespace的方式來共享同一個network namespace。用戶容器和Pause容器之間的關系有點類似于寄居蟹和海螺的關系。
因此,Container Runtime創建Pod內所有容器時,調用的都是同一個命令:
$ docker run --net=none
意思是只創建一個network namespace,而不初始化網絡協議棧。如果這個時候通過nsenter方式進入到容器,會看到里面只有一個本地回環設備lo。那么容器的eth0是怎么創建出來的呢?答案是CNI。
CNI主要負責容器的網絡設備初始化工作。Kubelet目前支持兩個網絡驅動,分別是:kubenet和CNI。
Kubenet是一個歷史產物,即將廢棄,因此這里也不準備過多介紹。CNI有多個實現,官方自帶的插件就有p2p,bridge等,這些插件負責初始化Pause容器的網絡設備,也就是給eth0分配IP等,到時候Pod內其他容器就用這個IP與外界通信。Flanne,Calico這些第三方插件解決Pod之間的跨機通信問題。容器之間的跨機通信,可以通過bridge網絡或overlay網絡來完成。
上圖是一個bridge網絡的示意圖。Node1上Pod的網段是10.1.1.0/24,接的Linux網橋是10.1.1.1,Node2上Pod的網段是10.1.2.0/24,接的Linux網橋是10.1.2.1,接在同一個網橋上的Pod通過局域網廣播通信。我們發現,Node1上的路由表的第二條是: 10.1.1.0/24 dev cni0
意思是所有目的地址是本機上Pod的網絡包,都發到cni0這個Linux網橋去,進而廣播給Pod。
注意看第三條路由規則:
10.1.2.0/24 via 192.168.1.101
10.1.2.0/24是Node2上Pod的網段,192.168.1.101又恰好是Node2的IP。意思是,目的地址是10.1.2.0/24的網絡包,發到Node2上。
這時候我們觀察Node2上面的第二條路由信息:
10.1.2.0/24 dev cni0
就會知道這個包會被接著發給Node2上的Linux網橋cni0,然后再廣播給目標Pod。回程報文同理走一條逆向的路徑。因此,我們可以得出一個小小的結論:bridge網絡本身不解決容器的跨機通信問題,需要顯式地書寫主機路由表,映射目標容器網段和主機IP的關系,集群內如果有N個主機,需要N-1條路由表項。
至于overlay網絡,它是構建在物理網絡之上的一個虛擬網絡,其中VXLAN是當前最主流的overlay標準。VXLAN就是用UDP包頭封裝二層幀,即所謂的MAC in UDP。
上圖即一個典型overlay網絡的拓撲圖。和bridge網路類似,Pod同樣接在Linux網橋上,目的地址是本機Pod的網絡包同樣發給Linux網橋cni0。不一樣的是,目的Pod在其他節點上的路由表規則,例如: 10.1.0.0/16 dev tun0
這次是直接發給本機的TAP設備tun0,而tun0就是overlay隧道網絡的入口。我們注意到,集群內所有機器都只需要這么一條路由表,而不需要像bridge網絡那樣,寫N-1條路由表項。那如何才能將網絡包正確地傳遞到目標主機的隧道口另一端呢?一般情況下,例如flannel的實現,會借助一個分布式的數據庫,用于記錄目的容器IP與所在主機的IP的映射關系,而且每個節點上都會運行一個agent,例如flanneld,會監聽在tun0上,進行封包和解包操作。例如:Node1上的容器發包給Node2上的容器,flanneld會在tun0處將一個目的地址是192.168.1.101:8472的UDP包頭(校驗和置成0)封裝到這個包的外層,然后接著主機網絡的東風順利到達Node2。監聽在Node2的tun0上的flanneld捕獲這個特殊的UDP包(檢驗和為0),知道這是一個overlay的封包,于是解開UDP包頭,將它發給本機的Linux網橋cni0,進而廣播給目的容器。
什么是CNI
CNI是Container Network Interface的縮寫,是容器網絡的標準化,試圖通過JSON來描述一個容器網絡配置。從上圖可以看出,CNI是Kubernetes與底層網絡插件之間的一個抽象層,為Kubernetes屏蔽了底層網絡實現的復雜度,同時也解耦了Kubernetes的具體網絡插件實現。
CNI主要有兩類接口,分別是在創建容器時調用的配置網絡接口:AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result,error)和刪除容器時調用的清理網絡接口:DelNetwork(net NetworkConfig, rt RuntimeConf)。
不論是配置網絡接口還是刪除網絡接口,都有兩個入參,分別是網絡配置和runtime配置。網絡配置很好理解,Rumtime配置則主要是容器運行時傳入的網絡namespace信息。符合CNI標準的默認/第三方網絡插件有:
其中CNI-Genie是一個開源的多網絡的容器解決方案,感興趣的讀者可以自行去Github上搜索。
下面我們將舉幾個CNI網絡插件的例子。
上圖是一個host-local + bridge插件組合的例子,在這么一個JSON文件中,我們定義了一個名為mynet的網絡,是一個bridge模型,而IP地址管理(ipam)使用的是host-local(在本地用一個文件記錄已經分配的容器IP地址)且可供分配的容器網段是10.10.0.0/16。至于Kubernetes如何使用它們?Kubelet和CNI約好了兩個默認的文件系統路徑,分別是/etc/cni/net.d用來存儲CNI配置文件和/opt/cni/bin目錄用來存放CNI插件的二進制文件,在我們這個例子中,至少要提前放好bridge和host-local這兩個插件的二進制,以及10-mynet.conf配置文件(叫什么名字隨意,Kubelet只解析*.conf文件)。由于主流的網絡插件都集成了bridge插件并提供了各自的ipam功能,因此在實際Kubernetes使用過程中我們并不需要操心上面過程,也無需做額外配置。
再來看一個最近Kubernetes V1.11版本合到社區主干的帶寬控制插件的使用方法。當我們書寫了以下Pod配置時:
Kubernetes就會自動為我們這個Pod分別限制上傳和下載的帶寬為最高10Mb/s。注意,由于這個特性較新,我們需要自己在/etc/cni/net.d目錄下寫一個配置文件,例如my-net.conf: {"type": "bandwidth", "capabilities": {"bandwidth": true}}
這個配置文件會告訴Kubelet去調用CNI的默認bandwidth插件,然后根據Pod annotation里面關于帶寬的ingress/egress值進行容器上行/下行帶寬的限制。當然,CNI插件最后調用的還是Linux tc工具。
Kubernetes Service機制
容器網絡模型講完后,我們再看下Kubernetes集群內訪問的Service機制。先從一個簡單的例子講起,客戶端訪問容器應用,最簡單的方式莫過于直接容器IP+端口了。但,簡單的生活總是暫時的。
當有多個后端實例,如何做到負載均衡?如何保持會話親和性?容器遷移,IP發生變化如何訪問?健康檢查怎么做?怎么通過域名訪問?
Kubernetes提供的解決方案是在客戶端和后端Pod之間引入一個抽象層:Service。什么是Kubernetes的Service呢?
Kubernetes的Service有時候也稱為Kubernetes的微服務,代表的是Kubernetes后端服務的入口,它注意包含服務的訪問IP(虛IP)和端口,因此工作在L4。既然Service只存儲服務入口信息,那如何關聯后端Pod呢?Service通過Label Selector選擇與之匹配的Pod。那么被Service選中的Pod,當它們Running且Ready后,Kubernetes的Endpoints Controller會生成一個新的Endpoints對象,記錄Pod的IP和端口,這就解決了前文提到的后端實例健康檢查問題。另外,Service的訪問IP和Endpoint/Pod IP都會在Kubernetes的DNS服務器里存儲域名和IP的映射關系,因此用戶可以在集群內通過域名的方式訪問Service和Pod。
Kubernetes Service的定義如下所示:
其中,spec.ClusterIP就是Service的訪問IP,俗稱虛IP,spec.ports[].port是Service的訪問端口,而與之對應的spec.ports[].targetPort是后端Pod的端口,Kubernetes內部會自動做一次映射。
Kubernetes Endpoints的定義如下所示:
其中,subsets[].addresses[].ip是后端Pod的IP,subsets[].ports是后端Pod的端口,與Service的targetPort對應。
下面我們來看下Kubernetes Service的工作原理。
如上圖所示,當用戶創建Service和對應后端Pod時,Endpoints Controller會觀察Pod的狀態變化,當Pod處于Running且Ready狀態時,Endpoints Controller會生成Endpoints對象。運行在每個節點上的Kube-proxy會觀察Service和Endpoints的更新,并調用其load balancer在主機上模塊刷新轉發規則。當前主流的load balancer實現有iptables和IPVS,iptables因為擴展性和性能不好,越來越多的廠商正開始使用IPVS模式。
Kubernetes Service有這么幾種類型:ClusterIP,NodePort和Load Balancer。其中,ClusterIP是默認類型,自動分配集群內部可以訪問的虛IP——Cluster IP。NodePort為Service在Kubernetes集群的每個Node上分配一個端口,即NodePort,集群內/外部可基于任何一個NodeIP:NodePort的形式來訪問Service。因此NodePort也成為“乞丐版”的Load Balancer,對于那些沒有打通容器網絡和主機網絡的用戶,NodePort成了他們從外部訪問Service的首選。LoadBalancer類型的Service需要Cloud Provider的支持,因為Service Controller會自動為之創建一個外部LB并配置安全組,Kubernetes原生支持的Cloud Provider就那么幾個:GCE,AWS。除了“外用”,Load Balancer還可以“內服”,即如果要在集群內訪問Load Balancer類型的Service,kube-proxy用iptables或ipvs實現了云服務提供商LB(一般都是L7的)的部分功能:L4轉發,安全組規則等。
Kubernetes Service創建好了,那么如何使用,即如何進行服務發現呢?Kubernetes提供了兩種方式:環境變量和域名。
環境變量即Kubelet為每個Pod注入所有Service的環境變量信息,形如:
這種方式的缺點是:容易環境變量洪泛,Docker啟動參數過長影響性能甚至直接導致容器啟動失敗。
域名的方式是,假設Service(my-svc)在namespace(my-ns)中,暴露名為http的TCP端口,那么在Kubernetes的DNS服務器會生成兩種記錄,分別是A記錄:域名(my-svc.my-ns)到Cluster IP的映射和SRV記錄,例如:_http._tcp.my-svc.my-ns到一個http端口號的映射。我們會在下文Kube-dns一節做更詳細的介紹。
前文提到,Service的load balancer模塊有iptables和IPVS實現。下面會一一進行分析。
Iptables是用戶空間應用程序,通過配置Netfilter規則表( Xtables )來構建linux內核防火墻。下面就是Kubernetes利用iptables的DNAT模塊,實現了Service入口地址(10.20.30.40:80)到Pod實際地址(172.17.0.2:8080)的轉換。
IPVS是LVS的負載均衡模塊,亦基于netfilter,但比iptables性能更高,具備更好的可擴展性。
如上所示,一旦創建一個Service和Endpoints,Kube-proxy的IPVS模式會做三樣事情:
好了,都說IPVS性能要好于iptables,無圖無真相,上實測數據!
通過上圖我們可以發現,IPVS刷新規則的時延明顯要低iptables幾個數量級。
從上圖我們又可以發現,IPVS相較于iptables,端到端的吞吐率和平均時延均由不小的優化。注意,這是端到端的數據,包含了底層容器網絡的RTT,還能有30%左右的性能提升。
上圖是iptables和IPVS在資源消耗方面的對比,孰優孰劣,不言而喻。
最后,問個開放性的問題。如何從集群外訪問Kubernetes Service?
前文已經提到,可以使用NodePort類型的Service,但這種“屌絲”的做法除了要求集群內Node有對外訪問IP外,還有一些已知的性能問題(具體請參考本公眾號另外一篇干貨文章《記一次Docker/Kubernetes上無法解釋的超時原因探尋之旅》)。使用LoadBalancer類型的Service?它又要求在特定的云服務上跑Kubernetes。而且Service只提供L4負載均衡功能,而沒有L7功能,一些高級的,L7的轉發功能,比如:基于HTTP header,cookie,URL的轉發就做不了。
在Kubernetes中,L7的轉發功能,集群外訪問Service,這些功能是專門交給Ingress的。
Kubernetes Ingress
何謂Ingress?從字面意思解讀,就是“入站流量”。Kubernetes的Ingress資源對象是指授權入站連接到達集群內服務的規則集合。具體含義看下面這個例子便一目了然:通常情況下,Service和Pod僅可在集群內部網絡中通過IP地址訪問。所有到達邊界路由的流量或被丟棄或被轉發到其他地方。Ingress就是在邊界路由處開個口子,放你進來。因此,Ingress是建立在Service之上的L7訪問入口,它支持通過URL的方式將Service暴露到Kubernetes集群外;支持自定義Service的訪問策略;提供按域名訪問的虛擬主機功能;支持TLS通信。
在上面這個例子,Ingress就可以基于客戶端請求的URL來做流量分發,轉發給不同的Service后端。
我們來看下Ingress資源對象的API定義:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress spec: tls: - secretName: testsecret backend: serviceName: testsvc servicePort: 80
把上面這個Ingress對象創建起來后,kubectl get一把,會看到:
其中,ADDRESS即Ingress的訪問入口地址,由Ingress Controller分配,一般是Ingress的底層實現LB的IP地址,例如:Ingress,GCE LB,F5等;BACKEND是Ingress對接的后端Kubernetes Service IP + Port;RULE是自定義的訪問策略,主要是基于URL的轉發策略,若為空,則訪問ADDRESS的所有流量都轉發給BACKEND。
下面給出一個Ingress的rules不為空的例子。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test spec: rules: - host: foo.bar.com http:paths:- path: /foobackend:serviceName: s1servicePort: 80- path: /barbackend:serviceName: s2servicePort: 80
這個例子和上面那個最明顯的區別在于,rules定義了path分別為/foo和/bar的分發規則,分別轉發給s1:80和s2:80。Kubectl get一把一目了然:
需要注意的是,當底層LB準備就緒時,Ingress Controller把LB的IP填充到ADDRESS字段。而在我們的例子中,這個LB顯然還未ready。
Ingress是一個非常“極客”和需要DIY的產物,Kubernetes只負責提供一個API定義,具體的Ingress Controller需要用戶自己實現!官方倒是提供了Nginx和GCE的Ingress Controller示例供開發者參考。實現一個Ingress Controller的大致框架無非是,List/Watch Kubernetes的Service,Endpoints,Ingress對象,刷新外部LB的規則和配置。
這還不算,如果想要通過域名訪問Ingress?需要用戶自己配置域名和Ingress IP的映射關系,比如:host文件,自己的DNS(不是kube-dns)。下文會講到,“高冷”的kube-dns只會負責集群內的域名解析,集群外的一概不管。
Kubernetes DNS
Kubernetes DNS說,剛剛誰念叨起本宮了?一言以蔽之,Kubernetes的DNS,就是用來解析Kubernetes集群內的Pod和Service域名的,而且一般是供Pod內的進程使用的!血統高貴,一般不給外人使用。那可能會有人好奇問一句,Pod到底怎么使用Kubernetes DNS呢?原來,kubelet配置--cluster-dns把DNS的靜態IP傳遞給每個容器。Kubernetes DNS一般通過插件方式部署到Kubernetes上,并為之綁定一個Service,而Service的Cluster IP往往是固定的。Kubernetes DNS目前有兩個實現,分別是kube-dns和CoreDNS。
對于Service,Kubernetes DNS服務器會生成兩類DNS記錄,分別是:A記錄和SRV記錄。而A記錄又對普通Service和headless Service有所區別。普通Service的A記錄是:{service name}.{service namespace}.svc.cluster.local -> Cluster IP的映射關系。后面域名后面一串子域名:svc.cluster.local是Kubelet通過--cluster-domain配置的偽域名。
Headless Service的A記錄是:{service name}.{service namespace}.svc.cluster.local -> 后端Pod IP列表的映射關系。
至于SRV記錄,則是按照一個約定俗稱的規定:
_{port name}._{port protocol}.{service name}.{service namespace}.svc.cluster.local –> Service Port
實現了對服務端口的查詢。
對于Pod,A記錄是:
{pod-ip}.{pod namespace}.pod.cluster.local -> Pod IP
如果Pod IP是1.2.3.4,上面的{pod-ip}即1-2-3-4。Pod的A記錄其實沒什么用,因為如果都知道Pod IP了,還用查DNS嗎?
如果在Pod Spec指定hostname和subdomain,那么Kubernetes DNS會額外生成Pod的A記錄就是:
{hostname}.{subdomain}.{pod namespace}.pod.cluster.local –> Pod IP
同樣,后面那一串子域名pod.cluster.local是kubelet配置的偽域名。
讓我們看下kube-dns的架構吧。
如上圖所示,kube-dns是“三進程”架構。
- kubedns:List/Watch Kubernetes Service和Endpoints變化。接入SkyDNS,在內存中維護DNS記錄,是dnsmasq的上游。
- dnsmasq:DNS配置工具,監聽53端口,為集群提供DNS查詢服務。提供DNS緩存,降低kubedns壓力。
- exechealthz:健康檢查,檢查kube-dns和dnsmasq的健康。
需要注意的是,dnsmasq是個C++寫的一個小程序,有內存泄露的“老毛病”。
雖然kube-dns血統純正,而且早早地進入到Kubernetes的“后宮”,也早有“名分”,但近來CoreDNS卻獨得Kubernetes SIG Network的圣寵。CoreDNS是個DNS服務器,原生支持Kubernetes,而且居然還是一個CNCF的項目!
與kube-dns的三進程架構不同,CoreDNS就一個進程,運維起來更加簡單。而且采用Go語言編寫,內存安全,高性能。值得稱道的是,CoreDNS采用的是“插件鏈”架構,每個插件掛載一個DNS功能,保證了功能的靈活、易擴展。盡管資歷不深,但卻“集萬千寵愛于一身”,自然是有兩把刷子的。
值得一提的是,以上性能測試數據是不帶cache情況下取得的,明顯要高于kube-dns。那么為什么建議使用CoreDNS呢?Kubernetes官方已經將CoreDNS扶正,成為了默認模式。除了性能好以外,還有什么其他優勢嗎?CoreDNS修復了kube-dns的一些“令人討厭”的“老生常談”的問題:
- dns#55 - Allow custom DNS entries for kube-dns
- dns#116 - Missing ‘A’ records for headless service with pods sharing hostname
- dns#131 - ExternalName not using stubDomains settings
- dns#167 - Enable round robin A/AAAA records
- dns#190 - kube-dns cannot run as non-root user
- dns#232 - Use pod’s name instead of pod’s hostname in DNS SRV records
同時,還有一些吸引人的特性:
- Zone transfers - list all records, or copy records to another server
- Namespace and label filtering - expose a limited set of services
- Adjustable TTL - adjust up/down default service record TTL
- Negative Caching - By default caches negative responses (e.g. NXDOMAIN)
其中,原生支持基于namespace隔離和過濾Service和Pod的DNS記錄這一條特性,在多租戶場景下格外有用。
Network Policy
Kubernetes默認情況下,底層網絡是“全連通”的。但如果我們需要實現以下愿景:即,只允許訪問default namespace的Label是app=web的Pod,default namespace的其他Pod都不允許外面訪問。這個隔離需求在多租戶的場景下十分普遍。Kubernetes的解決方案是Network Policy。
Network Policy說白了就是基于Pod源IP(所以Kubernetes網絡不能隨隨便便做SNAT啊!)的訪問控制列表,限制Pod的進/出流量,用白名單實現了一個訪問控制列表(ACL)。Network Policy作為Pod網絡隔離的一層抽象,允許使用Label Selector,namespace selector,端口,CIDR這四個維度限制Pod的流量進出。和Ingress一副德行的是,Kubernetes對Netowrk Policy還是只提供了API定義,不負責實現!
一般情況下,Policy Controller是由網絡插件提供的。支持Network Policy的網絡插件有Calico,Cilium,Weave Net,Kube-router,Romana。需要注意的是,flannel不在這個名單之列,似乎又找到了一個不用flannel的理由?
讓我們先來見識幾個默認網絡策略:
注:{}代表允許所有,[]代表拒絕所有。
如果要拒絕所有流量進入呢?比如,場景長這樣:
那么Network Policy對象應該定義成:
如果要限制部分流量進入呢?比如,場景長這樣:
那么Network Policy對象應該定義成:
如果只允許特定namespace的Pod流量進入呢?比如,場景長這樣:
那么Network Policy對象應該定義成:
如果限制流量從指定端口進入呢?比如,場景長這樣:
那么,Network Policy對象應該定義成:
未來工作
最后,暢想下Kubernetes網絡后面的發展趨勢。首先,kubenet會被廢棄。Kubenet本來就是一個特定時期的產物,那時候CNI尚未成熟,讓Kubernetes親自去干底層網絡這種“苦差事”,盡管Kubernetes是有一萬個不愿意,但如果完全沒有網絡連通方案,又會讓用戶詬病“過于高冷”,“易用性差”,甚至會讓那時的競爭對手docker swarm有機可圖。因此Kubernetes寫了一個簡單的網絡插件,即kubenet,一個bridge模型的容器連通性解決方案。但隨著CNI強勢崛起,以及kubenet并不支持網絡策略等硬傷,社區已經沒了繼續維護kubenet的熱情,因此廢棄kubenet也就被提上了議程。
IPv4/IPv6雙棧支持。經過大半年社區開發者的齊心協力,Kubernetes總算支持了IPv6。但目前的支持比較初級,IPv6還不能和IPv4混用。IPv4/IPv6的雙棧支持,勢在必行。
Pod Ready++。Pod有Ready和非Ready狀態之分,為何還要搞出個Ready++這種“量子化”的模糊界限呢?原因在于,一個Pod能否真的對外提供服務,除了依賴容器內進程ready(我們會放置探針,檢查進程狀態)這類內部條件外,還依賴諸如:Ingress,Service,網絡策略,外部LB等一系列外部因素。Pod Ready++的提出,就是為了將外部因素一齊納入Pod狀態的考量。
多網絡。也許是Kubernetes的“單Pod單IP”的網絡模型過于深入人心了,以至于在實現過程中都謹遵這一“金科玉律”。但我們知道,網絡的世界紛繁復雜,一塊網卡怎么可能cover所有場景呢?據最簡單的例子,一般我們會為一個IO密集型的作業配兩塊網絡,一塊網卡作為數據信道,另一塊網卡則作為控制信道。從單網絡到多網絡的遷移,道路并不平坦,甚至是處處荊棘和沼澤,且不說網絡插件,Service,DNS,Ingress等實現要大改,光API兼容性就讓你頭疼。好消息是經過整整兩年的拉鋸,社區Network Plumbing WG終于取得了階段性成果,如不出意外的話,應該是CRD + 多網路插件的形式支持Kubernetes的多網絡,保持Kubernetes原生API的穩定。支持多網絡的CNI插件有幾個,但真真落到生產的沒幾個,CNI-genie是其中一個有眾多粉絲基礎和經過生產環境檢驗的Kubernetes多網絡插件,了解一下?
最后,談下Service Mesh。嚴格說來,Service Mesh并不在Kubernetes核心的范圍之內。但是,在Kubernetes的幫助下,應用上云后,還面臨著服務治理的難題。現在大多數云原生的應用都是微服務架構,微服務的注冊,服務之間的相互調用關系,服務異常后的熔斷、降級,調用鏈的跟蹤、分析等待一系列現實問題擺在各機構面前。Service Mesh(服務網絡)就是解決這類微服務發現和治理問題的一個概念。在我看來,Service Mesh之于微服務架構就像TCP協議之于web應用。我們大部分人寫Web應用,關心的是RESTful,HTTP等上層協議,很少需要我們自己操心網絡報文超時重傳、分割組裝、內容校驗等底層細節。正是因為有了Service Mesh,企業在云原生和微服務架構的實踐道路上只需根據自己業務做適當的微服務拆分即可,無需過多關注底層服務發現和治理的復雜度。而Istio的出現,使得有些“學院派”的Service Mesh概念真正得到了落地,并且提供了真正可供操作、非侵入式的方案,讓諸如Spring Cloud,Dubbo這些“老古董”第一次有了被淘汰的危機感。
本文轉自DockOne-Kubernetes網絡一年發展動態與未來趨勢
總結
以上是生活随笔為你收集整理的Kubernetes网络一年发展动态与未来趋势的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [微信开发] - 用户获取推广二维码
- 下一篇: react useRef()函数