
简介这份文档面向 Kubernetes 运维、云原生网络工程师及正在选型容器网络方案的技术人员系统梳理了 CNCF 沙盒项目 Kube-OVN 的整体架构与落地要点。内容围绕其丰富功能、极端性能与简单操作三大特性展开涵盖子网管理、静态 IP 分配、VPC 多租户、跨集群互联、QoS、ACL、流量镜像等能力并深入讲解上游 OVN/OVS 组件、kube-ovn-controller 与 kube-ovn-cni 等核心控制器及 Agent 的职责以及监控运维扩展组件的用途。资源包为 1 个 docx 文档大小约 1.77MB结构紧凑便于通读与检索。目前已有 433 人学习下载。读者可借此快速建立 Kube-OVN 的组件全景认知理解 Kubernetes 资源到 OVN 逻辑网络的翻译流程掌握安装环境要求与一键部署思路为后续生产环境选型、部署与排障提供参考。1. Kube-OVN 到底解决了什么问题从 CNCF 沙箱到生产级 SDN 的落地逻辑如果你在 Kubernetes 集群里用过默认的 CNI大概率遇到过这些场景Pod 网段和物理网络不通、NetworkPolicy 只能做三层的粗粒度控制、想给租户划分子网得靠 namespace 硬隔离、排查丢包只能靠 tcpdump 盲抓。Kube-OVN 就是冲着这些痛点来的——它把 OVNOpen Virtual Network这套成熟的 SDN 控制面搬进了 K8s用 OVSOpen vSwitch做数据面转发让容器网络具备虚拟化级别的子网、VPC、ACL、QoS 和流量镜像能力。这个项目已经进入 CNCF 沙箱定位不是“又一个 CNI 插件”而是把 SDN 的能力完整暴露给 K8s 原生 API。适合谁适合那些集群规模超过单集群单网段、有租户隔离需求、或者需要把容器网络和现有虚拟化网络打通的团队。如果你只是跑个测试集群默认 CNI 够用但一旦涉及多租户、固定 IP、跨子网通信Kube-OVN 的投入产出比就出来了。2. Kube-OVN 的架构拆解OVN 控制面和 OVS 数据面怎么在 K8s 里跑起来2.1 核心组件与数据流向Kube-OVN 的架构可以分成三层理解。最上层是 K8s API用户通过 CRD 创建 VPC、Subnet、Vlan 这些资源。中间层是 Kube-OVN 自己的控制器组件包括 ovn-central跑 OVN 的北向和南向数据库、ovn-controller每个节点上的 OVN 代理、以及 kube-ovn-controller监听 K8s 资源变化并翻译成 OVN 逻辑流表。最底层是 OVS 网桥和流表实际决定数据包怎么转发。数据流向是这样的创建一个 Pod 时kube-ovn-controller 会从对应的 Subnet 里分配 IP然后在 OVN 北向数据库里创建逻辑端口ovn-controller 收到南向数据库的更新后把逻辑流表翻译成 OpenFlow 流表下发到 OVS。Pod 的 veth 一端插在 OVS 的 br-int 网桥上流量根据流表决定是走 overlay 隧道还是直接出物理网卡。这套架构的关键优势在于OVN 的逻辑网络抽象和 K8s 的资源模型能对上。Subnet 对应 OVN 的 logical switchVPC 对应 logical routerNetworkPolicy 对应 ACL。你不需要手动写 OVS 命令所有操作通过 K8s API 完成。2.2 和 Calico、Cilium 的选型对比选 Kube-OVN 之前先想清楚它和主流方案的差异。Calico 主打 BGP 路由方案性能好、社区大但子网和 ACL 能力偏弱做多租户隔离时通常要配合 namespace 和全局策略。Cilium 基于 eBPF可观测性和 L7 策略是强项但 eBPF 对内核版本有要求且虚拟化网络场景下的子网/VPC 抽象不如 OVN 直观。Kube-OVN 的差异化在于它把 SDN 那套 VPC、Subnet、ACL、QoS、流量镜像完整搬过来了。如果你的团队有虚拟化网络运维经验上手会很快。代价是组件更多——ovn-central 本身是有状态服务需要考虑高可用OVS 流表排查需要一定的 SDN 功底。维度Kube-OVNCalicoCilium数据面OVS/OpenFlowiptables/eBPFeBPF子网/VPC 抽象原生 CRD有限有限多租户隔离VPC Subnet ACLNamespace 全局策略Namespace 策略固定 IP支持有限有限流量镜像支持不支持支持内核要求较低较低较高2.3 最小化部署用 Helm 在现有集群跑通 Kube-OVN部署 Kube-OVN 最常见的方式是用官方 Helm Chart。以下步骤假设你有一个 K8s 集群且节点上还没有其他 CNI 在跑。# 添加 Helm 仓库 helm repo add kubeovn https://kubeovn.github.io/kube-ovn/ helm repo update # 查看可用版本 helm search repo kubeovn/kube-ovn --versions | head -20 # 安装指定 master 节点和隧道类型 helm install kube-ovn kubeovn/kube-ovn \ --namespace kube-system \ --set MASTER_NODESnode1,node2,node3 \ --set networking.TUNNEL_TYPEvxlan \ --set networking.EXCHANGE_LINK_NAMEeth0 \ --set networking.POD_CIDR10.16.0.0/16 \ --set networking.SVC_CIDR10.96.0.0/12 \ --set networking.JOIN_CIDR100.64.0.0/16参数说明MASTER_NODES指定跑 ovn-central 的节点建议至少三个做高可用。TUNNEL_TYPE选 vxlan 还是 geneve 取决于你的网络设备支持vxlan 兼容性更好。EXCHANGE_LINK_NAME是节点上用于 overlay 隧道的物理网卡名写错会导致跨节点 Pod 不通。POD_CIDR是默认子网网段JOIN_CIDR是节点间通信用的内部网段不要和现有网段冲突。安装完成后检查组件状态# 查看 kube-ovn 相关 Pod kubectl get pods -n kube-system | grep -E ovn|kube-ovn # 查看默认子网 kubectl get subnet # 查看 OVN 北向数据库状态 kubectl exec -n kube-system ovn-central-0 -- ovn-nbctl show如果 ovn-central Pod 起不来先看它有没有被调度到 MASTER_NODES 指定的节点上。如果 ovn-controller 报错检查 EXCHANGE_LINK_NAME 对应的网卡是否存在且 UP。2.4 创建第一个自定义子网和 VPC默认安装会创建一个名为 ovn-default 的子网。生产环境通常需要按业务划分子网。以下是一个自定义子网和 VPC 的示例# 创建 VPC apiVersion: kubeovn.io/v1 kind: Vpc metadata: name: tenant-a-vpc spec: namespaces: - tenant-a --- # 创建子网 apiVersion: kubeovn.io/v1 kind: Subnet metadata: name: tenant-a-subnet spec: vpc: tenant-a-vpc cidrBlock: 192.168.100.0/24 gateway: 192.168.100.1 namespaces: - tenant-a natOutgoing: true private: falsenatOutgoing: true表示这个子网的 Pod 访问外部网络时做 SNAT。private: false表示允许和同 VPC 内其他子网通信如果设为 true则只允许子网内通信。namespaces字段限定哪些 namespace 的 Pod 可以在这个子网里分配 IP。创建后验证kubectl get vpc kubectl get subnet kubectl get pod -n tenant-a -o wide # 查看 Pod IP 是否在 192.168.100.0/24 内3. 生产环境必须调对的参数从 MTU 到流表超时3.1 MTU 设置overlay 网络最容易翻车的地方Kube-OVN 默认用 vxlan 或 geneve 做 overlay 隧道这两种封装都会增加包头开销。vxlan 增加 50 字节geneve 增加 50-60 字节不等。如果物理网卡 MTU 是 1500Pod 网卡的 MTU 必须相应减小否则大包会被丢弃表现为“小文件传输正常大文件卡死”这种玄学问题。# 查看当前 Pod 网卡 MTU kubectl exec -it test-pod -- ip link show eth0 # 查看 OVS 网桥 MTU kubectl exec -n kube-system ovs-ovn-xxxxx -- ovs-vsctl show如果发现 MTU 不对可以在 Helm values 里调整networking: MTU: 1400 # 物理网卡 1500vxlan 封装后建议 1400血泪经验MTU 问题不会在部署后立刻暴露往往在跑数据库同步或大文件传输时才出现。建议部署完先跑一个 iperf3 大包测试。3.2 流表超时和 conntrack 参数OVS 的流表有超时机制默认的 idle_timeout 和 hard_timeout 可能不适合长连接场景。如果发现长连接莫名断开可以检查 OVS 流表# 查看流表 kubectl exec -n kube-system ovs-ovn-xxxxx -- ovs-ofctl dump-flows br-int # 查看 conntrack 表 kubectl exec -n kube-system ovs-ovn-xxxxx -- ovs-appctl dpctl/dump-conntrack如果 conntrack 表满了新连接会被丢弃。可以在 kube-ovn-controller 的启动参数里调整--conntrack-max和--conntrack-tcp-timeout-established。这些参数没有在 Helm values 里直接暴露需要通过--set覆盖 controller 的 args。3.3 子网 ACL 和 NetworkPolicy 的优先级Kube-OVN 支持两种策略Subnet 级别的 ACL 和 K8s 原生的 NetworkPolicy。两者同时存在时ACL 优先于 NetworkPolicy。这意味着如果你在 Subnet 上配了 deny allNetworkPolicy 里写 allow 也不会生效。# Subnet ACL 示例 apiVersion: kubeovn.io/v1 kind: Subnet metadata: name: tenant-a-subnet spec: acls: - action: drop direction: from-lport match: ip4 priority: 1001 - action: allow direction: from-lport match: ip4 ip4.src 192.168.100.0/24 priority: 1002排查策略问题时先用ovn-nbctl acl-list看 ACL 规则再用ovn-trace模拟数据包路径。ovn-trace是 OVN 自带的黑匣子工具能告诉你一个包在逻辑网络里经过了哪些流表、最终是 allow 还是 drop。4. 避坑与排查Kube-OVN 上线后最容易踩的五个坑4.1 Pod 跨节点不通同节点正常现象同一节点上的 Pod 互相能通跨节点就不通。原因overlay 隧道没建起来通常是 EXCHANGE_LINK_NAME 配错或者物理网卡没开 vxlan 所需的 UDP 端口。解决在节点上执行ovs-vsctl show看隧道接口是否存在检查ip -d link show里 vxlan 接口的 remote IP 是否正确。如果隧道接口存在但流量不通检查安全组或防火墙是否放行了 4789vxlan或 6081geneve端口。4.2 Pod 启动慢事件里报 IP 分配失败现象Pod 一直 Pendingdescribe 看到 “failed to allocate IP”。原因子网 IP 耗尽或者子网的 namespaces 字段不包含当前 namespace。解决kubectl get subnet看子网的 availableIPs 还剩多少检查子网的 namespaces 列表是否包含目标 namespace。如果是 IP 耗尽扩容子网 CIDR 或清理无用 Pod。4.3 修改子网 CIDR 后新 Pod 拿不到 IP现象改了 Subnet 的 cidrBlock新 Pod 分配 IP 失败。原因Kube-OVN 不支持在线修改子网 CIDR已分配的 IP 和 OVN 逻辑交换机的地址池不会自动同步。解决不要直接改现有子网的 CIDR。正确做法是新建一个子网把新 Pod 调度到新子网对应的 namespace或者重建子网需要先删除该子网下所有 Pod。4.4 ovn-central 单点故障导致网络中断现象ovn-central 所在节点宕机整个集群网络异常。原因默认安装只起了一个 ovn-central 副本没有做高可用。解决部署时确保 MASTER_NODES 至少三个节点并且 ovn-central 的 Pod 反亲和性配置正确。如果已经单点部署可以通过helm upgrade调整副本数但需要先确认 OVN 数据库的 raft 集群状态。4.5 流量镜像配了但抓不到包现象配置了 Mirror CRD但目标 Pod 收不到镜像流量。原因Mirror 的 target 和 source 必须在同一个 VPC 内且 target Pod 所在的子网不能开启 private。解决检查 Mirror 资源的 spec 里 vpc 字段是否和源 Pod 一致检查 target Pod 所在子网的 private 字段是否为 false。另外镜像流量会走 OVS 流表如果源 Pod 的流量本身被 ACL drop 了镜像也抓不到。5. 进阶技巧用 ovn-trace 和流量镜像做网络问题定位5.1 用 ovn-trace 模拟数据包路径ovn-trace 是 OVN 自带的诊断工具能模拟一个数据包在逻辑网络里的完整路径。当你怀疑某个 ACL 规则误杀了流量或者路由不对时它比 tcpdump 高效得多。# 进入 ovn-central Pod kubectl exec -it -n kube-system ovn-central-0 -- bash # 模拟从 192.168.100.10 到 192.168.100.20 的 ICMP 包 ovn-trace tenant-a-subnet \ inport tenant-a-subnet-192.168.100.10 \ eth.type 0x0800 \ ip4.src 192.168.100.10 \ ip4.dst 192.168.100.20 \ ip.proto 1输出会显示数据包经过了哪些 logical flow每一步是 allow 还是 drop以及最终从哪个端口出去。如果看到drop且 reason 是acl就去检查对应的 ACL 规则。5.2 流量镜像的实战配置流量镜像在生产环境里常用于安全审计和故障复现。Kube-OVN 的 Mirror CRD 可以把指定 Pod 的流量复制到另一个 Pod。apiVersion: kubeovn.io/v1 kind: Mirror metadata: name: mirror-web spec: vpc: tenant-a-vpc selector: - appweb target: pod: traffic-analyzer namespace: tenant-a这个配置会把 tenant-a-vpc 里所有带appweb标签的 Pod 的流量镜像到 traffic-analyzer Pod。注意 target Pod 需要有能力处理镜像流量否则会丢包。镜像流量不经过 conntrack所以不会影响原有连接的状态。5.3 一个我常用的排查习惯每次遇到网络问题我的顺序是先kubectl get subnet确认 IP 分配正常再ovn-nbctl show看逻辑拓扑然后ovn-trace模拟路径最后才上 tcpdump。这个顺序能覆盖 80% 的问题而且比抓包快得多。Kube-OVN 的组件多但每个组件都有对应的诊断命令关键是别一上来就抓包——先看控制面的状态再看数据面的流表最后才看包。希望帮到你。本文还有配套的精品资源点击获取