并不是所有OCP中应用都需要访问外部网络,默认情况下,OpenShift 不限制容器的出口访问流量。为防止来自被***容器集的恶意网络流量,我们可以控制集群出口流量。
OpenShift 提供了多种控制出口流量的方法:
OpenShift 出口防火墙
OpenShift 出口路由器
出口静态 IP
为了方便理解,我画一个思维导图:
红帽 OpenShift SDN提供的三个插件:
-
ovs-subnet 插件提供一个扁平网络,它分布到所有集群节点并可连接所有容器集。
ovs-multitenant 插件隔离每个 OpenShift 项目。此插件使用 虚拟可扩展局域网 (VXLAN) ,并为每个项目分配一个 虚拟网络 ID (VNID) 来进行隔离。
默认情况下,一个项目中的容器集无法访问其他项目中的容器集。您可以使用 oc adm pod-network join-projects 命令来联合项目,使得它们的容器集和服务能够*通信。以下命令允许 projectA 访问 projectB 中的容器集和服务,反之亦然。
ovs-networkpolicy 插件允许项目管理员使用 OpenShift 网络策略资源自行定义访问控制。默认情况下,如果未定义任何网络策略资源,项目中的容器集可以访问任何其他容器集。
描述节点和容器集网络
OpenShift 为每个集群节点配置一个名为 br0 的 Open vSwitch 网桥。
OpenShift 使用 虚拟以太网设备 (veth) 将容器集连接到 br0 网桥。veth 设备提供一对互连的接口:发送到一端的网络数据包由另一端接收。
OpenShift 为每个容器集创建一个 veth 设备,一端连接到容器集内的 eth0 接口,另一端则连接到 br0 网桥。
节点上的 tun0 接口是 br0 网桥上的 Open vSwitch 端口。OpenShift 使用该接口进行外部集群访问。OpenShift 通过组合使用网络路由、Netfilter NAT 规则和 br0 流表中的条目来配置通过 tun0 进行的外部访问。
OpenShift 使用节点上的 vxlan_sys_4789 接口或者 br0 中的 vxlan0 来构建节点之间的集群覆盖网络。不同节点上容器集之间的通信将经由这个接口。
配置出口防火墙
出口防火墙也是通过配置networkpolicy实现:
cat firewall.yaml
kind: EgressNetworkPolicy
apiVersion: v1
metadata:
name: myfirewall
spec:
egress:
- to:
cidrSelector: 192.168.12.0/24
type: Allow
- to:
dnsName: db-srv.example.com
type: Allow
- to:
dnsName: analytics.example.com
type: Allow
- to:
cidrSelector: 0.0.0.0/0
type: Deny
此对象允许出口流量传输到 192.168.12.0/24 网络,再传输到 db-srv.example.com 和 analytics.example.com 系统。最后一条规则拒绝所有其他流量。
由于 OpenShift 在没有规则匹配的情况下允许流量,并按顺序检查规则,因此最后一条规则充当“全部拒绝”默认值。规则仅作用于出口流量,不影响容器集间通信。
使用出口防火墙时有几个限制:
只有集群管理员才能创建 EgressNetworkPolicy 对象。项目成员或项目管理员无法在其项目中定义出口防火墙。
OpenShift 必须使用 ovs-multitenant 或 ovs-networkpolicy SDN 插件。
您无法在 OpenShift default 项目中定义出口防火墙。
每个项目只能定义一个 EgressNetworkPolicy 对象。
Egress 路由器
当容器尝试访问外部网络时,数据包将从容器集流到 br0 网桥,再到发生 NTA 的 tun0 接口,然后流到外部服务。从该服务的角度来看,连接源自OCP节点 IP 地址。
如果 OpenShift 将容器集重新放置到另一个节点,或者在多个节点上复制容器集,则外部服务可能会看到多个源 IP 地址。
因此,当防火墙保护服务时,您需要授权所有 OpenShift 节点 IP 地址。如果向集群添加新节点,则还需要更新防火墙规则。这会带来极大的困扰。
通过使用 OpenShift 出口路由器,您可以向防火墙和外部服务提供唯一可识别的源 IP 地址。
出口路由器是在项目中运行的特定容器集。它充当您的容器集和外部服务之间的代理。路由器容器集有两个网络接口:
eth0 ,用于和其他集群容器集通信
-
macvlan0 ,用于和外部服务通信
Macvlan 接口是特殊的接口,它直接将节点接口公开给容器。该接口具有底层网络可见的 MAC 地址。
出口路由器的运行模式可以是以下三种之一:重定向、HTTP 代理或 DNS 代理。下表介绍并且比较了这些模式。
重定向模式 | HTTP 代理模式 | DNS 代理模式 | |
---|---|---|---|
容器镜像 | openshift3/ose-pod |
openshift3/ose-egress-http-proxy |
openshift3/ose-egress-dns-proxy |
技术 | Netfilter NAT 规则 | Squid | HAProxy |
支持的协议 | TCP 和 UDP | HTTP 和 HTTPS | TCP |
通过路由器代理请求所需的应用更新 | 将外部服务的 IP 地址或名称替换为路由器前面的 OpenShift 服务的名称。 | 定义 http_proxy 或 https_proxy 环境变量。 |
将外部服务的 IP 地址或名称替换为路由器前面的 OpenShift 服务的名称。 |
出口静态 IP 地址
可以在项目级别的 NetNamespace 对象中定义静态 IP 地址。使用这种配置时,发送自项目中容器集的所有出口流量都源自于该 IP 地址。
与出口路由器不同,使用出口 IP 地址不会启动容器集,您也不必修改应用来通过路由器代理流量。
但是,为外部访问启用静态 IP 地址时有几个限制:
只有集群管理员才能在项目的 NetNamespace 对象中定义地址。
OpenShift 必须使用 ovs-networkpolicy SDN 插件。
oc patch netnamespace myproject \-p '{"egressIPs": ["172.25.250.19"]}'
netnamespace.network.openshift.io/myproject patched