網絡通信機制
k8s的網絡基於第三方插件實現,但是定義了一些插件兼容規范,該規范有CoreOS和Google聯合定制,叫做 CNI(Container Network Interface)。
calicoz支持更多的網絡層的安全策略,flannel不支持
公有雲大多使用flannel,使用vxlan+Directrouting模式
自建IDC使用哪種模型都可以,flannel配置比較簡單,calico功能較多
性能差別不大,calico性能會略高於flannel
私有雲推薦使用calico
公有雲推擠使用flannel
flannel
官網:https://coreos.com/flannel/docs/latest/
文檔:https://coreos.com/flannel/docs/latest/kubernetes.html
Flannel 網絡模型 (后端),Flannel目前有三種方式實現 UDP/VXLAN/host-gw
UDP:早期版本的Flannel使用UDP封裝完成報文的跨越主機轉發,其安全性及性能略有不足。
VXLAN:Linux 內核在在2012年底的v3.7.0之后加入了VXLAN協議支持,因此新版本的Flannel也有UDP轉換為 VXLAN,VXLAN本質上是一種tunnel(隧道)協議,用來基於3層網絡實現虛擬的2層網絡,目前flannel 的網絡模型已 經是基於VXLAN的疊加(覆蓋)網絡。
Host-gw:也就是Host GateWay,通過在node節點上創建到達各目標容器地址的路由表而完成報文的轉發,因此這種 方式要求各node節點本身必須處於同一個局域網(二層網絡)中,因此不適用於網絡變動頻繁或比較大型的網絡環境,但是 其性能較好。
Flannel 組件的解釋
- Cni0:網橋設備,每創建一個pod都會創建一對 veth pair,其中一端是pod中的eth0,另一端是Cni0網橋中的端口 (網卡),Pod中從網卡eth0發出的流量都會發送到Cni0網橋設備的端口(網卡)上,Cni0 設備獲得的ip地址是該節 點分配到的網段的第一個地址。
- Flannel.1: overlay網絡的設備,用來進行vxlan報文的處理(封包和解包),不同node之間的pod數據流量都從 overlay設備以隧道的形式發送到對端。
Flannel的系統文件及目錄
- root@node2:~# find / -name flannel
/run/flannel
/usr/bin/flannel
/var/lib/cni/flannel
flannel pod狀態
root@master1:~# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-85bd4f9784-95qcb 1/1 Running 0 6h15m
kube-flannel-ds-amd64-4dvn9 1/1 Running 0 23h
kube-flannel-ds-amd64-6zk8z 1/1 Running 0 23h
kube-flannel-ds-amd64-d54j4 1/1 Running 0 23h
kube-flannel-ds-amd64-hmnsj 1/1 Running 0 22h
kube-flannel-ds-amd64-k52kz 1/1 Running 0 23h
kube-flannel-ds-amd64-q42lh 1/1 Running 0 23h
當前node主機IP地址范圍
root@node1:~# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.20.0.0/16
FLANNEL_SUBNET=10.20.3.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
當前node主機cni信息
root@node1:~# cat /var/lib/cni/flannel/0929d39656c75c9518ac16a785c12ebc301a254d03e58387d27ff365e04562a0
{"cniVersion":"0.3.1","hairpinMode":true,"ipMasq":false,"ipam":{"routes":[{"dst":"10.20.0.0/16"}],"subnet":"10.20.3.0/24","type":"host-local"},"isDefaultGateway":true,"isGateway":true,"mtu":1450,"name":"cbr0","type":"bridge"}
UDP網絡模型(不可用)
重新執行網絡並重啟master與node服務器
- 設置flannel 后端
- FLANNEL_BACKEND: "host-gw"
- FLANNEL_BACKEND: "vxlan"
- FLANNEL_BACKEND: "UDP
修改backend為UDP
Type有變量FLANNEL_BACKEND定義
root@master1:~# vim /etc/ansible/roles/flannel/templates/kube-flannel.yaml.j2
net-conf.json: |
{
"Network": "{{ CLUSTER_CIDR }}",
"Backend": {
{% if FLANNEL_BACKEND == "vxlan" and DIRECT_ROUTING %}
"DirectRouting": true,
{% endif %}
"Type": "{{ FLANNEL_BACKEND }}"
}
}
查找定義FLANNEL_BACKEND變量的文件
root@master1:~# grep FLANNEL_BACKEND /etc/ansible/roles/flannel/ -R
/etc/ansible/roles/flannel/defaults/main.yml:#FLANNEL_BACKEND: "host-gw"
/etc/ansible/roles/flannel/defaults/main.yml:FLANNEL_BACKEND: "vxlan"
/etc/ansible/roles/flannel/templates/kube-flannel.yaml.j2:{% if FLANNEL_BACKEND == "vxlan" and DIRECT_ROUTING %}
/etc/ansible/roles/flannel/templates/kube-flannel.yaml.j2: "Type": "{{ FLANNEL_BACKEND }}"
將FLANNEL_BACKEND設置為UDP
root@master1:~# cat /etc/ansible/roles/flannel/defaults/main.yml
# 部分flannel配置,參考 docs/setup/network-plugin/flannel.md
# 設置flannel 后端
#FLANNEL_BACKEND: "host-gw"
#FLANNEL_BACKEND: "vxlan"
FLANNEL_BACKEND: "udp"
DIRECT_ROUTING: false
#flanneld_image: "quay.io/coreos/flannel:v0.10.0-amd64"
flanneld_image: "easzlab/flannel:v0.11.0-amd64"
# 離線鏡像tar包
flannel_offline: "flannel_v0.11.0-amd64.tar"
k8s需要重新安裝生效
VxLAN Directrouting
Directrouting 為在同一個二層網絡中的node節點啟用直接路由機制,類似於host-gw模式。
修改flannel支持Directrouting
需要讓配置文件在node節點重新生效
修改DIRECT_ROUTING:為true
root@master1:~# vim /etc/ansible/roles/flannel/defaults/main.yml
# 部分flannel配置,參考 docs/setup/network-plugin/flannel.md
# 設置flannel 后端
#FLANNEL_BACKEND: "host-gw"
FLANNEL_BACKEND: "vxlan"
DIRECT_ROUTING: true
#flanneld_image: "quay.io/coreos/flannel:v0.10.0-amd64"
flanneld_image: "easzlab/flannel:v0.11.0-amd64"
# 離線鏡像tar包
flannel_offline: "flannel_v0.11.0-amd64.tar"
重新配置network
root@master1:/etc/ansible# ansible-playbook 06.network.yml
master和node節點重啟或重裝k8s生效
root@node1:~# reboot
修改前的路由表
root@node1:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.203.104.254 0.0.0.0 UG 0 0 0 ens160
10.20.0.0 10.20.0.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.1.0 10.20.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.2.0 10.20.2.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.3.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.20.4.0 10.20.4.0 255.255.255.0 UG 0 0 0 flannel.1
10.20.5.0 10.20.5.0 255.255.255.0 UG 0 0 0 flannel.1
10.203.104.0 0.0.0.0 255.255.255.0 U 0 0 0 ens160
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
修改后的路由表
root@node1:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.203.104.254 0.0.0.0 UG 0 0 0 ens160
10.20.0.0 10.203.104.21 255.255.255.0 UG 0 0 0 ens160
10.20.1.0 10.203.104.20 255.255.255.0 UG 0 0 0 ens160
10.20.2.0 10.203.104.27 255.255.255.0 UG 0 0 0 ens160
10.20.3.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.20.4.0 10.203.104.28 255.255.255.0 UG 0 0 0 ens160
10.20.5.0 10.203.104.22 255.255.255.0 UG 0 0 0 ens160
10.203.104.0 0.0.0.0 255.255.255.0 U 0 0 0 ens160
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
host-gw網絡模型
修改FLANNEL_BACKEND為host-gw模型
root@master1:~# vim /etc/ansible/roles/flannel/defaults/main.yml
# 部分flannel配置,參考 docs/setup/network-plugin/flannel.md
# 設置flannel 后端
FLANNEL_BACKEND: "host-gw"
#FLANNEL_BACKEND: "vxlan"
DIRECT_ROUTING: false
#flanneld_image: "quay.io/coreos/flannel:v0.10.0-amd64"
flanneld_image: "easzlab/flannel:v0.11.0-amd64"
# 離線鏡像tar包
flannel_offline: "flannel_v0.11.0-amd64.tar"
重新配置network
root@master1:/etc/ansible# ansible-playbook 06.network.yml
master和node節點重啟或重裝k8s生效
root@node1:~# reboot
Flannel不同node上的pod的通信流程
Flannel.1 是一個overlay網絡的設備,用來進行 vxlan 報文的處理(封包和解包),不同node之間的pod數據流量 都從overlay設備以隧道的形式發送到對端。

->: pod中產生數據,根據pod的路由信息,將數據發送到Cni0
->: Cni0 根據節點的路由表,將數據發送到隧道設備flannel.1
->: Flannel.1查看數據包的目的ip,從flanneld獲得對端隧道設備的必要信息,封裝數據包。
->: Flannel.1將數據包發送到對端設備,對端節點的網卡接收到數據包
->: 對端節點發現數據包為overlay數據包,解開外層封裝,並發送到到本機flannel.1設備。
->: Flannel.1設備查看數據包,根據路由表匹配,將數據發送給Cni0設備。
->: Cni0匹配路由表,發送數據給網橋上對應的端口(pod)。

Calico
官網:https://www.projectcalico.org/
github: https://github.com/projectcalico/calico
Calico是一個純三層的網絡解決方案,為容器提供多node間的訪問通信,calico將每一個node節點都當做為一個路 由器(router),各節點通過BGP(Border Gateway Protocol) 邊界網關協議學習並在node節點生成路由規則,從而 將不同node節點上的pod連接起來進行通信。
BGP是一個去中心化的協議,它通過自動學習和維護路由表實現網絡的可用性,但是並不是所有的網絡都支持 BGP,另外為了跨網絡實現更大規模的網絡管理,calico 還支持IP-in-IP的疊加模型,簡稱IPIP,IPIP可以實現跨不 同網段建立路由通信,但是會存在安全性問題,其在內核內置,可以通過Calico的配置文件設置是否啟用IPIP,在 公司內部如果k8s的node節點沒有跨越網段建議關閉IPIP。
IPIP是一種將各Node的路由之間做一個tunnel,再把兩個網絡連接起來的模式。啟用IPIP模式時,Calico將在各 Node上創建一個名為"tunl0"的虛擬網絡接口。
BGP模式則直接使用物理機作為虛擬路由路(vRouter),不再創建額外的tunnel。
calico 核心組件
Felix:calico的agent,運行在每一台node節點上,其主要是維護路由規則、匯報當前節點狀態以確保pod的誇主機 通信。
BGP Client:每台node都運行,其主要負責監聽node節點上由felix生成的路由信息,然后通過BGP協議廣播至其他剩 余的node節點,從而相互學習路由實現pod通信。
Route Reflector:集中式的路由反射器,calico v3.3開始支持,當Calico BGP客戶端將路由從其FIB(Forward Information dataBase,轉發信息庫)通告到Route Reflector時,Route Reflector會將這些路由通告給部署 集群中的其他節點,Route Reflector專門用於管理BGP網絡路由規則,不會產生pod數據通信。
注:calico默認工作模式是BGP的node-to-node mesh,如果要使用Route Reflector需要進行相關配置。 https://docs.projectcalico.org/v3.4/usage/routereflector https://docs.projectcalico.org/v3.2/usage/routereflector/calico-routereflector

部署過程
修改ansible的hosts文件中的CLUSTER_NETWORK為calico
root@master1:~# grep CLUSTER_NETWORK /etc/ansible/hosts
CLUSTER_NETWORK="calico"
下載鏡像並上傳到harbor
root@master1:~# docker images | grep calico
calico/node v3.4.4 a8dbf15bbd6f 14 months ago 79.6MB
calico/cni v3.4.4 f5e5bae3eb87 14 months ago 75.4MB
calico/kube-controllers v3.4.4 0030ff291350 14 months ago 56.5MB
root@master1:~# docker tag calico/node:v3.4.4 harbor.linux.com/calico/node:v3.4.4
root@master1:~# docker push harbor.linux.com/calico/node:v3.4.4
root@master1:~# docker tag calico/cni:v3.4.4 harbor.linux.com/calico/cni:v3.4.4
root@master1:~# docker push harbor.linux.com/calico/cni:v3.4.4
root@master1:~# docker tag calico/kube-controllers:v3.4.4 harbor.linux.com/calico/kube-controllers:v3.4.4
root@master1:~# docker push harbor.linux.com/calico/kube-controllers:v3.4.4
calico-v3.4.yaml.j2配置文件
將image修改為harbor的地址,其他字段不需要修改
root@master1:/etc/ansible/roles/calico/templates# vim calico-v3.4.yaml.j2
開啟和關閉IPIP
root@master1:/etc/ansible# cat roles/calico/defaults/main.yml
# 部分calico相關配置,更全配置可以去roles/calico/templates/calico.yaml.j2自定義
# 如果 node 節點有多塊網卡,請設置 true
# 另外發現設置為 true 時能夠解決v1.10使用ipvs偶爾出現pod內‘dial tcp 10.68.0.1:443: i/o timeout’的 bug
NODE_WITH_MULTIPLE_NETWORKS: "true"
# etcd 集群服務地址列表, 根據etcd組成員自動生成
TMP_ENDPOINTS: "{% for h in groups['etcd'] %}https://{{ h }}:2379,{% endfor %}"
ETCD_ENDPOINTS: "{{ TMP_ENDPOINTS.rstrip(',') }}"
# 設置 CALICO_IPV4POOL_IPIP=“off”,可以提高網絡性能,條件限制詳見 docs/setup/calico.md
CALICO_IPV4POOL_IPIP: "Always" # 開啟IPIP
# 設置 Felix 日志級別
FELIX_LOG_LVL: "warning"
# 設置 calico-node使用的host IP,bgp鄰居通過該地址建立,可手工指定也可以自動發現
#IP_AUTODETECTION_METHOD: "interface=eth0"
IP_AUTODETECTION_METHOD: "can-reach={{ groups['kube-master'][0] }}"
# 更新支持calico 版本: [v3.2.x] [v3.3.x] [v3.4.x]
calico_ver: "v3.4.4"
# calico 主版本
calico_ver_main: "{{ calico_ver.split('.')[0] }}.{{ calico_ver.split('.')[1] }}"
# 離線鏡像tar包
calico_offline: "calico_{{ calico_ver }}.tar"
部署集群
root@master1:/etc/ansible# ansible-playbook 06.network.yml
驗證當前路由表
root@node1:~# calicoctl node status
