×

出口 IP 地址架构设计与实现

OpenShift Container Platform 出口 IP 地址功能允许您确保来自一个或多个命名空间中一个或多个 Pod 的流量对于集群网络外部的服务具有一致的源 IP 地址。

例如,您可能有一个 Pod 定期查询托管在集群外部服务器上的数据库。为了执行服务器的访问要求,数据包过滤设备被配置为仅允许来自特定 IP 地址的流量。为了确保您可以可靠地仅允许来自该特定 Pod 的对服务器的访问,您可以为向服务器发出请求的 Pod 配置特定的出口 IP 地址。

分配给命名空间的出口 IP 地址与用于将流量发送到特定目的地的出口路由器不同。

在某些集群配置中,应用程序 Pod 和入口路由器 Pod 运行在同一节点上。在这种情况下,如果您为应用程序项目配置了出口 IP 地址,则在您从应用程序项目向路由发送请求时不会使用该 IP 地址。

出口 IP 地址不得在任何 Linux 网络配置文件(例如 `ifcfg-eth0`)中配置。

平台支持

下表总结了各种平台上出口 IP 地址功能的支持情况

平台 支持

裸金属

VMware vSphere

Red Hat OpenStack 平台 (RHOSP)

Amazon Web Services (AWS)

Google Cloud Platform (GCP)

Microsoft Azure

IBM Z® 和 IBM® LinuxONE

用于 Red Hat Enterprise Linux (RHEL) KVM 的 IBM Z® 和 IBM® LinuxONE

IBM Power®

Nutanix

在 Amazon Web Services (AWS) 上配置的集群中,不支持将出口 IP 地址分配给控制平面节点(使用 EgressIP 功能)。(BZ#2039656).

公共云平台注意事项

对于在公共云基础设施上配置的集群,每个节点的可分配 IP 地址的绝对数量存在限制。每个节点可分配的 IP 地址的最大数量,或称 *IP 容量*,可以用以下公式描述。

IP capacity = public cloud default capacity - sum(current IP assignments)

虽然 Egress IP 功能管理每个节点的 IP 地址容量,但在部署中规划此限制非常重要。例如,对于在具有 8 个节点的裸机基础设施上安装的集群,您可以配置 150 个出口 IP 地址。但是,如果公共云提供商将每个节点的 IP 地址容量限制为 10 个,则可分配的 IP 地址总数只有 80 个。为了在这个示例云提供商中实现相同的 IP 地址容量,您需要分配 7 个额外的节点。

要确认公共云环境中任何节点的 IP 容量和子网,您可以输入 `oc get node <node_name> -o yaml` 命令。`cloud.network.openshift.io/egress-ipconfig` 注解包含节点的容量和子网信息。

注解值是一个数组,其中包含一个具有以下字段的对象,这些字段为主要网络接口提供以下信息:

  • `interface`:指定 AWS 和 Azure 上的接口 ID,以及 GCP 上的接口名称。

  • `ifaddr`:指定一个或两个 IP 地址族的子网掩码。

  • `capacity`:指定节点的 IP 地址容量。在 AWS 上,IP 地址容量是按 IP 地址族提供的。在 Azure 和 GCP 上,IP 地址容量包括 IPv4 和 IPv6 地址。

节点之间流量的出口 IP 地址的自动附加和分离是可用的。这允许命名空间中的许多 Pod 的流量对集群外部的位置具有一致的源 IP 地址。

RHOSP 出口 IP 地址功能创建一个名为 `egressip-<IP 地址>` 的 Neutron 预留端口。使用与 OpenShift Container Platform 集群安装相同的 RHOSP 用户,您可以将浮动 IP 地址分配给此预留端口,以便为出口流量提供可预测的 SNAT 地址。例如,当出口 IP 地址由于节点故障转移而从一个节点移动到另一个节点时,Neutron 预留端口将被删除并重新创建。这意味着浮动 IP 关联将丢失,您需要手动将浮动 IP 地址重新分配给新的预留端口。

当 RHOSP 集群管理员将浮动 IP 分配给预留端口时,OpenShift Container Platform 无法删除预留端口。`CloudPrivateIPConfig` 对象无法执行删除和移动操作,直到 RHOSP 集群管理员从预留端口取消分配浮动 IP。

以下示例说明了来自多个公共云提供商的节点的注解。为便于阅读,注解已缩进。

AWS 上的示例 `cloud.network.openshift.io/egress-ipconfig` 注解
cloud.network.openshift.io/egress-ipconfig: [
  {
    "interface":"eni-078d267045138e436",
    "ifaddr":{"ipv4":"10.0.128.0/18"},
    "capacity":{"ipv4":14,"ipv6":15}
  }
]
GCP 上的示例 `cloud.network.openshift.io/egress-ipconfig` 注解
cloud.network.openshift.io/egress-ipconfig: [
  {
    "interface":"nic0",
    "ifaddr":{"ipv4":"10.0.128.0/18"},
    "capacity":{"ip":14}
  }
]

以下部分描述了支持的公共云环境的 IP 地址容量,可用于容量计算。

Amazon Web Services (AWS) IP 地址容量限制

在 AWS 上,对 IP 地址分配的限制取决于配置的实例类型。有关更多信息,请参阅 每个实例类型的每个网络接口的 IP 地址

Google Cloud Platform (GCP) IP 地址容量限制

在 GCP 上,网络模型通过 IP 地址别名而不是 IP 地址分配来实现额外的节点 IP 地址。但是,IP 地址容量直接映射到 IP 别名容量。

IP 别名分配存在以下容量限制:

  • 每个节点,IPv4 和 IPv6 的 IP 别名最大数量为 100。

  • 每个 VPC,IP 别名的最大数量未指定,但 OpenShift Container Platform 可扩展性测试显示最大值约为 15,000。

有关更多信息,请参阅 每个实例 配额和 别名 IP 范围概述

Microsoft Azure IP 地址容量限制

在 Azure 上,IP 地址分配存在以下容量限制:

  • 每个 NIC,IPv4 和 IPv6 的可分配 IP 地址最大数量为 256。

  • 每个虚拟网络,分配的 IP 地址总数不能超过 65,536。

有关更多信息,请参阅 网络限制

在附加网络接口上使用出口 IP 的注意事项

在 OpenShift Container Platform 中,出站 IP 地址为管理员提供了一种控制网络流量的方式。出站 IP 地址可与br-ex(或主)网络接口一起使用,该接口是与 Open vSwitch 关联的 Linux 桥接接口,或者可与其他网络接口一起使用。

您可以运行以下命令检查您的网络接口类型

$ ip -details link show

主网络接口分配一个节点 IP 地址,该地址还包含子网掩码。此节点 IP 地址的信息可以通过检查每个集群节点的 Kubernetes 节点对象的k8s.ovn.org/node-primary-ifaddr批注来检索。在 IPv4 集群中,此批注类似于以下示例:"k8s.ovn.org/node-primary-ifaddr: {"ipv4":"192.168.111.23/24"}"

如果出站 IP 地址不在主网络接口子网的子网内,则可以使用另一个非主网络接口类型的 Linux 网络接口上的出站 IP 地址。这样做,OpenShift Container Platform 管理员可以更好地控制网络方面,例如路由、寻址、分段和安全策略。此功能为用户提供了通过特定网络接口路由工作负载流量的选项,例如流量分段或满足特殊要求。

如果出站 IP 地址不在主网络接口的子网内,则如果节点上存在其他网络接口,则可能会选择另一个网络接口进行出站流量。

您可以通过检查k8s.ovn.org/host-cidrs Kubernetes 节点批注来确定哪些其他网络接口可能支持出站 IP 地址。此批注包含为主网络接口找到的地址和子网掩码。它还包含其他网络接口地址和子网掩码信息。这些地址和子网掩码分配给使用最长前缀匹配路由机制确定哪个网络接口支持出站 IP 地址的网络接口。

OVN-Kubernetes 提供了一种机制来控制和引导来自特定命名空间和 Pod 的出站网络流量。这确保它通过特定网络接口并使用特定的出站 IP 地址退出集群。

将出站 IP 地址分配给非主网络接口的要求

对于希望出站 IP 地址和流量通过非主网络接口的特定接口路由的用户,必须满足以下条件:

  • OpenShift Container Platform 安装在裸机集群上。此功能在云或虚拟机管理程序环境中被禁用。

  • 您的 OpenShift Container Platform Pod 未配置为主机网络。

  • 如果删除网络接口,或者删除允许在接口上托管出站 IP 地址的 IP 地址和子网掩码,则会重新配置出站 IP 地址。因此,它可以分配给另一个节点和接口。

  • 必须为网络接口启用 IP 转发。要启用 IP 转发,您可以使用oc edit network.operator命令并像以下示例一样编辑对象:

    # ...
    spec:
      clusterNetwork:
      - cidr: 10.128.0.0/14
        hostPrefix: 23
      defaultNetwork:
        ovnKubernetesConfig:
          gatewayConfig:
            ipForwarding: Global
    # ...

将出站 IP 地址分配给 Pod

要将一个或多个出站 IP 地址分配给命名空间或命名空间中的特定 Pod,必须满足以下条件:

  • 集群中至少一个节点必须具有k8s.ovn.org/egress-assignable: ""标签。

  • 存在一个EgressIP对象,该对象定义了一个或多个出站 IP 地址,用作来自命名空间中 Pod 的离开集群的流量的源 IP 地址。

如果您在标记集群中任何节点以进行出站 IP 地址分配之前创建EgressIP对象,OpenShift Container Platform 可能会将每个出站 IP 地址分配给第一个具有k8s.ovn.org/egress-assignable: ""标签的节点。

为了确保出站 IP 地址广泛分布在集群中的节点之间,请务必在创建任何EgressIP对象之前将标签应用于您打算托管出站 IP 地址的节点。

将出站 IP 地址分配给节点

创建EgressIP对象时,以下条件适用于标有k8s.ovn.org/egress-assignable: ""标签的节点:

  • 出站 IP 地址一次只能分配给一个节点。

  • 出站 IP 地址在可以托管出站 IP 地址的可用节点之间均衡分配。

  • 如果EgressIP对象中的spec.EgressIPs数组指定了多个 IP 地址,则适用以下条件:

    • 任何节点都不会托管多个指定的 IP 地址。

    • 对于给定的命名空间,流量在指定的 IP 地址之间大致均衡分配。

  • 如果节点不可用,则分配给它的任何出站 IP 地址都会根据前面描述的条件自动重新分配。

当 Pod 与多个EgressIP对象的selector匹配时,无法保证EgressIP对象中指定的哪个出站 IP 地址被分配为 Pod 的出站 IP 地址。

此外,如果EgressIP对象指定多个出站 IP 地址,则无法保证可能使用哪个出站 IP 地址。例如,如果 Pod 与具有两个出站 IP 地址(10.10.20.110.10.20.2)的EgressIP对象的selector匹配,则对于每个 TCP 连接或 UDP 会话,任何一个都可能被使用。

出站 IP 地址配置的架构图

下图描述了出站 IP 地址配置。该图描述了在集群中的三个节点上运行的两个不同命名空间中的四个 Pod。这些节点在主机网络上分配了来自192.168.126.0/18CIDR 块的 IP 地址。

Architectural diagram for the egress IP feature.

节点 1 和节点 3 都标有k8s.ovn.org/egress-assignable: "",因此可用于分配出站 IP 地址。

图中的虚线描绘了来自 pod1、pod2 和 pod3 的流量从 Pod 网络流向节点 1 和节点 3 的集群出口的流程。当外部服务接收来自示例EgressIP对象选择的任何 Pod 的流量时,源 IP 地址为192.168.126.10192.168.126.102。流量在这两个节点之间大致均衡分配。

图中的以下资源将详细说明:

Namespace对象

命名空间在以下清单中定义:

Namespace 对象
apiVersion: v1
kind: Namespace
metadata:
  name: namespace1
  labels:
    env: prod
---
apiVersion: v1
kind: Namespace
metadata:
  name: namespace2
  labels:
    env: prod
EgressIP对象

下面的EgressIP对象描述了一个配置,该配置选择任何命名空间中所有带有env标签且值为prod的Pod。所选Pod的出口IP地址为192.168.126.10192.168.126.102

EgressIP对象
apiVersion: k8s.ovn.org/v1
kind: EgressIP
metadata:
  name: egressips-prod
spec:
  egressIPs:
  - 192.168.126.10
  - 192.168.126.102
  namespaceSelector:
    matchLabels:
      env: prod
status:
  items:
  - node: node1
    egressIP: 192.168.126.10
  - node: node3
    egressIP: 192.168.126.102

对于之前的示例配置,OpenShift Container Platform 将这两个出口 IP 地址分配给可用的节点。status字段反映了出口IP地址是否以及在哪里被分配。

EgressIP 对象

以下YAML描述了EgressIP对象的API。该对象的范围是集群范围的;它不是在命名空间中创建的。

apiVersion: k8s.ovn.org/v1
kind: EgressIP
metadata:
  name: <name> (1)
spec:
  egressIPs: (2)
  - <ip_address>
  namespaceSelector: (3)
    ...
  podSelector: (4)
    ...
1 EgressIPs对象的名称。
2 一个或多个IP地址的数组。
3 一个或多个选择器,用于将出口IP地址与命名空间关联。
4 可选:一个或多个选择器,用于将出口IP地址与指定命名空间中的Pod关联。应用这些选择器可以选中命名空间内的一个Pod子集。

以下YAML描述了命名空间选择器的段落

命名空间选择器段落
namespaceSelector: (1)
  matchLabels:
    <label_name>: <label_value>
1 一个或多个命名空间匹配规则。如果提供了多个匹配规则,则选择所有匹配的命名空间。

以下YAML描述了Pod选择器的可选段落

Pod选择器段落
podSelector: (1)
  matchLabels:
    <label_name>: <label_value>
1 可选:与指定的namespaceSelector规则匹配的命名空间中Pod的一个或多个匹配规则。如果指定,则仅选择匹配的Pod。命名空间中的其他Pod不会被选中。

在下面的示例中,EgressIP对象将192.168.126.11192.168.126.102出口IP地址与具有app标签(值为web)且位于具有env标签(值为prod)的命名空间中的Pod关联。

示例EgressIP对象
apiVersion: k8s.ovn.org/v1
kind: EgressIP
metadata:
  name: egress-group1
spec:
  egressIPs:
  - 192.168.126.11
  - 192.168.126.102
  podSelector:
    matchLabels:
      app: web
  namespaceSelector:
    matchLabels:
      env: prod

在下面的示例中,EgressIP对象将192.168.127.30192.168.127.40出口IP地址与任何不具有environment标签(值为development)的Pod关联。

示例EgressIP对象
apiVersion: k8s.ovn.org/v1
kind: EgressIP
metadata:
  name: egress-group2
spec:
  egressIPs:
  - 192.168.127.30
  - 192.168.127.40
  namespaceSelector:
    matchExpressions:
    - key: environment
      operator: NotIn
      values:
      - development

egressIPConfig 对象

作为出口IP的一个特性,reachabilityTotalTimeoutSeconds参数配置EgressIP节点可达性检查的总超时时间(秒)。如果在此超时时间内无法到达EgressIP节点,则该节点将被声明为失效。

您可以在egressIPConfig对象的配置文件中设置reachabilityTotalTimeoutSeconds的值。设置较大的值可能会导致EgressIP实现对节点更改的反应较慢。对于出现问题且无法访问的EgressIP节点,实现的反应会较慢。

如果从egressIPConfig对象中省略reachabilityTotalTimeoutSeconds参数,则平台将选择一个合理的默认值,该值可能会随着时间的推移而更改。当前默认值为1秒。值为0将禁用EgressIP节点的可达性检查。

下面的egressIPConfig对象描述了将reachabilityTotalTimeoutSeconds从默认的1秒探测更改为5秒探测。

apiVersion: operator.openshift.io/v1
kind: Network
metadata:
  name: cluster
spec:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  defaultNetwork:
    ovnKubernetesConfig:
      egressIPConfig: (1)
        reachabilityTotalTimeoutSeconds: 5 (2)
      gatewayConfig:
        routingViaHost: false
      genevePort: 6081
1 egressIPConfig包含EgressIP对象的选项配置。通过更改这些配置,您可以扩展EgressIP对象。
2 reachabilityTotalTimeoutSeconds的值接受从060的整数值。值为0将禁用egressIP节点的可达性检查。设置从160的值对应于探测向节点发送可达性检查的超时时间(秒)。

标记节点以托管出口IP地址

您可以将k8s.ovn.org/egress-assignable=""标签应用于集群中的节点,以便OpenShift Container Platform可以将一个或多个出口IP地址分配给该节点。

先决条件
  • 安装OpenShift CLI(oc)。

  • 以集群管理员身份登录集群。

步骤
  • 要标记节点以便它可以托管一个或多个出口IP地址,请输入以下命令:

    $ oc label nodes <node_name> k8s.ovn.org/egress-assignable="" (1)
    1 要标记的节点的名称。

    或者,您可以应用以下YAML将标签添加到节点:

    apiVersion: v1
    kind: Node
    metadata:
      labels:
        k8s.ovn.org/egress-assignable: ""
      name: <node_name>

后续步骤