《Kubernetes權威指南》——網絡原理


1 Kubernetes網絡模型

基本原則:每個Pod都擁有一個獨立IP,而且假定所有Pod都在一個可以直接連通的、扁平的網絡空間中。

  • 基於基本原則,用戶不需要額外考慮如何建立Pod之間的連接,也不需要考慮容器端口映射到主機端口等問題
  • 同一個Pod內部的所有容器共享一個網絡堆棧即網絡命名空間,Pod內的所有容器的端口是共享的
  • Kubernetes對集群網絡要求:
    • 所有容器都可以在不用NAT的方式下同別的容器通信
    • 所有節點都可以在不用NAT的方式下同所有容器通信,反之亦然
    • 容器的地址和別人看到的地址是同一個

2 Docker的網絡基礎

2.1 網絡命名空間

  • Linux在網絡棧中引入網絡命名空間(Network Namespace)為了支持網絡協議棧的多個實例,處於不同命名空間的網絡棧是完全隔離的
  • Linux的網絡命名空間內可以有自己獨立的路由表及獨立的Iptables/Netfilter設置來提供轉發、NAT及IP包過濾等功能
  • 需要納入命名空間的元素有進程、套接字、網絡設備等

2.1.1 網絡命名空間的實現

  • linux實現網絡命名空間的核心是讓網絡棧的全局變量變成一個Net Namespace變量的成員,然后協議棧的函數調用加入一個Namespace的參數
  • 網絡空間鏈表連接所有網絡空間,所有網絡棧變量都放入到網絡空間
  • 所有的網絡設置都只能屬於一個命名空間,通常物理設置只能關聯到root這個命名空間
  • 網絡命名空間代表是一個獨立的協議棧,所以他們之間是相互隔離的彼此無法通信協議棧內部看不到對方

2.1.2 網絡命名空間的操作

使用iproute2系列配置工具中的ip命令操作

ip netns add <name>     #創建一個命名空間

ip netns exec <name> <command>  #在命名空間內執行命令

ip netns exec <name> bash   #執行多個命令先進入sh

2.2 Veth設備對

Veth設備都是成對出現的,可以實現不同網絡命名空間之間進行通信

  • 在Veth設置的一端發送數據時它會將數據直接發送到另一端,並觸發另一端的接收操作

2.2.1 Veth操作命令

ip link add veth0 type veth peer name veth1     #創建veth設備對

ip link show    #查看所有網絡接口

ip link set veth1 netns netns1  #將veth1掛載到netns1命名空間下

ip link set dev veth1 up    #啟動veth1設備

2.2.2 Veth設備對如何查看對端

使用ethtool工具查看

ip netns exec netns1 ethtool -S veth1   #查詢netns1下的veth1的對端,看peer_ifindex

ip netns exec netns2 ip link    #查看peer_ifindex對應的值

2.3 網橋

  • 網橋是一個二層網絡設備,可以解析收發報文,讀取目標MAC地址信息和自己記錄的MAC表結合,來決策報文轉發端口
  • Linux中多網卡可以通過網橋提供這些設備之間相互轉發數據
  • 網橋處理轉發和丟棄報文外還可以將報文發送到上層(網絡層)

2.3.1 Linux網橋的實現

  • Linux內核通過一個虛擬網橋設備(Net Device)來實現橋接,其可以綁定若干個以太網接口設備,從而將它們橋接起來
  • Net Device可以有一個IP

3 Docker的網絡實現

docker的4類網絡模式:

1. host
2. container
3. none
4. bridge,默認設置

只介紹bridge模式

  • Docker Daemon第一次啟動時將創建一個虛擬網橋默認名為docker0,同時給其分配一個子網
  • 針對Docker中的容器都會創建一個Veth設備對,一端關聯網橋一端使用Linux的網絡命名空間映射到容器內的eth0設備,然后從網橋的地址段內給eth0分配一個IP
  • 為了讓容器跨主機通信就必須在主機的地址上分配端口,然后通過這個端口路由或代理到容器上

4 Kubernetes的網絡實現

4.1 容器到容器的通信

  • 同一個Pod內的容器共享同一個網絡命名空間,直接使用localhost即可

4.2 Pod之間的通信

  • 每個Pod都有一個真實的全局IP,每個Node內的不同Pod之間可以直接采用對方Pod的Ip通信

4.2.1 同一Node內Pod通信

  • 同一Node內的Pod通過Veth設備對連接到同一個docker0網橋上,Pod的IP也都是該網橋分配的
  • Pod內的默認路由都是docker0的地址,所有數據都通過docker0轉發

4.2.2 不同Node的Pod通信

  • Pod的地址是與docker0在同一個網段內,而docker0網段與宿主機網卡的IP網段完全不同,而通信只能走宿主機的網卡,因此通信必須通過宿主機IP來進行尋址和通信
  • Kubernetes會記錄所有正在運行Pod的IP分配信息,並將其寫入etcd作為Service的Endpoint
  • 支持不同Node之間Pod的通信條件:
    • 整個Kubernetes集群中Pod的IP不能沖突
    • 能將Pod的IP與Node的IP關聯起來,通過這個關聯實現相互訪問
  • 解決:
    • Kubernetes部署時多docker0的IP地址進行規划保證每個Node上的docker0地址不沖突
    • 通信時先找到Node的IP將數據發送到這個網卡上,然后讓宿主機將相應數據轉到具體docker0上

4.3 Pod到Service的通信

  • k8s在創建服務時為服務分配一個虛擬IP,客戶端通過該IP訪問服務,服務則負責將請求轉發到后端Pod上
  • Service是通過kube-proxy服務進程實現,該進程在每個Node上均運行可以看作一個透明代理兼負載均衡器
  • 對每個TCP類型Service,kube-proxy都會在本地Node上建立一個SocketServer來負責接受請求,然后均勻發送到后端Pod默認采用Round Robin負載均衡算法
  • Service的Cluster IP與NodePort等概念是kube-proxy通過Iptables的NAT轉換實現,kube-proxy進程動態創建與Service相關的Iptables規則
  • kube-proxy通過查詢和監聽API Server中Service與Endpoints的變化來實現其主要功能,包括為新創建的Service打開一個本地代理對象,接收請求針對針對發生變化的Service列表,kube-proxy會逐個處理,處理流程:
    • 如果該Service沒設置ClusterIP,則不做處理,否則獲取該Service的所有端口定義列表
    • 逐個讀取端口定義列表,根據端口名、Service名和Namespace對其進行修改
    • 更新負載均衡組件中對應Service的轉發Service的轉發地址列表
    • 對於已刪除的Service則進行清理

5 開源的網絡組件

  • Kubernetes的網絡模型假定所有Pod都在一個可以直接連通的扁平網絡空間,因此需要對網絡進行設置
  • 目前常見的模型有Flunnel、Open vSwitch及直接路由的方式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM