创建 VPC 原生集群

本页面介绍了如何在 Google Kubernetes Engine (GKE) 中配置 VPC 原生集群

如需详细了解 VPC 原生集群的优势和要求,请参阅 VPC 原生集群

准备工作

在开始之前,请确保您已执行以下任务:

使用以下任一方法设定默认的 gcloud 设置:

  • 使用 gcloud init(如果您想要在系统引导下完成默认设置)。
  • 使用 gcloud config(如果您想单独设置项目 ID、区域和地区)。

使用 gcloud init

如果您收到 One of [--zone, --region] must be supplied: Please specify location 错误,请完成本部分。

  1. 运行 gcloud init 并按照说明操作:

    gcloud init

    如果您要在远程服务器上使用 SSH,请使用 --console-only 标志来防止命令启动浏览器:

    gcloud init --console-only
  2. 按照说明授权 gcloud 使用您的 Google Cloud 帐号。
  3. 创建新配置或选择现有配置。
  4. 选择 Google Cloud 项目。
  5. 选择默认的 Compute Engine 区域。

使用 gcloud config

  • 设置默认项目 ID
    gcloud config set project project-id
  • 如果您使用的是区域级集群,请设置默认计算区域
    gcloud config set compute/zone compute-zone
  • 如果您使用的是地区级集群,请设置默认计算地区
    gcloud config set compute/region compute-region
  • gcloud 更新到最新版本:
    gcloud components update

步骤

按照以下步骤创建 VPC 原生集群并验证其已配置的 Pod IP 范围和 Service IP 地址范围。

在现有子网中创建集群

以下说明介绍了如何使用您所选的次要范围分配方法在现有子网中创建 VPC 原生 GKE 集群。

gcloud

  • 如需使用由 GKE 管理的次要范围分配方法,请运行以下命令:

    gcloud container clusters create cluster-name \
      --region=region \
      --enable-ip-alias \
      --subnetwork=subnet-name \
      --cluster-ipv4-cidr=pod-ip-range \
      --services-ipv4-cidr=services-ip-range
    
  • 如需使用由用户管理的次要范围分配方法,请运行以下命令:

    gcloud container clusters create cluster-name \
      --region=region \
      --enable-ip-alias \
      --subnetwork=subnet-name \
      --cluster-secondary-range-name=secondary-range-pods \
      --services-secondary-range-name=secondary-range-services
    

请将占位符替换为有效值:

  • cluster-name 是 GKE 集群的名称。
  • region 是创建集群的地区。如需创建区域级集群,请将此标志替换为 --zone=zone,其中 zone 为 Google Cloud 区域。
  • subnet-name 是现有子网的名称。子网的主要 IP 地址范围用于节点。子网必须位于集群所使用的地区。如果此项被省略,GKE 将尝试使用集群所在区域中的 default VPC 网络中的子网。
  • 如果次要范围分配方法由 GKE 管理
    • pod-ip-range 是以 CIDR 表示法表示的 IP 地址范围(例如 10.0.0.0/14)或 CIDR 地址块的子网掩码大小(例如 /14)。此项用于为 Pod 创建子网次要 IP 地址范围。如果您省略 --cluster-ipv4-cidr 选项,GKE 将自动选择 /14 范围(218 个地址)。系统会从 1.0.0.0/8(范围为 224 个地址)中随机选择自动选择的范围,且该范围不会包括分配给虚拟机和现有路由的 IP 地址范围,或分配给其他集群的范围。自动选择的范围可能与预留的 IP 地址动态路由或与此集群建立对等互连的 VPC 内的路由相冲突。如果您使用其中任一项,则应指定 --cluster-ipv4-cidr 以防止发生冲突。
    • services-ip-range 是以 CIDR 表示法表示的 IP 地址范围(例如 10.4.0.0/19)或 CIDR 地址块的子网掩码大小(例如 /19)。此项用于为 Service 创建子网次要 IP 地址范围。
  • 如果次要范围分配方法由用户管理
    • secondary-range-pods 是指定 subnet-name 中现有的次要 IP 地址范围的名称。 GKE 将整个子网次要 IP 地址范围用于集群的 Pod。
    • secondary-range-services 是指定 subnet-name 中现有的次要 IP 地址范围的名称。 GKE 将整个子网次要 IP 地址范围用于集群的 Service。

控制台

  1. 访问 Cloud Console 中的 Google Kubernetes Engine 菜单。

    访问 Google Kubernetes Engine 菜单

  2. 点击创建集群按钮。

  3. 在导航窗格的集群下,点击网络

  4. 网络下拉列表中,选择一个 VPC。

  5. 节点子网下拉列表中,选择集群的子网。

  6. 确保选中启用 VPC 原生流量路由(使用别名 IP)复选框。

  7. 如果您希望由 GKE 管理次要范围分配方法,请选中自动创建次要范围复选框。如果您已为所选子网创建了次要范围,并希望由用户管理次要范围分配方法,请取消选中此复选框。

  8. Pod 地址范围字段中,输入 Pod 范围(例如:10.0.0.0/14)。

  9. Service 地址范围字段中,输入服务范围(例如:10.4.0.0/19)。

  10. 根据需要配置集群。

  11. 点击创建

API

创建 VPC 原生集群时,您需要定义 IPAllocationPolicy 对象。您可以引用现有子网次要 IP 地址范围,也可以指定 CIDR 地址块。如需创建次要范围分配方法由用户管理的集群,请引用现有子网次要 IP 地址范围。如果您希望通过 GKE 管理范围分配方法,请提供 CIDR 地址块。

{
  "name": cluster-name,
  "description": description,
  ...
  "ipAllocationPolicy": {
    "useIpAliases": true,
    "clusterIpv4CidrBlock"      : string,
    "servicesIpv4CidrBlock"     : string,
    "clusterSecondaryRangeName" : string,
    "servicesSecondaryRangeName": string,

  },
  ...
}

其中:

  • "clusterIpv4CidrBlock" 是 Pod 的 CIDR 范围的大小/位置, 决定了 Pod 的次要范围的大小。它可以是采用 CIDR 表示法的“IP/大小”(例如 10.0.0.0/14)或“/大小”(例如 /14)。从 VPC 的可用空间中选择具有给定大小的空白空间。如果您将此项留空,则系统会查找有效范围并使用默认大小创建该范围。
  • "servicesIpv4CidrBlock" 是 Service 的 CIDR 范围的大小/位置。请参阅 "clusterIpv4CidrBlock" 的说明。
  • "clusterSecondaryRangeName" 是 Pod 次要范围的名称。 该次要范围必须已经存在,且属于与集群关联的子网(例如使用 --subnetwork 标志指定的子网)。
  • "serviceSecondaryRangeName" 是 Service 的次要范围的名称。该次要范围必须已经存在,且属于与集群关联的子网(例如使用 --subnetwork 标志指定的子网)。

Terraform

您可以使用 Terraform 模块通过 Terraform 轻松地创建一个 VPC 原生集群。

例如,您可以将此地址块添加到 Terraform 配置中:

module "gke" {
  source  = "terraform-google-modules/kubernetes-engine/google"
  version = "~> 12.0"

  project_id        = "project-id"
  name              = "cluster-name"
  region            = "region"
  network           = "network-name"
  subnetwork        = "subnet-name"
  ip_range_pods     = "secondary-range-pods"
  ip_range_services = "secondary-range-services"
}

替换以下内容:

  • project-id 是创建集群的项目 ID。
  • cluster-name 是 GKE 集群的名称。
  • region 是创建集群的地区。
  • network-name 是现有网络的名称。
  • subnet-name 是现有子网的名称。子网的主要 IP 地址范围用于节点。子网必须位于集群所使用的地区。
  • secondary-range-pods 是指定 subnet-name 中现有的次要 IP 地址范围的名称。 GKE 将整个子网次要 IP 地址范围用于集群的 Pod。
  • secondary-range-services 是指定 subnet-name 中现有的次要 IP 地址范围的名称。 GKE 将整个子网次要 IP 地址范围用于集群的 Service。

同时创建集群和子网

以下说明介绍了如何同时创建 VPC 原生 GKE 集群和子网。使用一个命令执行这两个步骤时,次要范围分配方法由 GKE 管理。

gcloud

如需同时创建 VPC 原生集群和子网,请执行以下命令:

gcloud container clusters create cluster-name \
    --region=region \
    --enable-ip-alias \
    --create-subnetwork name=subnet-name,range=node-ip-range \
    --cluster-ipv4-cidr=pod-ip-range \
    --services-ipv4-cidr=services-ip-range

其中:

  • cluster-name 是 GKE 集群的名称。
  • region 是创建集群的地区。如需创建区域级集群,请将此标志替换为 --zone=zone,其中 zone 为 GKE 区域。
  • subnet-name 是要创建的子网的名称。子网的地区与集群地区(或包含区域级集群的地区)相同。如果您希望 GKE 为您生成名称,请使用空字符串 (name="")。
  • node-ip-range 是以 CIDR 表示法表示的 IP 地址范围(例如 10.5.0.0/20)或 CIDR 地址块的子网掩码大小(例如 /20)。此项用于为节点创建子网主要 IP 地址范围。如果此项被省略,GKE 会在 VPC 中选择大小为 /20 的可用 IP 地址范围。
  • pod-ip-range 是以 CIDR 表示法表示的 IP 地址范围(例如 10.0.0.0/14)或 CIDR 地址块的子网掩码大小(例如 /14)。此项用于为 Pod 创建子网次要 IP 地址范围。如果此项被省略,GKE 将使用包含 218 个地址的随机选择 /14 范围。系统会从 1.0.0.0/8(范围为 224 个地址)中随机选择自动选择的范围,且该范围不会包括分配给虚拟机和现有路由的 IP 地址范围,或分配给其他集群的范围。自动选择的范围可能与预留的 IP 地址动态路由或与此集群建立对等互连的 VPC 内的路由相冲突。如果您使用其中任一项,则应指定 --cluster-ipv4-cidr 以防止发生冲突。
  • services-ip-range 是以 CIDR 表示法表示的 IP 地址范围(例如 10.4.0.0/19)或 CIDR 地址块的子网掩码大小(例如 /19)。此项用于为 Service 创建子网次要 IP 地址范围。如果此项被省略,GKE 将使用默认的 Service IP 地址范围大小 (/20)。

控制台

您无法使用 Cloud Console 同时创建集群和子网。您应先创建子网,然后在现有子网中创建集群

API

如需创建 VPC 原生集群,请在您的集群资源中定义 [IPAllocationPolicy] 对象:

{
  "name": cluster-name,
  "description": description,
  ...
  "ipAllocationPolicy": {
    "useIpAliases": true,
    "createSubnetwork": true,
    "subnetworkName": subnet-name
  },
  ...
}

createSubnetwork 字段会自动为集群创建和预配子网。subnetworkName 是可选字段;如果您将此字段留空,系统会自动为子网选择一个名称。

使用非 RFC 1918 专用 IP 地址范围

使用 1.14.2-gke.1 及更高版本的 GKE 集群可以将 RFC 1918 范围之外的专用 IP 地址范围用于节点、Pod 和 Service。如需查看可用作子网范围的内部 IP 地址的非 RFC 1918 专用范围的列表,请参阅 VPC 网络文档中的有效范围

非 RFC 1918 专用 IP 地址范围与专用集群和非专用集群兼容。

非 RFC 1918 专用范围是子网范围 - 您可以单独使用这些范围,也可以结合使用 RFC 1918 子网范围。节点、Pod 和 Service 会按照 VPC 原生集群的 IP 范围中所述继续使用子网范围。如果使用非 RFC 1918 范围,请注意以下几点:

  • 在创建集群的节点之前,子网范围(即使是使用非 RFC 1918 范围的子网范围)必须手动分配或由 GKE 分配。除非您替换集群,否则无法改用或停用非 RFC 1918 子网范围。

  • 内部 TCP/UDP 负载平衡器仅使用子网主要 IP 地址范围中的 IP 地址。为了使用非 RFC 1918 地址创建内部 TCP/UDP 负载平衡器,子网的主要 IP 地址范围必须为非 RFC 1918。

集群外部的目的地可能无法从专用的非 RFC 1918 范围接收流量。例如,RFC 1112(E 类)专用范围通常用作多播地址。如果集群之外的目的地无法处理来源为 RFC 1918 范围之外的专用 IP 地址的数据包,您可以执行以下操作:

  • 使用 RFC 1918 范围作为子网的主要 IP 地址范围。这样,集群中的节点会使用 RFC 1918 地址。

  • 确保您的集群正在运行 IP 伪装代理,并且目的地不在 nonMasqueradeCIDRs 列表中。这样,从 Pod 发送的数据包的来源 (SNAT) 会更改为节点地址 (RFC 1918)。

启用以不公开方式重用的公共 IP 地址范围

使用 1.14.2-gke.1 及更高版本的 GKE 集群能够以不公开方式将某些公共 IP 地址范围重用作内部子网 IP 地址范围。除了 VPC 网络文档中所述的特定受限范围,您能以不公开方式重用任何公共 IP 地址。

您的集群必须专用集群,才能使用以不公开方式重用的公共 IP 地址范围。不支持非专用 VPC 原生集群和基于路由的集群。

以不公开方式重用的公共地址范围是子网范围 - 您可以单独使用,也可以结合使用其他使用专用地址的子网范围。节点、Pod 和 Service 会按照 VPC 原生集群的 IP 范围中所述继续使用子网范围。在以不公开方式重用公共 IP 地址时,请注意以下几点:

  • 如果您将公共 IP 地址范围重用作子网范围,则您的集群就无法再与互联网上使用该公共地址范围的系统进行通信 - 该范围会成为集群的 VPC 网络中的内部 IP 地址范围。

  • 在创建集群的节点之前,子网范围(即使是以不公开方式重用公共 IP 地址范围的子网范围)必须手动分配或由 GKE 分配。除非您替换集群,否则无法改用或停用以不公开方式重用的公共 IP 地址。

  • 从使用以不公开方式重用的公共 IP 地址范围的 Pod 发送的数据包无法将其来源 (SNAT) 更改为节点地址。因此,您必须使用 --disable-default-snat 标志创建集群。如需详细了解此标志,请参阅 GKE 中的伪装功能

  • 由于 Pod 以不公开方式重用公共 IP 地址范围的集群必须是专用集群,因此如果 Pod 需要将流量发送到互联网上的目的地,您的集群必须使用 NAT 解决方案,例如 Cloud NAT。使用 Cloud NAT 时,您必须至少配置 NAT 网关,才能应用到 Pod 的集群子网次要 IP 地址范围。通过这种方式,Cloud NAT 会从 Pod IP 地址发送的数据包执行 SNAT,因为集群的 IP 伪装配置必须关闭默认 SNAT 行为。

使用以不公开方式重用的公共地址范围的集群示例

以下示例使用 gcloud 创建一个使用以不公开方式重用的公共 IP 地址范围的集群。您必须使用以下标志:

  • --enable-ip-alias:这会创建 VPC 原生集群,在您以不公开方式重用公共 IP 地址范围时需要此集群。
  • --enable-private-nodes:这会创建专用集群,在您以不公开方式重用公共 IP 地址范围时需要此集群。
  • --disable-default-snat:如果您要为 Pod 或节点以不公开方式重用公共 IP 地址,则需要使用此选项。必须停用 SNAT,以便将响应路由到生成流量的 Pod。

此命令会创建一个 VPC 原生专用集群,其中:

  • 节点使用子网的 10.0.0.0/24 主要 IP 地址范围。
  • Pod 以不公开方式将 5.0.0.0/16 公共 IP 地址范围重用作 Pod 的子网次要 IP 地址范围。
  • Service 以不公开方式将 5.1.0.0/16 公共 IP 地址范围重用作 Service 的子网次要 IP 地址范围。
gcloud container clusters create cluster-name \
  --enable-ip-alias \
  --enable-private-nodes \
  --disable-default-snat \
  --zone=zone \
  --create-subnetwork name=cluster-subnet,range=10.0.0.0/24 \
  --cluster-ipv4-cidr=5.0.0.0/16 \
  --services-ipv4-cidr=5.1.0.0/16 \
  --master-ipv4-cidr=master-CIDR

验证 Pod 范围和 Service 范围

创建 VPC 原生集群后,您可以验证其 Pod 范围和 Service 范围。

gcloud

如需验证集群,请运行以下命令:

gcloud container clusters describe cluster-name

在命令输出中,查看 ipAllocationPolicy 字段下方的内容:

  • clusterIpv4Cidr 是 Pod 的次要范围
  • servicesIpv4Cidr 是 Service 的次要范围

控制台

如需验证集群,请执行以下步骤:

  1. 访问 Cloud Console 中的 Google Kubernetes Engine 菜单。

    访问 Google Kubernetes Engine 菜单

  2. 选择所需的集群。

次要范围显示在详细信息标签下的集群部分中:

  • 容器地址范围是 Pod 的次要范围
  • Service 地址范围 是 Service 的次要范围

问题排查

本部分将介绍如何解决 VPC 原生集群的相关问题。

资源“projects/[PROJECT_NAME]/regions/XXX/subnetworks/default”尚未就绪

潜在原因
同一子网上存在并行操作。例如,正在创建其他 VPC 原生集群,或正在子网上添加或删除次要范围。
解决方法
重试此命令。

字段“resource.secondaryIpRanges[1].ipCidrRange”的值无效:XXX。IPCidrRange 无效:XXX 与区域“XXX”中的现有子网“default”冲突。

潜在原因

正在同时创建其他 VPC 原生集群,且该集群正尝试在同一 VPC 网络中分配相同的范围。

正在向同一 VPC 网络中的子网添加相同的次要范围。

解决方法

如果您没有指定任何次要范围,并且在创建集群时收到该错误,请重试集群创建命令。

Pod 没有足够的可用 IP 空间

表现

集群在较长时间内处于预配状态

集群创建返回托管实例组 (MIG) 错误

无法将新节点添加到现有集群

潜在原因

Pod IP 地址范围中未分配的空间对于集群中请求的节点而言不够大。例如,如果集群的 Pod IP 地址范围的网络掩码大小为 /23(512 个地址),并且每个节点的 Pod 数上限为 110,则您最多只能创建两个节点。(每个节点分配有一个网络掩码大小为 /24 的别名 IP 地址范围。)

解决方案

在审核并规划适当大小的主要 IP 地址范围和次要 IP 地址范围后,创建一个替换集群。请参阅 VCP 原生集群的 IP 范围IP 范围规划

如果您无法替换此集群,则或许可以通过创建一个每个节点的最大 Pod 数较小的新节点池来解决此问题。如果可以的话,请将工作负载迁移到该节点池,然后删除原有的节点池。通过减少每个节点的最大 Pod 数,您可以使固定的 Pod 次要 IP 地址范围支持更多的节点。如需详细了解所涉及的计算,请参阅 Pod 的子网次要 IP 地址范围节点限制范围

确认是否已停用默认 sNAT

使用以下命令检查默认 sNAT 的状态:

gcloud container clusters describe cluster-name

cluster-name 替换为您的集群名称。

输出将包含 disableDefaultSnat 字段,如下所示:

networkConfig:
  disableDefaultSnat: true
  network: ...

无法在没有 --enable-ip-alias 的情况下使用 --disable-default-snat

此错误消息和“must disable default sNAT (--disable-default-snat) before using public IP address privately in the cluster”表示您应在创建集群时明确设置 --disable-default-snat 标志,因为您是在专用集群中使用公共 IP 地址。

如果您看到类似“cannot disable default sNAT ...”的错误消息,则表示无法在集群中停用默认 SNAT。请检查您的集群配置。

在停用默认 sNAT 的情况下调试 Cloud NAT

如果您使用 --disable-default-snat 标志创建了一个专用集群,并且为 Cloud NAT 设置了互联网访问,但没有看到来自 Pod 的互联网绑定流量,请确保 Pod 范围包含在 Cloud NAT 配置中。

如果 Pod 到 Pod 的通信存在问题,请检查节点的 iptables 规则以验证 Pod 范围是否未被 iptables 规则伪装。如需了解如何列出 iptables 规则以及默认规则,请参阅 IP 伪装示例 iptables 输出。如果您尚未为集群配置 IP 伪装代理,GKE 会自动确保 Pod 到 Pod 的通信未被伪装。但是,如果配置了 IP 伪装代理,则该代理将替换默认的 IP 伪装规则。验证是否在 IP 伪装代理中配置了其他规则,以忽略对 Pod 范围的伪装。

限制

  • 您无法将 VPC 原生集群转换为基于路由的集群,也不能将基于路由的集群转换为 VPC 原生集群。
  • VPC 原生集群需要 VPC 网络。旧式网络不受支持。

  • 与任何 GKE 集群一样,Service (ClusterIP) 地址只能从集群内部访问。如果您需要从位于集群外部但位于集群 VPC 网络和地区内的虚拟机实例访问 Kubernetes Service,请创建一个内部 TCP/UDP 负载平衡器

后续步骤