简体中文 | English
Spiderpool 内置一个叫 coordinator
的 CNI meta-plugin, 它在 Main CNI 被调用之后再工作,它主要提供以下几个主要功能:
- 解决 underlay Pod 无法访问 ClusterIP 的问题
- 在 Pod 多网卡时,调谐 Pod 的路由,确保数据包来回路径一致
- 支持检测 Pod 的 IP 是否冲突(遗弃,现在由 IPAM 完成)
- 支持检测 Pod 的网关是否可达 (遗弃,现在由 IPAM 完成)
- 支持固定 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
如何解决或实现这些功能。
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 |
txQueueLen | 设置 Pod 的网卡传输队列 | 整数型 | optional | 0 |
detectOptions | 检测地址冲突和网关可达性的高级配置项: 包括发送探测报文次数(retries: 默认为 3 次), 和响应的超时时间(timeout: 默认为 100ms),还有发送报文的间隔(interval:默认为 10ms, 将会在未来版本中移除) | 对象类型 | 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。
我们在使用一些如 Macvlan、IPvlan、SR-IOV 等 Underlay CNI时,会遇到其 Pod 无法访问 ClusterIP 的问题,这常常是因为 underlay Pod 访问 CLusterIP 需要经过在交换机的网关,但网关上并没有去往 ClusterIP 的路由,导致无法访问。
关于 Underlay Pod 无法访问 ClusterIP 的问题,请参考 Underlay-CNI访问 Service
对于 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 回收机制 相关参数进行配置。
有一些传统应用可能需要通过固定的 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 个字节。
固定 Mac 地址后,为避免过时的 ARP 缓存表导致访问失败,Coordinator 插件会发送一个免费 ARP,通告新的 Mac 地址到局域网。
我们可以通过 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)是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
默认情况下,Coordinator 不会为 veth0 网卡配置本地链路地址。但有些场景下(比如服务网格),经过 veth0 网卡流入的网格流量会随 istio 设置的 iptables 规则重定向,如果 veth0 没有 IP 地址,这会导致这部分流量被丢弃(见#Issue3568)。所以在这个场景下,我们需要为 veth0 配置一个本地链路地址。
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: istio-demo
namespace: default
spec:
cniType: macvlan
macvlan:
master: ["eth0"]
enableCoordinator: true
coordinator:
vethLinkAddress: "169.254.200.1"
vethLinkAddress
默认为空,表示不配置。不为空则必须是一个合法的本地链路地址。
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 修复。 当 sysctlnf_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 设备转发。