kOps IPv6 集群配置指南:IPv6-only Pod 与双栈节点实战
【免费下载链接】kopsKubernetes Operations (kOps) - Production Grade k8s Installation, Upgrades and Management项目地址: https://gitcode.com/gh_mirrors/kop/kops
kOps(Kubernetes Operations)从 1.23 开始引入 IPv6 特性,并在 1.26 进入 Beta 阶段,支持配置IPv6-only Pod以及IPv6-only 或 dual-stack 节点的 Kubernetes 集群。本文以官方文档 docs/networking/ipv6.md 为骨架,结合仓库源码详细讲解 IPv6 模式的开启方式、VPC 与子网规划、路由与 NAT64 行为、CNI 选型及发行版限制,帮助你基于 kOps 在 AWS 上构建一个生产可用的 IPv6 集群。
IPv6 模式如何开启
kOps 通过集群 spec 中的nonMasqueradeCIDR字段来声明 IPv6 模式。默认情况下,nonMasqueradeCIDR指向 Kubernetes 内部网络(Pod IP)所用的 IPv4 网段(见 pkg/apis/kops/networking.go 中该字段的定义);当把它设置为::/0时,整个集群便进入 IPv6 模式:
spec: networking: nonMasqueradeCIDR: "::/0"命令行方式则更简单:kops create cluster提供--ipv6标志,该标志在 cmd/kops/create_cluster.go 中定义为:
cmd.Flags().BoolVar(&options.IPv6, "ipv6", false, "Use IPv6 for the pod network (AWS only)")--ipv6会同时设置nonMasqueradeCIDR等多个相关字段。注意其帮助文本明确写着 "(AWS only)",说明该能力仅面向 AWS 云提供商。
拓扑的默认值变化
IPv6 模式还会影响网络拓扑的默认行为。--topology标志的默认值是“根据 IPv4/IPv6 动态选择”的:
cmd.Flags().StringVarP(&options.Topology, "topology", "t", options.Topology, "Network topology for the cluster: 'public' or 'private'. Defaults to 'public' for IPv4 clusters and 'private' for IPv6 clusters.")也就是说,IPv4 集群默认public拓扑,而 IPv6 集群默认private拓扑。原因在于 IPv6-only 子网(private 拓扑的核心)对 Kubernetes 版本有硬性要求,详见下文。
IPv6 模式下的网络插件限制
从 cmd/kops/create_cluster.go 的自动补全逻辑可以看出,当启用--ipv6时,kubenet、flannel、kube-router、amazonvpc、gcp 等插件会被排除在可选列表之外,仅保留 external、cni(BYO CNI)、calico、cilium、cilium-eni、cilium-etcd、kindnet 等选项。这与文档中“仅支持 Calico、Cilium 与自带 CNI”的声明相互印证。
云提供商支持范围
kOps 目前仅在 AWS 上支持 IPv6。这一约束在代码层面同样有体现:集群校验逻辑会拒绝在非 AWS 云提供商上设置子网的ipv6CIDR字段(见 pkg/apis/kops/validation/validation.go):
if cluster.GetCloudProvider() != kops.CloudProviderAWS { for i := range subnets { if subnets[i].IPv6CIDR != "" { allErrs = append(allErrs, field.Forbidden(fieldPath.Index(i).Child("ipv6CIDR"), "ipv6CIDR can only be specified for AWS")) } } }另一个硬性前提是:IPv6 集群必须使用外部 Cloud Controller Manager(CCM)。kOps 会在创建集群时自动装配ExternalCloudControllerManager配置(见 upup/pkg/fi/cloudup/new_cluster.go 与 upup/pkg/fi/cloudup/new_cluster.go),由外部 CCM 负责 AWS 上的负载均衡器、路由等云资源编排。
VPC、子网与拓扑规划
VPC:共享或托管
VPC 既可以是 kOps 托管的,也可以是共享(shared)的。如果使用共享 VPC,则该 VPC必须预先关联 IPv6 CIDR 池,kOps 不会为共享 VPC 自动分配 IPv6 地址块。
子网 IPv6 CIDR 的/LEN#N特殊语法
子网的 IPv6 CIDR 可以在集群 spec 中显式指定,也可以使用特殊语法/LEN#N让 kOps 根据 VPC 的 IPv6 CIDR 自动推导:
LEN:子网前缀长度;N:该 CIDR 在 VPC IPv6 CIDR 内的十六进制序号。
例如,若 VPC 的 CIDR 为2001:db8::/56,那么ipv6CIDR: /64#a等价于显式写出2001:db8:0:a/64。
这一语法由 upup/pkg/fi/utils/net.go 中的ParseCIDRNotation解析实现,正则表达式为^/(\d+)#([a-f0-9]+)$,其中序号部分按十六进制解析:
func ParseCIDRNotation(subnet string) (int, int64, error) { re := regexp.MustCompile(`^/(\d+)#([a-f0-9]+)$`) s := re.FindStringSubmatch(subnet) ... netNum, err := strconv.ParseInt(s[2], 16, 64) ... return newSize, netNum, nil }解析出的前缀长度与序号随后交给CIDRSubnet(upup/pkg/fi/utils/net.go,其实现参考了 Terraform 的cidrsubnet函数语义)计算最终地址:
func CIDRSubnet(prefix string, newSize int, netNum int64) (string, error) { _, baseCIDR, err := net.ParseCIDR(prefix) ... newNetwork, err := cidr.SubnetBig(baseCIDR, newSize-oldSize, big.NewInt(netNum)) ... return newNetwork.String(), nil }在 kOps 的 AWS 任务层,awstasks.Subnet的Find/Render流程会在IPv6CIDR以/开头时调用calculateSubnetCIDR将其展开为真实地址(见 upup/pkg/fi/cloudup/awstasks/subnet.go 与 upup/pkg/fi/cloudup/awstasks/subnet.go),Terraform 输出路径同样支持该语法(upup/pkg/fi/cloudup/awstasks/subnet.go)。
校验侧(pkg/apis/kops/validation/validation.go)也做了对应约束:/LEN#N形式中LEN必须介于 0 与 128 之间;显式 CIDR 形式则必须是合法 IPv6 网段,且不能与serviceClusterIPRange重叠。
三种子网类型的职责分工
IPv6 集群中子网类型被重新定义:
| 子网类型 | 地址族 | 用途 |
|---|---|---|
Public | 双栈(dual-stack) | 公网子网,承担对外流量入口 |
Utility | 双栈(dual-stack) | 工具子网,托管 NAT 网关等辅助资源 |
Private | IPv6-only | 私有工作负载子网 |
DualStack(新增) | 双栈(dual-stack) | 类似Private,但保留 IPv4 地址 |
其中DualStack是 IPv6 特性引入的新子网类型,定义于 pkg/apis/kops/cluster.go:
// SubnetTypeDualStack means the subnet has no public addresses but is dual-stack. SubnetTypeDualStack SubnetType = "DualStack"控制平面与 APIServer 节点默认使用DualStack子网——因为 APIServer 需要被外部(含 IPv4 客户端)访问,纯 IPv6-only 的 private 子网无法满足这一需求。
DualStack子网是 IPv6 集群的专属类型,校验逻辑会拒绝在非 IPv6 集群中使用它(pkg/apis/kops/validation/validation.go):
if subnetSpec.Type == kops.SubnetTypeDualStack && !c.IsIPv6Only() { allErrs = append(allErrs, field.Forbidden(fieldPath.Child("type"), "subnet type DualStack may only be used in IPv6 clusters")) }其中IsIPv6Only()的实现正是检查Networking.NonMasqueradeCIDR是否为 IPv6 网段(见 pkg/apis/kops/cluster.go)。
版本要求:IPv6-only 子网需要 Kubernetes 1.22+
由于IPv6-only 子网要求 Kubernetes 1.22 或更高版本,因此 IPv6 集群若采用 private 拓扑(默认值),也一并继承了该版本下限。规划集群前请先确认目标 Kubernetes 版本满足此约束。
路由与 NAT64 行为
IPv6 集群在 AWS 上的路由由 kOps 的 awstasks 层自动编排,核心规则如下:
NAT64(64:ff9b::/96)
托管(managed)的 private 与 public 子网,只要配置了IPv6CIDR,就会将64:ff9b::/96(NAT64 保留前缀)的路由指向该子网 spec 中egress字段指定的目标;如果egress未设置,则默认指向该可用区(AZ)的 NAT Gateway。
这保证了 IPv6-only 的 Pod 能够访问 IPv4 互联网服务(通过 NAT64 转换)。
NAT Gateway 的放置位置
如果某个托管 public 子网需要 NAT Gateway,但该可用区内没有 utility 子网,那么 NAT Gateway 会被放置在该可用区列表中第一个 public 子网内。规划拓扑时需留意这一放置策略,避免出现 NAT 资源分布不均。
出站流量走向
- 托管private子网:除 NAT64 前缀外的其余出站 IPv6 流量,路由到VPC 的 Egress-only Internet Gateway;
- 托管public子网:其余出站 IPv6 流量,路由到VPC 的 Internet Gateway。
Egress-only Internet Gateway 是 AWS 专为 IPv6 出站设计的资源,kOps 在 upup/pkg/fi/cloudup/awstasks/egressonlyinternetgateway.go 中实现了其创建、查找与 Terraform 渲染逻辑;路由条目本身通过awstasks.Route支持IPv6CIDR目标网段(见 upup/pkg/fi/cloudup/awstasks/route.go),并明确限制“IPv4 不能路由到 Egress-only Internet Gateway”(upup/pkg/fi/cloudup/awstasks/route.go)。
egress 字段的合法范围
egress字段的取值受校验逻辑约束(pkg/apis/kops/validation/validation.go),仅允许:NAT Gateway、带既有 EIP 的 NAT Gateway、NAT EC2 实例、Transit Gateway 或 External 五种类型,且只能配置在 private 子网或具备 IPv6 能力的 public 子网上。
发行版支持:Debian 的例外
kOps 不支持在 Debian 上运行 IPv6 集群。原因从 Debian 11 起,Debian 发行版本身不支持 IPv6-only 实例。如果你的组织强依赖 Debian 镜像,则需要等待上游发行版能力补齐后再考虑 IPv6 迁移。
CNI 选型与注意事项
kOps 的 IPv6 支持仅覆盖以下 CNI 方案:
- Calico
- Cilium
- 自带 CNI(bring-your-own CNI)
所有 CNI 都必须遵守一条铁律:不得对 IPv6 地址做 masquerade(源地址伪装)——IPv6 出站流量依赖 AWS 路由层面的原生转发(Egress-only IGW / IGW),节点侧再做 NAT 会破坏地址语义与路由策略。
Calico 的额外要求
使用 Calico 运行 IPv6 时,节点 AMI必须是 Ubuntu 22.04 或 Flatcar 基础镜像。这是 Calico 的 IPv6 数据面能力对内核/系统组件的依赖所决定的硬性约束,选用其他镜像将无法得到 kOps 的官方支持。
实战:创建 IPv6 集群的参考命令
综合以上约束,一个典型的 IPv6 集群创建命令大致如下(仅示意,实际参数请按需调整):
kops create cluster \ --name=ipv6.example.com \ --state=s3://your-kops-state \ --zones=us-east-1a,us-east-1b \ --networking=calico \ --ipv6 \ --topology=private \ --kubernetes-version=1.30.0 \ --yes各参数与文档/源码的对应关系:
--ipv6:开启 IPv6 模式(定义于 cmd/kops/create_cluster.go),设置nonMasqueradeCIDR: "::/0";--networking=calico:IPv6 支持的 CNI 之一(Calico 需搭配 Ubuntu 22.04 / Flatcar AMI);也可选cilium或external/cni(BYO);--topology=private:IPv6 集群的默认拓扑;private 拓扑依赖 IPv6-only 子网,需要 Kubernetes ≥ 1.22;- 云提供商必须是 AWS(
--cloud=aws),且 kOps 会自动启用外部 Cloud Controller Manager。
创建后可通过kops edit cluster查看 spec,确认spec.networking.nonMasqueradeCIDR已变为::/0、各子网的ipv6CIDR已按/LEN#N语法分配到位。
限制与前置条件小结
- 仅 AWS:
--ipv6标志、ipv6CIDR字段均只在 AWS 上有效; - 外部 CCM 必需:IPv6 集群强制使用外部 Cloud Controller Manager;
- 共享 VPC 需自带 IPv6 池:kOps 不为共享 VPC 分配 IPv6 CIDR;
- 版本下限:IPv6-only 子网(private 拓扑)要求 Kubernetes ≥ 1.22;
- 发行版限制:Debian 不可用,Calico 需 Ubuntu 22.04 / Flatcar;
- CNI 限制:仅 Calico、Cilium、BYO CNI,且 CNI 禁止 masquerade IPv6。
按上述规则规划好 VPC、子网类型与 CNI 之后,即可借助 kOps 的自动化编排在 AWS 上获得一套具备 IPv6-only Pod 与双栈节点的生产级集群。
【免费下载链接】kopsKubernetes Operations (kOps) - Production Grade k8s Installation, Upgrades and Management项目地址: https://gitcode.com/gh_mirrors/kop/kops
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考