美文网首页Kubernetes精选学习
【K8s 精选】深入剖析 Kubernetes 网络模型

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

作者: 熊本极客 | 来源:发表于2021-09-28 23:06 被阅读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,实与宿主机与容器的通信。

    相关文章

      网友评论

        本文标题:【K8s 精选】深入剖析 Kubernetes 网络模型

        本文链接:https://www.haomeiwen.com/subject/umvzgltx.html