Kubernetes網路原理解析
1. kubernetes網路模型
1.1. 基礎原則
- 每個Pod都擁有一個獨立的IP地址,而且假定所有Pod都在一個可以直接連通的、扁平的網路空間中,不管是否執行在同一Node上都可以通過Pod的IP來訪問。
- k8s中Pod的IP是最小粒度IP。同一個Pod內所有的容器共享一個網路堆疊,該模型稱為IP-per-Pod模型。
- Pod由docker0實際分配的IP,Pod內部看到的IP地址和埠與外部保持一致。同一個Pod內的不同容器共享網路,可以通過localhost來訪問對方的埠,類似同一個VM內的不同程序。
- IP-per-Pod模型從埠分配、域名解析、服務發現、負載均衡、應用配置等角度看,Pod可以看作是一臺獨立的VM或物理機。
1.2. k8s對叢集的網路要求
- 所有容器都可以不用NAT的方式同別的容器通訊。
- 所有節點都可以在不同NAT的方式下同所有容器通訊,反之亦然。
- 容器的地址和別人看到的地址是同一個地址。
以上的叢集網路要求可以通過第三方開源方案實現,例如flannel。
1.3. 網路架構圖
1.4. k8s叢集IP概念彙總
由叢集外部到叢集內部:
IP型別 | 說明 |
---|---|
Proxy-IP | 代理層公網地址IP,外部訪問應用的閘道器伺服器。[實際需要關注的IP] |
Service-IP | Service的固定虛擬IP,Service-IP是內部,外部無法定址到。 |
Node-IP | 容器宿主機的主機IP。 |
Container-Bridge-IP | 容器網橋(docker0)IP,容器的網路都需要通過容器網橋轉發。 |
Pod-IP | Pod的IP,等效於Pod中網路容器的Container-IP。 |
Container-IP | 容器的IP,容器的網路是個隔離的網路空間。 |
2. Docker的網路基礎
2.1. Network Namespace
不同的網路名稱空間中,協議棧是獨立的,完全隔離,彼此之間無法通訊。同一個網路名稱空間有獨立的路由表和獨立的Iptables/Netfilter來提供包的轉發、NAT、IP包過濾等功能。
2.1.1. 網路名稱空間的實現
將與網路協議棧相關的全域性變數變成一個Net Namespace變數的成員,然後在呼叫協議棧函式中加入一個Namepace引數。
2.1.2. 網路名稱空間的操作
1、建立網路名稱空間
ip netns add
2、在名稱空間內執行命令
ip netns exec
3、進入名稱空間
ip netns exec bash
3. Docker的網路實現
3.1. 容器網路
Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的預設閘道器。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通訊。
Docker網橋是宿主機虛擬出來的,並不是真實存在的網路裝置,外部網路是無法定址到的,這也意味著外部網路無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過對映容器埠到宿主主機(埠對映),即docker run建立容器時候通過 -p 或 -P 引數來啟用,訪問容器的時候就通過[宿主機IP]:[容器埠]訪問容器。
3.2. 4類網路模式
Docker網路模式 | 配置 | 說明 |
---|---|---|
host模式 | –net=host | 容器和宿主機共享Network namespace。 |
container模式 | –net=container:NAME_or_ID | 容器和另外一個容器共享Network namespace。 kubernetes中的pod就是多個容器共享一個Network namespace。 |
none模式 | –net=none | 容器有獨立的Network namespace,但並沒有對其進行任何網路設定,如分配veth pair 和網橋連線,配置IP等。 |
bridge模式 | –net=bridge(預設為該模式) |
3.3. bridge模式
k8s只使用bridge模式。
在bridge模式下,Docker Daemon首次啟動時會建立一個虛擬網橋docker0,地址通常為172.x.x.x開頭,在私有的網路空間中給這個網路分配一個子網。由Docker建立處理的每個容器,都會建立一個虛擬以太裝置(Veth裝置對),一端關聯到網橋,另一端使用Namespace技術對映到容器內的eth0裝置,然後從網橋的地址段內給eth0介面分配一個IP地址。
一般情況,宿主機IP與docker0 IP、容器IP是不同的IP段,預設情況,外部看不到docker0和容器IP,對於外部來說相當於docker0和容器的IP為內網IP。
4. kubernetes的網路實現
k8s網路場景
- 容器與容器之間的直接通訊。
- Pod與Pod之間的通訊。
- Pod到Service之間的通訊。
- 叢集外部與內部元件之間的通訊。
4.1. Pod網路
Pod作為kubernetes的最小排程單元,Pod是容器的集合,是一個邏輯概念,Pod包含的容器都執行在同一個宿主機上,這些容器將擁有同樣的網路空間,容器之間能夠互相通訊,它們能夠在本地訪問其它容器的埠。 實際上Pod都包含一個網路容器,它不做任何事情,只是用來接管Pod的網路,業務容器通過加入網路容器的網路從而實現網路共享。Pod網路本質上還是容器網路,所以Pod-IP就是網路容器的Container-IP。
一般將容器雲平臺的網路模型打造成一個扁平化網路平面,在這個網路平面內,Pod作為一個網路單元同Kubernetes Node的網路處於同一層級
4.2. 容器之間的通訊
同一個Pod之間的不同容器因為共享同一個網路名稱空間,所以可以直接通過localhost直接通訊。
4.3. Pod之間的通訊
4.3.1. 同Node的Pod之間的通訊
同一個Node內,不同的Pod都有一個全域性IP,可以直接通過Pod的IP進行通訊。Pod地址和docker0在同一個網段。
4.3.2. 不同Node的Pod之間的通訊
不同的Node之間,Node的IP相當於外網IP,可以直接訪問,而Node內的docker0和Pod的IP則是內網IP,無法直接跨Node訪問。需要通過Node的網絡卡進行轉發。
所以不同Node之間的通訊需要達到兩個條件:
- 對整個叢集中的Pod-IP分配進行規劃,不能有衝突(可以通過第三方開源工具來管理,例如flannel)。
- 將Node-IP與該Node上的Pod-IP關聯起來,通過Node-IP再轉發到Pod-IP。
1. Pod間實現通訊
例如:Pod1和Pod2(同主機),Pod1和Pod3(跨主機)能夠通訊
實現:因為Pod的Pod-IP是Docker網橋分配的,Pod-IP是同Node下全域性唯一的。所以將不同Kubernetes Node的 Docker網橋配置成不同的IP網段即可。
2. Node與Pod間實現通訊
例如:Node1和Pod1/ Pod2(同主機),Pod3(跨主機)能夠通訊
實現:在容器叢集中建立一個覆蓋網路(Overlay Network),聯通各個節點,目前可以通過第三方網路外掛來建立覆蓋網路,比如Flannel和Open vSwitch等。
4.4. Service網路
Service的就是在Pod之間起到服務代理的作用,對外表現為一個單一訪問介面,將請求轉發給Pod,Service的網路轉發是Kubernetes實現服務編排的關鍵一環。Service都會生成一個虛擬IP,稱為Service-IP, Kuberenetes Porxy元件負責實現Service-IP路由和轉發,在容器覆蓋網路之上又實現了虛擬轉發網路。
Kubernetes Porxy實現了以下功能:
- 轉發訪問Service的Service-IP的請求到Endpoints(即Pod-IP)。
- 監控Service和Endpoints的變化,實時重新整理轉發規則。
- 負載均衡能力。
5. 開源的網路元件
5.1. Flannel
參考《Kubernetes權威指南》