导读:本期聚焦于坚哥创作的《集群 IPv6 双栈网络部署与排障的关键步骤是什么?》,敬请观看详情。某次测试集群启用 IPv6 双栈后,所有 Pod 都能 ping 通外部 IPv6 主机,唯独通过 Service 访问业务接口持续超时,排查两小时才发现 kube-proxy 的 ip6tables 规则没有同步。这类问题在双栈改造中并不少见。双栈部署的难点不只是给节点和 Pod 分配 IPv6 地址,更在于内核转发、CNI 插件 IPAM、Service 地址族和 CoreDNS 转发必须协同一致。很多故障表面上表现为 IPv6 地址无法访问,实际上根因往往是节点 sysctl 没有开启转发、Calico 未创建 IPv6 IPPool、Service 没有声明双栈策略或 DNS 没有返回 AAAA 记录。本文从地址规划、节点准备、CNI 配置到验证方法逐层展开,并给出 Pod 无地址、IPv6 路由不通、DNS 解析失败、NodePort 访问异常等常见故障的排查路径,适合正在规划或维护双栈集群的工程师参考。

集群从 IPv4 单栈迁移到 IPv6/IPv4 双栈,绝对不是修改一个地址前缀就能完成的工作。节点需要同时维护两套邻居发现和路由表,容器网络接口插件需要为每个 Pod 分配两族地址,kube-proxy 要分别维护 IPv4 和 IPv6 的转发规则,DNS 组件也要能同时返回 A 和 AAAA 记录。任何一个环节出现配置偏差,都会表现为部分协议栈可以通信、另一栈完全不通,或者 Pod 获取地址后仍然无法建立连接。本文以 Kubernetes 集群为对象,完整梳理双栈网络的规划、部署和排障路径。

集群 IPv6 双栈网络部署与排障的关键步骤是什么?

一、双栈网络规划与架构选择

地址规划是双栈部署的第一道门槛。Kubernetes 对 Pod 和 Service CIDR 支持同时配置 IPv4 与 IPv6 网段,中间用英文逗号隔开,顺序通常保持 IPv4 在前、IPv6 在后。Service CIDR 的 IPv6 段建议使用独立的 ULA 前缀,例如 fd00:10:96::/112,Pod CIDR 则使用 fd00:10:244::/56,这样既能避免与现网全局地址冲突,也能满足集群内部互通。节点自身必须具备可路由的全局 IPv6 地址或至少具备 ULA 地址,不能只保留链路本地 fe80 地址,否则跨节点 Pod 流量会因为找不到下一跳而被丢弃。

双栈部署对 CNI 插件有明确要求。Calico 和 Cilium 都支持 IPv4/IPv6 双栈,但配置入口完全不同。Calico 需要为 IPv6 单独声明 IPPool,并配置 blockSize 和 NAT 出站策略;Cilium 则通过 enable-ipv6 和 IPv6 Pod CIDR 参数开启。若使用 overlay 模式,还需要确认封装的隧道协议是否支持 IPv6。物理网络允许的情况下,BGP 或 host-gateway 模式可以避免额外的 IPv6 封装开销,但对节点间的 IPv6 路由连通性要求更高。

内核参数和 kubeadm 配置同样不能忽略。节点必须打开 IPv4 和 IPv6 转发,关闭 disable_ipv6。kubeadm 的 ClusterConfiguration 中需要启用 IPv6DualStack 特性门控,并同时向 api-server 和 controller-manager 传入双栈 service-cluster-ip-range。下面是一个最小化的 kubeadm 配置示例。

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.28.0
featureGates:
  IPv6DualStack: true
networking:
  podSubnet: 10.244.0.0/16,fd00:10:244::/56
  serviceSubnet: 10.96.0.0/12,fd00:10:96::/112
apiServer:
  extraArgs:
    service-cluster-ip-range: 10.96.0.0/12,fd00:10:96::/112
controllerManager:
  extraArgs:
    node-cidr-mask-size-ipv4: "24"
    node-cidr-mask-size-ipv6: "64"
    service-cluster-ip-range: 10.96.0.0/12,fd00:10:96::/112
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
  IPv6DualStack: true

节点侧还需要通过 sysctl 固化参数。很多情况下集群已经运行了一段时间,IPv6 被默认关闭,导致 CNI 插件无法创建 IPv6 地址。执行以下配置并重启 NetworkManager 或 systemd-sysctl 服务后,节点才能稳定承载双栈流量。

# 写入 /etc/sysctl.d/99-ipv6-dualstack.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv6.conf.all.accept_ra = 2
net.ipv6.conf.default.accept_ra = 2
sysctl --system

二、启用 CNI 插件与双栈 Service

以 Calico 为例,安装完成后默认通常只会创建 IPv4 IPPool,IPv6 地址段不会被分配。需要手动创建 IPv6 池,指定与 kubeadm 配置一致的 Pod CIDR。如果使用 Operator 安装,可以直接在 Installation 资源中追加 ipPools;如果使用 manifest 安装,则通过 calicoctl 或 kubectl apply 创建 IPPool 对象。下面的示例创建了一个不启用 IPIP、允许 NAT 出站的 IPv6 池。

apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
  name: ipv6-ip-pool
spec:
  cidr: fd00:10:244::/56
  blockSize: 64
  ipipMode: Never
  natOutgoing: true
  nodeSelector: all()

Pod 网络准备好之后,Service 也需要显式声明双栈能力。默认 Service 采用单栈策略,只会使用集群默认地址族。要让 Service 同时获得 IPv4 和 IPv6 ClusterIP,必须将 ipFamilyPolicy 设置为 RequireDualStack,并通过 ipFamilies 指定两族顺序。若使用 PreferDualStack,则会在双栈能力不可用时退化为单栈,适合需要渐进升级的集群。

apiVersion: v1
kind: Service
metadata:
  name: dualstack-svc
spec:
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
  - IPv4
  - IPv6
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

创建之后可以在控制节点执行 kubectl get svc dualstack-svc 查看是否同时分配了两个 CLUSTER-IP。进入任意 Pod 内,使用 curl -6 http://[fd00:10:96::1] 访问服务时,kube-proxy 需要能够根据 IPv6 目的地址正确挑选后端。如果 Pod 内只有 IPv4 路由,curl 会直接返回网络不可达,此时问题通常不在 Service,而在 Pod 的 IPv6 路由或 CNI 分配。

DNS 是双栈验证中容易被忽视的环节。当客户端通过域名访问双栈 Service 时,CoreDNS 会同时返回 A 和 AAAA 记录。若 CoreDNS 自身没有配置 IPv6 上游或没有监听 IPv6 地址,AAAA 查询可能超时,客户端会回退到 IPv4,导致双栈看似没有生效。可以通过 dig AAAA +short svc-name.namespace.svc.cluster.local 检查返回结果。

三、故障排查:从地址分配到转发链路

遇到 Pod 只有 IPv4 地址的故障,首先要确认节点 IPv6 是否开启、CNI 是否创建了 IPv6 IPPool,以及节点上是否存在对应 Pod CIDR 的 IPv6 路由。可以执行 ip -6 addr show scope global 查看节点全局 IPv6 地址,再执行 ip -6 route get fd00:10:244::10 测试到 Pod 地址的路径。如果返回 Network is unreachable,说明节点上的 IPv6 路由表不完整,需要检查 CNI 的节点路由注入过程,而不是继续修改 Pod 配置。

Service IPv6 访问异常时,最好的方法是缩小问题范围。先分别测试 Pod 到 Service ClusterIP 和节点到 Service ClusterIP 的连通性。如果节点能通但 Pod 不通,问题多半在 Pod 的 IPv6 默认路由或 CNI 策略;如果节点也不通,需要检查 kube-proxy。查看 ip6tables -t nat -L KUBE-SERVICES -n 中是否存在该 ClusterIP 对应的规则,ipvs 模式下还可以使用 ipvsadm -Ln 查看 IPv6 虚拟服务。kube-proxy 的双栈支持要求其配置中同时包含 IPv4 和 IPv6 的 cluster-cidr,只有单栈时无法生成 IPv6 规则。

对于外部访问 NodePort 失败的问题,必须先区分是 IPv4 还是 IPv6 链路异常。安全组或防火墙经常默认拒绝 IPv6 新端口,节点虽然监听了 IPv6 地址,外部仍无法建立连接。抓包是最直接的定位手段,例如在节点上执行 tcpdump -i any -nn 'ip6 and tcp port 80',观察 SYN 是否到达节点、节点是否回包。如果 SYN 被直接丢弃,需要检查 iptables 或 ip6tables 的 INPUT 链以及节点安全组;如果回包发出但客户端收不到,则要检查上游路由器或交换机的 IPv6 路由。

下面汇总了双栈排障中经常用到的一组命令,建议按照地址、路由、转发规则、抓包的顺序逐层执行。

kubectl get pod -n kube-system -l k8s-app=calico-node -o wide
kubectl logs -n kube-system calico-node-xxxxx -c calico-node --tail=100
ip -6 addr show scope global
ip -6 route get fd00:10:96::1
ip6tables -t nat -L KUBE-SERVICES -n | grep fd00:10:96
ipvsadm -Ln | grep fd00:10:96
tcpdump -i any -nn 'ip6 and tcp port 80'

双栈集群排障的核心思路是先确认地址是否分配,再确认路由是否可达,最后检查转发规则和链路层丢包。只要按这个顺序排查,大多数问题都能在较短时间内定位到具体组件。

IPv6双栈集群网络网络排障修改时间:2026-09-21 07:36:58

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0921/59971.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。