天天看點

Flannel網絡方案

     這裡講一下Flannel網絡方案,梳理下其工作方式,各個環節配置,以及轉發包流程。

    Fannel項目是CoreOS公司主推的容器網絡方案。目前實作的技術有三種,分别是:

  • UDP
  • Vxlan
  • Host-GW

1. UDP方式

        Udp方式是Flannel項目最早支援的,也是性能最差的一種。目前已經被棄用,不過,這種方式最直接、也是最容易了解的跨主機實作。

Flannel網絡方案

                                              Figure -- 1

如圖Figure -- 1,有兩台主控端節點1和節點2,分别有下面的配置:

  • 節點1:有容器1,IP位址是100.96.1.2,對應的docker0網橋IP位址是100.96.1.1,網絡插件背景fanneld在udp端口8285上偵聽,并建立了tun裝置fannel0。
  • 節點2:有容器3,IP位址是100.96.2.3,對應的docker0網橋IP位址是100.96.2.1,網絡插件背景fanneld在udp端口8285上偵聽,并建立了tun裝置fannel0。

        這裡,先講述下flannel0這個TUN裝置是個什麼樣的裝置?在linux中,TUN裝置是一種工作在三層的虛拟網絡裝置。它的工作原理非常簡單,即:在作業系統核心和使用者空間程式傳遞IP包。fannel0這個裝置的IP位址是100.96.1.0/16,其網絡位址是100.96.0.0,子網路遮罩:255.255.0.0,主機位址是:100.96.1.0。

      現在,來分析下節點1的容器1是如何與節點2的容器3之間互相IP通信的。

      1)容器1查詢路由表,比對預設路由,發送到容器2目的IP是100.96.2.3包到docker0(預設網關100.96.1.1)。

      2)節點1的交換裝置docker0發現收到的封包目的mac是自己時,就不做二層轉發,把封包送到ip協定棧,由核心路由轉發。

               # 在節點1 上

              $ ip route

                default via 10.168.0.1 dev eth0

                100.96.0.0/16 dev flannel0  proto kernel  scope link  src 100.96.1.0

                100.96.1.0/24 dev docker0  proto kernel  scope link  src 100.96.1.1

                10.168.0.0/24 dev eth0  proto kernel  scope link  src 10.168.0.2

             路由比對到第二條,就是100.96.0.0/16對應的路由規則,進而進入到fannel0這個裝置。

     3)在使用者态的flanneld程序,會在fannel0裝置上接收到這個IP包。fanneld程序檢視封包的目的IP位址是100.96.2.3,通過查詢etcd選擇發送封包到哪個節點。

          $ etcdctl ls /coreos.com/network/subnets

             /coreos.com/network/subnets/100.96.1.0-24

             /coreos.com/network/subnets/100.96.2.0-24

            /coreos.com/network/subnets/100.96.3.0-24

         $ etcdctl get /coreos.com/network/subnets/100.96.2.0-24

           {"PublicIP":"10.168.0.3"}

      查詢後,發現目的IP是100.96.2.3的容器在節點2上,fanneld把IP包封裝在UDP發送給節點2。

   4)節點2的處理流程與節點1類似,最終這個IP包會送到目的容器3。

   這裡需要掌握下面幾個關鍵的知識點:

  • 發到跨主控端容器的IP包,是根據fanneld添加的路由規則,經過fannel0這個TUN裝置送到flanneld這個服務程式的。
  • TUN這種虛拟的網絡裝置,用在核心和使用者空間互相收發IP包。
  • Etcd會記錄主控端容器網絡和主控端網絡的對應關系,fanneld程序根據這些記錄選擇發送目的容器的封包到哪個主控端。

思考:

      flannel0這個裝置的IP位址是100.96.1.0/16,可以設定成100.96.0.1嗎?為什麼不能設定成100.96.1.0/24?

2. VXLAN方式

       VXLAN,即Virtual Extensible LAN(虛拟可擴充區域網路),類似于VLAN(Virtual LAN),用于在實體的網絡内建立邏輯上獨立的二層廣播域。這裡講述下它們之間的差異:

  • VLAN支援2^12=4096個辨別,VXLAN支援2^24多大16M的辨別。
  • VXLAN将VXLAN封包加上以太幀頭後封裝在UDP中,使用實體網絡的ip和mac作為outer-header,通過IP網絡轉發;VLAN将VLAN封包加上以太幀頭直接通過實體以太網轉發。
  • VXlAN是在IP網絡上建構的虛拟Overlay Network,這個IP網絡可以跨主機、跨機房,跨地域,前提是IP互通;VLAN是在實體鍊路可通路的廣播域區域網路上建立的,地域上是有局限的。
  • VXLAN控制層面隧道實作主要分三種:軟體自學習、通過控制協定學習(IS-IS或者BGP)和通過SDN controller實作。VLAN控制層面實作主要分二種:管理者靜态配置(基于端口或者mac位址)和通過協定(GVRP、GARP)學習。

   VXLAN根據不同的業務場景,分為三種不同的組網模式:

  • Network Overlay 隧道封裝在實體交換機完成。這種Overlay的優勢在于實體網絡裝置性能轉發性能比較高,可以支援非虛拟化的實體伺服器之間的組網互通。
  • Host Overlay 隧道封裝在vSwitch、具備VXLAN功能的軟體完成,不用增加新的網絡裝置即可完成Overlay部署,可以支援虛拟化的伺服器之間的組網互通。
  • Hybrid Overlay是Network Overlay和Host Overlay的混合組網,可以支援實體伺服器和虛拟伺服器之間的組網互通。

       在學習了VXLAN基本原理以及組網模型後,再來了解在docker容器場景,通過VXLAN技術建構一個容器間可以互相通路的Overlay Network就比較容易了。Linux核心本身就支援VXLAN,是以說,通過核心實作Host Overlay方式組網,容器場景不需要滿足多租戶隔離,主控端軟體學習的方式實作控制層“隧道”,僅需建構一個bridge domain的VXLAN,容器就可以通過這個虛拟的Overlay Network互相通路了。

        這裡講述下VTEP這個裝置。為了能夠打通“隧道”,VXLAN會在主控端上設定一個特殊的網絡裝置作為“隧道”的兩端。這個裝置就叫作VTEP(VXLAN Tunnel End Point)。它的作用,就是封裝和解封裝容器發送和接收的二層資料幀(Ethernet Frame)。

Flannel網絡方案

                                           Figure -- 2

       如圖Figure -- 2所示,來分析下節點1的容器1是如何與節點2的容器3是如何IP通路。為了友善叙述,接下來會把這個容器發送的IP包稱為“原始IP包”,節點1和節點2上的fannel裝置分别稱為“源VETP裝置”和“目的VETP裝置”。

     1)容器1查詢路由表,比對預設路由,發送到容器2目的IP是10.1.16.3包到docker0(預設網關10.1.15.1)。

     2)節點1的交換裝置docker0發現收到的封包目的mac是自己時,就不做二層轉發,把封包送到ip協定棧,由核心路由轉發到fannel.1裝置處理。

      # 在節點1 上

       $ route -n

          Kernel IP routing table

          Destination     Gateway         Genmask      Flags Metric Ref  Use  Iface

          ...

         10.1.16.0       10.1.16.0       255.255.255.0   UG    0   0    0   flannel.1

         這條路由規則的意思是:發往10.1.16.0/24網段的IP包,都需要經過fannel.1裝置發出,并且下一跳網關位址是:10.1.16.0。這條路由是fanneld程序在節點2啟動并加入到fannel網絡後,在節點1(以及是以其他節點)上添加的。

     3)節點1的flannel.1,這個“源VETP裝置”收到“原始IP”後,添加Inner Ethernet Header和VXLAN Header,然後發送給“目的VTEP裝置”,這個Inner二層幀格式如下:

Flannel網絡方案

                                 Figure -- 3

       VNI:Virtual network identify,類似于VLAN ID,用來差別不同的VXLAN網絡,VNI不同的VXAN不能二層互通。fannel網絡方案預設建立VNI為1的VXLAN。

      dst mac:“目的VTEP裝置”的mac位址,在步驟二路由查詢到“目的VTEP裝置”的IP位址是10.1.16.0,根據ARP位址解析,來獲得對應IP的mac位址。

          # 在節點1上

            $ ip neigh show dev flannel.1

              10.1.16.0 lladdr 5e:f8:4f:00:e3:37 PERMANENT

              這條ARP entry,與步驟2)的路由一樣,也是fanneld程序在節點2啟動加入fannel網絡後添加到節點1(以及其他節點)上的。

   4)Linux核心的VXLAN子產品封裝這個Inner ethernet frame到UDP發送。前面已經知道了“目的VTEP裝置”的IP位址,不過它在哪台主控端上呢?在前面講VXLAN控制層面隧道實作時有講到有“軟體自學習”這種方式,在fannel網絡場景下,fannel.1裝置扮演一個“網橋”的角色,fanneld程序會在“網橋”的FDB(forwarding database)裡添加這麼一條記錄:

        # 在節點1上,使用“目的 VTEP 裝置”的 MAC 位址進行查詢

        $ bridge fdb show flannel.1 | grep 5e:f8:4f:00:e3:37

          5e:f8:4f:00:e3:37 dev flannel.1 dst 10.168.0.3 self permanent

      發送到“目的VTEP裝置”的資料,應該通過fannel.1裝置,發往IP位址為10.168.0.3的主機,即節點2,UDP包要發往的目的地找到了。

   5)接下來,就在主控端上和正常的UDP封包(如圖Figure -- 4)發送一樣了。

Flannel網絡方案

                               Figure -- 4

    6)節點2的處理流程與節點1類似,最終這個IP包會送到目的容器3。

思考:

  • flannel.1裝置的IP位址是10.1.15.0/32,子網路遮罩是255.255.255.255,網絡位址就是10.1.15.0,主機位址是0,這個fannel.1作為一個單點的區域網路了,可以通過該裝置發送包到網關10.1.16.0?
  • 主控端不在同一IP網絡的情況下,VXLAN方式可行嗎?

3. Host-GW方式

       前面兩小節,為大家講述了docker容器flannel網絡方案,運用UDP軟體轉發和VXLAN技術,解決了不同主控端之間容器通信的問題。通過分析,這兩種方式都存在着不小的性能損失。

  • UDP方式,“原始IP包”需要經過tun裝置從核心态到flanneld使用者态程序,然後通過UDP方式通過socket從使用者态到核心态,最後通過主機網卡發送出去。
  • VXLAN方式,雖然linux核心本身就支援該功能,不過整個通信過程,多了額外的封裝和解封裝,也帶來不少的性能損耗。

       除了上面兩種方式外,還有一種純三層的網絡方案(pure layer3),根據測試,host-gw的性能損失在10%左右,VXLAN方式,性能損失在20%~30%左右,UDP方式就更大了。而且,學習配置好路由規則後,資料層面的轉發在核心IP路由完成,不需要額外的軟體參與。

Flannel網絡方案

                                      Figure -- 5

      如圖Figure -- 5,節點1上的容器1通路節點2上的容器3。docker0裝置在收到“原始IP包”後,查詢路由表,發現這麼一條路由規則:

      10.1.16.0/24 via 10.168.0.3 dev eth0

這條規則的含義是:目的位址屬于10.1.16.0/24網段的IP包,都應該經過本機的eth0發送出去,并且它的下一跳是10.168.0.3。從figure -- 8可以看到,這個下一跳就是目的主控端節點2的IP位址。這樣,這個資料幀就會從節點1通過主控端的二層網絡順利到達節點2。

知識點:

        Host-gw的工作原理,其實就是在主控端上,添加一條到達每個fannel子網的路由,這條路由的下一跳即網關就是相對應的fannel子網所在的“主機”。這些路由規則是flanneld根據容器部署的場景建立和更新的。