IPv4/IPv6 双协议栈

Kubernetes 允许你配置单栈 IPv4 网络、单栈 IPv6 网络,或者双栈网络(两种网络族均启用)。本页面说明如何进行配置。
功能状态: Kubernetes v1.23 [稳定]

IPv4/IPv6 双栈网络支持为 PodService 分配 IPv4 和 IPv6 地址。

从 1.21 版本开始,你的 Kubernetes 集群默认启用 IPv4/IPv6 双栈网络,允许同时分配 IPv4 和 IPv6 地址。

支持的功能

Kubernetes 集群上的 IPv4/IPv6 双栈提供以下功能:

  • 双栈 Pod 网络(每个 Pod 分配一个 IPv4 和一个 IPv6 地址)
  • 启用 IPv4 和 IPv6 的 Services
  • Pod 集群外出口路由(例如互联网),通过 IPv4 和 IPv6 接口

先决条件

利用 IPv4/IPv6 双栈 Kubernetes 集群需要满足以下先决条件:

  • Kubernetes 1.20 或更高版本

    有关在早期 Kubernetes 版本中使用双栈服务的信息,请参阅该版本 Kubernetes 的文档。

  • 提供商支持双栈网络(云提供商或其他方式必须能够为 Kubernetes 节点提供可路由的 IPv4/IPv6 网络接口)

  • 一个支持双栈网络的网络插件

配置 IPv4/IPv6 双栈

要配置 IPv4/IPv6 双栈,请设置双栈集群网络分配:

  • kube-apiserver
    • --service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>
  • kube-controller-manager
    • --cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>
    • --service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>
    • --node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6 默认值:IPv4 为 /24,IPv6 为 /64
  • kube-proxy
    • --cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>
  • kubelet
    • --node-ip=<IPv4 IP>,<IPv6 IP>
      • 此选项对于裸机双栈节点(不使用 --cloud-provider 标志定义云提供商的节点)是必需的。如果你使用的是云提供商,并选择覆盖云提供商选择的节点 IP,请设置 --node-ip 选项。
      • (传统的内置云提供商不支持双栈 --node-ip。)

说明

IPv4 CIDR 示例:10.244.0.0/16(你需要提供你自己的地址范围)

IPv6 CIDR 示例:fdXY:IJKL:MNOP:15::/64(这仅展示格式,并非有效地址 - 参见 RFC 4193

服务

你可以创建可使用 IPv4、IPv6 或两者的 Services

Service 的地址族默认为第一个服务集群 IP 范围(通过 --service-cluster-ip-range 标志配置给 kube-apiserver)的地址族。

当你定义一个 Service 时,你可以选择将其配置为双栈。要指定你需要的行为,请将 .spec.ipFamilyPolicy 字段设置为以下值之一:

  • SingleStack:单栈服务。控制平面为 Service 分配一个集群 IP,使用第一个配置的服务集群 IP 范围。
  • PreferDualStack:在启用双栈时,为 Service 分配 IPv4 和 IPv6 集群 IP。如果未启用或不支持双栈,则回退到单栈行为。
  • RequireDualStack:在启用双栈时,从 IPv4 和 IPv6 地址范围分配 Service .spec.clusterIPs。如果未启用或不支持双栈,则 Service API 对象创建将失败。
    • 基于 .spec.ipFamilies 数组中第一个元素的地址族,从 .spec.clusterIPs 列表中选择 .spec.clusterIP

如果你想定义单栈使用的 IP 族,或定义双栈的 IP 族顺序,可以通过在 Service 上设置可选字段 .spec.ipFamilies 来选择地址族。

说明

.spec.ipFamilies 字段是条件性可变的:你可以添加或删除辅助 IP 地址族,但不能更改现有 Service 的主 IP 地址族。

你可以将 .spec.ipFamilies 设置为以下任何数组值:

  • ["IPv4"]
  • ["IPv6"]
  • ["IPv4","IPv6"](双栈)
  • ["IPv6","IPv4"](双栈)

你列出的第一个地址族将用于旧的 .spec.clusterIP 字段。

双栈 Service 配置场景

这些示例演示了各种双栈 Service 配置场景的行为。

新 Service 上的双栈选项

  1. 此 Service 规范未明确定义 .spec.ipFamilyPolicy。当你创建此 Service 时,Kubernetes 会从第一个配置的 service-cluster-ip-range 中为 Service 分配一个集群 IP,并将 .spec.ipFamilyPolicy 设置为 SingleStack。(无选择器的 Services 和有选择器的 headless Services 的行为方式相同。)

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      labels:
        app.kubernetes.io/name: MyApp
    spec:
      selector:
        app.kubernetes.io/name: MyApp
      ports:
        - protocol: TCP
          port: 80
    
  2. 此 Service 规范在 .spec.ipFamilyPolicy 中明确定义了 PreferDualStack。当你在双栈集群上创建此 Service 时,Kubernetes 会同时为该服务分配 IPv4 和 IPv6 地址。控制平面会更新 Service 的 .spec 以记录 IP 地址分配。.spec.clusterIPs 字段是主字段,包含两个已分配的 IP 地址;.spec.clusterIP 是一个辅助字段,其值从 .spec.clusterIPs 计算得出。

    • 对于 .spec.clusterIP 字段,控制平面记录与第一个服务集群 IP 范围具有相同地址族的 IP 地址。
    • 在单栈集群上,.spec.clusterIPs.spec.clusterIP 字段都只列出一个地址。
    • 在启用了双栈的集群上,在 .spec.ipFamilyPolicy 中指定 RequireDualStack 的行为与 PreferDualStack 相同。
    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      labels:
        app.kubernetes.io/name: MyApp
    spec:
      ipFamilyPolicy: PreferDualStack
      selector:
        app.kubernetes.io/name: MyApp
      ports:
        - protocol: TCP
          port: 80
    
  3. 此 Service 规范在 .spec.ipFamilies 中明确定义了 IPv6IPv4,并在 .spec.ipFamilyPolicy 中定义了 PreferDualStack。当 Kubernetes 在 .spec.clusterIPs 中分配 IPv6 和 IPv4 地址时,.spec.clusterIP 被设置为 IPv6 地址,因为它是 .spec.clusterIPs 数组中的第一个元素,从而覆盖了默认设置。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      labels:
        app.kubernetes.io/name: MyApp
    spec:
      ipFamilyPolicy: PreferDualStack
      ipFamilies:
      - IPv6
      - IPv4
      selector:
        app.kubernetes.io/name: MyApp
      ports:
        - protocol: TCP
          port: 80
    

现有 Service 上的双栈默认值

这些示例演示了在集群中刚刚启用双栈时,现有 Service 的默认行为。(将现有集群升级到 1.21 或更高版本将启用双栈。)

  1. 当在集群上启用双栈时,控制平面会将现有 Service(无论是 IPv4 还是 IPv6)配置为将 .spec.ipFamilyPolicy 设置为 SingleStack,并将 .spec.ipFamilies 设置为现有 Service 的地址族。现有的 Service 集群 IP 将存储在 .spec.clusterIPs 中。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      labels:
        app.kubernetes.io/name: MyApp
    spec:
      selector:
        app.kubernetes.io/name: MyApp
      ports:
        - protocol: TCP
          port: 80
    

    你可以使用 kubectl 检查现有服务来验证此行为。

    kubectl get svc my-service -o yaml
    
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app.kubernetes.io/name: MyApp
      name: my-service
    spec:
      clusterIP: 10.0.197.123
      clusterIPs:
      - 10.0.197.123
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app.kubernetes.io/name: MyApp
      type: ClusterIP
    status:
      loadBalancer: {}
    
  2. 当在集群上启用双栈时,即使 .spec.clusterIP 设置为 None,控制平面也会将现有的具有选择器的 headless Services 配置为将 .spec.ipFamilyPolicy 设置为 SingleStack,并将 .spec.ipFamilies 设置为第一个服务集群 IP 范围(通过 --service-cluster-ip-range 标志配置给 kube-apiserver)的地址族。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      labels:
        app.kubernetes.io/name: MyApp
    spec:
      selector:
        app.kubernetes.io/name: MyApp
      ports:
        - protocol: TCP
          port: 80
    

    你可以使用 kubectl 检查现有的具有选择器的 headless 服务来验证此行为。

    kubectl get svc my-service -o yaml
    
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app.kubernetes.io/name: MyApp
      name: my-service
    spec:
      clusterIP: None
      clusterIPs:
      - None
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app.kubernetes.io/name: MyApp
    

在单栈和双栈之间切换 Services

Services 可以从单栈更改为双栈,也可以从双栈更改为单栈。

  1. 要将 Service 从单栈更改为双栈,请根据需要将 .spec.ipFamilyPolicySingleStack 更改为 PreferDualStackRequireDualStack。当你将此 Service 从单栈更改为双栈时,Kubernetes 会分配缺失的地址族,以便 Service 现在拥有 IPv4 和 IPv6 地址。

    编辑 Service 规范,将 .spec.ipFamilyPolicySingleStack 更新为 PreferDualStack

    之前

    spec:
      ipFamilyPolicy: SingleStack
    

    之后

    spec:
      ipFamilyPolicy: PreferDualStack
    
  2. 要将 Service 从双栈更改为单栈,请将 .spec.ipFamilyPolicyPreferDualStackRequireDualStack 更改为 SingleStack。当你将此 Service 从双栈更改为单栈时,Kubernetes 只保留 .spec.clusterIPs 数组中的第一个元素,并将 .spec.clusterIP 设置为该 IP 地址,并将 .spec.ipFamilies 设置为 .spec.clusterIPs 的地址族。

无选择器的 Headless Services

对于没有选择器的 Headless Services 且未明确设置 .spec.ipFamilyPolicy.spec.ipFamilyPolicy 字段默认为 RequireDualStack

LoadBalancer 类型 Service

要为你的 Service 配置双栈负载均衡器:

  • .spec.type 字段设置为 LoadBalancer
  • .spec.ipFamilyPolicy 字段设置为 PreferDualStackRequireDualStack

说明

要使用双栈 LoadBalancer 类型的 Service,你的云提供商必须支持 IPv4 和 IPv6 负载均衡器。

出口流量

如果你想从使用不可公开路由 IPv6 地址的 Pod 启用出口流量以到达集群外目的地(例如公共互联网),你需要通过诸如透明代理或 IP 伪装等机制,使 Pod 能够使用公共路由的 IPv6 地址。ip-masq-agent 项目支持在双栈集群上进行 IP 伪装。

说明

确保你的 CNI 提供商支持 IPv6。

Windows 支持

Windows 上的 Kubernetes 不支持单栈“纯 IPv6”网络。但是,支持针对 Pod 和节点的 IPv4/IPv6 双栈网络,并带有单族服务。

你可以将 IPv4/IPv6 双栈网络与 l2bridge 网络一起使用。

说明

Windows 上的覆盖 (VXLAN) 网络不支持双栈网络。

你可以在Windows 上的网络主题中阅读有关 Windows 不同网络模式的更多信息。

接下来


最后修改时间:2024 年 6 月 12 日上午 10:06 (PST):修复 IPv4/IPv6 双栈中的引用 (5ead326713)