Kubernetes(K8s)_15_CNI
- CNI
 - 网络模型
 - Underlay
 - MAC VLAN
 - IP VLAN
 - Direct Route
 
- Overlay
 - VXLAN
 
- CNI插件
 - Flannel
 - Calico
 
- CNI配置
 - 内置实现
 
CNI
CNI(Container Network Interface): 实现容器网络连接的规范
- Kubernetes将网络通信可分为: Pod内容器、Pod、Pod与Service、外部与Service
 - CNI解决跨节点的网络通信方式分为: 
SDN、Static Route、Dynamic Route、Overlay 
// https://github1s.com/containernetworking/cni/blob/main/libcni/api.go#L100
// CNI CNI插件规范
type CNI interface {
    AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
    AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
    CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
    DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
    GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
    GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
    ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
    ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
    GCNetworkList(ctx context.Context, net *NetworkConfigList, args *GCArgs) error
    GetCachedAttachments(containerID string) ([]*NetworkAttachment, error)
}
 
kubelet调用CNI插件实现Pod网络配置
- kubelet在
/etc/cni/net.d目录查找CNI插件的配置文件(JSON格式) - 基于配置文件中各插件的
type属性到/opt/cni/bin目录查找可执行二进制文件 - 配合Pod元数据调用各插件的二进制文件执行操作, 实现Pod网络配置
 
网络模型
网络模型: 容器编排平台的网络拓扑设计
- Kubernetes的网络模型: Underlay、Overlay
 - 网络模型决定集群的网络安全、网络性能、可扩展性和网络策略等
 - Kubernetes中的网络模型与传统容器模型不同(以Pod为基础单位设计)
 
如: 传统的容器网络模型

- 每个节点都需具有个虚拟网桥
Bridge - 每个容器都独占个
Network命名空间, 且需配置两个接口 - 容器与主机之外通信时需通过
SNAT/DNAT实现(较高的网络复杂度) 
如: Kubernetes中Pod通信网络模型

- Pod都处于同一平面网络
 - 每个Pod都有个虚拟网络接口和全局唯一的IP
 - Pod内所有容器共享
Network命名空间(pause容器创建) - Pod内容器通过
lo接口实现容器间通信(类似本地进程通信) - Pod跨节点通信是基于
Veth Pair实现(节点的虚拟接口通过ARP Proxy实现代理) 
// Veth Pair(Virtual Ethernet Pair): 对称虚拟网络接口连接实现跨命名空间通信(Linux内核实现)
Underlay
Underlay(Underlay Network): 基于交换机和路由器等设备构建的物理网络模型
- 适用于网络性能敏感场景(无需额外的报文开销)
 - 容器可通过驱动程序直接使用宿主节点的网络接口
 - Underlay的常见实现: Bridge、MAC VLAN、IP VLAN、Direct Route
 
MAC VLAN
MAC VLAN: 以太网接口上虚拟多个网络接口
- 每个虚拟接口都有个唯一MAC, 并按需配置IP
 - MAC VALN要求物理接口处于混杂模式(适用于本地网络环境)
 - 由于唯一MAC特性需注意以下场景: 交换机校验MAC、网卡限制MAC数量
 
如: Bridge与MAC VALN对比

MAC VLAN的工作模式:
| 模式 | 说明 | 
|---|---|
| Private | 禁止同一物理接口上多个MAC VLAN通信 | 
| VPEA | 允许同一物理接口上多个MAC VALN通信 (需外部交换机弃用发夹模式, 或存在报文转发的路由器)  | 
| Bridge | 物理接口配置为网桥 (多个MAC VALN可通过网桥直接通信)  | 
| Passthru | 允许一个MAC VALN直接连接物理接口 | 
IP VLAN
IP VLAN: 以太网接口上虚拟多个网络接口
- 每个虚拟接口都有个唯一IP, 但共享物理接口的MAC
 - MAN VLAN和IP VLAN不可同时在一个物理接口上使用
 - Linux 4.2内除支持IP VLAN网络驱动(可通过
ip link命令验证) 
IP VLAN工作模式分为: IP VLAN L2、IP VLAN L3
- IP VLAN L2和MAC VLAN Bridge都支持ARP协议和广播流量
 - IP VLAN L3时网络栈将在容器内处理(类似路由器的报文处理机制)
 
如: L2和L3模型对比

Direct Route
DR(Direct Routing): 虚拟对称网络接口实现请求在L3时直接路由
- 本质: 维护每个节点的路由表信息(保证容器请求顺利到达)
 
如: Calico实现的DR

DR成为Underlay实现的主流原因:
- 更易于集成到数据中心的基础设施之上
 - 报文过滤和隔离的扩展性更高
 - 控制模型更精细
 
Overlay
Overlay(Overlay Network): 基于多个已存在的物理/逻辑网络构建的逻辑网络模型
- 节点需支持VXLAN、UDP、IPIP或GRE等隧道协议(对底层网络无要求)
 - 需额外的性能开销, 不适用于网络性能敏感场景(额外的隧道报文封装)
 - 可实现跨越多个L2/L3的逻辑网络子网(适用于混合云场景)
 - Overlay的底层是由Underlay负责(底层通信)
 
如: Overlay网络架构

- 节点间通信必须通过OS上对外通信的网络接口进行
 - 网络隧道本质: 将容器的通信报文封装成各自宿主节点之间的报文
 
网络隧道(Tunnelling): 基于种网络协议传输其他网络协议
- 功能: 基于物理/逻辑网络之上构建出新的逻辑网络
 - 本质: 在原始数据包的外部或内部添加额外的封装头部信息
 
VXLAN
VXLAN(Virtual eXtensible Local Area Network): 可构建高扩展虚拟局域网的网络虚拟化技术
- 本质: 通过
L2 over L4的报文封装模式将L2报文用L3协议封装(MAC-in-UDP) - VXLAN中IP报文不可分片, 且底层网络需配置足够大的
MTU值 - VXLAN的网关和路由信息都分为: 集中式、分布式
 
Bridge-Domain(BD): VXLAN的虚拟网络构建单元
- VNI: BD的全局唯一标识(类似
VLAN的VLAN ID) - 功能: 连接不同的VXLAN终端设备, 以实现逻辑隔离和跨子网通信(构建大二层网络)
 - 相同VNI在不同VTEP之间通信需借助L2网关, 不同VNI或与VXLAN之间通信则需借助L3网关
 
VTEP(VXLAN Tunnel Endpoints): VXLAN的物理网络边缘设备以传输数据(网络隧道的出入口)
- 功能: 虚拟网络中数据包的封包/解包, 以实现虚拟网络的扩展和互联
 - VXLAN通过添加额外设备构建虚拟逻辑网络, 可避免对底层网络的侵入
 - 支持VXLAN协议的交换机/主机都可模拟为VTEP(Linux 3.7内核模块支持)
 
CNI插件
CNI插件: 遵循CNI规范实现的可执行二进制文件
- 功能: 维护
CRI提供的Pod网络命名空间 - CNI插件实现分为两部分API: NetPlugin、IPAM
 - CNI插件选择因素: 底层网络架构、容器网络功能、网络性能
 
如: CNI插件配置Pod网络流程

- NetPlugin(网络管理插件): 创建/删除网络以及向网络添加/删除容器
 - IPAM(IP Address Management): 创建/删除地址池以及分配/回收容器IP
 - kubelet通过在每个Pod中创建
pause容器完成响应操作(CRI中称为Sandbox) 
// IPAM可分为: host-local(静态分配)、dhcp(续订租约)
Flannel
Flannel: 基于L3简单易配置CNI插件
- Flannel实现跨节点常用通信方式: VXLAN、host-gw、UDP
 - Flannel会在每个节点运行个
flanneld守护进程以完成各节点网络配置 flanneld会从Etcd加载JSON格式的网络配置等信息, 同时维护各节点的路由信息
VXLAN通信: VXLAN协议封装IP报文创建Overlay网络
- VXLAN通信需借助Linux内核的vxlan模块封装网络隧道报文
 flanneld启动时会将VTEP设备IP和节点MAC映射信息存储于Etcd依此生成解析记录- FDB(Forwarding Database): 存储VTEP设备路由转发信息(虚拟网络接口所在节点IP)
 - 直接路由: 
flanneld在节点添加必要路由信息, 以实现Pod间IP报文可在L2直接通信 
如: VXLAN协议封装报文

- VXLAN协议使用
UDP报文封装网络隧道内层数据帧(MAC会直接使用节点MAC) 
VXLAN通信流程(未开启直接路由):
- Pod发送送数据经由
flannel1.1接口封装成数据帧 flanneld将数据帧封装成UDP报文(目标地址为Pod所在节点IP), 并发送给目标flanneld- 目标
flanneld按照上述反向流程解析报文以将数据转发给目标Pod 
如: VXLAN通信流程(直接路由功能需配置开启)

flanneld在节点创建名为flannel1.1的虚拟网络接口作为网络隧道的VTEP设备- Flannel基于分布式网关模型, 将每个节点都视为到达该节点Pod子网的L2网关
 - 仅位于同一个L2之下的节点可使用直接路由(混合模式处理不同请求)
 
host-gw通信: 通过添加必要路由信息实现Pod在L2直接通信
- host-gw通信要求所有节点都必须位于一个L2之下(不再有网络隧道)
 
如: host-gw通信流程

Flannel分配IP流程:
- 预留个专用网络(默认为: 10.244.0.0/16)
 - 根据
flanneld申请将专用网络划分为多个子网分配给每个节点作为Pod CIDR - 节点通过IPAM插件以
host-local形式从Pod CIDR中分配IP flanneld将子网和IP分配等信息存储于Etcd
Calico
Calico: 高性能容器通信和网络安全CNI插件
- Calico基于L3解决网络通信, 并使节点通过BGP协议交换路由信息生成路由规则
 - Calico将每个节点上Pod组成的网络都视为个自治系统管理(虚拟网络)
 
BGP(Border Gateway Protocol): 基于路径矢量的路由协议
- 限制: 所有设备都需位于同一个L2
 - 本质: 通过维护路由表/前缀表实现自治系统之间的可达性
 - BGP可实现去中心化的自治路由, 使多个自治系统之间相互协作
 
如: Calico通过BGP路由

- 将每个节点视为虚拟路由器(vRouter), 并基于BGP协议生成路由规则
 - 将节点上的Pod都视为vRouter后的终端设备, 并分配个IP
 - 不同子网下的vRouter仍需基于
VXLAN/IPIP通信 
Calico基础构成组件
| 组件 | 说明 | 
|---|---|
| Felix | 网络接口管理、路由规划、ACL规划和状态报告等核心功能 (各节点的守护进程)  | 
| BIRD (BGP Internet Routing Daemon)  | BGP客户端 (节点守护进程将Felix生成的路由信息载入内核并广播)  | 
| Etcd | 存储Calico状态数据 (Etcd也是Calico各组件的通信总线)  | 
| BGP Reflector | 汇总/分发路由信息 (BGP由点对点变为与中心点单路通信模型)  | 
| 编排系统插件 | 将Calico整合进所在的编排系统 (API转换)  | 
如: Calico架构

IPIP: 基于IP报文的高性能网络隧道
- 本质: IP包的二次封装以实现IP层虚拟网桥
 - IPIP封装后报文头非常小, 所以相较于VXLAN性能更好(安全性降低)
 - IPIP能需依靠BGP维护各节点间的可达性(生成到达各节点的路由信息)
 
如: IPIP网络隧道

如: Calico运行流程

CNI配置
CNI配置: 以插件组合形式实现CNI功能配置
- CNI配置插件类别分为: main、ipam、meta
 - CNI配置需提供网络接口功能: ADD、DEL、CHECK、VERSION
 - kubelet以
JSON格式解析调用CNI配置(可从磁盘读取或其他源动态生成) 
常用CNI配置:
cniVersion: <String>      # CNI配置的语义版本
name: <String>            # CNI网络名称, 当前节点唯一
type: <String>            # CNI插件名称(kubelet在配置目录下查找并调用该可执行文件)
delegate: <Object>        # 委派其他插件
args: <Map[String]String> # 附加参数
ipMasq: <Boolean>         # 是否启用IP伪装
ipam: <Object>            # IPAM插件
  type: <String>          # IPAM插件名称(kubelet在配置目录下查找并调用该可执行文件)
  subnet: <String>        # 分配所基于的子网地址
  routes: <String>        # 路由信息
    dst: <String>         # 目标主机/网络
    gw: <String>          # 网关地址
dns: <Object>             # 容器的DNS属性
  nameservers: <[]String> # DNS服务器列表
  domain: <[]String>      # 用于短格式主机查找的本地域
  search: <[]String>      # 用于短格式主机查找的优先级排序的搜索域列表
  options: <[]String>     # 传递给解析程序的选项列表
 
- 可通过
plugins字段定义多个CNI插件协作(按定义顺序调用) - CNI配置文件必须是
conf、conflist、json后缀, 否则无法加载 - 目录下存在多个CNI配置文件时, 则会根据文件名升序排序以加载排序后首个文件
 
内置实现
内置实现: Kubernetes内置实现部分CNI插件
- 内置实现可参考源码: 
https://github.com/containernetworking/plugins 
main: 维护容器网络接口
| 插件 | 说明 | 
|---|---|
| bridge | 虚拟网桥 (将节点和其Pod接入网桥)  | 
| ipvlan | 容器中添加个IP VLAN接口 | 
| macvlan | 容器中添加个MAV VLAN接口 (创建个新MAC地址, 基于该MAC向容器转发报文)  | 
| loopback | 配置容器lo接口状态 | 
| ptp | veth pair接口 | 
| vlan | 分配个VLAN设备 | 
| host-device | 将节点的网络接口分配给Pod | 
ipam: 分配给容器IP
| 插件 | 说明 | 
|---|---|
| dhcp | 动态申请IP, 并需以租约续订 (每个节点需运行个dhcp守护进程以作为dhcp客户端)  | 
| host-local | 基于本地IP地址数据库分配IP | 
| static | 分配静态IP | 
meta: 网络功能扩展(调用其他插件)
| 插件 | 说明 | 
|---|---|
| tuning | 调正现存某接口的sysctl参数值 | 
| portmap | 通过iptables将节点的端口映射至容器(实现 hostPort功能) | 
| bandwidth | 通过流量控制工具tbf实现带宽限制 | 
| sbr | 配置基于源IP地址的路由 | 
| firewall | 防火墙 (基于 iptables/firewalld管理进出流量) | 



















