Kubernetes精选学习

【K8s 精选】深入剖析 Kubernetes 网络模型

2021-09-28  本文已影响0人  熊本极客

1 网络基础

1.1 网桥、网卡、MAC

网桥:将不同物理层连接在一起。
网卡:接收和转换信息的硬件。
MAC:MAC 是设备的地址。

网桥、网卡和 MAC 作用于数据链路层。如下图所示,网卡“插入”到网桥和设备中,使用网线连接网桥和设备两端的网卡。

网桥网卡和MAC的关系.jpg

1.2 Veth Pair

Veth Pair 可以参考Linux 虚拟网络设备 veth-pair 详解,看这一篇就够了

veth-pair 是一对的虚拟设备接口,一端连着协议栈,一端彼此相连。以网桥的连接方式为例,分析 veth-pair 的使用。网桥相当于交换机,可以中转两个 namespace 的流量。veth-pair 是“插在”设备和网桥之间的网卡。

1.3 iptables

iptables 详解可以参考iptables命令及一些常用规则

iptables 部分命令如下:

-t nat 表示配置的是 nat 表,raw 网址过滤、mangle 数据修改、net 地址转换、filter 包过滤(防火墙规则)
-A PREROUTING 表示添加一个 PREROUTING 链
-i eth0 表示指定数据包进入本机的网络接口
-p tcp --dport 422 代表匹配到的 tcp 协议的数据包,目的端口号是422
-j ACCEPT 表示接收数据包,例如 accept 是接收数据包、drop 是丢弃数据包、redirct 是重定向、snat 是源地址转换、dnat 是目标地址转换、masquerade 是 IP 伪装(NAT)、log 是日志记录
--to 192.168.102.37:22 表示转发到 192.168.102.37:22
#数据报伪装
#将源地址是 192.168.102.0/24 的数据包进行地址伪装
$iptables -t nat -A POSTROUTING -s 192.168.102.0/24 -j MASQUERADE
#将全部来源的数据包进行地址伪装
$iptables -t nat -A POSTROUTING -j MASQUERADE

# 数据包转发:设置 422 端口转发到 22 端口
# 方法1 指定数据包从 192.168.102.37:422 转发到 192.168.102.37:22
$iptables -t nat -A PREROUTING -p tcp -d 192.168.102.37 --dport 422 -j DNAT --to 192.168.102.37:22
#方法2 指定数据包从本机网卡 eth0 端口 443 转发到 192.168.102.37:22
$iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 443 -j DNAT --to 192.168.102.37:22

# 本机网卡 eth0 接收 137 udp 端口、138 tcp 端口的数据包 
$iptables –A INPUT –i eth0 –p udp –dport 137 –j ACCEPT
$iptables –A INPUT –i eth0 –p tcp –dport 138 –j ACCEPT

# 防火墙设置
# INPUT 链、FORWARD 链、OUTPUT 链允许全部数据包的传输
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

如下所示,iptables 与网络分层的关系。

iptables 与网络分层的关系.png

2 Kubernetes 网络插件 CNI 的工作流程

image.png

3 容器网络入门

关键问题:每个容器都有属于自己的 IP 和端口被隔离的容器进程,该如何跟其他 Network Namespace 里的容器进程进行交互呢

3.1 同一个宿主机下容器之间的通信

深入了解 Network Namespace 可以参考一文搞懂 Linux network namespace

容器利用 Network Namespace 实现网络的隔离,包括网络设备、IPV4 和 IPV6 协议栈、IP 路由表、防火墙、/proc/net 目录、/sys/class/net 目录、端口等。多个 Network Namespace 之间的通信需要利用 Veth Pair + 网桥,其中网桥具有 iptables 功能,只需要设置规则 iptables -A FORWARD -i bridgeA -j ACCEPT,即可允许数据包在网桥 bridgeA 中转发。

案例分析:同一个宿主机上实现容器 172.17.0.2 到容器 172.17.0.3 的通信。
Container1 172.17.0.2 访问 Container2 172.17.0.3 的流程
数据包 从 Container1 访问 Container2 172.17.0.3 的时候首先匹配到第二条路由规则(GateWay 0.0.0.0),意味着经过本机的 eth0,通过数据链路层 MAC 协议发送到 Container2 172.17.0.3。Container1 另一端的网卡 veth9c02e56 和 Container2 另一端的网卡 vethb4963f3 都“插入”网桥中。最后Container2 172.17.0.3 也是通过 eth0 接受数据包。

同一个宿主机下容器之间的通信.png
#进入容器 172.17.0.2 后,查看网络设备
$ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 364  bytes 8137175 (7.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 281  bytes 21161 (20.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        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
#分析:虚拟网卡 Veth Pair 的一端 eth0 在“插入”容器中。

#查看容器的路由表
#Destination 表示目标地址或者主机,Gateway 表示网关地址,Genmask 表示子网掩码,Flags-U 表示路由是活动的,Iface 表示 路由表项对应的输出接口       
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
#分析:eth0 是容器的默认路由设备。第二行表示网段 172.17.0.0/16 的请求都会交给 eth0 来处理
#登录容器所在的宿主机,查看网络设备
$ifconfig
...
docker0   Link encap:Ethernet  HWaddr 02:42:d8:e4:df:c1  
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:d8ff:fee4:dfc1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:309 errors:0 dropped:0 overruns:0 frame:0
          TX packets:372 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
          RX bytes:18944 (18.9 KB)  TX bytes:8137789 (8.1 MB)
veth9c02e56 Link encap:Ethernet  HWaddr 52:81:0b:24:3d:da  
          inet6 addr: fe80::5081:bff:fe24:3dda/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:288 errors:0 dropped:0 overruns:0 frame:0
          TX packets:371 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
          RX bytes:21608 (21.6 KB)  TX bytes:8137719 (8.1 MB)
#分析:宿主机有虚拟网卡 Veth Pair 的另一端 veth9c02e56

#查看网桥信息          
$brctl show
bridge name bridge id  STP enabled interfaces
docker0  8000.0242d8e4dfc1 no  veth9c02e56
#分析:通过网桥信息可以看到虚拟网卡 veth9c02e56 已经“插入”网桥 docker0 中

结论:被隔离在 Network Namespace 里的容器进程,通过 Veth Pair + 宿主机网桥实现了跟其它容器的数据交换

3.2 容器与不同宿主机的通信

案例分析:Node1 10.168.0.2 上的 Container1 172.17.0.2 访问 Node2 10.168.0.3。首先数据包通过 container1 eth0 和 docker0 veth9c02e56 传输到 docker0,接着根据 docker0 的 iptables 规则10.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 表示目标地址是 10.168.0.0/24 的数据包都交给 eth0。最后数据包经过 Node1 eth0 转发到住宿机网络,最终达到 Node2 10.168.0.3

容器与不同宿主机的通信.png

容器不通“外网”的定位思路:宿主机网络 》网桥 docker0 》网桥 iptables 防火墙规则
上述例子 Node1 Container1 到 Node2。首先在 Node1 上 curl Node2,判断宿主机之间的网络有无通。然后在 Node1 上 ifconfig 查询 docker0 的 IP 为 172.17.0.1,接着在 Node2 上直接 curl docker0。最后检查 docker0 上的 iptables 规则 iptables -A FORWARD -i docker0 -j ACCEPT,即防火墙有无打开。

4 Kubernetes 网络模型

本节以 Fannel-host-gw 为例,讲解 Kubernetes 的三层网络原理。host-gw 模式的原理是将宿主机的 Flannel 子网设置成该宿主机的 IP 地址,数据包通过路由直接在宿主机之间交换

Fannel-host-gw.png
#CNI 插件 Fannel 在 Node1 上创建这条路由规则
$ip route
10.244.1.0/24 via 10.168.0.3 dev eth0
#这条规则的含义:目的地址属于子网 10.244.1.0/24 的数据包,都会经过本机网卡 eth0,并且下一跳地址是 10.168.0.3
#分析:宿主机 Node1 eth0 到 Node2 eth0 的通信是直接采用路由规则转发,即数据帧是通过二层网络的 mac 协议,实现了在不同宿主机之间的转发。

结合上述 2.1 中容器与宿主机的通信。Node1 的容器 container1 10.244.0.2 到 Node2 的容器 container2 10.244.1.3 的数据包转发流程:
10.244.0.2 到 Node1 网桥 cni0:通过 Veth Pair + 网桥 cni0,即容器侧的 eth0 与宿主机网桥 cni0 侧 vethxxxxxxx,实现容器与宿主机的通信。
宿主机 Node1 到 Node2:直接配置网桥 cni0 路由规则转发,实现目的地是子网 10.244.1.0/24 的数据包,经过本机网卡 eth0,转发到 10.168.0.3
Node2 网桥 cni0 到 10.244.1.3:同理 ①,即宿主机网桥 cni0 侧 vethxxxxxxx 与 容器侧的 eth0,实与宿主机与容器的通信。

上一篇 下一篇

猜你喜欢

热点阅读