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及直接路由的方式