1. 程式人生 > 實用技巧 >k8s網路外掛-flannel

k8s網路外掛-flannel

轉載大佬博文:https://mp.weixin.qq.com/s/IxhJp16RbBsDlNrh1uTtdw

docker的四種網路型別

(1)bridge:這是Docker預設的網路驅動,此模式會為每一個容器分配NetworkNamespace和設定IP等,並將容器連線到一個虛擬網橋上,如果未指定網路驅動,就預設使用此驅動。

(2)host:此網路驅動直接使用宿主機的網路。

(3)none:此驅動不構造網路環境,如果採用了none網路驅動,那麼就只能使用loopback網路裝置,容器只能使用127.0.0.1的本機網路。

(4)overlay:可以實現容器跨主機通訊

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

一、flannel介紹

Flannel是CoreOS團隊針對Kubernetes設計的一個網路服務,它的功能是讓叢集中的不同節點建立的Docker容器都具有全叢集唯一的虛擬IP地址,Flannel的設計目的就是為叢集中的所有節點重新規劃IP地址,從而使得不同節點上的容器能夠獲得“同屬一個內網”且”不重複的”IP地址,並讓屬於不同節點上的容器能夠直接通過內網IP通訊,Flannel實質上是一種“覆蓋網路(overlaynetwork)”,也就是將TCP資料包裝在另一種網路包裡面進行路由轉發和通訊,目前已經支援udp、vxlan、host-gw、aws-vpc、gce路由等資料轉發方式。

二、flannel支援的路由轉發方式

1.vxlan,包含以下兩種模式

(1)vxlan:疊加網路模式,利用核心級別的VXLAN來封裝host之間傳送的包;

(2)Directrouting:直接路由模式,當主機位於同一子網時,啟用直接路由(類似host-gw),通過宿主機的物理網絡卡通訊;

2.host-gw:直接路由模式,要求所有pod在同一個網段中,host-gw效能好,依賴少,並且易於設定

3.UDP:不可用於生產環境,僅在核心或網路無法使用VXLAN或host-gw時,用UDP進行除錯

三、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叢集會直接呼叫k8sapi)存放網路配置、已分配的子網、主機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

kubectlget pods -nkube-system -o wide顯示如下:

kubectlgetconfigmap -nkube-system顯示如下:

這個kube-flannel-cfg用來設定上面看到的flannel是怎麼執行的,它可以把相關的變數注入到flannel的pod中。

kubectlgetconfigmapkube-flannel-cfg-nkube-system -oyaml可顯示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/

mkdirflannel

cd flannel

修改kube-flannel.yml檔案

kube-flannel.yaml這個檔案裡在net-conf.json欄位增加了”Directrouting”: true,表示是使用直接路由模式,如果沒有這個欄位就表示使用的是vxlan這種疊加網路模式通訊。

kubectldelete -fkube-flannel.yml

等到上面關於flannel的pod都刪除之後再重新執行:

kubectlapply -fkube-flannel.yml

kubectlget pods -nkube-system顯示如下,說明重新生成了flannel這個pod,這時後端通訊型別使用的就是directrouting了

驗證是否是通過Directrouting(直接路由模式)通訊

cd /root/manifests

kubectlapply -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

kubectlget pods -o wide顯示如下,說明pod建立成功:

視窗1:

kubectlexec -itmyapp-deploy-69b47bc96d-7s7zs -- /bin/sh

視窗2:

kubectlexec -itmyapp-deploy-69b47bc96d-lm4m4 -- /bin/sh

ping10.244.0.6

視窗3:抓包

tcpdump-iens160 -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之間的網路隔離,不支援網路策略