乐趣区

关于kubernetes:Kubernetes-Network-由浅入深

Kubernetes Network 由浅入深

次要是学习 深刻分析 Kubernetes专栏课的笔记。

一、单机容器网络

名词

  • 网络栈:网络栈包含了网卡 (Network Interface)、回环设施(Loopback Device)、路由表(Routing Table) 和Iptables规定,对于一个过程来说,这些因素,就形成了它发动申请和响应网络申请的根本环境。
  • 网桥 (Bridge):bridge 是一个虚构网络设备,所以具备网络设备的特色,能够配置 IPMAC 地址;Bridger是一个虚构交换机,具备和物理交换机相似的性能。它是工作在数据链路层的设施。
  • Veth Pair: 虚构网线,用来连贯容器到网桥上的;它被创立进去当前,总是以两张虚构网卡 (Veth Peer) 的模式成对呈现,并且,从其中一个网卡收回的数据包会主动呈现在与之对应的网卡上,哪怕是这两张 \_* 网卡 \_在不同的 Network Namespace 中。
  • ARP: 是一个通过三层的 IP 地址找到对应二层 MAC 地址的协定。
  • CAM 表 :虚构交换机(这里是网桥) 通过 MAC 地址学习保护的端口和 MAC 地址的对应表。

Host 网络

作为一个容器,在启动时能够通过指定-net=host,应用宿主机的Network Namespace

$ docker run -d -net=host --name nginx-1 nginx

应用 Host 网络的长处是网络性能较好,间接应用宿主机的网络栈,毛病是会引入共享网络资源的问题,比方端口抵触。所以,在少数状况下,咱们都心愿能应用本人 Network Namespace 里的网络栈,领有属于本人的 IP 和端口。

如何通信

如上图,形容了单节点容器网络的通信流程,上面次要按 C1->C2 的拜访流程来详细描述交互流程:

# 先创立两个容器,用于模仿发动申请, 启动两个 centos 容器,并在外面装置 net-tools 工具,才能够应用 ifconfig 命令
# 创立 C1,并装置 net-tools
$ docker run -d -it --name c1 centos /bin/bash
$ docker exec -it c1 bash
$ [root@60671509044e /]# yum install -y net-tools
# 创立 C2,并装置 net-tools
$ docker run -d -it --name c2 centos /bin/bash
$ docker exec -it c2 bash
$ [root@94a6c877b01a /]# yum install -y net-tools
  • 容器 C1C2启动之后,在容器中都有一条默认的路由规定,以后容器网段的所有申请都会走 eth0 网卡设施。

    • C1
# 进入 c1 容器,查看 ip 以及路由表
$ docker exec -it c1 bash
# 查看 IP
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.7  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:07  txqueuelen 0  (Ethernet)
        RX packets 6698  bytes 9678058 (9.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3518  bytes 195061 (190.4 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
        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
# 查看路由       
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        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
  • C2
# 进入 C2 容器查看 IP 和路由表
$ docker exec -it c2 bash
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.8  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:08  txqueuelen 0  (Ethernet)
        RX packets 6771  bytes 9681937 (9.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3227  bytes 179347 (175.1 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
        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
# 查看路由
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        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

上述容器事实有本人的 IP 以及 MAC 地址,并且每个容器中都有默认路由 _gateway 指向 eth0 网卡;并且 _gateway 有对应的 MAC 地址曾经存在于本地 ARP 缓存中。

  • 主机之间网络通信须要用到 MAC 地址,这是数据链路层辨认主机的形式,C1拜访 C2 的时候会先从本地 ARP 缓存中查找是否有 C2 容器对应的 IP:172.17.0.3MAC地址。如果没有就会发动 ARP 协定查找 MAC 地址。
# c1 -> c2 , 先发动 ARP 申请查找 MAC 地址,能够在容器中查看 ARP 缓存对应 IP 的 MAC
$ docker exec -it c1 bash
# 先查看本地的 ARP 缓存
$ [root@94a6c877b01a /]# arp
Address                  HWtype  HWaddress           Flags Mask            Iface
_gateway                 ether   02:42:2e:8d:21:d6   C                     eth0
# 执行 ping 命令就会发动 ARP 寻址申请
$ ping 172.17.0.8
# 再查问本地 arp 缓存,发现曾经有 MAC 地址存在了
$ [root@60671509044e /]# arp
Address                  HWtype  HWaddress           Flags Mask            Iface
172.17.0.8               ether   02:42:ac:11:00:08   C                     eth0
_gateway                 ether   02:42:2e:8d:21:d6   C                     eth0

ARP寻址流程:C1容器发动 ARP 申请,进过本地路由协定之后会把申请路由到网桥上,此时网桥 (Bridge) 充当一个虚构交换机,虚构替换机会把 ARP 播送到其它插入到网桥的所有容器,C2收到 ARP 协定之后会回复 MAC 地址。

  • 查找到 C2MAC地址之后就能够发动通信。

二、跨主机容器通信

跨主机之间容器通信按是否依赖底层网络环境来划分次要分为 OverlayUnderlay两种网络结构,Overlay网络要求只是主机之间网络可达即可,不要求主机之间同处二层域;Underlay对底层的基础设施有要求,依照实现的形式对底层的网络基础设施有不同的要求,比方 Flanan host-gw 组件要求主机之间同处二层域,也就是主机之间要连贯到一个交换机上。

名词

  • Overlay Network(笼罩网络): 在已有的宿主机网络之上,通过软件构建一个笼罩在宿主机网络之上的、能够把所有容器连通在一起的虚构网络。
  • Tun 设施 (Tunnel 设施):在Linux 中,TUN设施是一种工作在三层(Network Layer)的虚构网络设备;Tun设施的性能就是在操作系统内核和用户应用程序之间传递 IP 包,
  • VXLAN: 虚构可扩大局域网 (Virtual Extensible LAN), 是LINUX 内核反对的一种网络虚拟化技术,VXLAN齐全在内核态实现网络数据包的封装和解封装。
  • VTEP:虚构隧道端点设施,它既有 IP,也有MAC 地址。
  • BGP: 边界网关协定(Border Gateway Protocol), 它是一个 Linux 内核原生就反对的、专门用在大规模数据中心里保护不同的自治零碎之间路由信息的、无核心的路由协定。

跨主机通信

跨主机之间的容器通信,通过采纳 Overlay Network 来实现跨主机之间的容器通信,Overlay Network的实现有多种形式。

Overlay 模式

1、三层 Flannel UDP

Flannel UDP模式是 Flannel 最开始提供的一种最简略且最易实现的容器跨主网络计划,然而因为性能最差,所以起初被弃用。然而对于了解 Overlay 的实现形式还是很有参考意义的。

咱们以一个例子来讲述这个网络拜访的流程,在这个流程中,有两台宿主机,四个容器,咱们须要通过 Container-1 容器申请Container-4

Container-1容器向 Container-4 容器发动申请,Docker0是位于 Root Network Namespace 的,通过 veth peer 一头连着容器的 Network Namespace 一头连着位于 Root Netwrok NamespaceDocker0虚构网络设备。

  • 容器 100.96.1.2 拜访 100.96.2.2,因为目标地址不在Docker0 网桥的网段内 (通过ARP 申请一次就晓得指标容器不在此网桥上),所以这个 IP 会执行 Container-1 的默认路由规定中,容器中的默认路由规定就是如下的default via 172.17.0.1 dev eth0。对应到上图的步骤 1。
# 容器中默认设置的的路由规定,[root@94a6c877b01a /]# ip route
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2 
# 下一跳是 172.17.0.1 且从 eth0 设施上进来,通过查看 docker 的网络,172.17.0.1 就是 bridge 设施的网关 IP
lengrongfu@MacintoshdeMacBook-Pro ~ % docker network ls        
NETWORK ID     NAME                               DRIVER    SCOPE
e522990979b3   bridge                             bridge    local
# 查看网络
lengrongfu@MacintoshdeMacBook-Pro ~ % docker inspect network e522990979b3
[
    {
        "Name": "bridge",
        "Id": "e522990979b365e9df4d967c3600483e598e530361deb28513b6e75b8b66bedf",
        "Created": "2021-04-12T12:11:57.321486866Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"94a6c877b01ac3a1638f1c5cde87e7c58be9ce0aafd4a78efcb96528ab00ed94": {"Name":"c2","EndpointID":"a5c12fb3800991228f8dc3a2a8de1d6f4865439701a83558e4430c2aebf783a8","MacAddress":"02:42:ac:11:00:02","IPv4Address":"172.17.0.2/16","IPv6Address":""}
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}}
]
  • 进入到 Docker0 网桥之后就依照主机上的路由取决于后续如何走。如下就是主机的路由表,拜访指标 IP100.96.2.2的设施会命中第二条匹配规定,意思是拜访 100.96.0.0/16 网段的数据去 flannel0 设施,并且愿 IP100.96.1.0。对应到上图的步骤 2。
# Node1 路由表
$ ip route
1 Default via 10.168.0.1 dev eth0
2 100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.1.0
3 100.96.1.0/24 dev docker0 proto kernel scope link src 100.96.1.1
4 10.168.0.0/24 dev eth0 proto kernel scope link src 10.168.0.2
Flannel0 设施
  • 上述说了 Flannel0 是一个 TUN 虚构三层网络设备,次要是在内核态和用户态之间传递 IP 包;持续按上述的流程剖析,数据报文从内核态达到 Flannel0 设施之后,会被传递给创立 Flannel0 设施的过程也就是 FlannelD 过程,而后 flanneld 过程看到目标地址是 100.96.2.2, 就把数据报文发送到Node2 节点上的 flanneld 过程监听的 UDP 端口上。flanneld会把要发送的数据封装为一个 UDP 数据包收回去。对应到上图的步骤 3、4、5、6。

    • flanneld过程是怎么晓得 100.96.2.2 这个 ipNode2上呢,这是因为它利用了子网,在每个节点启动的时候都会被指定一个字网段,通过字网就能确定这个 ip 是属于那个节点的,子网被存在 etcd 外面。
  • Node2上的 flanneld 过程收到数据包之后,会发送到 flannel0 设施上,这是一个从用户态到内核态的过程,所以 Linux 内核网络协议栈就会负责解决这个 IP 包,具体的解决办法,就是通过本机的路由表来寻找这个 IP 包的下一步流向。对应到上图的步骤 7、8。
# node2 上的路由表
$ ip route
1 default via 10.168.0.1 dev eth0
2 100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.2.0
3 100.96.2.0/24 dev docker0 proto kernel scope link src 100.96.2.1
4 10.168.0.0/24 dev eth0 proto kernel scope link src 10.168.0.3
  • 通过解析出指标 ip100.96.2.2,他和第三条的路由规定匹配更加准确,这条路由规定的意思是把发往 100.96.2.0/24 网段的的数据包发送到 docker0 设施下来,并且设置源 IP100.96.2.1。对应到上图的步骤 9。
  • 数据包进入到 docker0 设施之后,docker0网桥会表演二层交换机的角色,将数据包发送给正确的 veth pair 对,进过此设施之后就进入到 Contaniner-2 的网络协议栈中。对应到上图的步骤 10。

Flannel UDP模式提供的是一个三层的 Overlay 网络,它首选对收回端的 IP 包进行 UDP 封装,而后在接收端进行解封装拿到原始 IP 包,进而把这个 IP 包转发给指标容器。

Flannel UDP模式有重大的性能问题,次要问题是,因为应用了 TUN 设施,仅在收回 IP 包的过程中,就须要通过三次用户态和内核态之间的数据拷贝。

2、三层 Calico ipip
3、二层 + 三层 VXLAN

VXLAN网络的设计思维是,在现有的三层网络之上,笼罩一层虚构的、由内核 VXLAN 模块负责保护的二层网络,使得连贯在这个 VXLAN 二层网络上的主机之间,能够像在同一个局域网那样自在通信。

为了能在二层网络上买通隧道,VXLAN会在宿主机上设置一个非凡的网络设备作为隧道的两端,这个设施就叫作 VTEP,全称是:(VXLAN Tun End Poin) 虚构隧道端点。

VTEP设施的作用和 flanneld 过程的作用是一样的,就是做数据包的封装和解封装,只不过,它进行封装和解封装的是二层数据帧,而且这个工作流程,全都是在内核里实现的。

Underlay 模式

1、三层模式 BGP

如上图是一个典型的 BGP 网络拓扑图,通过 Route1Route2作为边界路由网关,把其它 LAN 的路由信息写入到以后的路由中,就实现了不同 LAN 下的路由信息同步,达到三层网络全通。

Calico BGP 应用

​ 在理解了 BGP 之后,Calico我的项目的架构就非常容易了解了,它把每个主机节点当做一个边界路由来对待,所以在每个节点上都保留了所有其余节点的路由信息,咱们来剖析一下它的实现,它由三个局部组成:

  • CalicoCNI 插件,这是 CaclicoKubernetes对接的局部。
  • BIRDBGP 的客户端,专门负责在集群外面散发路由信息。
  • Felix, 它是一个 Demoset,负责在宿主机上插入路由规定(写入Linux 内核的 FIB 转发信息表),以及保护 Calico 所需的网络设备等工作。

Calico BGP模式和 Flannel host-gw 模式不同,Calico没有创立任何的虚构网桥设施,Calico的工作形式采纳如下图来阐明。

Calico BGP模式的网络交互图如上所示,如 container1 须要拜访 Container3,咱们来剖析下网络如何达到。因为没有采纳cni0 虚构网桥设施,因而 veth 设施对的一端是在容器的 Network Namespace 中的,一端是在宿主机的容器网络空间的,

  • 首先 Calico CNI 插件还须要在每个宿主机上为每个容器的 Veth Pair 设施配置一条路由规定,因为承受传入的 IP 包,比方:
# 192.168.0.2 节点上的路由信息有
$ ip route
10.20.0.2 dev cali1 scope link
10.20.0.3 dev cali2 scope link

# 192.168.0.3 节点上的路由信息有
$ ip route
10.20.1.2 dev cali3 scope link
10.20.1.3 dev cali4 scope link
  • 每个节点上还有 BGP 播送的其它节点路由协定,比方:
# 192.168.0.2 上有一条指向 192.169.0.3 的路由
$ ip route
10.20.1.0/24 via 192.168.0.3 dev eth0
# 192.168.0.3 上有一条指向 192.168.0.2 的路由
$ ip route
10.20.0.0/24 via 192.168.0.2 dev eth0
  • 默认的 Calico BGP 应用的是 Node to Node 的模式,会导致每个节点上的连贯以 N^2 的数独增长,个别举荐少于应用 100 个节点的集群中。在大规模集群中,须要用到一个叫 Route Reflector 的模式,所有的路由会对立上报到一个核心节点,其它节点都从核心节点进行同步。

Calico BGP模式和 Flannel host-gw 模式一样,都有一个对根底网络设施的依赖,要求集群宿主机之间是二层可达的。如果宿主机之间处在不同的 LAN 下,就须要应用 Calico ipipOverlay模式了。

2、二层 VLAN
3、Flannel host-gw

Flannel host-gw模式一张图就能够讲清楚他们之间的实现原理。

  • CNI0设施是一个三层交换机,具备二层交换机的性能,同时具备独立IP

flannelDaemonset 的形式在每个节点上启动一个 Flanneld 过程,用于保护每个节点上的路由信息,实现形式是,本地

如:192.168.1.0/24 via 10.20.0.3 dev eth0路由定义了拜访 192.168.1.0/24 网段的下一跳为 10.20.0.3 并从 eth0 设施出。

而后 IP 包被封装成帧发送进来的时候,会应用路由表里的下一跳来设置目标 MAC 地址;这样,就能通过二层网络达到目标宿主机。

因为他会应用下一跳的目标 MAC 地址,所以它要求宿主机之间是二层联通的,不如就没法通过应用 ARP 协定用 IP 去获取 MAC 地址了。

退出移动版