本文档介绍了如何配置 Google Distributed Cloud,以便为 Pod 提供多个网络接口(多 NIC)。pod 的多 NIC 功能可以帮助分离控制层面流量和数据层面流量,从而在层面之间创建隔离。额外的网络接口还可以支持 pod 的多播功能。用户集群支持 Pod 的多 NIC 功能,但管理员集群支持。
网络层面隔离对使用网络功能虚拟化 (NFV) 的系统非常重要,NFV 包括广域网 (SD-WAN) 中的软件定义网络、云访问安全代理 (CASB) 和下一代防火墙 (NG-FW)。这些类型的 NFV 依赖于访问多个接口分隔控制层面和数据层面。
多网络接口配置支持将网络接口与节点池相关联,从而提供性能优势。例如,集群可以包含多种节点类型。将高性能机器分组到一个节点池中时,您可以在节点池中创建更多接口以改善流量。
设置多个网络接口
通常,为 pod 设置多个网络接口包括三个步骤:
使用集群配置文件中的
multipleNetworkInterfaces
和enableDataplaneV2
字段为您的用户集群启用多 NIC。使用集群配置文件中的
additionalNodeInterfaces
部分指定网络接口,并创建一个或多个NetworkAttachmentDefinition
自定义资源。使用
k8s.v1.cni.cncf.io/networks
注解向 pod 分配网络接口。
启用多 NIC
通过将用户集群配置文件中的 multipleNetworkInterfaces
和 enableDataplaneV2
字段设置为 true
,为您的 Pod 启用多 NIC。
apiVersion: v1 multipleNetworkInterfaces: true enableDataplaneV2: true ...
指定网络接口
在集群配置文件中,在 additionalNodeInterfaces
部分中指定增加的节点网络接口。
例如,以下是用户集群配置文件的一部分,其中显示了一个增加的节点网络接口:
apiVersion: v1 multipleNetworkInterfaces: true enableDataplaneV2: true network: serviceCIDR: "10.96.0.0/20" podCIDR: "192.168.0.0/16" vCenter: networkName: network-private310 ... # New multiple network configs additionalNodeInterfaces: - networkName: "gke-network-1" ipBlockFilePath: "my-block-yaml" type: static
使用上述配置创建集群后,您必须在用户集群中创建一个或多个 NetworkAttachmentDefinition
(NAD) 自定义资源,并在其中指定增加的网络接口。NetworkAttachmentDefinitions
对应于 pod 可用的网络。以下示例展示了 NetworkAttachmentDefinition
的清单:
apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: gke-network-1 namespace: default spec: config: '{ "cniVersion":"0.3.0", "type": "ipvlan", "master": "ens224", # defines the node interface that this Pod interface would map to "mode": "l2", "ipam": { "type": "whereabouts", "range": "172.16.0.0/24" } }'
将清单保存为 YAML 文件(例如 my-nad.yaml
),然后创建 NetworkAttachmentDefinition
:
kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] apply -f my-nad.yaml
将网络接口分配给 pod
使用 k8s.v1.cni.cncf.io/networks
注解为 pod 分配一个或多个网络接口。每个网络接口都指定了命名空间和 NetworkAttachmentDefinition
的名称,并以正斜杠 (/
) 分隔。使用以英文逗号分隔的列表来指定多个网络接口。
在以下示例中,为 samplepod
Pod 分配了两个网络接口。网络接口由创建于 default
命名空间中的两个 NetworkAttachmentDefinitions
、gke-network-1
和 gke-network-2
的名称指定。
--- apiVersion: v1 kind: Pod metadata: name: samplepod annotations: k8s.v1.cni.cncf.io/networks: default/gke-network-1,default/gke-network-2 spec: containers: ...
将网络接口限制为一组节点
如果您不希望 NetworkAttachmentDefinition
适用于整个集群,则可以将其功能范围限制为一组节点。
您可以使用分配给节点的标准标签或您自己的自定义标签对集群节点进行分组。然后,您可以使用 k8s.v1.cni.cncf.io/nodeSelector
注解在 NetworkAttachmentDefinition
清单中指定节点标签。GKE on VMware 会强制将引用此自定义资源的所有 Pod 部署到具有此标签的节点上。
apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: annotations: k8s.v1.cni.cncf.io/nodeSelector: LABEL_KEY=LABEL_VALUE name: gke-network-1 spec: ...
以下示例展示了 NetworkAttachmentDefinition
上指示的 my-label=multinicNP
标签,并强制将已获分配 gke-network-1
网络的所有 Pod 部署到具有此标签的节点。
apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: annotations: k8s.v1.cni.cncf.io/nodeSelector: my-label=multinicNP name: gke-network-1 spec: ...
如需将自定义标签应用于节点,请使用 kubectl label nodes
命令:
kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes NODE_NAME LABEL_KEY=LABEL_VALUE
请替换以下内容:
NODE_NAME
:您要为其添加标签的节点的名称。LABEL_KEY
:要用于标签的键。LABEL_VALUE
:标签值。
在此示例中,为节点 my-node
提供 environment=production
标签:
kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes my-node environment=production
安全考量
NetworkAttachmentDefinition
提供对网络的完整访问权限,因此集群管理员在向其他用户提供创建、更新或删除权限时必须小心谨慎。如果必须隔离给定 NetworkAttachmentDefinition
,则可以在创建时指定非默认命名空间,这样只有该命名空间中的 Pod 可以访问它。
在下图中,default
命名空间中的 pod 无法访问 privileged
命名空间中的网络接口。
支持的 CNI 插件
本部分列出了 Google Distributed Cloud 的多 NIC 功能支持的 CNI 插件。在指定 NetworkAttachmentDefinition
时,请仅使用以下插件。
接口创建:
ipvlan
macvlan
bridge
Meta 插件:
portmap
sbr
tuning
IPAM 插件:
host-local
static
whereabouts
路由配置
具有一个或多个已分配 NetworkAttachmentDefinitions
的 pod 具有多个网络接口。默认情况下,在这种情况下,Pod 的路由表仅使用已分配 NetworkAttachmentDefinitions
中的本地可用其他接口进行扩展。绑定到默认网关的数据包仍配置为使用 Pod 的默认接口 eth0
。您可以使用以下 CNI 插件修改此行为:
sbr
static
whereabouts
例如,您可能希望大多数流量通过默认网关,这意味着流量将通过默认网络接口。但是,您希望某些特定流量通过其中一个非默认接口。根据目标 IP(正常路由)可能难以区分流量,因为这两种接口类型上的可用端点是同一个。在这种情况下,基于来源的路由 (SBR) 将能够发挥作用。
SBR 插件
sbr
插件可让应用控制路由决策。应用可以控制其建立的连接的来源 IP 地址。如果应用选择使用 NetworkAttachmentDefinition
的 IP 地址作为其来源 IP 地址,则数据包会到达 sbr
设置的额外路由表。sbr
路由表通过自己的默认网关发送流量,该网关将通过 NetworkAttachmentDefinition
的接口传输。该表中的默认网关 IP 由 whereabouts
或 static
插件中的 gateway
字段控制。sbr
插件作为链式插件运行。如需详细了解 sbr
插件(包括使用方法信息),请参阅基于来源的路由插件。
以下示例显示了 whereabouts
中设置的 "gateway":"21.0.111.254"
,以及 ipvlan
之后设置为链式插件的 sbr
:
# ip route
default via 192.168.0.64 dev eth0 mtu 1500
192.168.0.64 dev eth0 scope link
# ip route list table 100
default via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1
static 插件和 whereabouts 插件
whereabouts
插件基本上是 static
插件的扩展,二者共享路由配置。如需查看配置示例,请参阅静态 IP 地址管理插件。您可以定义要添加到 pod 的路由表的网关和路由。但是,您无法以这种方式修改 pod 的默认网关。
以下示例展示了在 NetworkAttachmentDefinition
中添加 "routes": [{ "dst": "172.31.0.0/16" }]
:
# ip route
default via 192.168.0.64 dev eth0 mtu 1500
172.31.0.0/16 via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1
192.168.0.64 dev eth0 scope link
配置示例
本部分说明了多 NIC 功能支持的一些常见网络配置。
多个 pod 使用一个网络连接:
一个 pod 使用多个网络连接:
多个网络连接指向一个 pod 使用的同一接口:
一个 pod 多次使用同一网络连接:
问题排查
如果额外的网络接口配置有误,则它们分配到的 pod 将不会启动。本部分重点介绍如何查找信息以排查多 NIC 功能的问题。
检查 pod 事件
Multus 通过 Kubernetes pod 事件报告故障。使用以下 kubectl describe
命令查看给定 pod 的事件:
kubectl describe pod POD_NAME
检查日志
对于每个节点,您可以在以下位置找到 Whereabouts 和 Multus 日志:
/var/log/whereabouts.log
/var/log/multus.log
检查 pod 接口
使用 kubectl exec
命令检查 pod 接口。成功应用 NetworkAttachmentDefinitions
后,pod 接口将如下输出所示:
user@node1:~$ kubectl exec samplepod-5c6df74f66-5jgxs -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 00:50:56:82:3e:f0 brd ff:ff:ff:ff:ff:ff
inet 21.0.103.112/21 scope global net1
valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 36:23:79:a9:26:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.2.191/32 scope global eth0
valid_lft forever preferred_lft forever
获取 pod 状态
使用 kubectl get
检索给定 pod 的网络状态:
kubectl get pods POD_NAME -oyaml
以下示例输出显示了具有多个网络的 pod 的状态:
apiVersion: v1
kind: Pod
metadata:
annotations:
k8s.v1.cni.cncf.io/network-status: |-
[{
"name": "",
"interface": "eth0",
"ips": [
"192.168.1.88"
],
"mac": "36:0e:29:e7:42:ad",
"default": true,
"dns": {}
},{
"name": "default/gke-network-1",
"interface": "net1",
"ips": [
"21.0.111.1"
],
"mac": "00:50:56:82:a7:ab",
"dns": {}
}]
k8s.v1.cni.cncf.io/networks: gke-network-1