红帽 OpenShift 的网络架构为无数容器化应用提供了可靠且可扩展的前端。服务基于 pod 标签提供简单的负载平衡,而路由则将这些服务公开给外部网络。这些概念非常适用于微服务,但对于在 OpenShift 虚拟化上的虚拟机中运行的应用来说,它们可能具有挑战性,因为现有的服务器管理基础架构已经就位,并且假定始终提供对虚拟机的完整访问权限。
在上一篇文章中,我演示了如何安装和配置 OpenShift 虚拟化,以及如何运行基本的虚拟机。在本文中,我将讨论配置 OpenShift 虚拟化集群的不同选项,以允许虚拟机以与其他常见虚拟机监控程序非常相似的方式访问外部网络。
将 OpenShift 连接到外部网络
除了内部容器集网络外,OpenShift 还可以配置为访问外部网络。这是通过在 OpenShift 集群中使用 NMState operator 来实现的。您可以从 OpenShift Operator Hub 安装 NMState operator。
NMState operator 与 Multus 配合使用,后者是 OpenShift 的 CNI 插件,允许容器集与多个网络通信。因为我们已经有至少一篇关于 Multus的精彩文章,所以我在这里放弃详细说明,而是重点介绍如何使用 NMState 和 Multus 将虚拟机连接到多个网络。
NMState 组件概述
安装了 NMState 操作器后,会添加三个 CustomResoureDefinition (CRD),使您能够在集群节点上配置网络接口。在 OpenShift 节点上配置网络接口时,您将与这些对象交互。
节点网络状态
(
nodenetworkstates.nmstate.io
) 为每个集群节点建立一个 NodeNetworkState (NNS) 对象。对象的内容详细说明了该节点的当前网络状态。NodeNetworkConfigurationPolicies
(
nodenetworkconfigurationpolicies.nmstate.io
) 是一项策略,告知 NMState operator 如何在节点组上配置不同的网络接口。简而言之,这些表示对 OpenShift 节点的配置更改。NodeNetworkConfigurationEnactments
(
nodenetworkconfigurationenactments.nmstate.io
) 将每个应用的 NodeNetworkConfigurationPolicy (NNCP) 结果存储在 NodeNetworkConfigurationEnactment (NNCE) 对象中。每个节点有一个 NNCE,用于每个 NNCP。
完成这些定义后,您可以继续在 OpenShift 节点上配置网络接口。我在本文中使用的实验硬件配置包含三个网络接口。第一个是enp1s0,它已在集群安装期间使用网桥br-ex进行了配置。这是我在下面的 Option #1 中使用的网桥和接口。第二个接口enp2s0与enp1s0位于同一网络上,我用它来配置下方Option #2 中的 OVS 网桥br0 。最后,接口enp8s0 连接到一个单独的网络,该网络无法访问互联网,也没有 DHCP 服务器。我使用此接口在下面的Option #3 中配置 Linux 网桥br1 。

选项 1:使用具有单个 NIC 的外部网络
如果您的 OpenShift 节点只有一个用于联网的 NIC,则将虚拟机连接到外部网络的唯一选择是重复使用br-ex 网桥,这是 OVN-Kubernetes 集群中运行的所有节点的默认设置。这意味着,此选项可能不适用于使用旧版 Openshift-SDN 的集群。
由于无法完全重新配置br-ex 网桥而不会对集群的基本操作造成负面影响,因此您必须改为向该网桥添加本地网络。您可以通过以下NodeNetworkConfigurationPolicy
设置来实现这一目标:
$ cat br-ex-nncp.yaml
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br-ex-network
spec:
nodeSelector:
node-role.kubernetes.io/worker: ''
desiredState:
ovn:
bridge-mappings:
- localnet: br-ex-network
bridge: br-ex
state: present
在大多数情况下,上面的示例在将本地网络添加到br-ex 网桥的每个环境中都是相同的。通常要更改的唯一部分是 NNCP 的名称 (.metadata.name) 和 localnet 的名称 (.spec.desiredstate.ovn.bridge-mappings)。在本例中,它们都是br-ex-network,但名称是任意的,不需要彼此相同。在配置NetworkAttachmentDefinition
时,需要为localnet 使用任何值,因此请记住该值以供日后使用!
将 NNCP 配置应用到集群节点:
$ oc apply -f br-ex-nncp.yaml
nodenetworkconfigurationpolicy.nmstate.io/br-ex-network
使用以下命令检查 NNCP 和 NNCE 的进度:
$ oc get nncp
NAME STATUS REASON
br-ex-network Progressing ConfigurationProgressing
$ oc get nnce
NAME STATUS STATUS AGE REASON
lt01ocp10.matt.lab.br-ex-network Progressing 1s ConfigurationProgressing
lt01ocp11.matt.lab.br-ex-network Progressing 3s ConfigurationProgressing
lt01ocp12.matt.lab.br-ex-network Progressing 4s ConfigurationProgressing
在本例中,名为 br-ex-network 的单个 NNCP 已为每个节点生成了一个 NNCE。几秒钟后,该过程完成:
$ oc get nncp
NAME STATUS REASON
br-ex-network Available SuccessfullyConfigured
$ oc get nnce
NAME STATUS STATUS AGE REASON
lt01ocp10.matt.lab.br-ex-network Available 83s SuccessfullyConfigured
lt01ocp11.matt.lab.br-ex-network Available 108s SuccessfullyConfigured
lt01ocp12.matt.lab.br-ex-network Available 109s SuccessfullyConfigured
您现在可以转到NetworkAttachmentDefinition
,这部分定义了虚拟机如何连接到您刚刚创建的新网络。
NetworkAttachmentDefinition 配置
要在 OpenShift 控制台中创建NetworkAttachmentDefinition
,请选择您要在其中创建虚拟机的项目(本例中为 vmtest),再前往Networking > NetworkAttachmentDefinitions。然后,单击标有 Create networkattachmentdefinition 的蓝色按钮。

控制台会显示一个表单,您可以使用它来创建 NetworkAttachmentDefinition:

Name 字段是任意的,但在本例中,我使用的名称与用于 NNCP 的名称相同 (br-ex-network
)。对于 Network Type,您必须选择OVN Kubernetes secondary localnet 网络。
在 Bridge map 字段中,输入您之前配置的 localnet 的名称(本例中也恰好是br-ex-network
)。由于字段要求提供“网桥映射”,因此您可能会想要输入“br-ex”,但实际上,您必须使用您创建的 localnet,它已连接到br-ex
。
或者,您可以使用 YAML 文件而不是使用控制台来创建 NetworkAttachmentDefinition
:
$ cat br-ex-network-nad.yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: br-ex-network
namespace: vmtest
spec:
config: '{
"name":"br-ex-network",
"type":"ovn-k8s-cni-overlay",
"cniVersion":"0.4.0",
"topology":"localnet",
"netAttachDefName":"vmtest/br-ex-network"
}'
$ oc apply -f br-ex-network-nad.yaml
networkattachmentdefinition.k8s.cni.cncf.io/br-ex-network created
在上面的 NetworkAttachmentDefinition
YAML 中,.spec.config 中的 name 字段是来自 NNCP 的 localnet 的名称,而 netAttachDefName 是必须与 .metadata 部分中两个相同字段匹配的命名空间/名称(本例中为 vmtest/br-ex-network)。
虚拟机使用静态 IP 或 DHCP 进行 IP 寻址,因此 NetworkAttachmentDefinition
虚拟机 NIC 配置
要将新的外部网络用于虚拟机,请修改虚拟机的 Network interfaces 部分,再选择新的 vmtest/br-ex-network 作为Network 类型。也可以在此表单中自定义 MAC 地址。
继续像往常一样创建虚拟机。虚拟机启动后,您的虚拟 NIC 将连接到外部网络。在本例中,外部网络具有 DHCP 服务器,因此会自动分配 IP 地址,并且允许访问该网络。
删除 br-ex 上的 NetworkAttachmentDefinition 和 localnet
如果您想撤消上述步骤,请首先确保没有虚拟机在使用NetworkAttachmentDefinition
,然后使用控制台将它删除。或者,使用命令:
$ oc delete network-attachment-definition/br-ex-network -n vmtest
networkattachmentdefinition.k8s.cni.cncf.io "br-ex-network" deleted
接下来,删除NodeNetworkConfigurationPolicy
。删除策略不会撤销 OpenShift 节点上的更改!
$ oc delete nncp/br-ex-network
nodenetworkconfigurationpolicy.nmstate.io "br-ex-network" deleted
删除 NNCP 也会删除所有关联的 NNCE:
$ oc get nnce
No resources found
最后,修改之前使用的 NNCP YAML 文件,但将 bridge-mapping 状态从present
更改为absent
:
$ cat br-ex-nncp.yaml
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br-ex-network
spec:
nodeSelector:
node-role.kubernetes.io/worker: ''
desiredState:
ovn:
bridge-mappings:
- localnet: br-ex-network
bridge: br-ex
state: absent # Changed from present
重新应用更新的 NNCP:
$ oc apply -f br-ex-nncp.yaml
nodenetworkconfigurationpolicy.nmstate.io/br-ex-network
$ oc get nncp
NAME STATUS REASON
br-ex-network Available SuccessfullyConfigured
$ oc get nnce
NAME STATUS STATUS AGE REASON
lt01ocp10.matt.lab.br-ex-network Available 2s SuccessfullyConfigured
lt01ocp11.matt.lab.br-ex-network Available 29s SuccessfullyConfigured
lt01ocp12.matt.lab.br-ex-network Available 30s SuccessfullyConfigured
localnet 配置现已删除。您可以安全地删除 NNCP。
选项 2:将外部网络与专用 NIC 上的 OVS 网桥搭配使用
OpenShift 节点可以连接到使用不同物理 NIC 的多个网络。虽然存在许多配置选项(如绑定和 VLAN),但在本例中,我仅使用专用 NIC 来配置 OVS 网桥。有关高级配置选项的更多信息,如创建绑定或使用 VLAN,请参阅我们的文档。
您可以使用此命令查看所有节点接口(为方便起见,此处截断了输出):
$ oc get nns/lt01ocp10.matt.lab -o jsonpath='{.status.currentState.interfaces[3]}' | jq
{
…
"mac-address": "52:54:00:92:BB:00",
"max-mtu": 65535,
"min-mtu": 68,
"mtu": 1500,
"name": "enp2s0",
"permanent-mac-address": "52:54:00:92:BB:00",
"profile-name": "Wired connection 1",
"state": "up",
"type": "ethernet"
}
在本例中,所有节点上未使用的网络适配器是 enp2s0。
与上一示例中一样,首先使用 NNCP 在节点上创建名为br0
的新 OVS 网桥,该网桥使用未使用的 NIC(本例中为enp2s0)。NNCP 如下所示:
$ cat br0-worker-ovs-bridge.yaml
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br0-ovs
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
interfaces:
- name: br0
description: |-
A dedicated OVS bridge with enp2s0 as a port
allowing all VLANs and untagged traffic
type: ovs-bridge
state: up
bridge:
options:
stp: true
port:
- name: enp2s0
ovn:
bridge-mappings:
- localnet: br0-network
bridge: br0
state: present
关于上例,首先要注意的是 .metadata.name 字段,它是任意的,用于标识 NNCP 的名称。您还可以在文件末尾附近看到,您正在向新的 br0 网桥添加 localnet 网桥映射,就像您在单个 NIC 示例中对 br-ex 所做的那样。
在上一使用 br-ex 作为网桥的示例中,可以安全地假定所有 OpenShift 节点都有一个使用此名称的网桥,因此您将 NNCP 应用到了所有工作程序节点。但是,在当前场景中,同一网络可能存在具有不同 NIC 名称的异构节点。在这种情况下,您必须向每个节点类型添加标签,以标识它具有的配置。然后,使用上例中的 .spec.nodeSelector ,您可以将配置仅应用到将使用此配置的节点。对于其他节点类型,您可以修改 NNCP 和nodeSelector
,并在这些节点上创建相同的网桥,即使底层 NIC 名称不同。
在本例中,NIC 名称全部相同,因此您可以将相同的 NNCP 用于所有节点。
现在应用 NNCP,就像您对单个 NIC 示例所做的那样:
$ oc apply -f br0-worker-ovs-bridge.yaml
nodenetworkconfigurationpolicy.nmstate.io/br0-ovs created
和以前一样,成功创建和应用 NNCP 和 NNCE 需要一些时间。您可以在 NNS 中看到新的网桥:
$ oc get nns/lt01ocp10.matt.lab -o jsonpath='{.status.currentState.interfaces[3]}' | jq
{
…
"port": [
{
"name": "enp2s0"
}
]
},
"description": "A dedicated OVS bridge with enp2s0 as a port allowing all VLANs and untagged traffic",
…
"name": "br0",
"ovs-db": {
"external_ids": {},
"other_config": {}
},
"profile-name": "br0-br",
"state": "up",
"type": "ovs-bridge",
"wait-ip": "any"
}
NetworkAttachmentDefinition 配置
为 OVS 网桥创建 NetworkAttachmentDefinition 的过程与前面使用单个 NIC 的示例相同,因为在这两种情况下,您都在创建 OVN 网桥映射。在当前示例中,网桥映射名称为br0-network
,因此这是您在NetworkAttachmenDefinition
创建表单中使用的名称:

或者,您可以使用 YAML 文件创建NetworkAttachmentDefinition
:
$ cat br0-network-nad.yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: br0-network
namespace: vmtest
spec:
config: '{
"name":"br0-network",
"type":"ovn-k8s-cni-overlay",
"cniVersion":"0.4.0",
"topology":"localnet",
"netAttachDefName":"vmtest/br0-network"
}'
$ oc apply -f br0-network-nad.yaml
networkattachmentdefinition.k8s.cni.cncf.io/br0-network created
虚拟机 NIC 配置
与之前一样,使用名为vmtest/br0-network
的新NetworkAttachmentDefinition
作为 NIC 网络,照常创建虚拟机。

虚拟机启动时,NIC 使用节点上的br0 网桥。在本例中,br0 的专用 NIC 与br-ex 网桥位于同一网络上,因此您从与之前相同的子网中获取 IP 地址,并且允许网络访问。
删除 NetworkAttachmentDefinition 和 OVS 网桥
删除NetworkAttachmentDefinition
和 OVS 网桥的流程与上一示例大致相同。确保没有虚拟机正在使用NetworkAttachmentDefinition
,然后从控制台或命令行将其删除:
$ oc delete network-attachment-definition/br0-network -n vmtest
networkattachmentdefinition.k8s.cni.cncf.io "br0-network" deleted
接下来,删除NodeNetworkConfigurationPolicy
(请记住,删除策略不会撤销 OpenShift 节点上的更改):
$ oc delete nncp/br0-ovs
nodenetworkconfigurationpolicy.nmstate.io "br0-ovs" deleted
删除 NNCP 也会删除关联的 NNCE:
$ oc get nnce
No resources found
最后,修改之前使用的 NNCP YAML 文件,但将接口状态从“up”更改为“absent”,并将网桥映射状态从“present”更改为“absent”:
$ cat br0-worker-ovs-bridge.yaml
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br0-ovs
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
Interfaces:
- name: br0
description: |-
A dedicated OVS bridge with enp2s0 as a port
allowing all VLANs and untagged traffic
type: ovs-bridge
state: absent # Change this from “up” to “absent”
bridge:
options:
stp: true
port:
- name: enp2s0
ovn:
bridge-mappings:
- localnet: br0-network
bridge: br0
state: absent # Changed from present
重新应用更新的 NNCP。成功处理 NNCP 后,您可以将其删除。
$ oc apply -f br0-worker-ovs-bridge.yaml
nodenetworkconfigurationpolicy.nmstate.io/br0-ovs created
选项 3:通过专用 NIC 上的 Linux 网桥使用外部网络
在 Linux 网络中,OVS 网桥和 Linux 网桥具有相同的用途。使用其中一种的决定最终取决于环境的需求。互联网上有无数文章讨论这两种网桥类型的优缺点。简而言之,Linux 网桥比 OVS 网桥更成熟、更简单,但功能不那么丰富,而 OVS 网桥的优势在于提供了比 Linux 网桥更多的隧道类型和其他现代功能,但故障排除起来有点困难。就 OpenShift 虚拟化而言,由于MultiNetworkPolicy等原因,您可能应默认为在 Linux 网桥上使用 OVS 网桥,但使用任一选项都可以成功部署。
请注意,当虚拟机接口连接到 OVS 网桥时,默认的 MTU 为 1400。当虚拟机接口连接到 Linux 网桥时,默认的 MTU 为 1500。有关集群 MTU 大小的更多信息,请参见官方文档。
节点配置
与前面的示例一样,我们使用专用 NIC 来创建新的 Linux 网桥。为了有趣起见,我将 Linux 网桥连接到一个没有 DHCP 服务器的网络,以便您可以了解这对连接到该网络的虚拟机有何影响。
在本例中,我在接口enp8s0 上创建名为 br1 的 Linux 网桥,该网桥附加到没有互联网接入或 DHCP 服务器的 172.16.0.0/24 网络。NNCP 如下所示:
$ cat br1-worker-linux-bridge.yaml
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br1-linux-bridge
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
interfaces:
- name: br1
description: Linux bridge with enp8s0 as a port
type: linux-bridge
state: up
bridge:
options:
stp:
enabled: false
port:
- name: enp8s0
$ oc apply -f br1-worker-linux-bridge.yaml
nodenetworkconfigurationpolicy.nmstate.io/br1-worker created
和前面一样,成功创建和应用 NNCP 和 NNCE 需要几秒钟时间。
NetworkAttachmentDefinition 配置
为 Linux 网桥创建NetworkAttachmentDefinition
的过程与前面的两个示例稍有不同,因为这一次您连接的不是 OVN localnet。对于 Linux 网桥连接,您可以直接连接到新的网桥。以下是NetworkAttachmenDefinition
创建表单:

在本例中,请选择 CNV Linux 网桥
的 Network Type ,并将实际网桥的名称放入 Bridge name 字段,本例中为 br1
。
虚拟机 NIC 配置
现在,创建另一个虚拟机,但将名为 vmtest/br1-network
的新 NetworkAttachmentDefinition
用于 NIC 网络。这会将 NIC 连接到新的 Linux 网桥。

虚拟机启动时,NIC 使用节点上的 br1 网桥。在本例中,专用 NIC 所在的网络没有 DHCP 服务器,也没有互联网接入,因此请使用nmcli 为 NIC 手动指定一个 IP 地址,并仅验证本地网络上的连接。
删除 NetworkAttachmentDefinition 和 Linux 网桥
与前面的示例一样,若要删除 NetworkAttachmentDefinition
和 Linux 网桥,首先要确保没有虚拟机在使用NetworkAttachmentDefinition
。从控制台或命令行将其删除:
$ oc delete network-attachment-definition/br1-network -n vmtest
networkattachmentdefinition.k8s.cni.cncf.io "br1-network" deleted
接下来,删除NodeNetworkConfigurationPolicy:
$ oc delete nncp/br1-linux-bridge
nodenetworkconfigurationpolicy.nmstate.io "br1-linux-bridge" deleted
删除 NNCP 也会删除所有关联的 NNCE(请记住,删除策略不会撤销 OpenShift 节点上的更改):
$ oc get nnce
No resources found
最后,修改 NNCP YAML 文件,将接口状态从 up
更改为 absent
:
$ cat br1-worker-linux-bridge.yaml
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br1-linux-bridge
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
interfaces:
- name: br1
description: Linux bridge with enp8s0 as a port
type: linux-bridge
state: absent # Changed from up
bridge:
options:
stp:
enabled: false
port:
- name: enp8s0
重新应用更新的 NNCP。成功处理 NNCP 后,可以将其删除。
$ oc apply -f br1-worker-linux-bridge.yaml
nodenetworkconfigurationpolicy.nmstate.io/br1-worker created
OpenShift 虚拟化中的高级网络
许多 OpenShift 虚拟化用户可以从红帽 OpenShift 内置的各种高级网络功能中受益。但是,随着越来越多的工作负载从传统虚拟机监控程序迁移,您可能希望利用现有的基础架构。这可能需要将 OpenShift 虚拟化工作负载直接连接到其外部网络。NMState operator 与 Multus 网络相结合,提供了一种灵活的方法来实现性能和连接,从而简化从传统虚拟机监控程序到红帽 OpenShift 虚拟化的过渡。
要了解有关 OpenShift 虚拟化的更多信息,您可以查看我的另一篇关于主题的博客文章,或者查看我们网站上的产品。有关本文所述网络主题的更多信息,红帽 OpenShift文档中包含您需要的所有详细信息。最后,如果您想观看演示或亲自使用 OpenShift 虚拟化,请联系您的客户经理。
关于作者
Matthew Secaur is a Red Hat Principal Technical Account Manager (TAM) for Canada and the Northeast United States. He has expertise in Red Hat OpenShift Platform, Red Hat OpenShift Virtualization, Red Hat OpenStack Platform, and Red Hat Ceph Storage.