CNI網路插件指南

Container Network Interface (CNI) 最早是由CoreOS發起的容器網路規範,是Kubernetes網路插件的基礎。其基本思想為:Container Runtime在創建容器時,先創建好network namespace,然後調用CNI插件為這個netns配置網路,其後再啟動容器內的進程。現已加入CNCF,成為CNCF主推的網路模型。

CNI插件包括兩部分:

  • CNI Plugin負責給容器配置網路,它包括兩個基本的介面
    • 配置網路: AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result, error)
    • 清理網路: DelNetwork(net NetworkConfig, rt RuntimeConf) error
  • IPAM Plugin負責給容器分配IP地址,主要實現包括host-local和dhcp。

所有CNI插件均支持通過環境變數和標準輸入傳入參數,如

$ echo {"cniVersion": "0.3.1","name": "mynet","type": "macvlan","bridge": "cni0","isGateway": true,"ipMasq": true,"ipam": {"type": "host-local","subnet": "10.244.1.0/24","routes": [{ "dst": "0.0.0.0/0" }]}} | sudo CNI_COMMAND=ADD CNI_NETNS=/var/run/netns/a CNI_PATH=./bin CNI_IFNAME=eth0 CNI_CONTAINERID=a CNI_VERSION=0.3.1 ./bin/bridgenn$ echo {"cniVersion": "0.3.1","type":"IGNORED", "name": "a","ipam": {"type": "host-local", "subnet":"10.1.2.3/24"}} | sudo CNI_COMMAND=ADD CNI_NETNS=/var/run/netns/a CNI_PATH=./bin CNI_IFNAME=a CNI_CONTAINERID=a CNI_VERSION=0.3.1 ./bin/host-localn

Bridge

Bridge是最簡單的CNI網路插件,它首先在Host創建一個網橋,然後再通過veth pair連接該網橋到container netns。

注意,Bridge模式下,多主機網路通信需要額外配置主機路由。可以藉助Flannel或者Quagga動態路由等來自動配置。

配置示例

{n "cniVersion": "0.3.0",n "name": "mynet",n "type": "bridge",n "bridge": "mynet0",n "isDefaultGateway": true,n "forceAddress": false,n "ipMasq": true,n "hairpinMode": true,n "ipam": {n "type": "host-local",n "subnet": "10.10.0.0/16"n }n}n

# export CNI_PATH=/opt/cni/binn# ip netns add nsn# /opt/cni/bin/cnitool add mynet /var/run/netns/nsn{n "interfaces": [n {n "name": "mynet0",n "mac": "0a:58:0a:0a:00:01"n },n {n "name": "vethc763e31a",n "mac": "66:ad:63:b4:c6:de"n },n {n "name": "eth0",n "mac": "0a:58:0a:0a:00:04",n "sandbox": "/var/run/netns/ns"n }n ],n "ips": [n {n "version": "4",n "interface": 2,n "address": "10.10.0.4/16",n "gateway": "10.10.0.1"n }n ],n "routes": [n {n "dst": "0.0.0.0/0",n "gw": "10.10.0.1"n }n ],n "dns": {}n}n# ip netns exec ns ip addrn1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1n link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00n9: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultn link/ether 0a:58:0a:0a:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0n inet 10.10.0.4/16 scope global eth0n valid_lft forever preferred_lft forevern inet6 fe80::8c78:6dff:fe19:f6bf/64 scope link tentative dadfailedn valid_lft forever preferred_lft forevern# ip netns exec ns ip routendefault via 10.10.0.1 dev eth0n10.10.0.0/16 dev eth0 proto kernel scope link src 10.10.0.4n

IPAM

DHCP

DHCP插件是最主要的IPAM插件之一,用來通過DHCP方式給容器分配IP地址,在macvlan插件中也會用到DHCP插件。

在使用DHCP插件之前,需要先啟動dhcp daemon:

/opt/cni/bin/dhcp daemon &n

然後配置網路使用dhcp作為IPAM插件

{n ...n "ipam": {n "type": "dhcp",n }n}n

host-local

host-local是最常用的CNI IPAM插件,用來給container分配IP地址。

IPv4:

{n "ipam": {n "type": "host-local",n "subnet": "10.10.0.0/16",n "rangeStart": "10.10.1.20",n "rangeEnd": "10.10.3.50",n "gateway": "10.10.0.254",n "routes": [n { "dst": "0.0.0.0/0" },n { "dst": "192.168.0.0/16", "gw": "10.10.5.1" }n ],n "dataDir": "/var/my-orchestrator/container-ipam-state"n }n}n

IPv6:

{n "ipam": {n "type": "host-local",n "subnet": "3ffe:ffff:0:01ff::/64",n "rangeStart": "3ffe:ffff:0:01ff::0010",n "rangeEnd": "3ffe:ffff:0:01ff::0020",n "routes": [n { "dst": "3ffe:ffff:0:01ff::1/64" }n ],n "resolvConf": "/etc/resolv.conf"n }n}n

ptp

ptp插件通過veth pair給容器和host創建點對點連接:veth pair一端在container netns內,另一端在host上。可以通過配置host端的IP和路由來讓ptp連接的容器之前通信。

{n "name": "mynet",n "type": "ptp",n "ipam": {n "type": "host-local",n "subnet": "10.1.1.0/24"n },n "dns": {n "nameservers": [ "10.1.1.1", "8.8.8.8" ]n }n}n

IPVLAN

IPVLAN 和 MACVLAN 類似,都是從一個主機介面虛擬出多個虛擬網路介面。一個重要的區別就是所有的虛擬介面都有相同的 mac 地址,而擁有不同的 ip 地址。因為所有的虛擬介面要共享 mac 地址,所有有些需要注意的地方:

  • DHCP 協議分配 ip 的時候一般會用 mac 地址作為機器的標識。這個情況下,客戶端動態獲取 ip 的時候需要配置唯一的 ClientID 欄位,並且 DHCP server 也要正確配置使用該欄位作為機器標識,而不是使用 mac 地址

IPVLAN支持兩種模式:

  • L2 模式:此時跟macvlan bridge 模式工作原理很相似,父介面作為交換機來轉發子介面的數據。同一個網路的子介面可以通過父介面來轉發數據,而如果想發送到其他網路,報文則會通過父介面的路由轉發出去。
  • L3 模式:此時ipvlan 有點像路由器的功能,它在各個虛擬網路和主機網路之間進行不同網路報文的路由轉發工作。只要父介面相同,即使虛擬機/容器不在同一個網路,也可以互相 ping 通對方,因為 ipvlan 會在中間做報文的轉發工作。注意 L3 模式下的虛擬介面 不會接收到多播或者廣播的報文(這個模式下,所有的網路都會發送給父介面,所有的 ARP 過程或者其他多播報文都是在底層的父介面完成的)。另外外部網路默認情況下是不知道 ipvlan 虛擬出來的網路的,如果不在外部路由器上配置好對應的路由規則,ipvlan 的網路是不能被外部直接訪問的。

創建ipvlan的簡單方法為

ip link add link <master-dev> <slave-dev> type ipvlan mode { l2 | L3 }n

cni配置格式為

{n "name": "mynet",n "type": "ipvlan",n "master": "eth0",n "ipam": {n "type": "host-local",n "subnet": "10.1.2.0/24"n }n}n

需要注意的是

  • ipvlan插件下,容器不能跟Host網路通信
  • 主機介面(也就是master interface)不能同時作為ipvlan和macvlan的master介面

MACVLAN

MACVLAN可以從一個主機介面虛擬出多個macvtap,且每個macvtap設備都擁有不同的mac地址(對應不同的linux字元設備)。MACVLAN支持四種模式

  • bridge模式:數據可以在同一master設備的子設備之間轉發
  • vepa模式:VEPA 模式是對 802.1Qbg 標準中的 VEPA 機制的軟體實現,MACVTAP 設備簡單的將數據轉發到master設備中,完成數據匯聚功能,通常需要外部交換機支持 Hairpin 模式才能正常工作
  • private模式:Private 模式和 VEPA 模式類似,區別是子 MACVTAP 之間相互隔離
  • passthrough模式:內核的 MACVLAN 數據處理邏輯被跳過,硬體決定數據如何處理,從而釋放了 Host CPU 資源

創建macvlan的簡單方法為

ip link add link <master-dev> name macvtap0 type macvtapn

cni配置格式為

{n "name": "mynet",n "type": "macvlan",n "master": "eth0",n "ipam": {n "type": "dhcp"n }n}n

需要注意的是

  • macvlan需要大量 mac 地址,每個虛擬介面都有自己的 mac 地址
  • 無法和 802.11(wireless) 網路一起工作
  • 主機介面(也就是master interface)不能同時作為ipvlan和macvlan的master介面

Flannel

Flannel通過給每台宿主機分配一個子網的方式為容器提供虛擬網路,它基於Linux TUN/TAP,使用UDP封裝IP包來創建overlay網路,並藉助etcd維護網路的分配情況。

Weave Net

Weave Net是一個多主機容器網路方案,支持去中心化的控制平面,各個host上的wRouter間通過建立Full Mesh的TCP鏈接,並通過Gossip來同步控制信息。這種方式省去了集中式的K/V Store,能夠在一定程度上減低部署的複雜性,Weave將其稱為「data centric」,而非RAFT或者Paxos的「algorithm centric」。

數據平面上,Weave通過UDP封裝實現L2 Overlay,封裝支持兩種模式,一種是運行在user space的sleeve mode,另一種是運行在kernal space的 fastpath mode。Sleeve mode通過pcap設備在Linux bridge上截獲數據包並由wRouter完成UDP封裝,支持對L2 traffic進行加密,還支持Partial Connection,但是性能損失明顯。Fastpath mode即通過OVS的odp封裝VxLAN並完成轉發,wRouter不直接參与轉發,而是通過下發odp 流表的方式控制轉發,這種方式可以明顯地提升吞吐量,但是不支持加密等高級功能。

Calico

Calico 是一個基於BGP的純三層的數據中心網路方案(不需要Overlay),並且與OpenStack、Kubernetes、AWS、GCE等IaaS和容器平台都有良好的集成。

Calico在每一個計算節點利用Linux Kernel實現了一個高效的vRouter來負責數據轉發,而每個vRouter通過BGP協議負責把自己上運行的workload的路由信息像整個Calico網路內傳播——小規模部署可以直接互聯,大規模下可通過指定的BGP route reflector來完成。 這樣保證最終所有的workload之間的數據流量都是通過IP路由的方式完成互聯的。Calico節點組網可以直接利用數據中心的網路結構(無論是L2或者L3),不需要額外的NAT,隧道或者Overlay Network。

此外,Calico基於iptables還提供了豐富而靈活的網路Policy,保證通過各個節點上的ACLs來提供Workload的多租戶隔離、安全組以及其他可達性限制等功能。

OVN

OVN (Open Virtual Network) 是OVS提供的原生虛擬化網路方案,旨在解決傳統SDN架構(比如Neutron DVR)的性能問題。

OVN為Kubernetes提供了兩種網路方案:

OVN為Kubernetes提供了兩種網路方案:

  • Overaly: 通過ovs overlay連接容器
  • Underlay: 將VM內的容器連到VM所在的相同網路(開發中)

其中,容器網路的配置是通過OVN的CNI插件來實現。

本文轉自《Kubernetes指南》開源書,歡迎關注和參與。


推薦閱讀:

漫畫:Kubernetes中的ConfigMap和Secret
[原] 數據科學的容器革命
如何在 Windows 上運行 Linux 容器

TAG:Kubernetes | Docker | 容器 |