Coordinator
简体中文 | English
Spiderpool 内置一个叫 coordinator
的 CNI meta-plugin, 它在 Main CNI 被调用之后再工作,它主要提供以下几个主要功能:
- 解决 underlay Pod 无法访问 ClusterIP 的问题
- 在 Pod 多网卡时,调谐 Pod 的路由,确保数据包来回路径一致
- 支持检测 Pod 的 IP 是否冲突
- 支持检测 Pod 的网关是否可达
- 支持固定 Pod 的 Mac 地址前缀
注意: 如果您的操作系统是使用 NetworkManager 的 OS,比如 Fedora、Centos等,强烈建议配置 NetworkManager 的配置文件(/etc/NetworkManager/conf.d/spidernet.conf),避免 NetworkManager 干扰 coordinator
创建的 Veth 虚拟接口,影响通信:
~# cat > /etc/NetworkManager/conf.d/spidernet.conf <<EOF
[keyfile]
unmanaged-devices=interface-name:^veth*;interface-name:${IFACER_INTERFACE}
EOF
~# systemctl restart NetworkManager
下面我们将详细的介绍 coordinator
如何解决或实现这些功能。
CNI 配置字段说明
Field | Description | Schema | Validation | Default |
---|---|---|---|---|
type | CNI 的类型 | 字符串 | required | coordinator |
mode | coordinator 运行的模式. "auto": coordinator 自动判断运行在 Underlay 或者 Overlay; "underlay": 为 Pod 创建一对 Veth 设备,用于转发集群东西向流量。由 Pod 的 Underlay 网卡转发南北向流量; "overlay": 不额外创建 veth 设备,运行在多网卡模式。由 overlay 类型的 CNI(calico,cilium) 转发集群东西向流量,由 underlay 网卡转发南北向流量; "disable": 禁用 coordinator | 字符串 | optional | auto |
tunePodRoutes | Pod 多网卡模式下,是否调协 Pod 的路由,解决访问来回路径不一致的问题 | 布尔型 | optional | true |
podDefaultRouteNic | Pod 多网卡时,配置 Pod 的默认路由网卡。默认为 "", 其 value 实际为 Pod 第一张拥有默认路由的网卡 | 字符串 | optional | "" |
podDefaultCniNic | K8s 中 Pod 默认的第一张网卡 | 布尔型 | optional | eth0 |
detectGateway | 创建 Pod 时是否检查网关是否可达 | 布尔型 | optional | false |
detectIPConflict | 创建 Pod 时是否检查 Pod 的 IP 是否冲突 | 布尔型 | optional | false |
podMACPrefix | 是否固定 Pod 的 Mac 地址前缀, 前缀长度为两个字节, 由":"拼接。注意:首字节的最低位必须是 "0"。比如 "0a:1b"。 | 字符串 | optional | "" |
overlayPodCIDR | 默认的集群 Pod 的子网,会注入到 Pod 中。不需要配置,自动从 Spidercoordinator default 中获取 | []stirng | optional | 默认从 Spidercoordinator default 中获取 |
serviceCIDR | 默认的集群 Service 子网, 会注入到 Pod 中。不需要配置,自动从 Spidercoordinator default 中获取 | []stirng | optional | 默认从 Spidercoordinator default 中获取 |
hijackCIDR | 额外的需要从主机转发的子网路由。比如nodelocaldns 的地址: 169.254.20.10/32 | []stirng | optional | 空 |
hostRuleTable | 策略路由表号,同主机与 Pod 通信的路由将会存放于这个表号 | 整数型 | optional | 500 |
podRPFilter | 设置 Pod 的 sysctl 参数 rp_filter | 整数型 | optional | 0 |
hostRPFilter | (遗弃)设置节点 的 sysctl 参数 rp_filter | 整数型 | optional | 0 |
txQueueLen | 设置 Pod 的网卡传输队列 | 整数型 | optional | 0 |
detectOptions | 检测地址冲突和网关可达性的高级配置项: 包括重试次数(默认为 3 次), 探测间隔(默认为 1s) 和 超时时间(默认为 1s) | 对象类型 | optional | 空 |
logOptions | 日志配置,包括 logLevel(默认为 debug) 和 logFile(默认为 /var/log/spidernet/coordinator.log) | 对象类型 | optional | - |
如果您通过
SpinderMultusConfig CR
帮助创建 NetworkAttachmentDefinition CR,您可以在SpinderMultusConfig
中配置coordinator
(所有字段)。参考: SpinderMultusConfig。
Spidercoordinators CR
作为coordinator
插件的全局缺省配置(所有字段),其优先级低于 NetworkAttachmentDefinition CR 中的配置。 如果在 NetworkAttachmentDefinition CR 未配置, 将使用Spidercoordinator CR
作为缺省值。更多详情参考: Spidercoordinator。
解决 underlay Pod 无法访问 ClusterIP 的问题
我们在使用一些如 Macvlan、IPvlan、SR-IOV 等 Underlay CNI时,会遇到其 Pod 无法访问 ClusterIP 的问题,这常常是因为 underlay Pod 访问 CLusterIP 需要经过在交换机的网关,但网关上并没有去往 ClusterIP 的路由,导致无法访问。
关于 Underlay Pod 无法访问 ClusterIP 的问题,请参考 Underlay-CNI访问 Service
支持检测 Pod 的 IP 是否冲突( alpha 阶段)
对于 Underlay 网络,IP 冲突是无法接受的,这可能会造成严重的问题。在创建 Pod 时,我们可借助 coordinator
检测 Pod 的 IP 是否冲突,支持同时检测 IPv4 和 IPv6 地址。通过发送 ARP 或 NDP 探测报文,
如果发现回复报文的 Mac 地址不是来自 Pod 本身的网卡,那我们认为这个 IP 是冲突的,并拒绝 IP 冲突的 Pod 被创建。
此外,我们默认还会对发生 IP 冲突的**无状态**的 Pod 释放所有的已分配的 IP 使其重新分配,使得 Pod 在下一次重新调用 CNI 时能够尝试分配到其它非冲突的 IP。对于发生 IP 冲突的**有状态**的 Pod,为了保持 IP 地址也是有状态设计,我们不会对其释放。您可通过 spiderpool-agent 环境变量 SPIDERPOOL_ENABLED_RELEASE_CONFLICT_IPS
来控制此功能。
我们可以通过 Spidermultusconfig 配置它:
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: detect-ip
namespace: default
spec:
cniType: macvlan
macvlan:
master: ["eth0"]
coordinator:
detectIPConflict: true # Enable detectIPConflict
若 IP 冲突检查发现某 IP 已被占用,请检查是否被集群中其他处于
Terminating
阶段的 无状态 Pod 所占用,并配合 IP 回收机制 相关参数进行配置。
支持检测 Pod 的网关是否可达(alpha)
在 Underlay 网络下,Pod 访问外部需要通过网关转发。如果网关不可达,那么在外界看来,这个 Pod 实际是失联的。有时候我们希望创建 Pod 时,其网关是可达的。 我们可借助 coordinator
检测 Pod 的网关是否可达,
支持检测 IPv4 和 IPv6 的网关地址。我们通过发送 ARP 探测报文,探测网关地址是否可达。如果网关不可达,将会阻止 Pod 创建:
我们可以通过 Spidermultusconfig 配置它:
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: detect-gateway
namespace: default
spec:
cniType: macvlan
macvlan:
master: ["eth0"]
enableCoordinator: true
coordinator:
detectGateway: true # Enable detectGateway
注意: 有一些交换机不允许被 arp 探测,否则会发出告警,在这种情况下,我们需要设置 detectGateway 为 false
支持固定 Pod 的 Mac 地址前缀(alpha)
有一些传统应用可能需要通过固定的 Mac 地址或者 IP 地址来耦合应用的行为。比如 License Server 可能需要应用固定的 Mac 地址或 IP 地址为应用颁发 License。如果 Pod 的 Mac 地址发生改变,已颁发的 License 可能无效。
所以需要固定 Pod 的 Mac 地址。 Spiderpool 可通过 coordinator
固定应用的 Mac 地址,固定的规则是配置 Mac 地址前缀(2字节) + 转化 Pod 的 IP(4字节) 组成。
注意:
目前支持修改 Macvlan 和 SR-IOV 作为 CNI 的 Pod。 IPVlan L2 模式下主接口与子接口 Mac 地址一致,不支持修改
固定的规则是配置 Mac 地址前缀(2字节) + 转化 Pod 的 IP(4字节) 组成。一个 IPv4 地址长度 4 字节,可以完全转换为2 个 16 进制数。对于 IPv6 地址,只取最后 4 个字节。
我们可以通过 Spidermultusconfig 配置它:
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: overwrite-mac
namespace: default
spec:
cniType: macvlan
macvlan:
master: ["eth0"]
enableCoordinator: true
coordinator:
podMACPrefix: "0a:1b" # Enable detectGateway
当 Pod 创建完成,我们可以检测 Pod 的 Mac 地址的前缀是否是 "0a:1b"
配置网卡传输队列(txQueueLen)
传输队列长度(txqueuelen)是TCP/IP协议栈网络接口的一个值,它设置了网络接口设备内核传输队列中允许的数据包数量。如果txqueuelen值过小,可能导致在Pod之间的通信中丢失数据包。如果需要,我们可以对其进行配置:
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: txqueue-demo
namespace: default
spec:
cniType: macvlan
macvlan:
master: ["eth0"]
enableCoordinator: true
coordinator:
txQueueLen: 2000
自动获取集群 Service 的 CIDR
Kubernetes 1.29 开始支持以 ServiceCIDR 资源的方式配置集群 Service 的 CIDR,更多信息参考 KEP 1880。如果您的集群支持 ServiceCIDR,Spiderpool-controller 组件 自动监听 ServiceCIDR 资源的变化,将读取到的 Service 子网信息自动更新到 Spidercoordinator 的 Status 中。
~# kubectl get servicecidr kubernetes -o yaml
apiVersion: networking.k8s.io/v1alpha1
kind: ServiceCIDR
metadata:
creationTimestamp: "2024-01-25T08:36:00Z"
finalizers:
- networking.k8s.io/service-cidr-finalizer
name: kubernetes
resourceVersion: "504422"
uid: 72461b7d-fddd-409d-bdf2-83d1a2c067ca
spec:
cidrs:
- 10.233.0.0/18
- fd00:10:233::/116
status:
conditions:
- lastTransitionTime: "2024-01-28T06:38:55Z"
message: Kubernetes Service CIDR is ready
reason: ""
status: "True"
type: Ready
~# kubectl get spidercoordinators.spiderpool.spidernet.io default -o yaml
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderCoordinator
metadata:
creationTimestamp: "2024-01-25T08:41:50Z"
finalizers:
- spiderpool.spidernet.io
generation: 1
name: default
resourceVersion: "41645"
uid: d1e095db-d6e8-4413-b60e-fcf31ad2bf5e
spec:
detectGateway: false
detectIPConflict: false
hijackCIDR:
- 10.244.64.0/18
- fd00:10:244::/112
podRPFilter: 0
hostRPFilter: 0
hostRuleTable: 500
mode: auto
podCIDRType: auto
podDefaultRouteNIC: ""
podMACPrefix: ""
tunePodRoutes: true
txQueueLen: 0
status:
phase: Synced
serviceCIDR:
- 10.233.0.0/18
- fd00:10:233::/116
已知问题
- underlay 模式下,underlay Pod 与 Overlay Pod(calico or cilium) 进行 TCP 通信失败
此问题是因为数据包来回路径不一致导致,发出的请求报文匹配源Pod 侧的路由,会通过 veth0
转发到主机侧,再由主机侧转发至目标 Pod。 目标 Pod 看见数据包的源 IP 为 源 Pod 的 Underlay IP,直接走 Underlay 网络而不会经过源 Pod 所在主机。
在该主机看来这是一个非法的数据包(意外的收到 TCP 的第二次握手报文,认为是 conntrack table invalid), 所以被 kube-proxy 的一条 iptables 规则显式的 drop 。 目前可以通过切换 kube-proxy 的模式为 ipvs 规避。这个问题预计在 k8s 1.29 修复。
当 sysctl nf_conntrack_tcp_be_liberal
设置为 1 时,kube-proxy 将不会下发这条 DROP 规则。
- overlay 模式下, 当 Pod 附加多张网卡时。如果集群的缺省CNI 为 Cilium, Pod 的 underlay 网卡 无法与节点通信。
我们借助缺省CNI创建 Veth 设备,实现 Pod 的 underlay IP 与节点通信(正常情况下,macvlan 在 bridge 模式下, 其父子接口无法直接),但 Cilium 不允许非 Cilium 子网的 IP 从 Veth 设备转发。