一 Kubernetes網路模型概述 1.1 Kubernetes網路模型 Kubernetes網路模型設計的一個基礎原則是:每個Pod都擁有一個獨立的IP地址,並假定所有Pod都在一個可以直接連通的、扁平的網路空間中。所以不管它們是否運行在同一個Node(宿主機)中,都要求它們可以直接通過對方的I ...
一 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包過濾等功能。 為了隔離出獨立的協議棧,需要納入命名空間的元素有進程、套接字、網路設備等。進程創建的套接字必須屬於某個命名空間,套接字的操作也必須在命名空間中進行。同樣,網路設備也必須屬於某個命名空間。因為網路設備屬於公共資源,所以可以通過修改屬性實現在命名空間之間移動。- 網路命名空間的實現
- 網路命名空間操作
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網橋的實現
- 網橋的常用操作命令
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規則
- PREROUTING:報文進入網路介面尚未進入路由之前的時刻;
- INPUT:路由判斷是本機接收的報文,準備從內核空間進入到用戶空間的時刻;
- FORWARD:路由判斷不是本機接收的報文,需要路由轉發,路由轉發的那個時刻;
- OUTPUT:本機報文需要發出去 經過路由判斷選擇好埠以後,準備發送的那一刻 ;
- POSTROUTING:FORWARD/OUTPUT 已經完成,報文即將出網路介面的那一刻 。