双栈 Service 是什么
双栈(dual-stack)指集群里的 Pod 与 Service 同时拥有 IPv4 和 IPv6 地址。它首先是集群级能力:kube-apiserver / kube-controller-manager 的 Service CIDR 与 Pod CIDR(--cluster-cidr)都要配两段地址;单个 Service 再通过 spec.ipFamilyPolicy 与 spec.ipFamilies 决定要几个地址族。该能力在 Kubernetes v1.16 进入 alpha、v1.21 进入 beta、v1.23 GA,所以单栈集群里改 Service 字段不会凭空多出 IPv6 地址。
基本信息
| 适用版本 | Kubernetes v1.23 及以上(GA),v1.16 alpha / v1.21 beta |
|---|---|
| 相关字段 | spec.ipFamilyPolicy、spec.ipFamilies、status.clusterIPs |
| 默认取值 | ipFamilyPolicy: SingleStack,ipFamilies: [IPv4] |
| 集群前提 | Service CIDR 与 Pod CIDR 均为双段;CNI 与 kube-proxy 支持双栈 |
| 不可变字段 | ipFamilies 与 clusterIPs 在 Service 创建后不可修改 |
典型使用场景
- 纯 IPv6 内网:客户端只走 IPv6 时,Service 必须有 IPv6 的 ClusterIP 才能被发现
- IPv4 地址紧张时的扩容:新业务优先分 IPv6,老业务保持 IPv4 不动
- 对外服务需要同时提供 A 与 AAAA 记录,满足 IPv6 合规或评测要求
- 灰度迁移:清单固定写 PreferDualStack,双栈集群自动发两个地址,单栈集群退化为单栈照样能创建
- 地址族排障:核对 Service 地址族、EndpointSlice 端点与后端进程监听地址是否一致
双栈 Service 声明
双栈 Service 声明
apiVersion: v1
kind: Service
metadata:
name: web
spec:
ipFamilyPolicy: PreferDualStack # 双栈集群发两个地址,单栈集群自动退化
ipFamilies: ["IPv4", "IPv6"] # 列表首项是主地址族,创建后不可改
selector:
app: web
ports:
- name: http
port: 80
targetPort: 8080 # 后端必须同时监听两种地址族创建与核对
创建与核对
kubectl get svc web -o jsonpath='{.spec.ipFamilyPolicy} {.spec.ipFamilies} {.spec.clusterIPs}{"\n"}' # 看策略、地址族、两个 ClusterIP
kubectl get endpointslices -l kubernetes.io/service-name=web -o jsonpath='{range .items[*]}{.addressType} {.endpoints[*].addresses}{"\n"}{end}' # 两种地址族是否都有端点
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name} {.spec.podCIDRs}{"\n"}{end}' # 节点 Pod CIDR 是否双段
kubeadm init --pod-network-cidr=10.244.0.0/16,fd00:10:244::/56 --service-cidr=10.96.0.0/12,fd00:10:96::/112 # 集群侧双 CIDR 前提示例ipFamilyPolicy 取值对照
| 取值 | 含义 | 使用建议 |
|---|---|---|
| SingleStack | 只分配一个地址族(默认 IPv4) | 单栈环境保持默认,不要为了以后可能用得上提前改 |
| PreferDualStack | 双栈集群发两个地址;单栈集群退化为单栈 | 迁移期首选,同一份清单在两种集群都能创建 |
| RequireDualStack | 必须双栈,集群不支持时 Service 创建失败 | 确认 CNI、DNS、后端监听全链路双栈后再用 |
headless Service(clusterIP: None)在双栈下由 EndpointSlice 分别给出两种地址族的端点;CoreDNS 按客户端查询类型应答,A 查询返回 IPv4、AAAA 查询返回 IPv6。因此「只看到一种地址」多半是查询类型不同,不一定是双栈没生效,用 dig 明确指定 A 与 AAAA 各查一次即可。
外部可达性另算:NodePort 在两种地址族上使用同一端口,LoadBalancer 与 Ingress 能否提供 IPv6 取决于云厂商和控制器实现。双栈 Service 只保证集群内地址族齐备,对外出口仍需单独验证。
应用只监听 0.0.0.0 时仅覆盖 IPv4:双栈要求监听地址为 ::(Linux 默认同时接受 IPv4 连接)或显式开两个 socket,同时检查 NetworkPolicy 的 ipBlock 是否包含 IPv6 网段。