一、Bridge網絡介紹
1.網絡模型圖
2.Bridge網絡的構建過程,對上圖的各個網絡名稱做解釋說明
(1)安裝Docker時,創建一個名為docke0的虛擬網橋,虛擬網橋使用“10.0.0.0-10.255.255.255 “、”172.16.0.0-172.31.255.255″和“192.168.0.0——192.168.255.255”這三個私有網絡的地址范圍。
通過 ifconfig命令可以查看docker0網橋的信息:
通過 docker network inspect bridge 可以查看網橋的子網網絡范圍和網關:
(2)運行容器時,會在宿主機上創建虛擬網卡vethpair設備,vethpair設備是成對出現的,從而組成一個數據通道,數據從一個設備進入,就會從另一個設備出來。將vethpair設備的一端放在新創建的容器中,命名為eth0;另一端放在宿主機的docker0中,以veth為前綴的名字命名。通過brctlshow 命令查看放在docker0中的veth pair設備
ifconfig
brctl show
3.外部訪問
bridge的docker0是虛擬出來的網橋,因此無法被外部的網絡訪問。因此需要在運行容器時通過-p和-P參數將容器的端口映射到宿主機上相應的端口。實際上Docker是采用NAT的方式,將容器內部的服務監聽端口與宿主機的某一個端口port 進行綁定,使得宿主機外部可以將網絡報文發送至容器。
1)通過-P參數,將容器的端口映射到宿主機的隨機端口:
docker run -P {images}
2)通過-p參數,將容器的端口映射到宿主機的制定端口:
docker run -p {hostPort}:{containerPort} {images}
二、kubernetes常見的網絡通信方式
1、pod內部容器間的通信:同一個pod內的多個容器間的通信
2、pod和pod之間的通信:從一個pod Ip到另一個pod Ip
3、pod與service通信:pod ip到serviceip
(1)pod內部容器之間通信
pod內部的容器是共享網絡名稱空間的,所以容器直接可以使用localhost訪問其他容器;k8s在啟動容器的時候會先啟動一個Pause容器,這個容器就是實現這個功能的。
pause:
每個Pod里運行着一個特殊的被稱之為Pause的容器,其他容器則為業務容器,這些業務容器共享Pause容器的網絡棧和Volume存儲卷,因此他們之間通信和數據交換更為高效,在設計時我們可以充分利用這一特性將一組密切相關的服務進程放入同一個Pod中。
(2)pod與pod之間的通信
此種類型又分為兩種情況:
兩個pod在同一台節點上:此時是利用docker默認的網橋bridge方式互連容器的。
兩個pod在不同節點上:這種情況k8s官方推薦的是使用flannel網絡,pod的ip分配由flannel統一分配,通訊過程也是走flannel的網橋方式。
(3)pod與service服務之間的通信
通過暴露主機IP和端口的形式進行通訊
要解決上面的幾種通信問題,需要靠CNI網絡插件實現
要解決上面四種通信的問題,需要靠CNI插件接口:
kubernetes中的網絡插件
Kubernetes中常見的網絡插件有哪些?
1.flannel:能提供ip地址,但不支持網絡策略
2.calico:既提供ip地址,又支持網絡策略
3.canal:flannel和calico結合,通過flannel提供ip地址,calico提供網絡策略
什么叫做網絡策略?
網絡策略:可以達到多租戶網絡隔離,可以控制入網和出網流量,入網和出網ip訪問的一種策略
三、flannel網絡方案
1、flannel介紹
Flannel是CoreOS團隊針對Kubernetes設計的一個網絡服務,它的功能是讓集群中的不同節點創建的Docker容器都具有全集群唯一的虛擬IP地址,Flannel的設計目的就是為集群中的所有節點重新規划IP地址,從而使得不同節點上的容器能夠獲得“同屬一個內網”且”不重復的”IP地址,並讓屬於不同節點上的容器能夠直接通過內網IP通信,Flannel實質上是一種“覆蓋網絡(overlaynetwork)”,也就是將TCP數據包裝在另一種網絡包里面進行路由轉發和通信,目前已經支持udp、vxlan、host-gw、aws-vpc、gce路由等數據轉發方式。
2、flannel支持的路由轉發方式
1、vxlan(源數據包封裝在另一種網絡包里面進行路由轉發和通信)
包含以下兩種模式
- vxlan:疊加網絡模式,利用內核級別的VXLAN來封裝host之間傳送的包;
- Directrouting:直接路由模式,當主機位於同一子網時,啟用直接路由(類似host-gw),通過宿主機的物理網卡通信;
2、host-gw:直接路由模式,要求所有pod在同一個網段中,host-gw性能好,依賴少,並且易於設置。Flannel通過在各個節點上的Agent進程,將容器網絡的路由信息刷到主機的路由表上,這樣一來所有的主機都有整個容器網絡的路由數據了。
3、UDP:不可用於生產環境,僅在內核或網絡無法使用VXLAN或 host-gw時,用 UDP 進行調試。最早支持的一種方式,由於性能最差,目前已經棄用
VXLAN
# kubeadm部署指定Pod網段
kubeadm init --pod-network-cidr=10.244.0.0/16
# 二進制部署指定
cat /opt/kubernetes/cfg/kube-controller-manager.conf --allocate-node-cidrs=true \ --cluster-cidr=10.244.0.0/16 \ # kube-flannel.yml net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } }
flannel網絡原理圖
原理圖解釋說明
1.網卡和組件說明
安裝flannel時會創建一個名為flannel0的網橋,這個網橋的一端連接docker0的網橋,另一端連接一個名為flanneld的服務進程。
Flanneld守護進程:它需要連etcd,利用etcd來管理可分配的IP資源,同時監控etcd中每個Pod的實際地址,將docker0發給它的數據包裝起來,利用物理網絡的連接將數據包投遞到目標flanneld上,從而完成pod到pod之間的通信
2.ping包走向
(1)數據從源容器中發出后,經由所在主機的docker0虛擬網卡轉發到flannel0虛擬網卡,flanneld服務監聽在網卡的另外一端。
(2)源主機的flanneld服務將原本的數據內容封裝成一個數據包,然后根據自己的路由表投遞給目的節點的flanneld服務,數據到達以后被解包,然后直接進入目的節點的flannel0虛擬網卡,然后被轉發到目的主機的docker0虛擬網卡,最后就像本機容器通信一樣由docker0路由到達目標容器。
注:
flannel通過Etcd分配了每個節點可用的IP地址段后,可以保證每個結點上容器分配的地址不沖突。
四、flannel的原理
flannel旨在解決不同節點上的容器網絡互聯問題,大致原理是為每個 host 分配一個子網,容器從此子網中分配IP,這些 IP可以在 host間路由,容器間無需 NAT 轉發就可以跨主機通信,為了在各個主機間共享信息,flannel 用 etcd(如果是k8s集群會直接調用k8s api)存放網絡配置、已分配的子網、主機ip等信息。
通過具體例子解釋容器跨節點通信時數據包走向
假設容器1是nginx,容器2是tomcat
(1)在發送端的node1節點上,數據請求從nginx容器(10.0.46.2:2379)發出后,首先經由所在主機的docker0虛擬網卡(10.0.46.1)轉發到flannel0虛擬網卡(10.0.46.0)。
(2)接着flannel服務將原本的數據內容UDP封裝后根據自己的路由表投遞給目的節點的flanneld服務。在此包中,包含有router-ip(宿主機源ip:192.168.8.227 ;宿主機目的ip:192.168.8.228),還有容器ip(source:10.0.46.2:2379dest:10.0.90.2:8080)等數據信息。
(3)然后在接收端node2節點上,數據到達以后被解包,直接進入目的節點的flannel0虛擬網卡中(10.0.90.0),且被轉發到目的主機的docker0虛擬網卡(10.0.90.1),最后就像本機容器通信一樣由docker0路由到達目標 tomcat 容器(10.0.90.2:8080)。
五、flannel部署及參數配置
1.部署
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl get pods -n kube-system -o wide 顯示如下:
kubectl get configmap -n kube-system 顯示如下:
這個kube-flannel-cfg用來設置上面看到的flannel是怎么運行的,它可以把相關的變量注入到flannel的pod中。
kubectl get configmap kube-flannel-cfg -n kube-system -o yaml可顯示configmap的yaml文件內容,具體內容在備注列出
net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } } 上面可以看到使用的后端網絡模型是vxlan,為pod分配的網段是10.244.0.0/16
2.把flannel后端的通信類型修改成Directrouting
重新修改flannel的yaml文件
cd/root/manifests/
mkdir flannel
cd flannel
修改kube-flannel.yml文件
kube-flannel.yaml這個文件里在net-conf.json字段增加了”Directrouting”: true,表示是使用直接路由模式,如果沒有這個字段就表示使用的是vxlan這種疊加網絡模式通信。
kubectl delete -f kube-flannel.yml
等到上面關於flannel的pod都刪除之后再重新執行:
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system 顯示如下,說明重新生成了flannel這個pod,這時后端通信類型使用的就是directrouting了
驗證是否是通過Directrouting(直接路由模式)通信
cd /root/manifests
kubectl apply -f deploy-myapp.yaml
cat deploy-myapp.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
kubectl get pods -o wide 顯示如下,說明pod創建成功:
窗口1:
kubectl exec -itmyapp-deploy-69b47bc96d-7s7zs -- /bin/sh
窗口2:
kubectl exec -itmyapp-deploy-69b47bc96d-lm4m4 -- /bin/sh
ping10.244.0.6
窗口3:抓包
tcpdump -i ens160 -nnhost 172.21.0.100 顯示如下:
上面可以看到兩個pod之間的通信是通過ens160,而不是overlay(覆蓋網絡),這樣就提高了網絡傳輸性能;如果兩個節點是跨網段的,那么就會降級到vxlan(疊加網絡)模式,否則就可以使用直接路由模式。
3.把flannel的后端通信方式改成host-gw
修改kube-flannel.yml文件的如下部分
net-conf.json: | { "Network":"10.244.0.0/16", "Backend":{ "Type":"host-gw" } }
注:上面修改flannel的網絡模式,一般在剛開始安裝flannel的時候修改,不要在線上直接修改
4.flannel中vxlan和host-gw的區別
vxlan模式下的的vxlan是一種覆蓋網絡;host-gw是直接路由模式,將主機作為網關,依賴於純三層的ip轉發。
不同網絡模型的性能分析
1.vxlan的Directrouting模式和host-gw模式性能一樣,都是通過宿主機的物理網絡進行通信,效率高於vxlan的vxlan模式,但是不能實現跨網段通信; 2.如果要跨網段通信vxlan的Directrouting模式會自動降級到vxlan的vxlan這種疊加網絡模式
5.Flannel網絡優點:
1)集群中的不同Node主機創建的Docker容器都具有全集群唯一的虛擬IP地址。
2)etcd保證了所有node上flanned所看到的配置是一致的,同時每個node上的flanned監聽etcd上的數據變化,實時感知集群中node的變化
6.Flannel網絡缺點:
不支持pod之間的網絡隔離,不支持網路策略
六、卸載flannel網絡
#第一步,在master節點刪除flannel
kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#第二步,在node節點清理flannel網絡留下的文件
ifconfig cni0 down ip link delete cni0 ifconfig flannel.1 down ip link delete flannel.1 rm -rf /var/lib/cni/ rm -f /etc/cni/net.d/* 注:執行完上面的操作,重啟kubelet
#第三步,應用calico相關的yaml文件
七、有待梳理
源地址:https://mp.weixin.qq.com/s/J0rV2gPzb-lx3ldJa2U4Tg
為了能夠在二層網絡上打通“隧道”,VXLAN 會在宿主機上設置一個特殊的網絡設備作為“隧道”的兩端。這個設備就叫 VTEP,即:VXLAN Tunnel End Point(虛擬隧道端點)。下圖flannel.1的設備就是VXLAN所需的VTEP設備。示意圖如下
1. 容器路由:容器根據路由表從eth0發出
# ip route
default via 10.244.0.1 dev eth0
10.244.0.0/24 dev eth0 scope link src 10.244.0.45
10.244.0.0/16 via 10.244.0.1 dev eth0
2. 主機路由:數據包進入到宿主機虛擬網卡cni0,根據路由表轉發到flannel.1虛擬網卡,也就是來到了隧道的入口。
# ip route
default via 192.168.31.1 dev ens33 proto static metric 100
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
最后一條規則意思是,凡是發往10.244.2.0/24網段的數據包,都需要經過flannel.1設備發出,並且網關地址是10.244.2.0,即Node2 VTEP設備flannel.1。
3. VXLAN封裝:而這些VTEP設備之間組成一個二層網絡,但是二層網絡必須要知道目的MAC地址,那這個MAC地址從哪獲取到呢?其實在flanneld進程啟動后,就會自動添加其他節點ARP記錄,可以通過ip命令查看,如下所示:
# ip neigh show dev flannel.1
10.244.1.0 lladdr ca:2a:a4:59:b6:55 PERMANENT
10.244.2.0 lladdr d2:d0:1b:a7:a9:cd PERMANENT
可以看到10.244.2.0對應MAC地址是d2:d0:1b:a7:a9:cd。
4. 二次封包:知道了目的MAC地址,Linux內核就可以進行二層封包了。但是,對於宿主機網絡來說這個二層幀並不能在宿主機二層網絡里傳輸。所以接下來,Linux內核還要把這個數據幀進一步封裝成為宿主機網絡的一個普通數據幀,好讓它載着內部數據幀,通過宿主機的eth0網卡進行傳輸。
5. 封裝到UDP包發出去:在封裝成宿主機網絡可傳輸的數據幀時,還缺少目標宿主機MAC地址,也就是說這個UDP包該發給哪台宿主機呢?
flanneld進程也維護着一個叫做FDB的轉發數據庫,所以使用這個目的IP與MAC地址進行封裝。
6. 數據包到達目的宿主機:是宿主機與宿主機之間通信了,數據包從Node1的eth0網卡發出去,Node2接收到數據包,解封裝發現是VXLAN數據包,把它交給flannel.1設備。flannel.1設備則會進一步拆包,取出原始IP包(源容器IP和目標容器IP),通過cni0網橋二層轉發給容器。