咱們知道docker官方並無提供多主機的容器通訊方案,單機網絡的模式主要有host,container,brige,none。none這種模式,顧名思義就是docker自己不去管理網絡模式,交由其餘管理和分配,好比cni。Flannel是一個專爲kubernetes定製的三層網絡解決方案,主要用於解決容器的跨主機通訊問題。node
首先,flannel利用Kubernetes API或者etcd用於存儲整個集羣的網絡配置,其中最主要的內容爲設置集羣的網絡地址空間。例如,設定整個集羣內全部容器的IP都取自網段「10.1.0.0/16」。
接着,flannel在每一個主機中運行flanneld做爲agent,它會爲所在主機從集羣的網絡地址空間中,獲取一個小的網段subnet,本主機內全部容器的IP地址都將從中分配。
而後,flanneld再將本主機獲取的subnet以及用於主機間通訊的Public IP,一樣經過kubernetes API或者etcd存儲起來。
最後,flannel利用各類backend ,例如udp,vxlan,host-gw等等,跨主機轉發容器間的網絡流量,完成容器間的跨主機通訊。docker
Flannel爲每一個主機提供獨立的子網,整個集羣的網絡信息存儲在etcd上。對於跨主機的轉發,目標容器的IP地址,須要從etcd獲取。
先上圖,比較直觀:
express
步驟:網絡
在經常使用的vxlan模式中,涉及到上面步驟提到的封包和拆包,這也是Flannel網絡傳輸效率相對低的緣由。併發
下面重點說一下host-gw模式。
hostgw是最簡單的backend,它的原理很是簡單,直接添加路由,將目的主機當作網關,直接路由原始封包。
例如,咱們從etcd中監聽到一個EventAdded事件subnet爲10.1.15.0/24被分配給主機Public IP 192.168.0.100,hostgw要作的工做就是在本主機上添加一條目的地址爲10.1.15.0/24,網關地址爲192.168.0.100,輸出設備爲上文中選擇的集羣間交互的網卡便可。對於EventRemoved事件,只需刪除對應的路由。tcp
由於沒有了封包和拆包,host-gw的性能是最好的。ide
不過host-gw 要求主機網絡二層直接互聯。因此每一個節點上有n-1個路由,而n個節點一共有n(n-1)/2個路由以保證flannel的flat網絡能力。性能
爲何host-gw 要求主機網絡二層直接互聯?
首先經過抓包分析,抓包結果以下圖:this
能夠看出host-gw在傳輸層走的是tcp。而後在網絡層的源IP和目的IP均是容器的IP,虛擬IP。這就決定了二層互聯,由於只有交換機是不關注源IP和目的IP。假如兩臺主機在兩個lan中,二層不通,三層通,那麼就須要路由器,而路由器是沒法識別容器的這些ip。固然也能夠配置路由規則,可是顯然沒有這麼作的。spa
Openshift默認也是使用Flannel host-gw容器網絡方案,其官網也清晰的畫出了host-gw的data flow diagram。
示例配置:
{ "Network": "10.0.0.0/8", "SubnetLen": 20, "SubnetMin": "10.10.0.0", "SubnetMax": "10.99.0.0", "Backend": { "Type": "udp", "Port": 7890 } }
啓動參數:
--public-ip="": IP accessible by other nodes for inter-host communication. Defaults to the IP of the interface being used for communication. --etcd-endpoints=http://127.0.0.1:4001: a comma-delimited list of etcd endpoints. --etcd-prefix=/coreos.com/network: etcd prefix. --etcd-keyfile="": SSL key file used to secure etcd communication. --etcd-certfile="": SSL certification file used to secure etcd communication. --etcd-cafile="": SSL Certificate Authority file used to secure etcd communication. --kube-subnet-mgr: Contact the Kubernetes API for subnet assignment instead of etcd. --iface="": interface to use (IP or name) for inter-host communication. Defaults to the interface for the default route on the machine. This can be specified multiple times to check each option in order. Returns the first match found. --iface-regex="": regex expression to match the first interface to use (IP or name) for inter-host communication. If unspecified, will default to the interface for the default route on the machine. This can be specified multiple times to check each regex in order. Returns the first match found. This option is superseded by the iface option and will only be used if nothing matches any option specified in the iface options. --iptables-resync=5: resync period for iptables rules, in seconds. Defaults to 5 seconds, if you see a large amount of contention for the iptables lock increasing this will probably help. --subnet-file=/run/flannel/subnet.env: filename where env variables (subnet and MTU values) will be written to. --subnet-lease-renew-margin=60: subnet lease renewal margin, in minutes. --ip-masq=false: setup IP masquerade for traffic destined for outside the flannel network. Flannel assumes that the default policy is ACCEPT in the NAT POSTROUTING chain. -v=0: log level for V logs. Set to 1 to see messages related to data path. --healthz-ip="0.0.0.0": The IP address for healthz server to listen (default "0.0.0.0") --healthz-port=0: The port for healthz server to listen(0 to disable) --version: print version and exit
接下來,會重點講代碼的實現部分。