一 Kubernetes網路模型概述
1.1 Kubernetes網路模型
Kubernetes網路模型設計的一個基礎原則是:每個Pod都擁有一個獨立的IP地址,并假定所有Pod都在一個可以直接連通的、扁平的網路空間中,所以不管它們是否運行在同一個Node(宿主機)中,都要求它們可以直接通過對方的IP進行訪問,設計這個原則的原因是,用戶不需要額外考慮如何建立Pod之間的連接,也不需要考慮如何將容器埠映射到主機埠等問題, 實際上,在Kubernetes的集群里,IP是以Pod為單位進行分配的,一個Pod內部的所有容器共享一個網路堆疊(相當于一個網路命名空間,它們的IP地址、網路設備、配置等都是共享的),按照這個網路原則抽象出來的為每個Pod都設定一個IP地址的模型也被稱作IP-per-Pod模型, 由于Kubernetes的網路模型假設Pod之間訪問時使用的是對方Pod的實際地址,所以一個Pod內部的應用程式看到的自己的IP地址和埠與集群內其他Pod看到的一樣,它們都是Pod實際分配的IP地址,將IP地址和埠在Pod內部和外部都保持一致,也就不需要使用NAT來進行地址轉換了, Kubernetes的網路之所以這么設計,主要原因就是可以兼容過去的應用,當然,我們使用Linux命令“ipaddrshow”也能看到這些地址,和程式看到的沒有什么區別,所以這種IP-per-Pod的方案很好地利用了現有的各種域名決議和發現機制, 為每個Pod都設定一個IP地址的模型還有另外一層含義,那就是同一個Pod內的不同容器會共享同一個網路命名空間,也就是同一個Linux網路協議堆疊,這就意味著同一個Pod內的容器可以通過localhost來連接對方的埠,這種關系和同一個VM內的行程之間的關系是一樣的,看起來Pod內容器之間的隔離性減小了,而且Pod內不同容器之間的埠是共享的,就沒有所謂的私有埠的概念了,如果應用必須要使用一些特定的埠范圍,那么也可以為這些應用單獨創建一些Pod,反之,對那些沒有特殊需要的應用,由于Pod內的容器是共享部分資源的,所以可以通過共享資源互相通信,這顯然更加容易和高效,針對這些應用,雖然損失了可接受范圍內的部分隔離性,卻也是值得的, IP-per-Pod模式和Docker原生的通過動態埠映射方式實作的多節點訪問模式有如下差別:- 主要區別是后者的動態埠映射會引入埠管理的復雜性,而且訪問者看到的IP地址和埠與服務提供者實際系結的不同(因為NAT的緣故,它們都被映射成新的地址或埠了),這也會引起應用配置的復雜化,
- 同時,標準的DNS等名字決議服務也不適用了,甚至服務注冊和發現機制都比較復雜,因為在埠映射情況下,服務自身很難知道自己對外暴露的真實的服務IP和埠,外部應用也無法通過服務所在容器的私有IP地址和埠來訪問服務,
- 所有容器都可以在不用NAT的方式下同別的容器通信,
- 所有節點都可以在不用NAT的方式下同所有容器通信,反之亦然,
- 容器的地址和別人看到的地址是同一個地址,
二 Docker網路基礎
Docker本身的技術依賴于近年來Linux內核虛擬化技術的發展,所以Docker對Linux內核的特性有很強的依賴,Docker通常使用到的與Linux網路有關的主要技術有:網路命名空間(Network Namespace)、Veth設備對、網橋、ipatables和路由,2.1 網路命名空間
為了支持網路協議堆疊的多個實體,Linux在網路堆疊中引入了網路命名空間,這些獨立的協議堆疊被隔離到不同的命名空間中, 處于不同命名空間中的網路堆疊是完全隔離的,彼此之間無法通信,通過對網路資源的隔離,就能在一個宿主機上虛擬多個不同的網路環境,Docker正是利用了網路的命名空間特性,實作了不同容器之間的網路隔離,在Linux的網路命名空間中可以有自己獨立的路由表及獨立的iptables設定來提供包轉發、NAT及IP包過濾等功能, 為了隔離出獨立的協議堆疊,需要納入命名空間的元素有行程、套接字、網路設備等,行程創建的套接字必須屬于某個命名空間,套接字的操作也必須在命名空間中進行,同樣,網路設備也必須屬于某個命名空間,因為網路設備屬于公共資源,所以可以通過修改屬性實作在命名空間之間移動,- 網路命名空間的實作
在新生成的私有命名空間中只有回環設備(名為“lo”且是停止狀態),其他設備默認都不存在,若需要其他設備,則要手工建立,
從網路角度,每個namespace提供了一份獨立的網路協議堆疊(網路設備介面、IPV4、IPV6、IP路由、防火墻規則、sockets等),一個設備(Linux Device)只能位于一個namespace中,不同namespace中的設備可以利用veth pair進行橋接,
namespace可實作隔離的資源:
- 網路命名空間操作
1 [root@k8smaster01 ~]# ip netns add mytestns #創建命名空間 2 [root@k8smaster01 ~]# ip netns exec mytestns <command> #進入命名空間bash 3 [root@k8smaster01 ~]# ip netns exec mytestns bash #進入命名空間bash 4 [root@k8smaster01 ~]# exit #退出命名空間 5 [root@k8smaster01 ~]# ip link set <device> netns mytestns #轉移設備注意:因為一個設備只能屬于一個命名空間,所以轉移后在這個命名空間中就看不到這個設備了,在設備里面有一個重要的屬性:NETIF_F_ETNS_LOCAL,如果這個屬性為on,就不能被轉移到其他命名空間中,Veth設備屬于可以轉移的設備,而很多其他設備如lo設備、vxlan設備、ppp設備、bridge設備等都是不可以轉移的,
2.2 Veth設備對
引入Veth設備對是為了在不同的網路命名空間之間通信,利用它可以直接將兩個網路命名空間連接起來,由于要連接兩個網路命名空間,所以Veth設備都是成對出現的,很像一對以太網卡,并且中間有一根直連的網線,通常將其中一端稱為另一端的peer, 在Veth設備的一端發送資料時,它會將資料直接發送到另一端,并觸發另一端的接收操作,Veth設備對的示意圖如下:
- veth pair操作
1 [root@k8smaster01 ~]# ip link add veth0 type veth peer name veth1 #創建veth設備對 2 [root@k8smaster01 ~]# ip link show | grep veth #當前查看veth 3 [root@k8smaster01 ~]# ip netns add ns0 4 [root@k8smaster01 ~]# ip netns add ns1 #創建命名空間 5 [root@k8smaster01 ~]# ip link set veth0 netns ns0 6 [root@k8smaster01 ~]# ip link set veth1 netns ns1 #veth移入命名空間 7 [root@k8smaster01 ~]# ip netns exec ns0 ip link show #進入命名空間查看veth 8 [root@k8smaster01 ~]# ip netns exec ns0 ip addr add local 192.168.10.1/24 dev veth0 9 [root@k8smaster01 ~]# ip netns exec ns1 ip addr add local 192.168.10.2/24 dev veth1 #設定對應的IP 10 [root@k8smaster01 ~]# ip netns exec ns0 ifconfig veth0 up 11 [root@k8smaster01 ~]# ip netns exec ns1 ifconfig veth1 up #開啟設備 12 [root@k8smaster01 ~]# ip netns exec ns0 ping 192.168.10.2 #連通性測驗
提示:在Docker內部,Veth設備對也是連通容器與宿主機的主要網路設備,
1 [root@k8smaster01 ~]# ip netns exec ns0 ethtool -S veth0 2 NIC statistics: 3 peer_ifindex: 9 4 [root@k8smaster01 ~]# ip netns exec ns1 ip link | grep 9
2.3 網橋
Linux可以支持多個不同的網路,它們之間能夠相互通信,可通過網橋將這些網路連接起來并實作各網路中主機的相互通信, 網橋是一個二層的虛擬網路設備,把若干個網路介面“連接”起來,以使得網路介面之間的報文能夠互相轉發,網橋能夠決議收發的報文,讀取目標MAC地址的資訊,和自己記錄的MAC表結合,來決策報文的轉發目標網路介面, 為了實作轉發功能,網橋學習源MAC地址(二層網橋轉發的依據就是MAC地址),在轉發報文時,網橋只需要向特定的網口進行轉發,來避免不必要的網路互動,如果接受到未學習到的地址,就無法知道這個報文應該向哪個網路介面轉發,就將報文廣播給所有的網路介面(報文來源的網路介面除外), 在實際的網路中,網路拓撲若出現改變,如設備被移動到另一個埠上,卻沒有發送任何資料,網橋設備就無法感知到這個變化,網橋還是向原來的埠轉發資料包,在這種情況下資料就會丟失,所以網橋還要對學習到的MAC地址表加上超時時間(默認為5min),如果網橋收到了對應埠MAC地址回發的包,則重置超時時間,否則過了超時時間后,就認為設備已經不在那個埠上了,它就會重新廣播發送, 對于多網卡、多虛擬的設備,Linux的網橋提供了在這些設備之間互相轉發資料的二層設備,Linux內核支持網口的橋接(目前只支持以太網介面),但是與單純的交換機不同,交換機只是一個二層設備,對于接收到的報文,要么轉發,要么丟棄,運行著Linux內核的機器本身就是一臺主機,有可能是網路報文的目的地,其收到的報文除了轉發和丟棄,還可能被送到網路協議堆疊的上層(網路層),從而被自己(這臺主機本身的協議堆疊)消化,所以既可以把網橋看作一個二層設備,也可以把它看作一個三層設備,- Linux網橋的實作
如上圖所示,網橋設備br0系結了eth0和eth1,對于網路協議堆疊的上層來說,只看得到br0就行,因為橋接是在資料鏈路層實作的,上層不需要關心橋接的細節,所以協議堆疊上層需要發送的報文被送到br0,網橋設備的處理代碼判斷報文該被轉發到eth0還是eth1,或者兩者皆轉發;反之,從eth0或從eth1接收到的報文被提交給網橋的處理代碼,在這里會判斷報文應該被轉發、丟棄還是被提交到協議堆疊上層,而有時eth0、eth1也可能會作為報文的源地址或目的地址,直接參與報文的發送與接收,從而繞過網橋,
- 網橋的常用操作命令
提示:可通過# yum -y install bridge-utils安裝brctl,
為網橋增加網口,在Linux中,一個網口其實就是一個物理網卡,
1 [root@k8smaster01 ~]# ip link add tap1 type veth peer name tap1_peer 2 [root@k8smaster01 ~]# ip link add tap2 type veth peer name tap2_peer 3 [root@k8smaster01 ~]# ip link add tap3 type veth peer name tap3_peer 4 [root@k8smaster01 ~]# ip link add tap4 type veth peer name tap4_peer 5 #創建veth pair 6 [root@k8smaster01 ~]# ip netns add ns1 7 [root@k8smaster01 ~]# ip netns add ns2 8 [root@k8smaster01 ~]# ip netns add ns3 9 [root@k8smaster01 ~]# ip netns add ns4 10 #創建namespace 11 [root@k8smaster01 ~]# ip link set tap1 netns ns1 12 [root@k8smaster01 ~]# ip link set tap2 netns ns2 13 [root@k8smaster01 ~]# ip link set tap3 netns ns3 14 [root@k8smaster01 ~]# ip link set tap4 netns ns4 15 #tap和namespace關聯 16 [root@k8smaster01 ~]# brctl addbr br1 #創建橋 17 [root@k8smaster01 ~]# brctl addif br1 tap1_peer 18 [root@k8smaster01 ~]# brctl addif br1 tap2_peer 19 [root@k8smaster01 ~]# brctl addif br1 tap3_peer 20 [root@k8smaster01 ~]# brctl addif br1 tap4_peer 21 #把相應的tap添加至bright中 22 [root@k8smaster01 ~]# ip netns exec ns1 ip addr add local 192.168.20.1/24 dev tap1 23 [root@k8smaster01 ~]# ip netns exec ns2 ip addr add local 192.168.20.2/24 dev tap2 24 [root@k8smaster01 ~]# ip netns exec ns3 ip addr add local 192.168.20.3/24 dev tap3 25 [root@k8smaster01 ~]# ip netns exec ns4 ip addr add local 192.168.20.4/24 dev tap4 26 #配置相應IP地址 27 [root@k8smaster01 ~]# ip link set br1 up 28 [root@k8smaster01 ~]# ip link set tap1_peer up 29 [root@k8smaster01 ~]# ip link set tap2_peer up 30 [root@k8smaster01 ~]# ip link set tap3_peer up 31 [root@k8smaster01 ~]# ip link set tap4_peer up 32 [root@k8smaster01 ~]# ip netns exec ns1 ip link set tap1 up 33 [root@k8smaster01 ~]# ip netns exec ns2 ip link set tap2 up 34 [root@k8smaster01 ~]# ip netns exec ns3 ip link set tap3 up 35 [root@k8smaster01 ~]# ip netns exec ns4 ip link set tap4 up 36 #將bright和tap設定為up 37 [root@k8smaster01 ~]# ip netns exec ns1 ping 192.168.20.2 #互ping
提示:若物理網卡作為網橋的一個網口,則此物理網卡將在鏈路層作業(是一個純鏈路層設備),就不再需要IP地址了,可以取消物理網卡的IP,給網橋配置一個IP地址,
2.4 iptables和Netfilter
Linux提供了一套機制來為用戶實作自定義的資料包處理程序,在Linux網路協議堆疊中有一組回呼函式掛接點,通過這些掛接點掛接的鉤子函式可以在Linux網路堆疊處理資料包的程序中對資料包進行一些操作,例如過濾、修改、丟棄等, 整個掛接點技術叫作Netfilter和iptables,Netfilter負責在內核中執行各種掛接的規則,運行在內核模式中;而iptables是在用戶模式下運行的行程,負責協助和維護內核中Netfilter的各種規則表,二者互相配合來實作整個Linux網路協議堆疊中靈活的資料包處理機制,- iptables規則
- filter:實作防火墻功能;
- nat:實作NAT功能;
- mangle:實作流量整形,
- iptables-save: 按照命令的方式列印iptables的內容,
- iptables-vnL: 以另一種格式顯示Netfilter表的內容,
- Netfilter規則
在這些時刻點中,iptables三張表(模塊)并不是所有的時刻都全部進行處理,在同一個時刻點,也可以有多個模塊進行處理,對于不同模塊誰先處理,誰后處理,可參考如下順序,
解釋:
- PREROUTING:報文進入網路介面尚未進入路由之前的時刻;
- INPUT:路由判斷是本機接收的報文,準備從內核空間進入到用戶空間的時刻;
- FORWARD:路由判斷不是本機接收的報文,需要路由轉發,路由轉發的那個時刻;
- OUTPUT:本機報文需要發出去 經過路由判斷選擇好埠以后,準備發送的那一刻 ;
- POSTROUTING:FORWARD/OUTPUT 已經完成,報文即將出網路介面的那一刻 ,
2.5 路由
Linux系統包含一個完整的路由功能,當IP層在處理資料發送或者轉發時,會使用路由表來決定發往哪里,在通常情況下,如果主機與目的主機直接相連,那么主機可以直接發送IP報文到目的主機,這個程序比較簡單,例如,通過點對點的鏈接或網路共享,如果主機與目的主機沒有直接相連,那么主機會將IP報文發送給默認的路由器,然后由路由器來決定往哪里發送IP報文, 路由功能由IP層維護的一張路由表來實作,當主機收到資料報文時,它用此表來決策接下來應該做什么操作,當從網路側接收到資料報文時,IP層首先會檢查報文的IP地址是否與主機自身的地址相同,如果資料報文中的IP地址是主機自身的地址,那么報文將被發送到傳輸層相應的協議中,如果報文中的IP地址不是主機自身的地址,并且主機配置了路由功能,那么報文將被轉發,否則,報文將被丟棄, 路由表中的資料一般是以條目形式存在的,一個典型的路由表條目通常包含以下主要的條目項,- 目的IP地址:此欄位表示目標的IP地址,這個IP地址可以是某主機的地址,也可以是一個網路地址,如果這個條目包含的是一個主機地址,那么它的主機ID將被標記為非零;如果這個條目包含的是一個網路地址,那么它的主機ID將被標記為零,
- 下一跳路由器的IP地址:若并非最終目的的路由器,則該條目給出的下一個路由器的地址用來轉發在相應介面接收到的IP資料報文,
- 標志:這個欄位提供了另一組重要資訊,例如,目的IP地址是一個主機地址還是一個網路地址,此外,從標志中可以得知下一個路由器是一個真實路由器還是一個直接相連的介面,
- 網路介面規范:為一些資料報文的網路介面規范,該規范將與報文一起被轉發,
在通過路由表轉發時,如果任何條目的第1個欄位完全匹配目的IP地址(主機)或部分匹配條目的IP地址(網路),它將指示下一個路由器的IP地址,條目中的所有其他欄位將提供更多的輔助資訊來為路由轉發做決定, 如果沒有找到一個完全匹配的IP,就接著搜索相匹配的網路ID,如果找到,那么該資料報文會被轉發到指定的路由器上,可以看出,網路上的所有主機都通過這個路由表中的單個(這個)條目進行管理, 如果上述兩個條件都不匹配,那么該資料報文將被轉發到一個默認的路由器上, 如果上述步驟都失敗,默認路由器也不存在,那么該資料報文最終無法被轉發,任何無法投遞的資料報文都將產生一個ICMP主機不可達或ICMP網路不可達的錯誤,并將此錯誤回傳給生成此資料報文的應用程式,
- 路由表的創建
MAIN表用于各類網路IP地址的轉發,它的建立既可以使用靜態配置生成,也可以使用動態路由發現協議生成,動態路由發現協議一般使用組播功能來通過發送路由發現資料,動態地交換和獲取網路的路由資訊,并更新到路由表中,
Linux下支持路由發現協議的開源軟體有許多,常用的有Quagga、Zebra等,
- 路由表的查看
在它顯示的資訊中,如果標志是U,則說明是可達路由;如果標志是G,則說明這個網路介面連接的是網關,否則說明這個介面直連主機,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/122572.html
標籤:Linux
