天天看點

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

作者 | 淺奕

來源 | 阿裡技術公衆号

本文需要讀者熟悉 Ethernet(以太網)的基本原理和 Linux 系統的基本網絡指令,以及 TCP/IP 協定族并了解傳統的網絡模型和協定包的流轉原理。文中涉及到 Linux 核心的具體實作時,均以核心 v4.19.215 版本為準。

一 核心網絡包接收流程

1 從網卡到核心協定棧

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

如圖[1],網絡包到達 NC(Network Computer,本文指實體機)時,由 NIC(Network Interface Controller,網絡接口控制器,俗稱網卡)裝置處理,NIC 以中斷的方式向核心傳遞消息。Linux 核心的中斷處理分為上半部(Top Half)和下半部(Bottom Half)。上半部需要盡快處理掉和硬體相關的工作并傳回,下半部由上半部激活來處理後續比較耗時的工作。

具體到 NIC 的處理流程如下:當 NIC 收到資料時,會以 DMA 方式将資料拷貝到 Ring Buffer (接收隊列) 裡描述符指向的映射記憶體區域,拷貝完成後會觸發中斷通知 CPU 進行處理。這裡可以使用 ethtool -g {裝置名,如eth0} 指令檢視 RX/TX (接收/發送)隊列的大小。CPU 識别到中斷後跳轉到 NIC 的中斷處理函數開始執行。此時要區分 NIC 的工作模式,在早先的非 NAPI(New API)[2]模式下,中斷上半部更新相關的寄存器資訊,檢視接收隊列并配置設定 sk_buff 結構指向接收到的資料,最後調用 netif_rx() 把 sk_buff 遞交給核心處理。在 netif_rx() 的函數的流程中,這個配置設定的 sk_buff 結構被放入 input_pkt_queue隊列後,會把一個虛拟裝置加入poll_list 輪詢隊列并觸發軟中斷 NET_RX_SOFTIRQ 激活中斷下半部。此時中斷上半部就結束了,詳細的處理流程可以參見 net/core/dev.c 的 netif_rx() -> netif_rx_internal() -> enqueue_to_backlog() 過程。下半部 NET_RX_SOFTIRQ 軟中斷對應的處理函數是 net_rx_action(),這個函數會調用裝置注冊的 poll() 函數進行處理。非 NAPI 的情況下這個虛拟裝置的 poll() 函數固定指向 process_backlog() 函數。這個函數将 sk_buff 從 input_pkt_queue 移動到 process_queue 中,調用 __netif_receive_skb() 函數将其投遞給協定棧,最後協定棧相關代碼會根據協定類型調用相應的接口進行後續的處理。特别地,這裡的 enqueue_to_backlog() 以及 process_backlog() 函數也用于和啟用了 RPS 機制後的相關邏輯。

非 NAPI(New API)模式下每個網絡包的到達都會觸發一次中斷處理流程,這麼做降低了整體的處理能力,已經過時了。現在大多數 NIC 都支援 NAPI 模式了。NAPI 模式下在首包觸發 NIC 中斷後,裝置就會被加入輪詢隊列進行輪詢操作以提升效率,輪詢過程中不會産生新的中斷。為了支援 NAPI,每個 CPU 維護了一個叫 softnet_data 的結構,其中有一個 poll_list 字段放置所有的輪詢裝置。此時中斷上半部很簡單,隻需要更新 NIC 相關的寄存器資訊,以及把裝置加入poll_list 輪詢隊列并觸發軟中斷 NET_RX_SOFTIRQ就結束了。中斷下半部的處理依舊是 net_rx_action() 來調用裝置驅動提供的 poll() 函數。隻是 poll() 此時指向的就是裝置驅動提供的輪詢處理函數了(而不是非 NAPI 模式下的核心函數 process_backlog())。這個裝置驅動提供的輪詢 poll() 函數最後也會調用 __netif_receive_skb() 函數把 sk_buff 送出給協定棧處理。

非 NAPI 模式和 NAPI 模式下的流程對比如下(其中灰色底色是裝置驅動要實作的,其他都是核心自身的實作):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

關于 NAPI 模式網絡裝置驅動的實作以及詳細的 NAPI 模式的處理流程,這裡提供一篇文章和其譯文作為參考[3](強烈推薦)。這篇文章很詳細的描述了 Intel Ethernet Controller I350 這個 NIC 裝置的收包和處理細節(其姊妹篇發包處理過程和譯文[4])。另外收包這裡還涉及到多網卡的 Bonding 模式(可以在/proc/net/bonding/bond0 裡檢視模式)、網絡多隊列(sudo lspci -vvv 檢視 Ethernet controller 的 Capabilities資訊裡有 MSI-X: Enable+ Count=10 字樣說明 NIC 支援,可以在 /proc/interrupts 裡檢視中斷綁定情況)等機制。這些本文都不再贅述,有興趣的話請參閱相關資料[5]。

2 核心協定棧網絡包處理流程

前文說到 NIC 收到網絡包構造出的 sk_buff 結構最終被 __netif_receive_skb() 送出給了核心協定棧解析處理。這個函數首先進行 RPS[5] 相關的處理,資料包會繼續在隊列裡轉一圈(一般開啟了 RSS 的網卡不需要開啟 RPS)。如果需要分發包到其他 CPU 去處理,則會使用 enqueue_to_backlog() 投遞給其他 CPU 的隊列,并在 process_backlog()) 中觸發 IPI(Inter-Processor Interrupt,處理器間中斷,于 APIC 總線上傳輸,并不通過 IRQ)給其他 CPU 發送通知(net_rps_send_ipi()函數)。

最終,資料包會由 __netif_receive_skb_core() 進行下一階段的處理。這個處理函數主要的功能有:

  • 處理ptype_all 上所有的 packet_type->func(),典型場景是 tcpdump 等工具的抓包回調(paket_type.type 為 ETH_P_ALL,libcap 使用 AF_PACKET Address Family)
  • 處理 VLAN(Virtual Local Area Network,虛拟區域網路)封包 vlan_do_receive() 以及處理網橋的相關邏輯(skb->dev->rx_handler() 指向了 br_handle_frame())
  • 處理 ptype_base上所有的 packet_type->func() , 将資料包傳遞給上層協定層處理,例如指向 IP 層的回調 ip_rcv() 函數

截至目前,資料包仍舊在資料鍊路層的處理流程中。這裡複習下 OSI 七層模型與 TCP/IP 五層模型:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

在網絡分層模型裡,後一層即為前一層的資料部分,稱之為載荷(Payload)。一個完整的 TCP/IP 應用層資料包的格式如下[6]:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

__netif_receive_skb_core() 的處理邏輯中需要關注的是網橋和接下來 IP 層以及 TCP/UDP 層的處理。首先看 IP 層,__netif_receive_skb_core() 調用 deliver_skb(),後者調用具體協定的 .func() 接口。對于 IP 協定,這裡指向的是 ip_rcv() 函數。這個函數做了一些統計和檢查之後,就把包轉給了 Netfilter [7]架構并指定了函數 ip_rcv_finish() 進行後續的處理(如果包沒被 Netfilter 丢棄)。經過路由子系統檢查處理後,如果包是屬于本機的,那麼會調用 ip_local_deliver() 将資料包繼續往上層協定轉發。這個函數類似之前的邏輯,依舊是呈遞給 Netfilter 架構并指定函數 ip_local_deliver_finish() 進行後續的處理,這個函數最終會檢查和選擇對應的上層協定接口進行處理。

常見的上層協定比如 TCP 或者 UDP 協定的流程不在本文讨論的範圍内,僅 TCP 的流程所需要的篇幅足以超過本文所有的内容。這裡給出 TCP 協定(v4)的入口函數 tcp_v4_rcv() 以及 UDP 協定的入口函數 udp_rcv() 作為指引自行研究,也可以閱讀其他的資料進行進一步的了解[9]。

3 Netfilter/iptables 與 NAT(網絡位址轉換)

關于 Netfilter 架構需要稍微着重的強調一下,因為後文要提到的網絡政策和很多服務透出的實作都要使用 Netfilter 提供的機制。

Netfilter 是核心的包過濾架構(Packet Filtering Framework)的實作。簡單說就是在協定棧的各個層次的包處理函數中内置了很多的 Hook 點來支援在這些點注冊回調函數。

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

圖檔來自 Wikimedia,可以點開參考文獻[8]檢視大圖(svg 矢量圖,可以調大網頁顯示百分比繼續放大)。

Linux 上最常用的防火牆 iptables 即是基于 Netfilter 來實作的(nftables 是新一代的防火牆)。iptables 基于表和鍊(Tables and Chains)的概念來組織規則。注意這裡不要被“防火牆”這個詞誤導了,iptables 所能做的不僅僅是對包的過濾(Filter Table),還支援對包進行網絡位址轉換(NAT Table)以及修改包的字段(Mangle Table)。在網絡虛拟化裡,用的最多的便是 NAT 位址轉換功能。通常此類功能一般在網關網絡裝置或是負載均衡裝置中很常見。當 NC 需要在内部進行網絡相關的虛拟化時,也是一個類似網關以及負載均衡裝置了。

在設定 iptables 的 NAT 規則前,還需要打開核心的包轉發功能 echo "1" > /proc/sys/net/ipv4/ip_forward 才可以。另外建議也打開 echo "1" /proc/sys/net/bridge/bridge-nf-call-iptables 開關(可能需要 modprobe br_netfilter)。bridge-nf-call-iptables 從上面的源碼分析就能了解,網橋的轉發處理是在 Netfilter 規則之前的。是以預設情況下二層網橋的轉發是不會受到三層 iptables 的限制的,但是很多虛拟化網絡的實作需要 Netfilter 規則生效,是以核心也支援了讓網橋的轉發邏輯也調用一下 Netfilter 的規則。這個特性預設情況不開啟,是以需要檢查開關。至于具體的 iptables 指令,可以參考這篇文章和其譯文[10]進行了解,本文不再讨論。

這裡強調下,Netfilter 的邏輯運作在核心軟中斷上下文裡。如果 Netfilter 添加了很多規則,必然會造成一定的 CPU 開銷。下文在提到虛拟化網絡的性能降低時,很大一部分開銷便是源自這裡。

二 虛拟網絡裝置

在傳統的網絡認知裡,網絡就是由帶有一個或多個 NIC 的一組 NC 使用硬體媒體和 switch(交換機)、Router(路由器)所組成的一個通信集合(圖檔來自 [11],下同):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

網絡虛拟化作為 SDN(Software Defined Network,軟體定義網絡)的一種實作,無非就是虛拟出 vNIC(虛拟網卡)、vSwitch(虛拟交換機)、vRouter(虛拟路由器)等裝置,配置相應的資料包流轉規則而已。其對外的接口必然也是符合其所在的實體網絡協定規範的,比如 Ethernet 和 TCP/IP 協定族。

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

随着 Linux 網絡虛拟化技術的演進,有了若幹種虛拟化網絡裝置,在虛拟機和虛拟容器網絡中得到了廣泛的應用。典型的有 Tap/Tun/Veth、Bridge 等:

  • Tap/Tun 是 Linux 核心實作的一對虛拟網絡裝置,Tap/Tun 分别工作在二層/三層。Linux 核心通過 Tap/Tun 裝置和綁定該裝置的使用者空間之間交換資料。基于 Tap 驅動即可實作虛拟機 vNIC 的功能,Tun 裝置做一些其他的轉發功能。
  • Veth 裝置總是成對建立(Veth Pair),一個裝置收到核心發送的資料後,會發送到另一個裝置上去,可以把 Veth Pair 可以想象成一對用網線連接配接起來的 vNIC 裝置。
  • Bridge 是工作在二層的虛拟網橋。這是虛拟裝置,雖然叫網橋,但其實類似 vSwitch 的設計。當 Bridge 配合 Veth 裝置使用時,可以将 Veth 裝置的一端綁定到一個Bridge 上,相當于真實環境把一個 NIC 接入一個交換機裡。

虛拟機和容器的網絡在傳輸流程上有些差別,前者比如 KVM 一般是使用 Tap 裝置将虛拟機的 vNIC 和主控端的網橋 Bridge 連接配接起來。而容器的 Bridge 網絡模式是将不同 Namespace 裡的 Veth Pair 連接配接網橋 Bridge 來實作通信(其他方式下文讨論)。

Linux Bridge 配合橋接或者 NAT 模式很容易可以實作同主機或跨主機的虛拟機/容器之間通信,而且 Bridge 本身也支援 VLAN 的配置,可以實作一些三層交換機的能力。但是很多廠商都在研發功能更豐富的虛拟交換機,流行的有 Cisco Nexus 1000V、 VMware Virtual Switch 以及廣泛使用的開源的 Open vSwitch[12] 等。利用 vSwitch,可以建構出支援更多封裝協定、更進階的虛拟網絡:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

1 Linux Bridge + Veth Pair 轉發

VRF(Virtual Routing and Forwarding,虛拟路由轉發)在網絡領域中是個很常見的術語。上世紀九十年代開始,很多二層交換機上就能建立出 4K 的 VLAN 廣播域了。4K 是因為 VLAN 标簽的格式遵循 802.1q 标準,其中定義的 VLAN ID 是 12 位的緣故(802.1q in 802.1q 可以做到 4094*4094 個,0 和 4095 保留)。如今 VRF 概念被引入三層,單個實體裝置上也可以有多個虛拟路由/轉發執行個體了。Linux 的 VRF 實作了對三層的網絡協定棧的虛拟,而 Network Namespace(以下簡稱 netns)虛拟了整個網絡棧。一個 netns 的網絡棧包括:網卡(Network Interface)、回環裝置(Loopback Device)、路由表(Routing Table)和 iptables 規則。本文使用 netns 進行示範(畢竟在讨論容器),下文使用 ip[14] 指令建立和管理 netns 以及 Veth Pair 裝置。

建立、檢視、删除 Network Namespace

# 建立名為 qianyi-test-1 和 add qianyi-test-2 的命名 netns,可以在 /var/run/netns/ 下檢視
ip netns add qianyi-test-1
ip netns add qianyi-test-2

# 檢視所有的 Network Namespace
ip netns list

# 删除 Network Namespace
ip netns del qianyi-test-1
ip netns del qianyi-test-2           

執行結果如圖(删除先不執行):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

有興趣的話可以使用 strace 指令跟蹤這個建立過程看看 ip 指令是怎麼建立的(strace ip netns add qianyi-test-1)。

在 netns 中執行指令

# 在 qianyi-test-1 這個 netns 中執行 ip addr 指令(甚至可以直接執行 bash 指令得到一個 shell)
# nsenter 這個指令也很好用,可以 man nsenter 了解
ip netns exec qianyi-test-1 ip addr           

執行結果如下:

圖檔

這個新建立的 netns 裡一貧如洗,隻有一個孤獨的 lo 網卡,還是 DOWN 狀态的。下面開啟它:

開啟 lo 網卡,這個很重要

ip netns exec qianyi-test-1 ip link set dev lo up

ip netns exec qianyi-test-2 ip link set dev lo up

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

狀态變成了 UNKOWN,這是正常的。這個狀态是驅動提供的,但是 lo 的驅動沒有做這個事情。

建立 Veth Pair 裝置

# 分别建立 2 對名為 veth-1-a/veth-1-b 和 veth-2-a/veth-2-b 的 Veth Pair 裝置
ip link add veth-1-a type veth peer name veth-1-b
ip link add veth-2-a type veth peer name veth-2-b           

使用 ip addr 指令可以檢視:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

8-9,10-11 便是上面建立出來的 2 對 Veth Pair 裝置,此時它們都沒有配置設定 IP 位址且是 DOWN 狀态。

将 Veth Pair 裝置加入 netns

# 将 veth-1-a 裝置加入 qianyi-test-1 這個 netns
ip link set veth-1-a netns qianyi-test-1

# 将 veth-1-b 裝置加入 qianyi-test-2 這個 netns
ip link set veth-1-b netns qianyi-test-2

# 為裝置添加 IP 位址/子網路遮罩并開啟
ip netns exec qianyi-test-1 ip addr add 10.0.0.101/24 dev veth-1-a
ip netns exec qianyi-test-1 ip link set dev veth-1-a up

ip netns exec qianyi-test-2 ip addr add 10.0.0.102/24 dev veth-1-b
ip netns exec qianyi-test-2 ip link set dev veth-1-b up           

此時我們分别在兩個 netns 中執行 ip addr 指令,即可看到裝置已經存在,且路由表(route 或 ip route 指令)也被預設建立了:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

這裡操作和檢視裝置都必須采用 ip netns exec {...} 的方式進行,如果指令很多,也可以把執行的指令換成 bash,這樣可以友善的在這個 shell 裡對該 netns 進行操作。

現在通過 veth-1-a/veth-1-b 這對 Veth Pair 聯通了 qianyi-test-1 和 qianyi-test-2 這兩個 netns,這兩個 netns 之間就可以通過這兩個 IP 位址互相通路了。

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

ping 的同時在 101 上抓包的結果如下:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

可以很清楚的看到,eth-1-a(10.0.0.101)先通過 ARP (Address Resolution Protocol,位址解析協定)詢問 10.0.0.102 的 MAC 位址。得到回應後,就以 ICMP (Internet Control Message Protocol,Internet 封包控制協定) request 和 reply 了,這也正是 ping 使用的協定。

ARP 解析的緩存資訊也可以通過 arp 指令檢視:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

此時的網絡連接配接模式是這樣的:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

這種連接配接模式,就很像是現實中把兩個帶有 NIC 的裝置用網線連接配接起來,然後配置了相同網段的 IP 後彼此就可以通信了。那如果超過一個裝置需要建立互聯呢?現實中就需要交換機等網絡裝置了。還記得前文中說的 Linux 自帶的 Bridge 麼?接下來就使用 Bridge 機制建立網絡。

進行下面的試驗前需要把 veth-1-a/veth-1-b 這對 Veth Pair 從 qianyi-test-1 和 qianyi-test-2 移動回主控端的 netns 裡,恢複初始的環境。

# 主控端的 netns id 是 1(有些系統可能不是,請查詢相關系統的文檔)
ip netns exec qianyi-test-1 ip link set veth-1-a netns 1
ip netns exec qianyi-test-2 ip link set veth-1-b netns 1           

建立 Linux Bridge 并配置網絡

# 建立一個名為 br0 的 bridge 并啟動(也可以使用 brctl 指令)
ip link add br0 type bridge
ip link set br0 up

# 将 veth-1-a/veth-1-b 和 veth-2-a/veth-2-b 這兩對 Veth Pair 的 a 端放入 qianyi-test-1 和 qianyi-test-2
ip link set veth-1-a netns qianyi-test-1
ip link set veth-2-a netns qianyi-test-2

# 為 veth-1-a 和 veth-2-a 配置 IP 并開啟
ip netns exec qianyi-test-1 ip addr add 10.0.0.101/24 dev veth-1-a
ip netns exec qianyi-test-1 ip link set dev veth-1-a up

ip netns exec qianyi-test-2 ip addr add 10.0.0.102/24 dev veth-2-a
ip netns exec qianyi-test-2 ip link set dev veth-2-a up

# 将 veth-1-a/veth-1-b 和 veth-2-a/veth-2-b 這兩對 Veth Pair 的 b 端接入 br0 網橋并開啟接口
ip link set veth-1-b master br0
ip link set dev veth-1-b up
ip link set veth-2-b master br0
ip link set dev veth-2-b up           

執行完可以檢視建立好的網橋和配置好的 IP,實際上 brctl show 指令顯示的結果更易懂,可以很清楚的看到 veth-1-b 和 veth-2-b 連接配接在了網橋的接口上。當 Veth Pair 的一端連接配接在網橋上時,就會從“網卡”退化成一個“水晶頭”。

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

當下模式抓包的結果并沒有什麼差別,但網絡連接配接模式不同:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

按照這個模式,如果有更多的 Network Namespace 和 Veth Pair 的話,使用相同的方式添加就可以水準擴充了。

但是嘗試從 qianyi-test-1 中 ping 主控端自然是不通的,因為沒有任何網絡規則可以通路到主控端的網絡:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

上面的截圖中有個 docker0 的網橋。當機器上安裝了 Docker 之後會被自動設定好這個網橋供 Docker 使用。可能你注意到了,這個名為 docker0 的網橋居然是有 IP 位址的。現實中的網橋自然是沒有 IP 的,但是 Linux Bridge 這個虛拟裝置是可以設定的。當 Bridge 設定 IP 之後,就可以将其設定成這個内部網絡的網關(Gateway),再配合路由規則就可以實作最簡單的虛拟網絡跨機通信了(類似現實中的三層交換機)。

下面繼續給 br0 網橋建立位址并在 veth-1-a 和 veth-2-a 上設定其為預設的網關位址:

# 确認路由轉發開啟
echo "1" > /proc/sys/net/ipv4/ip_forward

# 為 br0 設定 IP 位址
ip addr add local 10.0.0.1/24 dev br0

# 為 veth-1-a 和 veth-2-a 設定預設網關
ip netns exec qianyi-test-1 ip route add default via 10.0.0.1
ip netns exec qianyi-test-2 ip route add default via 10.0.0.1           

此時就能成功的通路主控端位址了(主控端上的路由表在 ip link set br0 up 這一步自動建立了):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

網絡模型進一步變成了這樣:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

如果此時,另一台主控端上也存在另一個網段的網橋和若幹個 netns 的話,怎麼讓他們互通呢?分别在兩邊主控端上配置一條到目的主控端的路由規則就好了。假設另一台主控端的 IP 位址是 10.97.212.160,子網是 10.0.1.0/24 的話,那麼需要在目前機器上加一條 10.0.1.0/24 via 10.97.212.160 的規則,10.97.212.160 上加一條 10.0.0.0/24 via 10.97.212.159 的規則就可以了(或者 iptables 配置 SNAT/DNAT 規則)。那如果有 N 台呢?那就會是個 N * N 條的規則,會很複雜。這就一個簡單的 Underlay 模式的容器通信方案了。缺點也很明顯,要求對主控端底層網絡有修改權,且比較難和底層網絡解耦。那如果能在實體網絡上建構出一個橫跨所有主控端的虛拟網橋,把所有相關的 netns 裡面的裝置都連接配接上去,不就可以解耦了麼。這就是 Overlay Network(覆寫網絡)方案,下文會進行闡述。至于本節其他虛拟網絡裝置的安裝和配置(比如 Open vSwitch)也是比較類似的,這裡不再贅述,有興趣的話可以自行檢視文檔并測試。

2 Overlay 網絡方案之 VXLAN

VXLAN(Virtual eXtensible Local Area Network,虛拟可擴充區域網路,RFC7348)[16],VLAN 的擴充協定,是由 IETF 定義的 NVO3(Network Virtualization over Layer 3)标準技術之一(其他有代表性的還有 NVGRE、STT)。但是 VXLAN 和 VLAN 想要解決的問題是不一樣的。VXLAN 本質上是一種隧道封裝技術,它将資料鍊路層(L2)的以太網幀(Ethernet frames)封裝成傳輸層(L4)的 UDP 資料報(Datagrams),然後在網絡層(L3)中傳輸。效果就像資料鍊路層(L2)的以太網幀在一個廣播域中傳輸一樣,即跨越了三層網絡卻感覺不到三層的存在。因為是基于 UDP 封裝,隻要是 IP 網絡路由可達就可以建構出龐大的虛拟二層網絡。也因為是基于高層協定再次封裝,性能會比傳統的網絡低 20%~30% 左右(性能資料随着技術發展會有變化,僅代表目前水準)。

這裡簡要介紹下 VXLAN 的 2 個重要概念:

  • VTEP(VXLAN Tunnel Endpoints,VXLAN 隧道端點),負責 VXLAN 封包的封裝和解封,對上層隐藏了鍊路層幀的轉發細節
  • VNI(VXLAN Network Identifier,VXLAN 網絡辨別符),代表不同的租戶,屬于不同 VNI 的虛拟網絡之間不能直接進行二層通信。

VXLAN 的封包格式如圖[17]:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

Linux kernel v3.7.0 版本開始支援 VXLAN 網絡。但為了穩定性和其他功能,請盡量選擇 kernel v3.10.0 及之後的版本。下面我們使用 10.97.212.159 和 11.238.151.74 這兩台機器建立一個測試的 VXLAN 網絡。

# 10.97.212.159 上操作

# 建立名為 qianyi-test-1 和 add qianyi-test-2 的命名 netns,可以在 /var/run/netns/ 下檢視
ip netns add qianyi-test-1
ip netns add qianyi-test-2

# 開啟 lo 網卡,這個很重要
ip netns exec qianyi-test-1 ip link set dev lo up
ip netns exec qianyi-test-2 ip link set dev lo up

# 建立一個名為 br0 的 bridge 并啟動(也可以使用 brctl 指令)
ip link add br0 type bridge
ip link set br0 up

# 分别建立 2 對名為 veth-1-a/veth-1-b 和 veth-2-a/veth-2-b 的 Veth Pair 裝置
ip link add veth-1-a type veth peer name veth-1-b
ip link add veth-2-a type veth peer name veth-2-b

# 将 veth-1-a/veth-1-b 和 veth-2-a/veth-2-b 這兩對 Veth Pair 的 a 端放入 qianyi-test-1 和 qianyi-test-2
ip link set veth-1-a netns qianyi-test-1
ip link set veth-2-a netns qianyi-test-2

# 為 veth-1-a 和 veth-2-a 配置 IP 并開啟
ip netns exec qianyi-test-1 ip addr add 10.0.0.101/24 dev veth-1-a
ip netns exec qianyi-test-1 ip link set dev veth-1-a up

ip netns exec qianyi-test-2 ip addr add 10.0.0.102/24 dev veth-2-a
ip netns exec qianyi-test-2 ip link set dev veth-2-a up

# 将 veth-1-a/veth-1-b 和 veth-2-a/veth-2-b 這兩對 Veth Pair 的 b 端接入 br0 網橋并開啟接口
ip link set veth-1-b master br0
ip link set dev veth-1-b up
ip link set veth-2-b master br0
ip link set dev veth-2-b up

# 11.238.151.74 上操作

# 建立名為 qianyi-test-3 和 add qianyi-test-4 的命名 netns,可以在 /var/run/netns/ 下檢視
ip netns add qianyi-test-3
ip netns add qianyi-test-4

# 開啟 lo 網卡,這個很重要
ip netns exec qianyi-test-3 ip link set dev lo up
ip netns exec qianyi-test-4 ip link set dev lo up

# 建立一個名為 br0 的 bridge 并啟動(也可以使用 brctl 指令)
ip link add br0 type bridge
ip link set br0 up

# 分别建立 2 對名為 veth-3-a/veth-3-b 和 veth-4-a/veth-4-b 的 Veth Pair 裝置
ip link add veth-3-a type veth peer name veth-3-b
ip link add veth-4-a type veth peer name veth-4-b

# 将 veth-3-a/veth-3-b 和 veth-4-a/veth-4-b 這兩對 Veth Pair 的 a 端放入 qianyi-test-3 和 qianyi-test-4
ip link set veth-3-a netns qianyi-test-3
ip link set veth-4-a netns qianyi-test-4

# 為 veth-3-a 和 veth-4-a 配置 IP 并開啟
ip netns exec qianyi-test-3 ip addr add 10.0.0.103/24 dev veth-3-a
ip netns exec qianyi-test-3 ip link set dev veth-3-a up

ip netns exec qianyi-test-4 ip addr add 10.0.0.104/24 dev veth-4-a
ip netns exec qianyi-test-4 ip link set dev veth-4-a up

# 将 veth-3-a/veth-3-b 和 veth-4-a/veth-4-b 這兩對 Veth Pair 的 b 端接入 br0 網橋并開啟接口
ip link set veth-3-b master br0
ip link set dev veth-3-b up
ip link set veth-4-b master br0
ip link set dev veth-4-b up           

這一長串的指令和之前的步驟完全一緻,建構了一個如下圖所示的網絡環境:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

這個環境裡,10.0.0.101 和 10.0.0.102 是通的,10.0.0.103 和 10.0.0.104 也是通的,但是顯然 10.0.0.101/10.0.0.102 和 10.0.0.103/10.0.0.104 是無法通信的。

接下來配置 VXLAN 環境打通這四個 netns 環境:

# 10.97.212.159 上操作(本機有多個位址時可以用 local 10.97.212.159 指定)
ip link add vxlan1 type vxlan id 1 remote 11.238.151.74 dstport 9527 dev bond0
ip link set vxlan1 master br0
ip link set vxlan1 up

# 11.238.151.74 上操作(本機有多個位址時可以用 local 11.238.151.74 指定)
ip link add vxlan2 type vxlan id 1 remote 10.97.212.159 dstport 9527 dev bond0
ip link set vxlan2 master br0
ip link set vxlan2 up           

使用 brctl show br0 指令可以看到兩個 VXLAN 裝置都連接配接上去了:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

然後從 10.0.0.101 上就可以 ping 通 10.0.0.103 了:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

在 10.0.0.101 上抓的包來看,就像是二層互通一樣:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

直接檢視 arp 緩存,也是和二層互通一模一樣:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

使用 arp -d 10.0.0.103 删掉這個緩存項目,在主控端上重新抓包并儲存檔案,然後用 WireShark 打開看看(因為上面設定的不是 VXLAN 預設端口 4789,還需要設定 WireShark 把抓到的 UDP 解析為 VXLAN 協定):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

我們得到了預期的結果。此時的網絡架構如圖所示:

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

那麼問題來了,這裡使用 UDP 協定能實作可靠通信嗎?當然可以,可靠性不是這一層考慮的事情,而是裡層被包裹的協定需要考慮的。完整的通信原理其實也并不複雜,兩台機器上各自有 VTEP(VXLAN Tunnel Endpoints,VXLAN 隧道端點)裝置,監聽着 9527 端口上發送的 UDP 資料包。在收到資料包後拆解通過 Bridge 傳遞給指定的裝置。那 VETP 這個虛拟裝置怎麼知道類似 10.0.0.3 這樣的位址要發送給哪台機器上的 VETP 裝置呢?這可是虛拟的二層網絡,底層網絡上可不認識這個位址。事實上在 Linux Bridge 上維護着一個名為 FDB(Forwarding Database entry)的二層轉發表,用于儲存遠端虛拟機/容器的 MAC 位址、遠端 VTEP 的 IP,以及 VNI 的映射關系,可以通過 bridge fdb 指令來對 FDB 表進行操作:

# 新增條目
bridge fdb add <remote_host_mac_addr> dev <vxlan_interface> dst <remote_host_ip_addr>

# 删除條目
bridge fdb del <remote_host_mac_addr> dev <vxlan_interface>

# 替換條目
bridge fdb replace <remote_host_mac_addr> dev <vxlan_interface> dst <remote_host_ip_addr>

# 顯示條目
bridge fdb show           

上面這個簡單的實驗就 2 台機器,使用了指令的方式直接指定了彼此的 VTEP 位址,當 fdb 表查不到資訊時發給對方就行了,這是最簡單的互聯模式。大規模 VXLAN 網絡下,就需要考慮如何發現網絡中其他的 VETP 位址了。解決這個問題一般有 2 種方式:一是使用多點傳播/多點傳播( IGMP, Internet Group Management Protocol),把節點組成一個虛拟的整體,包不清楚發給誰的話就廣播給整個組了(上述實驗中的建立 VETH 裝置的指令修改為多點傳播/多點傳播位址比如 224.1.1.1 就行,remote 關鍵字也要改成 group,具體請參閱其他資料);二是通過外部的分布式控制中心來收集 FDB 資訊并分發給同一個 VXLAN 網絡的所有節點。多點傳播/多點傳播受限于底層網絡的支援情況和大規模下的的性能問題,比如很多雲網絡上不一定允許這麼做。是以下文在讨論和研究 K8s 的網絡方案時會看到很多網絡插件的實作采用的都是類似後者的實作方式。

這節就介紹到這裡了。當然 Overlay 網絡方案也不止 VXLAN 這一種方式,隻是目前很多主流的方案都采用了這種方式。其他的 Overlay 模式看上去眼花缭亂,其實說白了,無非就是 L2 over L4,L2 over L3,L3 over L3 等等各種包裝方式罷了,懂了基本原理之後都沒什麼大不了的。網絡虛拟化的裝置和機制也有很多[18],細說的話一天都說不完,但是基本的網絡原理掌握之後,無非是各種協定包的流轉罷了。

三 K8s 的網絡虛拟化實作

1 K8s 的網絡模型

每一個 Pod 都有它自己的 IP 位址,這就意味着你不需要顯式地在每個 Pod 之間建立連結, 你幾乎不需要處理容器端口到主機端口之間的映射。這将建立一個幹淨的、向後相容的模型,在這個模型裡,從端口配置設定、命名、服務發現、 負載均衡、應用配置和遷移的角度來看,Pod 可以被視作虛拟機或者實體主機。

Kubernetes 對所有網絡設施的實施,都需要滿足以下的基本要求(除非有設定一些特定的網絡分段政策):

  • 節點上的 Pod 可以不通過 NAT 和其他任何節點上的 Pod 通信
  • 節點上的代理(比如:系統守護程序、kubelet)可以和節點上的所有 Pod 通信

備注:僅針對那些支援 Pods 在主機網絡中運作的平台(比如:Linux):

  • 那些運作在節點的主機網絡裡的 Pod 可以不通過 NAT 和所有節點上的 Pod 通信

這個模型不僅不複雜,而且還和 Kubernetes 的實作廉價的從虛拟機向容器遷移的初衷相相容, 如果你的工作開始是在虛拟機中運作的,你的虛拟機有一個 IP,這樣就可以和其他的虛拟機進行通信,這是基本相同的模型。

Kubernetes 的 IP 位址存在于 Pod 範圍内 - 容器共享它們的網絡命名空間 - 包括它們的 IP 位址和 MAC 位址。這就意味着 Pod 内的容器都可以通過 localhost 到達各個端口。這也意味着 Pod 内的容器都需要互相協調端口的使用,但是這和虛拟機中的程序似乎沒有什麼不同, 這也被稱為“一個 Pod 一個 IP”模型。

這幾段話引用自 K8s 的官方文檔[19],簡單概括下就是一個 Pod 一個獨立的 IP 位址,所有的 Pod 之間可以不通過 NAT 通信。這個模型把一個 Pod 的網絡環境近似等同于一個 VM 的網絡環境。

2 K8s 的主流網絡插件實作原理

K8s 中的網絡是通過插件方式實作的,其網絡插件有 2 種類型:

  • CNI 插件:遵守 CNI(Container Network Interface,容器網絡接口)規範,其設計上偏重互操作性
  • Kubenet 插件:使用 bridge 和 host-local CNI 插件實作了基本的 cbr0
一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

圖檔來自[20],本文隻關注 CNI 接口插件。主流的 K8s 網絡插件有這些[21],本文選出 github star 數在千以上的幾個項目分析下:

Flannel

CNI 是由 CoreOS 提出的規範,那就先看下 CoreOS 自己的 Flannel 項目的設計。Flannel 會在每台機主控端上部署一個名為 flanneld 的代理程序,網段相關的資料使用 Kubernetes API/Etcd 存儲。Flannel 項目本身是一個架構,真正為我們提供容器網絡功能的,是 Flannel 的後端實作。

目前的 Flannel 有下面幾種後端實作:VXLAN、host-gw、UDP 以及阿裡雲和其他大廠的支援後端(雲廠商都是實驗性支援),還有諸如 IPIP、IPSec 等一些隧道通信的實驗性支援。按照官方文檔的建議是優先使用 VXLAN 模式,host-gw 推薦給經驗豐富且想要進一步提升性能的使用者(雲環境通常不能用,原因後面說),UDP 是 Flannel 最早支援的一種性能比較差的方案,基本上已經棄用了。

下文分别對這三種模式進行分析。

1)VXLAN

使用 Linux 核心 VXLAN 封裝資料包的方式和原理上文已經介紹過了,Flannel 建立了一個名為 flannel.1 的 VETH 裝置。因為 flanneld 程序的存在,是以注冊和更新新的 VETH 裝置關系的任務就依靠這個程序了。是以好像也沒什麼需要說的了,就是每個新的 K8s Node 都會建立 flanneld 這個 DeamonSet 模式的守護程序。然後注冊、更新新的 VETH 裝置就變得非常自然了,全局的資料自然也是儲存在 Etcd 裡了。這種方式圖已經畫過了,無非是裝置名字不一樣(VETH 叫 flannel.1,網橋叫 cni0)而已。

2)host-gw

顧名思義,host-gw 就是把主控端 Host 當做 Gateway 網關來處理協定包的流動。這個方式上文其實也示範過了,至于節點的變化和路由表的增删也是依靠 flanneld 在做的。這個方案優缺點都很明顯,最大的優點自然是性能,實打實的直接轉發(性能整體比主控端層面的通信低 10%,VXLAN 可是20% 起步,甚至 30%)。缺點也很明顯,這種方式要求主控端之間是二層連通的,還需要對基礎設施有掌控權(編輯路由表),這個在雲服務環境一般較難實作,另外規模越來越大時候的路由表規模也會随之增大。這種方式原理上比較簡單,圖不畫了。

3)UDP

每台主控端上的 flanneld 程序會建立一個預設名為 flannel0 的 Tun 裝置。Tun 裝置的功能非常簡單,用于在核心和使用者應用程式之間傳遞 IP 包。核心将一個 IP 包發送給 Tun 裝置之後,這個包就會交給建立這個裝置的應用程式。而程序向 Tun 裝置發送了一個 IP 包,那麼這個 IP 包就會出現在主控端的網絡棧中,然後根據路由表進行下一跳的處理。在由 Flannel 管理的容器網絡裡,一台主控端上的所有容器都屬于該主控端被配置設定的一個“子網”。這個子網的範圍資訊,所屬的主控端 IP 位址都儲存在 Etcd 裡。flanneld 程序均監聽着主控端上的 UDP 8285 端口,互相之間通過 UDP 協定包裝 IP 包給目的主機完成通信。之前說過這個模式性能差,差在哪裡?這個方案就是一個在應用層模拟實作的 Overlay 網絡似得(像不像一個使用者态實作的 VETH 裝置?),資料包相比核心原生支援的 VXLAN 協定在使用者态多了一次進出(flanneld 程序封包/拆包過程),是以性能上損失要大一些。

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

Calico

Calico 是個挺有意思的項目,基本思想是把主控端完全當成路由器,不使用隧道或 NAT 來實作轉發,把所有二三層流量轉換成三層流量,并通過主控端上的路由配置完成包的轉發。

Calico 和之前說的 Flannel 的 host-gw 模式差別是什麼?首先 Calico 不使用網橋,而是通過路由規則在不同的 vNiC 間轉發資料。另外路由表也不是靠 Etcd 存儲和通知更新,而是像現實環境一樣直接用 BGP(Border Gateway Protocol, 邊界網關協定)進行路由表資料交換。BGP 挺複雜的,詳細的闡述這個協定有點費勁(而且我也不是很懂),在本文裡隻需要知道這個協定使得路由裝置可以互相發送和學習對方的路由資訊來充實自己就可以了,有興趣的話請查閱其他資料進一步了解。回到 Calico,主控端上依舊有個名為 Felix 的守護程序和一個名為 BIRD的 BGP 用戶端。

上文說過,Flannel 的 host-gw 模式要求主控端二層是互通的(在一個子網),在 Calico 這裡依然有這個要求。但是 Calico 為不在一個子網的環境提供了 IPIP 模式的支援。開啟這個模式之後,主控端上會建立一個 Tun 裝置以 IP 隧道(IP tunnel)的方式通信。當然用了這個模式之後,包又是L3 over L3 的 Overlay 網絡模式了,性能也和 VXLAN 模式相當。

全路由表的通信方式也沒有額外元件,配置好 IP 路由轉發規則後全靠核心路由子產品的流轉來做。IPIP 的架構圖也是大同小異的,也不畫了。

Cilium

eBPF-based Networking, Security, and Observability

光從這個介紹上就看出來 Cilium 散發出的那種與衆不同的氣息。這個項目目前的 Github Star 數字快過萬了,直接力壓前面兩位。Cilium 部署後會在主控端上建立一個名為 cilium-agent 的守護程序,這個程序的作用就是維護和部署 eBPF 腳本來實作所有的流量轉發、過濾、診斷的事情(都不依賴 Netfilter 機制,kenel > v4.19 版本)。從原理圖的角度畫出來的架構圖很簡單(配圖來自 github 首頁):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

Cilium 除了支援基本的網絡連通、隔離與服務透出之外,依托 eBPF 是以對主控端網絡有更好的觀測性和故障排查能力。這個話題也很大,本文就此收住。這裡給兩幾篇寫的很好的文章何其譯文可以進一步了解22。

3 K8s 容器内通路隔離

上文介紹了網絡插件的機制和實作原理,最終可以建構出一個二層/三層連通的虛拟網絡。預設情況下 Pod 間的任何網絡通路都是不受限的,但是内部網絡中經常還是需要設定一些通路規則(防火牆)的。

針對這個需求,K8s 抽象了一個名為 NetworkPolicy 的機制來支援這個功能。網絡政策通過網絡插件來實作,要使用網絡政策就必須使用支援 NetworkPolicy 的網絡解決方案。為什麼這麼說?因為不是所有的網絡插件都支援 NetworkPolicy 機制,比如 Flannel 就不支援。至于 NetworkPolicy 的底層原理,自然是使用 iptables 配置 netfilter 規則來實作對包的過濾的。NetworkPolicy 配置的方法和 iptables/Netfilter 的原理細節不在本文範圍内,請參閱其他資料進行了解24。

4 K8s 容器内服務透出

在一個 K8s 叢集内部,在網絡插件的幫助下,所有的容器/程序可以互相進行通信。但是作為服務提供方這是不夠的,因為很多時候,服務的使用方不會在同一個 K8s 叢集内的。那麼就需要一種機制将這個叢集内的服務對外透出。K8s 使用 Service 這個對象來完成這個能力的抽象。Service 在 K8s 裡是個很重要的對象,即使在 K8s 内部進行通路,往往也是需要 Service 包裝的(一來 Pod 位址不是永遠固定的,二來總是會有負載均衡的需求)。

一句話概括 Service 的原理就是:Service = kube-proxy + iptables 規則。當一個 Service 建立時,K8s 會為其配置設定一個 Cluster IP 位址。這個位址其實是個 VIP,并沒有一個真實的網絡對象存在。這個 IP 隻會存在于 iptables 規則裡,對這個 VIP:VPort 的通路使用 iptables 的随機模式規則指向了一個或者多個真實存在的 Pod 位址(DNAT),這個是 Service 最基本的工作原理。那 kube-proxy 做什麼?kube-proxy 監聽 Pod 的變化,負責在主控端上生成這些 NAT 規則。這個模式下 kube-proxy 不轉發流量,kube-proxy 隻是負責疏通管道。

K8s 官方文檔比較好的介紹了 kube-proxy 支援的多種模式和基本的原理[26]。早先的 userspace 模式基本上棄用了,上面所述的 iptables 随機規則的做法在大規模下也不推薦使用了(想想為什麼)。現在最推薦的當屬 IPVS 模式了,相對于前兩種在大規模下的性能更好。如果說 IPVS 這個詞比較陌生的話,LVS 這個詞恐怕是我們耳熟能詳的。在這個模式下,kube-proxy 會在主控端上建立一個名為 kube-ipvs0 的虛拟網卡,然後配置設定 Service VIP 作為其 IP 位址。最後 kube-proxy 使用核心的 IPVS 子產品為這個位址設定後端 POD 的位址(ipvsadm 指令可以檢視)。其實 IPVS 在核心中的實作也是用了 Netfilter 的 NAT 機制。不同的是,IPVS 不會為每一個位址設定 NAT 規則,而是把這些規則的處理放到了核心态,保證了 iptables 規則的數量基本上恒定,比較好的解決了之前的問題。

上面說的隻是解決了負載均衡的問題,還沒提到服務透出。K8s 服務透出的方式主要有 NodePort、LoadBalancer 類型的 Service(會調用 CloudProvider 在公有雲上為你建立一個負載均衡服務)以及 ExternalName(kube-dns 裡添加 CNAME)的方式。對于第二種類型,當 Service 繁多但是又流量很小的情況下,也可以使用 Ingress 這個 Service 的 Service 來收斂掉[27]。Ingress 目前隻支援七層 HTTP(S) 轉發(Service 目前隻支援四層轉發),從這個角度猜猜 Ingress 怎麼實作的?來張圖看看吧[28](當然還有很多其他的 Controller[29]):

一文了解 K8s 容器網絡虛拟化開啟 lo 網卡,這個很重要

對于這部分,本文不再進行詳細闡述了,無非就是 NAT,NAT 多了就想辦法收斂 NAT 條目。按照慣例,這裡給出一篇特别好的 kube-proxy 原理闡述的文章供進一步了解[30]。

四 總結

網絡虛拟化是個很大的話題,很難在一篇文章中完全講清楚。盡管這篇文章盡量想把重要的知識節點編織清楚,但受限于作者本人的精力以及認知上的限制,可能存在疏忽甚至錯漏。如有此類問題,歡迎在評論區讨論/指正。參考文獻裡給出了很多不錯的資料值得進一步去學習(部分位址受限于網絡環境,可能需要特定的方式才能通路)。

參考文獻

1、TCP Implementation in Linux: A Brief Tutorial, Helali Bhuiyan, Mark McGinley, Tao Li, Malathi Veeraraghavan, University of Virginia:

https://www.semanticscholar.org/paper/TCP-Implementation-in-Linux-%3A-A-Brief-Tutorial-Bhuiyan-McGinley/f505e259fb0cd8cf3f75582d46cd209fd9cb1d1a

2、NAPI, linuxfoundation,

https://wiki.linuxfoundation.org/networking/napi

3、Monitoring and Tuning the Linux Networking Stack: Receiving Data, Joe Damato,譯文:Linux 網絡棧監控和調優:接收資料(2016):

http://arthurchiao.art/blog/tuning-stack-rx-zh/

4、Monitoring and Tuning the Linux Networking Stack: Sending Data, Joe Damato, 譯文:Linux 網絡棧監控和調優:發送資料(2017):

http://arthurchiao.art/blog/tuning-stack-tx-zh/

5、Scaling in the Linux Networking Stack,

https://github.com/torvalds/linux/blob/master/Documentation/networking/scaling.rst

6、Understanding TCP internals step by step for Software Engineers and System Designers, Kousik Nath

7、Netfilter,

https://www.netfilter.org/

8、Netfilter-packet-flow,

https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

9、Analysis TCP in Linux,

https://github.com/fzyz999/Analysis_TCP_in_Linux

10、NAT - Network Address Translation, 譯文:NAT - 網絡位址轉換(2016):

http://arthurchiao.art/blog/nat-zh/

11、Virtual networking in Linux, By M. Jones, IBM Developer:

https://developer.ibm.com/tutorials/l-virtual-networking/

12、Open vSwitch,

http://www.openvswitch.org/

13、Linux Namespace,

https://man7.org/linux/man-pages/man7/namespaces.7.html

14、ip,

https://man7.org/linux/man-pages/man8/ip.8.html

15、Veth,

https://man7.org/linux/man-pages/man4/veth.4.html

16、VxLAN,

https://en.wikipedia.org/wiki/Virtual_Extensible_LAN

17、QinQ vs VLAN vs VXLAN, John,

https://community.fs.com/blog/qinq-vs-vlan-vs-vxlan.htm

18、Introduction to Linux interfaces for virtual networking, Hangbin Liu:

https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking#

19、Cluster Networking, 英文位址

https://kubernetes.io/zh/docs/concepts/cluster-administration/networking/

20、THE CONTAINER NETWORKING LANDSCAPE: CNI FROM COREOS AND CNM FROM DOCKER, Lee Calcote:

https://thenewstack.io/container-networking-landscape-cni-coreos-cnm-docker/

21、CNI - the Container Network Interface,

https://github.com/containernetworking/cni

22、Making the Kubernetes Service Abstraction Scale using eBPF, [譯] 利用 eBPF 支撐大規模 K8s Service (LPC, 2019):

https://linuxplumbersconf.org/event/4/contributions/458/

23、基于 BPF/XDP 實作 K8s Service 負載均衡 (LPC, 2020)

https://linuxplumbersconf.org/event/7/contributions/674/

24、A Deep Dive into Iptables and Netfilter Architecture, Justin Ellingwood:

https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture

25、Iptables Tutorial 1.2.2, Oskar Andreasson:

https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html

26、Virtual IPs and service proxies, 英文位址:

https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

27、Ingress, 英文位址:

https://kubernetes.io/docs/concepts/services-networking/ingress/

28、NGINX Ingress Controller,

https://www.nginx.com/products/nginx-ingress-controller/

29、Ingress Controllers, 英文位址:

https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/

30、Cracking kubernetes node proxy (aka kube-proxy), [譯] 深入了解 Kubernetes 網絡模型:自己實作 Kube-Proxy 的功能:

https://cloudnative.to/blog/k8s-node-proxy/

虛拟化技術入門

本章主要講解雲計算技術的核心技術之一虛拟化技術,課程首先說明了虛拟化技術的主要作用以及常見實作方法,并針對硬體中常用的虛拟化技術(CPU、記憶體、IO)進行詳細的講解,最後還針對目前流行的開源虛拟化項目進行說明,講解其出現的漏洞以及阿裡雲是怎樣完成漏洞分析和處理的。

點選這裡

,檢視詳情!

繼續閱讀