1. 淺談 Kubernetes 網(wǎng)絡(luò)模型(CNI)

        共 4208字,需瀏覽 9分鐘

         ·

        2020-09-23 15:07

        來(lái)源:https://morven.life/notes/networking-6-k8s-summary/


        Kubernetes通過(guò)整合規(guī)模龐大的容器實(shí)例形成集群,這些容器實(shí)例可能運(yùn)行在異構(gòu)的底層網(wǎng)絡(luò)環(huán)境中,如何保證這些容器間的互通是實(shí)際生產(chǎn)環(huán)境中首要考慮的問(wèn)題之一。

        Kubernetes網(wǎng)絡(luò)基本要求

        Kubernetes對(duì)容器技術(shù)做了更多的抽象,其中最重要的一點(diǎn)是提出pod的概念,pod是Kubernetes資源調(diào)度的基本單元,我們可以簡(jiǎn)單地認(rèn)為pod是容器的一種延伸擴(kuò)展,從網(wǎng)絡(luò)的角度來(lái)看,pod必須滿足以下條件:

        1. 每一個(gè)Pod都有一個(gè)獨(dú)特的IP地址,所有pod都在一個(gè)可以直接連通的、扁平的網(wǎng)絡(luò)空間中

        2. 同一個(gè)pod內(nèi)的所有容器共享同一個(gè)netns網(wǎng)絡(luò)命名空間

        基于這樣的基本要求,我們可以知道:

        1. 同一個(gè)pod內(nèi)的所有容器之間共享端口,可直接通過(guò)localhost+端口來(lái)訪問(wèn)

        2. 由于每個(gè)pod有單獨(dú)的IP,所以不需要考慮容器端口與主機(jī)端口映射以及端口沖突問(wèn)題

        事實(shí)上,Kubernetes進(jìn)一步確定了對(duì)一個(gè)合格集群網(wǎng)絡(luò)的基本要求:

        1. 任意兩個(gè)pod之間其實(shí)是可以直接通信的,無(wú)需顯式地使用NAT進(jìn)行地址的轉(zhuǎn)換;

        2. 任意集群節(jié)點(diǎn)node與任意pod之間是可以直接通信的,無(wú)需使用明顯的地址轉(zhuǎn)換,反之亦然;

        3. 任意pod看到自己的IP跟別人看見(jiàn)它所用的IP是一樣的,中間不能經(jīng)過(guò)地址轉(zhuǎn)換;

        也就是說(shuō),必須同時(shí)滿足以上三點(diǎn)的網(wǎng)絡(luò)模型才能適用于kubernetes,事實(shí)上,在早期的Kubernetes中,并沒(méi)有什么網(wǎng)絡(luò)標(biāo)準(zhǔn),只是提出了以上基本要求,只有滿足這些要求的網(wǎng)絡(luò)才可以部署Kubernetes,基于這樣的底層網(wǎng)絡(luò)假設(shè),Kubernetes設(shè)計(jì)了pod-deployment-service的經(jīng)典三層服務(wù)訪問(wèn)機(jī)制。直到1.1發(fā)布,Kubernetes才開(kāi)始采用全新的CNI(Container Network Interface)網(wǎng)絡(luò)標(biāo)準(zhǔn)。

        CNI

        其實(shí),我們?cè)谇懊娼榻B容器網(wǎng)絡(luò)的時(shí)候,就提到了CNI網(wǎng)絡(luò)規(guī)范,CNI相對(duì)于CNM(Container Network Model)對(duì)開(kāi)發(fā)者的約束更少,更開(kāi)放,不依賴于Docker。事實(shí)上,CNI規(guī)范確實(shí)非常簡(jiǎn)單,詳見(jiàn):https://github.com/containernetworking/cni/blob/master/SPEC.md

        實(shí)現(xiàn)一個(gè)CNI網(wǎng)絡(luò)插件只需要一個(gè)配置文件一個(gè)可執(zhí)行的文件

        • 配置文件描述插件的版本、名稱、描述等基本信息

        • 可執(zhí)行文件會(huì)被上層的容器管理平臺(tái)調(diào)用,一個(gè)CNI可執(zhí)行文件自需要實(shí)現(xiàn)將容器加入到網(wǎng)絡(luò)的ADD操作以及將容器從網(wǎng)絡(luò)中刪除的DEL操作(以及一個(gè)可選的VERSION查看版本操作)

        Kubernetes使用CNI網(wǎng)絡(luò)插件的基本工作流程:

        1. kubelet先創(chuàng)建pause容器生成對(duì)應(yīng)的netns網(wǎng)絡(luò)命名空間

        2. 根據(jù)配置調(diào)用具體的CNI插件,可以配置成CNI插件鏈來(lái)進(jìn)行鏈?zhǔn)秸{(diào)用

        3. 當(dāng)CNI插件被調(diào)用時(shí),它根據(jù)環(huán)境變量以及命令行參數(shù)來(lái)獲得網(wǎng)絡(luò)命名空間netns、容器的網(wǎng)絡(luò)設(shè)備等必要信息,然后執(zhí)行ADD操作

        4. CNI插件給pause容器配置正確的網(wǎng)絡(luò),pod中其他的容器都是用pause容器的網(wǎng)絡(luò)

        如果不清楚什么是pause容器,它在pod中處于什么樣的位置,請(qǐng)查看之前的筆記:https://morven.life/notes/from-container-to-pod/

        pod網(wǎng)絡(luò)模型

        要了解kubernetes網(wǎng)絡(luò)模型的實(shí)現(xiàn)原理,我們就要從單個(gè)pod入手,事實(shí)上,一旦熟悉了單個(gè)pod的網(wǎng)絡(luò)模型,就會(huì)發(fā)現(xiàn)kubernetes網(wǎng)絡(luò)模型基本遵循和容器網(wǎng)絡(luò)模型一樣的原理。

        通過(guò)前面的筆記從docker容器到pod,我們知道pod啟動(dòng)的時(shí)候先創(chuàng)建pause容器生成對(duì)應(yīng)的netns網(wǎng)絡(luò)命名空間,然后其他容器共享pause容器創(chuàng)建的網(wǎng)絡(luò)命名空間。而對(duì)于單個(gè)容器的網(wǎng)絡(luò)模型我們之前也介紹過(guò),主要就是通過(guò)docker0網(wǎng)橋設(shè)備與veth設(shè)備對(duì)連接不同的容器網(wǎng)絡(luò)命名空間,由此,我們可以得到如下圖所示的單個(gè)pod網(wǎng)絡(luò)模型的創(chuàng)建過(guò)程:


        可以看到,同一個(gè)pod里面的其他容器共享pause容器創(chuàng)建的網(wǎng)絡(luò)命名空間,也就是說(shuō),所有的容器共享相同的網(wǎng)絡(luò)設(shè)備,路由表設(shè)置,服務(wù)端口等信息,仿佛是在同一臺(tái)機(jī)器上運(yùn)行的不同進(jìn)程,所以這些容器之間可以直接通過(guò)localhost與對(duì)應(yīng)的端口通信;對(duì)于集群外部的請(qǐng)求,則通過(guò)docker0網(wǎng)橋設(shè)備充當(dāng)?shù)木W(wǎng)關(guān),同時(shí)通過(guò)iptables做地址轉(zhuǎn)換。我們會(huì)發(fā)現(xiàn),這其實(shí)就是對(duì)當(dāng)個(gè)容器的bridge網(wǎng)絡(luò)模型的擴(kuò)展。

        主流kubernetes網(wǎng)絡(luò)方案

        上一小節(jié)我們知道單個(gè)pod的網(wǎng)絡(luò)模型是容器網(wǎng)絡(luò)模型的擴(kuò)展,但是pod與pod之間的是怎么相互通信的呢?這其實(shí)與容器之間相互通信非常類似,也分為同一個(gè)主機(jī)上的pod之間與跨主機(jī)的pod之間兩種。

        如容器網(wǎng)絡(luò)模型一樣,對(duì)于統(tǒng)一主機(jī)上的pod之間,通過(guò)docker0網(wǎng)橋設(shè)備直接二層(數(shù)據(jù)鏈路層)網(wǎng)絡(luò)上通過(guò)MAC地址直接通信:


        而跨主機(jī)的pod之間的相互通信也主要有以下兩個(gè)思路:

        1. 修改底層網(wǎng)絡(luò)設(shè)備配置,加入容器網(wǎng)絡(luò)IP地址的管理,修改路由器網(wǎng)關(guān)等,該方式主要和SDN(Software define networking)結(jié)合。

        2. 完全不修改底層網(wǎng)絡(luò)設(shè)備配置,復(fù)用原有的underlay平面網(wǎng)絡(luò),解決容器跨主機(jī)通信,主要有如下兩種方式:

          • 隧道傳輸(Overlay):將容器的數(shù)據(jù)包封裝到原主機(jī)網(wǎng)絡(luò)的三層或者四層數(shù)據(jù)包中,然后使用主機(jī)網(wǎng)絡(luò)的IP或者TCP/UDP傳輸?shù)侥繕?biāo)主機(jī),目標(biāo)主機(jī)拆包后再轉(zhuǎn)發(fā)給目標(biāo)容器。Overlay隧道傳輸常見(jiàn)方案包括Vxlan、ipip等,目前使用Overlay隧道傳輸技術(shù)的主流容器網(wǎng)絡(luò)有Flannel等;


        • 修改主機(jī)路由:把容器網(wǎng)絡(luò)加到主機(jī)路由表中,把主機(jī)網(wǎng)絡(luò)設(shè)備當(dāng)作容器網(wǎng)關(guān),通過(guò)路由規(guī)則轉(zhuǎn)發(fā)到指定的主機(jī),實(shí)現(xiàn)容器的三層互通。目前通過(guò)路由技術(shù)實(shí)現(xiàn)容器跨主機(jī)通信的網(wǎng)絡(luò)如Flannel host-gw、Calico等;


        下面簡(jiǎn)單介紹幾種主流的方案:

        • Flannel是目前使用最為普遍的方案,提供了多種網(wǎng)絡(luò)backend,它支持多種數(shù)據(jù)路徑,也適合于overlay/underlay等多種場(chǎng)景。對(duì)于overlay的數(shù)據(jù)包封裝,可以使用用戶態(tài)的UDP,內(nèi)核態(tài)的Vxlan(性能相對(duì)較好),甚至在集群規(guī)模不大,且處于同一個(gè)二層域時(shí)可以采用host-gw的方式修改主機(jī)路由表;

        • Weave工作模式與Flannel很相似的,它最早只提供了UDP(稱為sleeve模式)的網(wǎng)絡(luò)方式,后來(lái)又加上了fastpass方式(基于VxLAN),不過(guò)Weave消除了Flannel中用來(lái)存儲(chǔ)網(wǎng)絡(luò)地址的額外組件,自己集成了高可用的數(shù)據(jù)存儲(chǔ)功能;

        • Calico主要是采用了修改主機(jī)路由,節(jié)點(diǎn)之間采用BGP的協(xié)議去進(jìn)行路由的同步。但是現(xiàn)實(shí)中的網(wǎng)絡(luò)并不總是支持BGP路由的,因此Calico也支持內(nèi)核中的IPIP模式,使用overlay的方式來(lái)傳輸數(shù)據(jù);

        策略控制(Network Policy)

        Network Policy)是Kubernetes提供的基于策略的網(wǎng)絡(luò)控制,用于隔離應(yīng)用并提高安全性。它使用Kubernetes中常用的標(biāo)簽選擇器模擬傳統(tǒng)的分段網(wǎng)絡(luò),并通過(guò)策略控制它們之間的東西流量以及與外部交流的南北流量。

        Note: 確保使用的網(wǎng)絡(luò)插件支持策略控制(Network Policy),比如Flannel就沒(méi)有實(shí)現(xiàn)Network Policy;

        下面的例子是配置一個(gè)典型的Network Policy的實(shí)例:

        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
        name: test-network-policy
        namespace: default
        spec:
        podSelector:
        matchLabels:
        role: db
        policyTypes:
        - Ingress
        - Egress
        ingress:
        - from:
        - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
        - namespaceSelector:
        matchLabels:
        project: myproject
        - podSelector:
        matchLabels:
        role: frontend
        ports:
        - protocol: TCP
        port: 6379
        egress:
        - to:
        - ipBlock:
        cidr: 10.0.0.0/24
        ports:
        - protocol: TCP
        port: 5978

        它使用標(biāo)簽選擇器namespaceSelectorposSelector控制pod之間的流量,流量的行為模式主要由以下三個(gè)對(duì)象決定:

        1. 控制對(duì)象:通過(guò)spec.podSelector篩選

        2. 流量方向:ingress控制入pod流量,egress控制出pod流量

        3. 流量特征:對(duì)端-IP-協(xié)議-端口

        通過(guò)使用Network Policy可以實(shí)現(xiàn)對(duì)進(jìn)出流的精確控制,它采用各種選擇器(標(biāo)簽或namespace),找到一組滿足條件的pod,或者找到相當(dāng)于通信的兩端,然后通過(guò)流量的特征描述來(lái)決定它們之間是不是可以連通,可以理解為一個(gè)白名單的機(jī)制。


        - END -

        ?推薦閱讀?
        小團(tuán)隊(duì)如何從零搭建一個(gè)自動(dòng)化運(yùn)維體系?
        為什么 HTTPS 是安全的?
        面試管:用了HTTPS就安全了嗎?HTTPS 會(huì)被抓包嗎?
        支付寶架構(gòu)師眼中的高并發(fā)架構(gòu)
        SpringCloud微服務(wù)項(xiàng)目運(yùn)維必知必會(huì)
        Java 應(yīng)用最常見(jiàn)的3個(gè)問(wèn)題排查思路
        一篇漫畫帶你了解 Linux 內(nèi)核長(zhǎng)啥樣!



        點(diǎn)亮,服務(wù)器三年不宕機(jī)

        瀏覽 184
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 东北毛片 | 国产寡妇又大又粗又大 | 免费看h片网站 | 自拍偷拍第3页 | 人人色综合网 |