23.10. 配置出口 IP 地址
作为集群管理员,您可以配置 OVN-Kubernetes Container Network Interface(CNI)集群网络供应商,为命名空间分配一个或多个出口 IP 地址,或分配给命名空间中的特定 pod。
23.10.1. 出口 IP 地址架构设计和实施
OpenShift Container Platform 出口 IP 地址功能可确保来自一个或多个命名空间中的一个或多个 pod 的流量具有集群网络之外的服务具有一致的源 IP 地址。
例如,您可能有一个 pod 定期查询托管在集群外服务器上的数据库。要强制对服务器进行访问要求,将数据包过滤设备配置为只允许来自特定 IP 地址的流量。为确保您可以可靠地允许从该特定 pod 访问服务器,您可以为向服务器发出请求的 pod 配置特定的出口 IP 地址。
分配给命名空间的出口 IP 地址与用来向特定目的地发送流量的出口路由器不同。
在一些集群配置中,应用程序 Pod 和入口路由器 pod 在同一个节点上运行。如果您在这种情况下为应用程序项目配置出口 IP 地址,当您向应用程序项目发送请求时,不会使用 IP 地址。
不能在任何 Linux 网络配置文件中配置出口 IP 地址,比如 ifcfg-eth0
。
23.10.1.1. 平台支持
下表概述了对不同平台中的出口 IP 地址功能的支持:
平台 | 支持 |
---|---|
裸机 | 是 |
VMware vSphere | 是 |
Red Hat OpenStack Platform (RHOSP) | 否 |
Amazon Web Services (AWS) | 是 |
Google Cloud Platform (GCP) | 是 |
Microsoft Azure | 是 |
在 Amazon Web Services(AWS)上置备的集群中不支持使用 EgressIP 功能将出口 IP 地址分配给 control plane 节点。(BZ#2039656)
23.10.1.2. 公共云平台注意事项
对于在公共云基础架构上置备的集群,每个节点绝对的 IP 地址会有一个约束。如下公式描述了每个节点的可分配 IP 地址或 IP 容量 上限:
IP capacity = public cloud default capacity - sum(current IP assignments)
虽然 Egress IP 功能管理每个节点的 IP 地址容量,但在部署中计划这个约束非常重要。例如,对于在具有 8 个节点的裸机基础架构上安装的集群,您可以配置 150 个出口 IP 地址。但是,如果公共云提供商将 IP 地址容量限制为每个节点 10 个 IP 地址,则可分配 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 地址。
以下示例演示了来自多个公共云提供商上节点的注解。注解被缩进以便于阅读。
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 地址容量,用于容量计算。
23.10.1.2.1. Amazon Web Services(AWS)IP 地址容量限制
在 AWS 上,IP 地址分配的限制取决于配置的实例类型。如需更多信息,请参阅 每个实例类型的每个网络接口的 IP 地址
23.10.1.2.2. Google Cloud Platform(GCP)IP 地址容量限制
在 GCP 中,网络模型通过 IP 地址别名而不是 IP 地址分配来实施额外的节点 IP 地址。但是,IP 地址容量直接映射到 IP 别名容量。
IP 别名分配存在以下容量限制:
- 每个节点,IPv4 和 IPv6 的最大 IP 别名数为 10。
- 对于每个 VPC,IP 别名的最大数量没有被指定,但 OpenShift Container Platform 可扩展性测试显示最大为 15,000 个。
如需更多信息,请参阅 Per instance 配额和 Alias IP 范围概述。
23.10.1.2.3. Microsoft Azure IP 地址容量限制
在 Azure 上,IP 地址分配有以下容量限制:
- 对于每个 NIC,对于 IPv4 和 IPv6,可分配 IP 地址的最大数量为 256。
- 对于每个虚拟网络,分配的 IP 地址的最大数量不能超过 65,536。
如需更多信息,请参阅网络限制。
23.10.1.3. 将出口 IP 分配给 pod
要将一个或多个出口 IP 分配给命名空间中的命名空间或特定 pod,必须满足以下条件:
-
集群中至少有一个节点必须具有
k8s.ovn.org/egress-assignable: ""
标签。 -
存在一个
EgressIP
对象定义一个或多个出口 IP 地址,用作从命名空间中离开集群的流量的源 IP 地址。
如果您在为出口 IP 分配标记集群中的任何节点之前创建 EgressIP
对象,OpenShift Container Platform 可能会将每个出口 IP 地址分配给第一个节点,并使用 k8s.ovn.org/egress-assignable: ""
标签。
要确保出口 IP 地址在集群中的不同节点广泛分发,请在创建任何 EgressIP
对象前,始终将标签应用到您想托管出口 IP 地址的节点。
23.10.1.4. 将出口 IP 分配给节点
在创建 EgressIP
对象时,以下条件适用于标记为 k8s.ovn.org/egress-assignable: ""
标签的节点:
- 每次不会将出口 IP 地址分配给多个节点。
- 出口 IP 地址可在可以托管出口 IP 地址的可用节点之间平衡。
如果
EgressIP
对象中的spec.EgressIPs
数组指定了多个 IP 地址,则适用以下条件:- 任何节点都不会托管超过一个指定的 IP 地址。
- 流量在给定命名空间的指定 IP 地址之间大致相等。
- 如果节点不可用,则会自动重新分配给它的所有出口 IP 地址,但符合前面描述的条件。
当 Pod 与多个 EgressIP
对象的选择器匹配时,无法保证在 EgressIP
对象中指定的出口 IP 地址被分配为 pod 的出口 IP 地址。
另外,如果 EgressIP
对象指定了多个出口 IP 地址,则无法保证可以使用哪些出口 IP 地址。例如,如果 pod 与带有两个出口 IP 地址 (10.10.20.1
和 10.10.20.2
) 的 EgressIP
对象的选择器匹配,其中任何一个都可以用于每个 TCP 连接或 UDP 对话。
23.10.1.5. 出口 IP 地址配置架构图
下图显示了出口 IP 地址配置。图中描述了,在一个集群的三个节点上运行的两个不同命名空间中的四个 pod。节点从主机网络上的 192.168.126.0/18
CIDR 块中分配 IP 地址。
Node 1 和 Node 3 都标记为 k8s.ovn.org/egress-assignable: ""
,因此可用于分配出口 IP 地址。
图中的横线描述了 pod1、pod2 和 pod 3 的流量流,通过 pod 网络来从 Node 1 和 Node 3 出口集群。当外部服务从示例 EgressIP
对象选择的任何 pod 接收流量时,源 IP 地址为 192.168.126.10
或 192.168.126.102
。这两个节点之间流量大致平衡。
图中的以下资源被详细描述:
命名空间
对象命名空间在以下清单中定义:
命名空间对象
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.10
和192.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 地址。
23.10.2. EgressIP 对象
以下 YAML 描述了 EgressIP
对象的 API。对象有效的范围为集群,它不是在命名空间中创建的。
apiVersion: k8s.ovn.org/v1 kind: EgressIP metadata: name: <name> 1 spec: egressIPs: 2 - <ip_address> namespaceSelector: 3 ... podSelector: 4 ...
以下 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.11
和 192.168.126.102
出口 IP 地址与将 app
标签设置为 web
的 pod 关联,并位于将 env
标签设置为 prod
的命名空间中:
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.30
和 192.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
23.10.3. 标记节点以托管出口 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>