概述
首先k8s里面容器是存在於pod里面的,所以容器之間通訊,一般分為三種類型:
1. pod內部容器之間
2. pod 與 pod 容器之間
3. pod 訪問service服務
pod內部容器之間
這種情況下容器通訊比較簡單,因為k8s pod內部容器是共享網絡空間的,所以容器直接可以使用localhost訪問其他容器。
k8s在啟動容器的時候會先啟動一個pause容器,這個容器就是實現這個功能的。
pod 與 pod 容器之間
這種類型又可以分為兩種情況:
1. 兩個pod在一台主機上面
2. 兩個pod分布在不同主機之上
針對第一種情況,就比較簡單了,就是docker默認的docker網橋互連容器。
第二種情況需要更為復雜的網絡模型了,k8s官方推薦的是使用flannel組建一個大二層扁平網絡,pod的ip分配由flannel統一分配,通訊過程也是走flannel的網橋。
docker --daemon --bip=172.17.18.1/24
注意其中的“--bip=172.17.18.1/24”這個參數,它限制了所在節點容器獲得的IP范圍。
每個node上面都會創建一個flannel0虛擬網卡,用於跨node之間通訊。所以容器直接可以直接使用pod id進行通訊。
跨節點通訊時,發送端數據會從docker0路由到flannel0虛擬網卡,接收端數據會從flannel0路由到docker0,這是因為flannel會添加一個路由
發送端:
route -n 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0 172.17.13.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
接收端:
route -n 172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0 172.17.12.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
例如現在有一個數據包要從IP為172.17.13.2的容器發到IP為172.17.12.2的容器。根據數據發送節點的路由表,它只與172.17.0.0/16匹配這條記錄匹配,因此數據從docker0出來以后就被投遞到了flannel0。同理在目標節點,由於投遞的地址是一個容器,因此目的地址一定會落在docker0對於的172.17.12.0/24這個記錄上,自然的被投遞到了docker0網卡。
flannel的原理是將網絡包封裝在udp里面,所以發送端和接收端需要裝包和解包,對性能有一定的影響。
k8s也支持其他的網絡模型,比較有名的還有calico,不過我並沒有使用過。
pod 訪問service服務
這里涉及到k8s里面一個重要的概念service。它是一個服務的抽象,通過label(k8s會根據service和pod直接的關系創建endpoint,可以通過kubectl get ep查看)關聯到后端的pod容器。
Service分配的ip叫cluster ip是一個虛擬ip(相對固定,除非刪除service),這個ip只能在k8s集群內部使用,如果service需要對外提供,只能使用Nodeport方式映射到主機上,使用主機的ip和端口對外提供服務。(另外還可以使用LoadBalance方式,但這種方式是在gce這樣的雲環境里面使用的 )。
節點上面有個kube-proxy進程,這個進程從master apiserver獲取信息,感知service和endpoint的創建,然后做兩個事:
1. 為每個service 在集群中每個節點上面創建一個隨機端口,任何該端口上面的連接會代理到相應的pod
2. 集群中每個節點安裝iptables規則,用於clusterip + port路由到上一步定義的隨機端口上面,所以集群中每個node上面都有service的轉發規則:
KUBE-PORTALS-CONTAINER //從容器中通過service cluster ip和端口訪問service的請求 KUBE-PORTALS-HOST //從主機中通過service cluster ip和端口訪問service的請求 KUBE-NODEPORT-CONTAINER //從容器中通過service nodeport端口訪問service的請求 KUBE-NODEPORT-HOST //從主機中通過service nodeport端口訪問service的請求。
見下面測試環境的內容:
-A KUBE-NODEPORT-CONTAINER -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 50171 -j REDIRECT --to-ports 52244 -A KUBE-NODEPORT-HOST -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 50171 -j DNAT --to-destination 10.45.25.227:52244 -A KUBE-PORTALS-CONTAINER -d 10.254.120.169/32 -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 1521 -j REDIRECT --to-ports 52244 -A KUBE-PORTALS-HOST -d 10.254.120.169/32 -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 1521 -j DNAT --to-destination 10.45.25.227:52244
52244就是kube-proxy針對service “"smart/ccdb:port1521"” 在節點上面監聽的端口。
原文:https://www.jianshu.com/p/b4eabf55533d