Kubernetes之十九---Kubernetes網絡插件體系及flannel基礎

1、背景

        自Docker 技術誕生以來,採用容器技術用於開發、測試甚至是生產環境的企業或組織 與日俱增。 然而,將容器技術應用於生產環境時如何確定合適的網絡方案依然是亟待解決的 最大問題,這也曾是主機虛擬化時代的著名難題之一,它不僅涉及了網絡中各組件的互連互 通,還需要將容器與不相關的其他容器進行有效隔離以確保其安全性。 本章將主要講述容器 網絡模型的進化、 Kubernetes 的網絡模型、常用網絡插件以及網絡策略等相關的話題。

 

2、Kubernetes 網絡模型及CNI插件

        Docker 的傳統網絡模型在應用至日趨複雜的實際業務場景時必將導致複雜性的幾何級 數上升,由此,Kubernetes 設計了一種網絡模型,它要求所有容器都能夠通過一個扁平的網 絡平面直接進行通信(在同一 IP 網絡中),無論它們是否運行於集羣中的同一節點。 不過, 在 Kubernetes 集羣中, IP 地址分配是以 Pod 對象爲單位,而非容器, 同一Pod 內的所有容 器共享同一網絡名稱空間。

 

2.1 Docker容器的網絡模型

Docker 容器網絡的原始模型主要有三種: Bridge(橋接)、Host(主機)及 Container(容器)。

  • Bridge 模型藉助於虛擬網橋設備爲容器建立網絡連接
  • Host 模型則設定容器直接共享使用 節點主機的網絡名稱空間
  • Container 模型則是指多個容器共享同一個網絡名稱空間,從 而彼此之間能夠以本地通信的方式建立連接。 

      Docker 守護進程首次啓動時-,它會在當前節點上創建一個名爲 dockerO 的橋設備,並默認配置其使用 172.17.0.0/16 網絡,該網絡是 Bridge 模型的一種實現, 也是創建 Docker 容 器時默認使用的網絡模型。 如圖所示, 創建 Docker 容器時,默認有四種網絡可供選擇 使用 ,從而表現出了四種不同類型的容器,具體如下。 

  • Closed container (封閉式容器): 此類容器使用“ None ”網絡,它們沒有對外通信的 網絡接 口,而是僅具有 IO 接口,通常僅用於不需要網絡的後端作業處理場景。
  • Bridged container (橋接式容器):此類容器使用“ Bridge,,模型的網絡,對於每個網 絡接口,容器引擎都會爲每個容器創建一對(兩個)虛擬以太網設備,一個配置爲容 器的接口設備,另一個則在節點主機上接人指定的虛擬網橋設備(默認爲 docker0 )。
  • Open container (開放式容器): 此類容器使用“ Host,,模型的網絡,它們共享使用 Docker 主機的網絡及其接口 。
  • Joined container(聯盟式容器):此類容器共享使用某個已存在的容器的網絡名稱空間, 即共享並使用指定的容器的網絡及其接口 。

 

 

2.2 Kubernetes 網絡模型

         Kubernetes 的網絡模型主要可用於解決四類通信需求:同一Pod 內容器間的通信(Contamer to Container)、 Pod 間的通信( Pod to Pod)、 Service 到 Pod 間的通信( Service to Pod)以及 集羣外部與 Service 之間的通信(external to Service) 。

Pod容器之間的通信方式:

  • Containers-Containers:lo
  • Pod-Pod
  • Pod-Service
  • Pod-External Clients

 

2.2.1 容器間通信 

     Pod 對象內的各容器共享同一網絡名稱空間,它通常由構建 Pod 對象的基礎架構容器所提供,例如,由 pause 鏡像啓動的容器。 所有運行於同一個 Pod 內的容器與同一主機上的多 個進程類似,彼此之間可通過 lo 接口完成交互,如圖所示, Pod P 內的 Container! 和 Container2 之間的通信即爲容器間通信。

 

2.2.2 Pod間通信

        各Pod 對象需要運行於同一個平面網絡中,每個 Pod 對象擁有一個集羣全局唯一的地 址並可直接用於與其他 Pod 進行通信,圖中的 Pod P 和 Pod Q 之間的通信。 此網絡 也稱爲 Pod 網絡。 另外,運行 Pod 的各節點也會通過橋接設備等持有此平面網絡中的一個 IP 地址,如圖 l 1-3 中的 cbr0 接口,這就意味着 Node 到 Pod 間的通信也可在此網絡上直接 進行。 因此, Pod 間的通信或 Pod 到 Node 間的通信比較類似於同一 IP 網絡中主機間進行的通信。

 

 此類通信模型中的通信需求也是 Kubernetes 的各網絡插件需要着力解決的問題,它們 的實現方式有疊加網絡模型和路由網絡模型等,流行的解決方案有十數種之多,例如前面使 用到的flannel。

 

2.2.3 Service與Pod間的通信

        Service 資源的專用網絡也稱爲集羣網絡( Cluster Network),需要在啓動 kube-apiserver 時經由“ --service-cluster叩-range”選項進行指定,如 10.96.0.0/12,而每個 Service 對象在 此網絡中均擁一個稱爲 Cluster-IP 的固定地址。 管理員或用戶對 Service 對象的創建或更改 操作由 API Server 存儲完成後觸發各節點上的 kube-proxy,並根據代理模式的不同將其定義 爲相應節點上的 iptables 規則或 ipvs 規則,藉此完成從 Service 的 Cluster-IP與 Pod-IP 之間的報文轉發,如圖所示。 

 

 

2.2.4 集羣外部到 Pod 對象之間的通信 

         將集羣外部的流量引入到 Pod 對象的方 式有受限於 Pod 所在的工作節點範圍的節點 端口( nodePort)和主機網絡( hostNetwork) 兩種,以及工作於集羣級別的 NodePort 或 LoadBalancer 類型的 Service 對象。 不過, 即便是四層代理的模式也要經由兩級轉發才能到達目標pod資源:請求流量首先到達外部負載均衡器,由其調度至某個工作節點之 上,而後再由工作節點的 netfilter ( kube“proxy)組件上的規則( iptables 或 ipvs)調度至某 個目標 Pod 對象。

 

2.3 Pod 網絡的實現方式

        每個 Pod 對象內的基礎架構容器均使用一個獨立的網絡名稱空間,並共享給同一Pod 內的其他容器使用。 每個名稱空間均有其專用的獨立網絡協議戰及其相關的網絡接口設備。 一個網絡接口僅能屬於一個網絡名稱空間,於是,運行多個 Pod 必然要求使用多個網絡名 稱空間,也就需要用到多個網絡接口設備。 不過 一個易於實現的方案是使用軟件實現的僞 網絡接口及模擬線纜將其連接至物理接口 。 僞網絡接口的實現方案常見的有虛擬網橋、多路複用及硬件交換三種。

  • 虛擬網橋:創建一對虛擬以太網接口( veth),一個接人容器內部,另一個留置於根 名稱空間內井藉助於 Linux 內核橋接功能或 OpenVSwitch ( OVS)關聯至真實的物理 接口 。

  • 多路複用 : 多路複用可以由一箇中間網絡設備組成,它暴露了多個虛擬接口,可使 用數據包轉發規則來控制每個數據包轉到的目標接口 。 MACVLAN 爲每個虛擬接口 配置一個 MAC 地址並基於此地址完成二層報文收發,而 IPVLAN 是基於 IP 地址的 並使用單個 MAC,從而使其更適合 VM。

  • 硬件交換: 現今市面上的大多數 NIC 都支持單根 I/O 虛擬化( SR-IOV),它是創建虛 擬設備的一種實現方式。 每個虛擬設備自身均表現爲一個獨立的 PCI 設備,井有着 自己的 VLAN 及與硬件強制關聯的 QoS。 SR-IOV 提供了接近硬件級別的性能,但 在公共雲中通常是不可用的。

        大多數情況下,用戶希望創建跨越多個 L2 或口的邏輯網絡子網,這就要藉助於疊加 封裝協議來實現(最常見的是 VXLAN,它將疊加流量封裝到 UDP 數據包中)。 不過,由 於控制平面缺乏標準化, VXLAN 可能會引人更高的開銷,並且來自不同供應商的多個VXLAN 網絡通常無法互操作。 而 Kubernetes 還將大量使用 iptables 和 NAT 來攔截進入邏 輯/ 虛擬地址的流量並將其路由到適當的物理目的地。

 

        無論上述哪種方式應用於容器環境中,其實現過程都需要大量的操作步驟。 不過,目前Kubernetes 支持使用CNI插件來編排網絡,以實現 Pod 及集羣網絡管理功能的自動 化。 每次 Pod 被初始化或刪除時 kubelet 都會調用默認的 CNI 插件創建一個虛擬設備接 口附加到相關的底層網絡,爲其設置 IP 地址、路由信息並將其映射到 Pod 對象的網絡名稱 空間。 

        配置Pod的網絡時,kubelet 首先在默認的/etc/cni/net.d目錄中查找CNI JSON配置 文件,接着基於 type 屬性到/o[t/cni/bin中查找相關的插件二進制文件,如下面示例中的 “ portmap ” 。 隨後,由 CNI 插件調用 IPAM 插件( IP 地址管理)來設置每個接口的 IP 地址, 如 host-local 或 dhcp 等:

 

2.4 CNI 插件及其常見的實現

        Kubemetes 設計了網絡模型,但將其實現交給了網絡插件。 於是,各種解決方案不斷湧 現。 爲了規範及兼容各種解決方案, CoreOS 和 Google 聯合制定了 CNI ( Contain巳r Network Interface)標準,旨在定義容器網絡模型規範。 它連接了兩個組件: 容器管理系統和網絡插 件。 它們之間通過 JSON 格式的文件進行通信,以實現容器的網絡功能。 具體的工作均由插 件來實現,包括創建容器 netns、關聯網絡接口到對應的 netns 以及爲網絡接口分配 IP 等。 CNI 的基本思想是:容器運行時環境在創建容器時,先創建好網絡名稱空間( netns), 然後調用CNI 插件爲這個netns 配置網絡,而後再啓動容器內的進程。 

        CNI 本身只是規範,付諸生產還需要有特定的實現。 目前, CNI 提供的插件分爲三類: main、 meta 和 ipam。 main一類的插件主要在於實現某種特定的網絡功能,例如 loopback、 bridge、 macvlan 和 ipvlan 等; meta 一類的插件自身並不提供任何網絡實現,而是用於調用 其他插件,例如調用 flannel; ipam 僅用於分配 IP 地址,而不提供網絡實現。 

       CNI 具有很強的擴展性和靈活性,例如,如果用戶對某個插件具有額外的需求,則 可以通過輸入中的 args 和環境變量 CNI_ARGS 進行傳遞,然後在插件中實現自定義的功 能,這大大增加了它的擴展性。另外,CNI 插件將 main 和 ipam 分開,賦予了用戶自由組 合它們的機制,甚至一個 CNI 插件也可以直接調用另外一個 CNI 插件。 CNI 目前已經是 Kubernetes 當前推薦的網絡方案。 常見的 CNI 網絡插件包含如下這些主流的項目 。 

  • Flannel :一個爲 Kubernetes 提供疊加網絡的網絡插件,它基於 Linux TUN/TAP ,使 用 UDP 封裝 IP 報文來創建疊加網絡,並藉助 etcd 維護網絡的分配情況。
  • Calico : 一個基於 BGP 的三層網絡插件 並且也支持網絡策略來實現網絡的訪問控 制;它在每臺機器上運行一個 vRouter,利用 Linux 內核來轉發網絡數據包, 並藉助 iptables 實現防火牆等功能。
  • Canal : 由 Flannel 和 Calico 聯合發佈的一個統一網絡捅件,提供 CNI 網絡插件,並支持網絡策略。

 

3、基於CNI網絡模型實現

3.1 創建副本pod

1、創建多個副本pod,用來實驗效果

[root@master bin]# kubectl create deployment myapp --image=ikubernetes/myapp:v1      # 創建一個myapp的pod
deployment.apps/myapp created

[root@master bin]# kubectl scale deployment myapp --replicas=3                       # 將myapp的pod分爲三個副本
deployment.apps/myapp scaled

  

2、查看副本詳細信息

[root@master ~]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
myapp-5c6976696c-2md48   1/1     Running   0          4m33s   10.244.1.120   node1   <none>           <none>
myapp-5c6976696c-l2hbl   1/1     Running   0          67s     10.244.2.118   node2   <none>           <none>
myapp-5c6976696c-n2k97   1/1     Running   0          57s     10.244.1.121   node1   <none>           <none>

  

3、此時上面可以通信是在cni0這個網絡橋上,以下是各個網絡之前通訊的網絡模式接口:cni0、docker0、eth0、flannel.1

[root@node2 ~]# ifconfig         # 查看對應的cni0信息
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.2.1  netmask 255.255.255.0  broadcast 10.244.2.255
        inet6 fe80::d0cb:f7ff:feac:2285  prefixlen 64  scopeid 0x20<link>
        ether d2:cb:f7:ac:22:85  txqueuelen 1000  (Ethernet)
        RX packets 37017  bytes 6844157 (6.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 40564  bytes 4730267 (4.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:1e:a1:3e:9e  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.7.103  netmask 255.255.255.0  broadcast 192.168.7.255
        inet6 fe80::20c:29ff:fe62:fd2a  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:62:fd:2a  txqueuelen 1000  (Ethernet)
        RX packets 82626  bytes 46977592 (44.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 77948  bytes 7494426 (7.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.2.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::7ce1:4dff:fef3:3395  prefixlen 64  scopeid 0x20<link>
        ether 7e:e1:4d:f3:33:95  txqueuelen 0  (Ethernet)
        RX packets 1625  bytes 136500 (133.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1625  bytes 136500 (133.3 KiB)
        TX errors 0  dropped 8 overruns 0  carrier 0  collisions 0

 

3.2 測試cni0通信效果

1、在master節點上與node節點上進行互通

[root@master ~]# kubectl exec -it myapp-5c6976696c-2md48 -- /bin/sh
/ # ping 10.244.2.118
PING 10.244.2.118 (10.244.2.118): 56 data bytes
64 bytes from 10.244.2.118: seq=0 ttl=62 time=1.421 ms
64 bytes from 10.244.2.118: seq=1 ttl=62 time=0.755 ms
^C
--- 10.244.2.118 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.755/1.088/1.421 ms

  

2、在node1節點上查看此時的tcpdump信息,此時可以看到兩個pod之間是可以通過icmp協議通信

[root@node1 ~]# tcpdump -i cni0 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on cni0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:38:27.505778 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 0, length 64
17:38:27.506494 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 0, length 64
17:38:28.506758 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 1, length 64
17:38:28.509794 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 1, length 64
17:38:29.508176 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 2, length 64
17:38:29.508651 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 2, length 64
17:38:30.509067 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 3, length 64
17:38:30.509436 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 3, length 64

 

4、flannel 網絡插件

    各 Docker 主機在 docker0橋上默認使用同一個子網,不同節點的容器很可能會得到相 同的地址,於是跨節點的容器問通信會面臨地址衝突的問題。 另外,即使人爲地設定多個 節點上的 docker0橋使用不同的子網,其報文也會因爲在網絡中缺乏路由信息而無法準確送 達。 事實上,各種CNI 插件都至少要解決這兩類問題。

    對於第一個問題, flannel 的解決辦法是,預留使用一個網絡,如 I0.244.0.0/16,而後 自動爲每個節點的 Docker 容器引擎分配一個子網,如 10.244.1.0/24 和 10.244.20/24 ,並將其分配信息保存於etcd 持久存儲。對於第二個問題, flannel 有着多種不同的處理方法,每 一種處理方法也可以稱爲一種網絡模型,或者稱爲flannel使用的後端。 

  •  VxLAN : Linux 內核自 3.7.0 版本起支持 VxLAN, flannel 的此種後端意味着使用內 核中的 VxLAN 模塊封裝報文,這也是 flannel 較爲推薦使用的方式。

 

 

  •  host-gw :即 Host GateWay,它通過在節點上創建到達目標容器地址的路由直接完成 報文轉發,因此這種方式要求各節點本身必須在同一個二層網絡中,故該方式不太 適用於較大的網絡規模(大二層網絡除外)。host-gw 有着較好的轉發性能,且易於設定,推薦對報文轉發性能要求較高的場景使用。
  • UDP :使用普通 UDP 報文封裝完成隧道轉發,其性能較前兩種方式要低很多,僅應 該在不支持前兩種方式的環境中使用。

         flannel 初創之後的一段時期內,不少環境中的 Linux 發行版的內核尚且不支持 VxLAN,而 host-gw 模式有着略高的網絡技術門檻,故此大多數部署場景只好使用 UDP 模 式, flannel 因而不幸地落下性能不好的聲名 。 不過,目前 flannel 的部署默認後端已經是疊 加網絡模型 VxLAN。 另外,除了這三種後端之外, flannel 還實驗性地支持 AliVPC、 AWS VPC、 Alloc 和 GCE 幾種後端。

 

4.1 flannel配置參數

爲了跟蹤各子網分配信息等, flannel 使用 etcd 來存儲虛擬 IP 和主機 IP 之間的映射,各個節點上運行的 flanneld 守護進程負責監視 etcd 中的信息並完成報文路由 。 默認情況下,flannel的配置信息保存於etcd 的鍵名/coreos .com/network/config 之下,可以使用 etcd 服務 的客戶端工具來設定或修改其可用的相關配置。 config 的值是一個 JSON 格式的字典數據結 構,它可以使用的鍵包含以下幾個。 

  • Network: flannel 於全局使用的 CIDR 格式的 IPv4 網絡,字符串格式, 此爲必選鍵, 餘下的均爲可選。
  • SubnetLen :將 Network 屬性指定的 IPv4 網絡基於指定位的掩碼切割爲供各節點使 用的子網,此網絡的掩碼小於 24 時(如 16 ),其切割子網時使用的掩碼默認爲 24 位。
  • SubnetMin :可用作分配給節點使用的起始子網,默認爲切分完成後的第一個子網; 字符串格式。
  • SubnetMax: 可用作分配給節點使用的最大子網,默認爲切分完成後最大的一個子網; 字符串格式。
  • Backend : flannel 要使用的後端類型,以及後端的相關配置,字典格式; VxLAN、 host-gw 和 UDP 後端各有其相關的參數。

         以上配置信息可直接由 flannel 保存於 etcd 存儲中,也可交由 Kubernetes 進行存儲。 具 體使用的方式取決於管理員或部署程序的默認配置。 另外, flannel 默認使用 VxLAN 後端, 但 VxLAN direct routing 和 host-gw 卻有着更好的性能表現。

 

4.2 VxLAN 後端和 direct routing

VxLAN 全稱 Virtual extensible Local Area Network (虛擬可擴展局域網),是 VLAN 擴展方案草案,採用的是 MAC in UDP 封裝方式是 NVo3 ( Network Virtualization over Layer3 )中的一種網絡虛擬化技術 ,如下圖所示。 具體實現方式爲 :將虛擬網絡的數據 幀添加到 VxLAN 首部後,封裝在物理網絡的 UDP 報文中,然後以傳統網絡的通信方式傳 送該 UDP 報文,待其到達目的主機後,去掉物理網絡報文的頭部信息以及 VxLAN 首部, 然後將報文交付給目的終端如圖 l 1-9 所示的拓撲結構中,跨節點的 Pod 間通信即爲如此。不過,整個過程中通信雙方對物理網絡無所感知。

 

 

 

 

 

 

5、在flannel進行網絡通信

5.1 進行flannel網絡通信

1、在master節點上與node節點上進行ping,此時的flannel網絡模式將cni0的網絡模式進行封裝了

[root@master ~]# kubectl exec -it myapp-5c6976696c-2md48 -- /bin/sh
/ # ping 10.244.2.118
PING 10.244.2.118 (10.244.2.118): 56 data bytes
64 bytes from 10.244.2.118: seq=0 ttl=62 time=1.421 ms
64 bytes from 10.244.2.118: seq=1 ttl=62 time=0.755 ms
^C
--- 10.244.2.118 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.755/1.088/1.421 ms

  

2、在node1節點上查看此時的tcpdump信息,此時可以看到兩個pod之間也可以通過隧道icmp協議通信

[root@node1 ~]# tcpdump -i flannel.1 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on cni0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:38:27.505778 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 0, length 64
17:38:27.506494 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 0, length 64
17:38:28.506758 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 1, length 64
17:38:28.509794 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 1, length 64
17:38:29.508176 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 2, length 64
17:38:29.508651 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 2, length 64
17:38:30.509067 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 3840, seq 3, length 64
17:38:30.509436 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 3840, seq 3, length 64

  

5.2 將VxLAN改爲DirectRouting網絡模型

           注意: 爲了保證所有 Pod 均能得到正確的網絡配置,建議在創建 Pod 資源之前事先配置好網絡插件,甚至是事先了解並根據自身業務需求測試完成中意的目標網絡插件,在 選型完成後再部署 Kub巳metes 集羣,而儘量避免中途修改 , 否則有些 Pod 資源可能 會需要重建。

5.2.1 將VxLAN改爲Direct Routing模式

1、在github上下載對應的flannel的yaml文件

[root@master ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

  

2、修改yaml文件內容,添加DirectRouting字段信息

  [root@master ~]# vim kube-flannel.yml 
  ...............        #  前面內容省略
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan",             # vxlan後面加上逗號
        "DirectRouting": true        # DirectRouting字段是布爾值形式,後面的true不需要加雙引號
      }
    }

  

3、基於yaml文件創建新的flannel,並查看信息,此時的DirectRouting模型已經加載成功

[root@master ~]# kubectl apply -f kube-flannel.yml   #  基於yaml文件創建新的flannel
podsecuritypolicy.policy/psp.flannel.unprivileged configured
clusterrole.rbac.authorization.k8s.io/flannel unchanged
clusterrolebinding.rbac.authorization.k8s.io/flannel unchanged
serviceaccount/flannel unchanged
configmap/kube-flannel-cfg configured
daemonset.apps/kube-flannel-ds-amd64 configured
daemonset.apps/kube-flannel-ds-arm64 configured
daemonset.apps/kube-flannel-ds-arm configured
daemonset.apps/kube-flannel-ds-ppc64le configured
daemonset.apps/kube-flannel-ds-s390x configured

[root@master ~]# kubectl get cm kube-flannel-cfg -n kube-system -o yaml   # 查看此時的網絡模型信息
apiVersion: v1
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan",
        "DirectRouting": true     # 此時的DirectRouting模型已經加載成功
      }
    }

  

4、查看此時的flannel重載是否生效,此時是已經生效了

[root@master ~]# kubectl get pods -n kube-system
NAME                             READY   STATUS    RESTARTS   AGE
coredns-5644d7b6d9-28wzt         1/1     Running   26         13d
coredns-5644d7b6d9-dfwv4         1/1     Running   27         13d
etcd-master                      1/1     Running   26         13d
kube-apiserver-master            1/1     Running   26         13d
kube-controller-manager-master   1/1     Running   28         13d
kube-flannel-ds-amd64-6hh59      1/1     Running   0          2m57s
kube-flannel-ds-amd64-77rvg      1/1     Running   0          4m10s
kube-flannel-ds-amd64-xgrtr      1/1     Running   0          3m34s
kube-proxy-cqvj8                 1/1     Running   25         12d
kube-proxy-pntl4                 1/1     Running   23         12d
kube-proxy-tjdvz                 1/1     Running   23         12d
kube-scheduler-master            1/1     Running   28         13d

 

5.2.2 驗證修改後效果

1、再未修改前的DirectRouting的路由模型時,屬於flannel.1的隧道封裝模型

[root@node1 ~]# route  -n 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.7.2     0.0.0.0         UG    0      0        0 eth0
10.244.0.0      192.168.7.101   255.255.255.0   UG    0      0        0 eth0
10.244.1.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.2.0      192.168.7.103   255.255.255.0   UG    0      0        0 flannel.1  # flannel.1封裝效果
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.7.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

  

2、此時在node1節點上查看路由信息,就是以eth0的路由形式顯示了,此時就不會再有隧道封裝了

[root@node1 ~]# route  -n 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.7.2     0.0.0.0         UG    0      0        0 eth0
10.244.0.0      192.168.7.101   255.255.255.0   UG    0      0        0 eth0
10.244.1.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.2.0      192.168.7.103   255.255.255.0   UG    0      0        0 eth0  # 此時node1就以eth0進行顯示
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.7.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

  

3、開始在master節點是ping  node節點

[root@master ~]# kubectl exec -it myapp-5c6976696c-2md48 -- /bin/sh
/ # ping 10.244.2.118
PING 10.244.2.118 (10.244.2.118): 56 data bytes
64 bytes from 10.244.2.118: seq=0 ttl=62 time=1.421 ms
64 bytes from 10.244.2.118: seq=1 ttl=62 time=0.755 ms
^C
--- 10.244.2.118 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.755/1.088/1.421 ms

  

4、此時在node1上查看對應的物理網卡eth0信息,物理網卡之間的網絡也是互通的

[root@node1 ~]# tcpdump -i eth0  -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:48:03.287790 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 4352, seq 0, length 64
17:48:03.288820 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 4352, seq 0, length 64
17:48:04.288559 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 4352, seq 1, length 64
17:48:04.289054 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 4352, seq 1, length 64
17:48:05.289795 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 4352, seq 2, length 64
17:48:05.290262 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 4352, seq 2, length 64
17:48:06.290673 IP 10.244.1.120 > 10.244.2.118: ICMP echo request, id 4352, seq 3, length 64
17:48:06.291437 IP 10.244.2.118 > 10.244.1.120: ICMP echo reply, id 4352, seq 3, length 64

  

5.3 flannel重載爲Direct Routing未生效解決辦法

1、查看此時的flannel的標籤信息

[root@master ~]# kubectl get pods -n kube-system --show-labels
NAME                             READY   STATUS    RESTARTS   AGE     LABELS
coredns-5644d7b6d9-28wzt         1/1     Running   26         13d     k8s-app=kube-dns,pod-template-hash=5644d7b6d9
coredns-5644d7b6d9-dfwv4         1/1     Running   27         13d     k8s-app=kube-dns,pod-template-hash=5644d7b6d9
etcd-master                      1/1     Running   26         13d     component=etcd,tier=control-plane
kube-apiserver-master            1/1     Running   26         13d     component=kube-apiserver,tier=control-plane
kube-controller-manager-master   1/1     Running   28         13d     component=kube-controller-manager,tier=control-plane
kube-flannel-ds-amd64-6hh59      1/1     Running   0          4m23s   app=flannel,controller-revision-hash=7cf85bbbfc,pod-template-generation=2,tier=node
kube-flannel-ds-amd64-77rvg      1/1     Running   0          5m36s   app=flannel,controller-revision-hash=7cf85bbbfc,pod-template-generation=2,tier=node
kube-flannel-ds-amd64-xgrtr      1/1     Running   0          5m      app=flannel,controller-revision-hash=7cf85bbbfc,pod-template-generation=2,tier=node
kube-proxy-cqvj8                 1/1     Running   25         12d     controller-revision-hash=56c95f6b7b,k8s-app=kube-proxy,pod-template-generation=1
kube-proxy-pntl4                 1/1     Running   23         12d     controller-revision-hash=56c95f6b7b,k8s-app=kube-proxy,pod-template-generation=1
kube-proxy-tjdvz                 1/1     Running   23         12d     controller-revision-hash=56c95f6b7b,k8s-app=kube-proxy,pod-template-generation=1
kube-scheduler-master            1/1     Running   28         13d     component=kube-scheduler,tier=control-plane

  

 2、刪除對應的flannel標籤信息,此時對應的flannel就會重新創建

[root@master ~]# kubectl delete pods -l app=flannel -n kube-system
pod "kube-flannel-ds-amd64-6hh59" deleted
pod "kube-flannel-ds-amd64-77rvg" deleted
pod "kube-flannel-ds-amd64-xgrtr" deleted

  

3、此時查看新的flannel已經創建成功

[root@master ~]# kubectl get pods -n kube-system
NAME                             READY   STATUS    RESTARTS   AGE
coredns-5644d7b6d9-28wzt         1/1     Running   26         13d
coredns-5644d7b6d9-dfwv4         1/1     Running   27         13d
etcd-master                      1/1     Running   26         13d
kube-apiserver-master            1/1     Running   26         13d
kube-controller-manager-master   1/1     Running   28         13d
kube-flannel-ds-amd64-d2crx      1/1     Running   0          4s      # 查看新的flannel在4s之前創建成功
kube-flannel-ds-amd64-dbzbs      1/1     Running   0          3s      # 查看新的flannel在3s之前創建成功
kube-flannel-ds-amd64-kfw8d      1/1     Running   0          8s      # 查看新的flannel在8s之前創建成功
kube-proxy-cqvj8                 1/1     Running   25         12d
kube-proxy-pntl4                 1/1     Running   23         12d
kube-proxy-tjdvz                 1/1     Running   23         12d
kube-scheduler-master            1/1     Running   28         13d

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章