K8S集群网络生产级探究

K8S集群网络

网络基础知识

1、公司网络架构
mark
  • 路由器:网络出口
  • 核心层:主要完成数据高效转发、链路备份等
  • 汇聚层:网络策略、安全、工作站交换机的接入、VLAN之间通信等功能
  • 接入层:工作站的接入
1、一个局域网内主机A10)和主机B(20)之间通讯流程:
网段:192.168.31.0/24
源IP和目的IP均在同一子网下。
四元组:源IP 源MAC 目的IP 目的MAC

- 在本机查找ARP缓存表,ARP广播包询问20的MAC地址是多少。 

2、主机A10)和主机B(20)不在同一个局域网内之间通讯流程:
VLAN1:192.168.31.0/24
VLAN2:192.168.32.0/24

- 主机A自顶向下将数据封装成链路层帧,缓存在主机A的适配器缓存中,主机A通过查看适配器中ARP表对应的MAC地址,将链路层帧发送到与其连接的第一跳路由器上,当链路层帧到达该路由器后,路由器根据自身的路由器转发表转发到指定的出口IP再一层层转向目的VLAN。
2、交换技术

有想过局域网内主机怎么通信的?主机访问外网又是怎么通信的?

想要搞懂这些问题得从交换机、路由器讲起。

交换机工作在OSI参考模型的第二次,即数据链路层。交换机拥有一条高带宽的背部总线交换矩阵,在同一时间可进行多个端口对之间的数据传输。

交换技术分为2层和3层:

  • 2层:主要用于小型局域网,仅支持在数据链路层转发数据,对工作站接入。

  • 3层:三层交换技术诞生,最初是为了解决广播域的问题,多年发展,三层交换机书已经成为构建中大型网络的主要力量。

广播域

交换机在转发数据时会先进行广播,这个广播可以发送的区域就是一个广播域。交换机之间对广播帧是透明的,所以交换机之间组成的网络是一个广播域。

路由器的一个接口下的网络是一个广播域,所以路由器可以隔离广播域。

ARP(地址解析协议,在IPV6中用NDP替代)

发送这个广播帧是由ARP协议实现,ARP是通过IP地址获取物理地址的一个TCP/IP协议。

三层交换机

前面讲的二层交换机只工作在数据链路层,路由器则工作在网络层。而功能强大的三层交换机可同时工作在数据链路层和网络层,并根据 MAC地址或IP地址转发数据包。

VLAN(Virtual Local Area Network):虚拟局域网

VLAN是一种将局域网设备从逻辑上划分成一个个网段。

一个VLAN就是一个广播域,VLAN之间的通信是通过第3层的路由器来完成的。VLAN应用非常广泛,基本上大部分网络项目都会划分vlan。

VLAN的主要好处:

  • 分割广播域,减少广播风暴影响范围。
  • 提高网络安全性,根据不同的部门、用途、应用划分不同网段
3、路由技术

路由器主要分为两个端口类型:LAN口和WAN口

  • WAN口:配置公网IP,接入到互联网,转发来自LAN口的IP数据包。

  • LAN口:配置内网IP(网关),连接内部交换机。

路由器是连接两个或多个网络的硬件设备,将从端口上接收的数据包,根据数据包的目的地址智能转发出去。

路由器的功能:

  • 路由
  • 转发
  • 隔离子网
  • 隔离广播域

路由器是互联网的枢纽,是连接互联网中各个局域网、广域网的设备,相比交换机来说,路由器的数据转发很复杂,它会根据目的地址给出一条最优的路径。那么路径信息的来源有两种:动态路由和静态路由。

静态路由:指人工手动指定到目标主机的地址然后记录在路由表中,如果其中某个节点不可用则需要重新指定。

动态路由:则是路由器根据动态路由协议自动计算出路径永久可用,能实时地适应网络结构的变化。

常用的动态路由协议:

  • RIP( Routing Information Protocol ,路由信息协议)

  • OSPF(Open Shortest Path First,开放式最短路径优先)

  • BGP(Border Gateway Protocol,边界网关协议)

4、OSI七层模型

OSI(Open System Interconnection)是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。

层次 名称 功能 协议数据单元(PDU) 常见协议
7 应用层 为用户的应用程序提供网络服务,提供一个接口。 数据 HTTP、FTP、Telnet
6 表示层 数据格式转换、数据加密/解密 数据单元 ASCII
5 会话层 建立、管理和维护会话 数据单元 SSH、RPC
4 传输层 建立、管理和维护端到端的连接 段/报文 TCP、UDP
3 网络层 IP选址及路由选择 分组/包 IP、ICMP、RIP、OSPF
2 数据链路层 硬件地址寻址,差错效验等。 ARP、WIFI
1 物理层 利用物理传输介质提供物理连接,传送比特流。 比特流 RJ45、RJ11
mark
5、TCP/UDP协议

TCP(Transmission Control Protocol,传输控制协议),面向连接协议,双方先建立可靠的连接,再发送数据。适用于传输数据量大,可靠性要求高的应用场景。

UDP(User Data Protocol,用户数据报协议),面向非连接协议,不与对方建立连接,直接将数据包发送给对方。适用于一次只传输少量的数据,可靠性要求低的应用场景。相对TCP传输速度快。

4.2 Kubernetes网络模型

Kubernetes 要求所有的网络插件实现必须满足如下要求:

  • 一个Pod一个IP
  • 所有的 Pod 可以与任何其他 Pod 直接通信,无需使用 NAT 映射
  • 所有节点可以与所有 Pod 直接通信,无需使用 NAT 映射
  • Pod 内部获取到的 IP 地址与其他 Pod 或节点与其通信时的 IP 地址是同一个。
1、Docker容器网络模型

先看下Linux网络名词:

  • 网络的命名空间:Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信;Docker利用这一特性,实现不同容器间的网络隔离。

  • Veth设备对:Veth设备对的引入是为了实现在不同网络命名空间的通信。

  • Iptables/Netfilter:Docker使用Netfilter实现容器网络转发。

  • 网桥:网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。

  • 路由:Linux系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里。

Docker容器网络示意图如下:

mark
2、Pod 网络

问题:Pod是K8S最小调度单元,一个Pod由一个容器或多个容器组成,当多个容器时,怎么都用这一个Pod IP?

实现:k8s会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了。即网络设备、IP地址、Mac地址等。这就是解决网络共享的一种解法。在Pod的IP地址就是infra container的IP地址。

mark

在 Kubernetes 中,每一个 Pod 都有一个真实的 IP 地址,并且每一个 Pod 都可以使用此 IP 地址与 其他 Pod 通信。

Pod之间通信会有两种情况:

  • 两个Pod在同一个Node上
  • 两个Pod在不同Node上

先看下第一种情况:两个Pod在同一个Node上

同节点Pod之间通信道理与Docker网络一样的,如下图:

  1. 对 Pod1 来说,eth0 通过虚拟以太网设备(veth0)连接到 root namespace;
  2. 网桥 cbr0 中为 veth0 配置了一个网段。一旦数据包到达网桥,网桥使用ARP 协议解析出其正确的目标网段 veth1;
  3. 网桥 cbr0 将数据包发送到 veth1;
  4. 数据包到达 veth1 时,被直接转发到 Pod2 的 network namespace 中的 eth0 网络设备。

再看下第二种情况:两个Pod在不同Node上

K8S网络模型要求Pod IP在整个网络中都可访问,这种需求是由第三方网络组件实现。

3、CNI(容器网络接口)

CNI(Container Network Interface,容器网络接口):是一个容器网络规范,Kubernetes网络采用的就是这个CNI规范,CNI实现依赖两种插件,一种CNI Plugin是负责容器连接到主机,另一种是IPAM负责配置容器网络命名空间的网络。

CNI插件默认路径:

# ls /opt/cni/bin/

地址:https://github.com/containernetworking/cni

当你在宿主机上部署Flanneld后,flanneld 启动后会在每台宿主机上生成它对应的CNI 配置文件(它其实是一个 ConfigMap),从而告诉Kubernetes,这个集群要使用 Flannel 作为容器网络方案。

CNI配置文件路径:

/etc/cni/net.d/10-flannel.conflist

当 kubelet 组件需要创建 Pod 的时候,先调用dockershim它先创建一个 Infra 容器。然后调用 CNI 插件为 Infra 容器配置网络。

这两个路径在kubelet启动参数中定义:

--network-plugin=cni \
--cni-conf-dir=/etc/cni/net.d \
--cni-bin-dir=/opt/cni/bin