NetworkPolicy
一、基礎網路
Kubernetes網絡模型設計的一個基礎原則是:每個Pod都擁有一個獨立的IP地址,并假定所有Pod都在一個可以直接連通的、扁平的網絡空間中。所以不管它們是否運行在同一個Node(宿主機)中,都要求它們可以直接通過對方的IP進行訪問。設計這個原則的原因是,用戶不需要額外考慮如何建立Pod之間的連接,也不需要考慮如何將容器端口映射到主機端口等問題。
Linux在網絡棧中引入了網絡命名空間,這些獨立的協議棧被隔離到不同的命名空間中。處于不同命名空間中的網絡棧是完全隔離的,彼此之間無法通信。通過對網絡資源的隔離,就能在一個宿主機上虛擬多個不同的網絡環境。Docker正是利用了網絡的命名空間特性,實現了不同容器之間的網絡隔離。
Linux系統包含一個完整的路由功能。當IP層在處理數據發送或者轉發時,會使用路由表來決定發往哪里。在通常情況下,如果主機與目的主機直接相連,那么主機可以直接發送IP報文到目的主機,這個過程比較簡單。例如,通過點對點的鏈接或網絡共享,如果主機與目的主機沒有直接相連,那么主機會將IP報文發送給默認的路由器,然后由路由器來決定往哪里發送IP報文。
路由功能由IP層維護的一張路由表來實現。當主機收到數據報文時,它用此表來決策接下來應該做什么操作。當從網絡側接收到數據報文時,IP層首先會檢查報文的IP地址是否與主機自身的地址相同。如果數據報文中的IP地址是主機自身的地址,那么報文將被發送到傳輸層相應的協議中。如果報文中的IP地址不是主機自身的地址,并且主機配置了路由功能,那么報文將被轉發,否則報文將被丟棄。
路由表中的數據一般是以條目形式存在的。一個典型的路由表條目通常包含以下主要的條目項。
(1)目的IP地址:此字段表示目標的IP地址。這個IP地址可以是某主機的地址,也可以是一個網絡地址。如果這個條目包含的是一個主機地址,那么它的主機ID將被標記為非零;如果這個條目包含的是一個網絡地址,那么它的主機ID將被標記為零。
(2)下一個路由器的IP地址:這里采用“下一個”的說法,是因為下一個路由器并不總是最終的目的路由器,它很可能是一個中間路由器。條目給出的下一個路由器的地址用來轉發在相應接口接收到的IP數據報文。
(3)標志:這個字段提供了另一組重要信息,例如,目的IP地址是一個主機地址還是一個網絡地址。此外,從標志中可以得知下一個路由器是一個真實路由器還是一個直接相連的接口。
(4)網絡接口規范:為一些數據報文的網絡接口規范,該規范將與報文一起被轉發。
在通過路由表轉發時,如果任何條目的第1個字段完全匹配目的IP地址(主機)或部分匹配條目的IP地址(網絡),那么它將指示下一個路由器的IP地址。這是一個重要的信息,因為這些信息直接告訴主機(具備路由功能的)數據包應該被轉發到哪個路由器。而條目中的所有其他字段將提供更多的輔助信息來為路由轉發做決定。
查看路由表
[root@k8s-master01 config]#ip route show table local type local
local 10.1.2.21 dev ens160 proto kernel scope host src 10.1.2.21
local 10.96.0.1 dev kube-ipvs0 proto kernel scope host src 10.96.0.1
local 10.96.0.10 dev kube-ipvs0 proto kernel scope host src 10.96.0.10
local 10.96.4.191 dev kube-ipvs0 proto kernel scope host src 10.96.4.191
local 10.96.5.219 dev kube-ipvs0 proto kernel scope host src 10.96.5.219
local 10.96.8.233 dev kube-ipvs0 proto kernel scope host src 10.96.8.233
local 10.96.16.42 dev kube-ipvs0 proto kernel scope host src 10.96.16.42
local 10.96.20.101 dev kube-ipvs0 proto kernel scope host src 10.96.20.101
local 10.96.26.89 dev kube-ipvs0 proto kernel scope host src 10.96.26.89
local 10.96.26.90 dev kube-ipvs0 proto kernel scope host src 10.96.26.90
local 10.96.40.158 dev kube-ipvs0 proto kernel scope host src 10.96.40.158
local 10.96.41.143 dev kube-ipvs0 proto kernel scope host src 10.96.41.143
local 10.96.43.227 dev kube-ipvs0 proto kernel scope host src 10.96.43.227
local 10.96.44.6 dev kube-ipvs0 proto kernel scope host src 10.96.44.6
local 10.96.49.49 dev kube-ipvs0 proto kernel scope host src 10.96.49.49
local 10.96.51.158 dev kube-ipvs0 proto kernel scope host src 10.96.51.158
local 10.96.54.208 dev kube-ipvs0 proto kernel scope host src 10.96.54.208
local 10.96.57.40 dev kube-ipvs0 proto kernel scope host src 10.96.57.40
local 10.96.82.18 dev kube-ipvs0 proto kernel scope host src 10.96.82.18
local 10.96.86.174 dev kube-ipvs0 proto kernel scope host src 10.96.86.174
local 10.96.107.17 dev kube-ipvs0 proto kernel scope host src 10.96.107.17
local 10.96.107.142 dev kube-ipvs0 proto kernel scope host src 10.96.107.142
local 10.96.130.60 dev kube-ipvs0 proto kernel scope host src 10.96.130.60
local 10.96.142.27 dev kube-ipvs0 proto kernel scope host src 10.96.142.27
local 10.96.149.137 dev kube-ipvs0 proto kernel scope host src 10.96.149.137
local 10.96.164.40 dev kube-ipvs0 proto kernel scope host src 10.96.164.40
local 10.96.165.97 dev kube-ipvs0 proto kernel scope host src 10.96.165.97
local 10.96.167.19 dev kube-ipvs0 proto kernel scope host src 10.96.167.19
local 10.96.169.66 dev kube-ipvs0 proto kernel scope host src 10.96.169.66
local 10.96.193.178 dev kube-ipvs0 proto kernel scope host src 10.96.193.178
local 10.96.197.180 dev kube-ipvs0 proto kernel scope host src 10.96.197.180
local 10.96.213.58 dev kube-ipvs0 proto kernel scope host src 10.96.213.58
local 10.96.215.96 dev kube-ipvs0 proto kernel scope host src 10.96.215.96
local 10.96.226.93 dev kube-ipvs0 proto kernel scope host src 10.96.226.93
local 10.96.234.147 dev kube-ipvs0 proto kernel scope host src 10.96.234.147
local 10.96.247.97 dev kube-ipvs0 proto kernel scope host src 10.96.247.97
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
local 172.16.32.128 dev tunl0 proto kernel scope host src 172.16.32.128
local 172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1
local 192.168.122.1 dev virbr0 proto kernel scope host src 192.168.122.1
二、Docker網絡
標準的Docker支持以下4類網絡模式。
- ◎ host模式:使用–net=host指定。
- ◎ container模式:使用–net=container:NAME_or_ID指定。
- ◎ none模式:使用–net=none指定。
- ◎ bridge模式:使用–net=bridge指定,為默認設置。
在Kubernetes管理模式下通常只會使用bridge模式,所以本節只介紹Docker在bridge模式下是如何支持網絡的。
在bridge模式下,Docker Daemon首次啟動時會創建一個虛擬網橋,默認的名稱是docker0,然后按照RPC1918的模型在私有網絡空間中給這個網橋分配一個子網。針對由Docker創建的每一個容器,都會創建一個虛擬以太網設備(Veth設備對),其中一端關聯到網橋上,另一端使用Linux的網絡命名空間技術映射到容器內的eth0設備,然后在網橋的地址段內給eth0接口分配一個IP地址。
其中ip1是網橋的IP地址,Docker Daemon會在幾個備選地址段里給它選一個地址,通常是以172開頭的一個地址,這個地址和主機的IP地址是不重疊的。ip2是Docker在啟動容器時在這個地址段選擇的一個沒有使用的IP地址。
啟動后,Docker還將Veth設備對的名稱映射到eth0網絡接口。ip3就是主機的網卡地址。
在一般情況下,ip1、ip2和ip3是不同的IP段,所以在默認不做任何特殊配置的情況下,在外部是看不到ip1和ip2的。
三、Kubernetes網絡
同一個Pod內的容器(Pod內的容器是不會跨宿主機的)共享同一個網絡命名空間,共享同一個Linux協議棧。所以對于網絡的各類操作,就和它們在同一臺機器上一樣,它們甚至可以用localhost地址訪問彼此的端口。
1. 容器到容器通信
容器1和容器2共享一個網絡的命名空間,共享一個命名空間的結果就是它們好像在一臺機器上運行,它們打開的端口不會有沖突,可以直接使用Linux的本地IPC進行通信(例如消息隊列或者管道)。其實,這和傳統的一組普通程序運行的環境是完全一樣的,傳統程序不需要針對網絡做特別的修改就可以移植,它們之間的相互訪問只需使用localhost就可以。
2. Pod到Pod之間通信
每一個Pod都有一個真實的全局IP地址,同一個Node內的不同Pod之間可以直接采用對方Pod的IP地址通信,而且不需要采用其他發現機制,例如DNS、Consul或者etcd。
Pod容器既有可能在同一個Node上運行,也有可能在不同的Node上運行,所以通信也分為兩類:同一個Node上Pod之間的通信和不同Node上Pod之間的通信。
1.同一個Node上Pod之間的通信
Pod1和Pod2都是通過Veth連接到同一個docker0網橋的,它們的IP地址IP1、IP2都是從docker0的網段上動態獲取的,和網橋本身的IP3屬于同一個網段。
另外,在Pod1、Pod2的Linux協議棧上,默認路由都是docker0的地址,也就是說所有非本地地址的網絡數據,都會被默認發送到docker0網橋上,由docker0網橋直接中轉。
綜上所述,由于它們都關聯在同一個docker0網橋上,地址段相同,所以它們之間是能直接通信的。
2.不同Node上Pod之間的通信
Pod中的數據在發出時,需要有一個機制能夠知道對方Pod的IP地址掛在哪個具體的Node上。也就是說,先要找到Node對應宿主機的IP地址,將數據發送到這個宿主機的網卡,然后在宿主機上將相應的數據轉發到具體的docker0上。一旦數據到達宿主機Node,那個Node內部的docker0便知道如何將數據發送到Pod了。
IP1對應的是Pod1,IP2對應的是Pod2,Pod1在訪問Pod2時,首先要將數據從源Node的eth0發送出去,找到并到達Node2的eth0,即先是從IP3到IP4的傳送,之后才是從IP4到IP2的傳送。
四、Calico網絡插件
Calico是一個基于BGP的純三層的網絡方案,與OpenStack、Kubernetes、AWS、GCE等云平臺都能夠良好地集成。Calico在每個計算節點都利用Linux Kernel實現了一個高效的vRouter來負責數據轉發。
每個vRouter都通過BGP1協議把在本節點上運行的容器的路由信息向整個Calico網絡廣播,并自動設置到達其他節點的路由轉發規則。Calico保證所有容器之間的數據流量都是通過IP路由的方式完成互聯互通的。Calico節點組網時可以直接利用數據中心的網絡結構(L2或者L3),不需要額外的NAT、隧道或者Overlay Network,沒有額外的封包解包,能夠節約CPU運算,提高網絡效率。
Calico的主要組件如下:
- ◎ Felix:Calico Agent,運行在每個Node上,負責為容器設置網絡資源(IP地址、路由規則、iptables規則等),保證跨主機容器網絡互通。
- ◎ etcd:Calico使用的后端存儲。
- ◎ BGP Client:負責把Felix在各Node上設置的路由信息通過BGP廣播到Calico網絡。
- ◎ Route Reflector:通過一個或者多個BGP Route Reflector完成大規模集群的分級路由分發。
- ◎ CalicoCtl:Calico命令行管理工具。
查看已經部署的pod
[root@k8s-master01 config