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

1 Kubernetes網絡模型

基本原則:每一個Pod都擁有一個獨立IP,並且假定全部Pod都在一個能夠直接連通的、扁平的網絡空間中。node

  • 基於基本原則,用戶不須要額外考慮如何創建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命令操做linux

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工具查看docker

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模式bash

  • 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及直接路由的方式
相關文章
相關標籤/搜索