本文已超过一年。较旧的文章可能包含过时内容。请检查页面信息自发布以来是否已不再准确。
在 Kubernetes 中强制执行网络策略
编者注: 本文是关于 Kubernetes 1.8 新特性的系列深度文章之一。
Kubernetes 现在提供了使用网络策略来强制执行 Pod 之间通信规则的功能。此特性在 Kubernetes 1.7 中已稳定,并可用于支持它的网络插件。Kubernetes 1.8 版本为此特性增加了更好的能力。
网络策略:它意味着什么?
在采用默认设置配置的 Kubernetes 集群中,所有 Pod 都可以互相发现并通信,不受任何限制。新的 Kubernetes 对象类型 NetworkPolicy 允许你允许或阻止流向 Pod 的流量。
如果你在 Kubernetes 集群中运行多个应用或与多个团队共享一个集群,那么一个安全最佳实践是创建防火墙,允许 Pod 相互通信,同时阻止其他网络流量。网络策略对应于虚拟机世界中的安全组概念。
如何将网络策略添加到我的集群?
网络策略由网络插件实现。这些插件通常在你的集群中安装一个叠加网络来强制执行配置的网络策略。许多网络插件,包括 Calico、Romana 和 Weave Net,都支持使用网络策略。
Google Container Engine (GKE) 在使用以下命令创建集群时,也使用 Calico 网络插件为网络策略提供 Beta 支持
gcloud beta container clusters create --enable-network-policy
如何配置网络策略?
安装实现网络策略的网络插件后,你需要创建一个类型为 NetworkPolicy 的 Kubernetes 资源。此对象描述了两组基于标签的 Pod 选择器字段,匹配:
- 网络策略应用于的 Pod 集(必需)
- 允许相互访问的 Pod 集(可选)。如果你省略此字段,则不匹配任何 Pod;因此,不允许任何 Pod 访问。如果你指定一个空的 Pod 选择器,它将匹配所有 Pod;因此,允许所有 Pod 访问。
示例:限制流向 Pod 的流量
以下网络策略示例阻止了所有流向一组 Web 服务器 Pod 的集群内流量,但策略配置允许的 Pod 除外。
要实现此设置,请使用以下清单创建 NetworkPolicy
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
app: foo
应用此配置后,只有标签为 app: foo 的 Pod 才能与标签为 app: nginx 的 Pod 通信。有关更详细的教程,请参阅Kubernetes 文档。
示例:默认限制所有 Pod 之间的流量
如果你将 spec.podSelector 字段指定为空,则网络策略匹配的 Pod 集将是命名空间中的所有 Pod,默认阻止所有 Pod 之间的流量。在这种情况下,你必须显式创建网络策略,白名单允许 Pod 之间的所有通信。
你可以通过在你的 Kubernetes 集群中应用以下清单来启用这样的策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector:
其他网络策略特性
除了前面的示例,你可以让 Network Policy API 强制执行更复杂的规则
- 出口网络策略 (Egress network policies):在 Kubernetes 1.8 中引入,你可以限制你的工作负载与指定 IP 范围之外的资源建立连接。
- IP 块支持:除了使用 podSelector/namespaceSelector,你还可以使用 CIDR 块指定 IP 范围,以允许/拒绝入站 (ingress) 或出站 (egress) 规则中的流量。
- 跨命名空间策略 (Cross-namespace policies):使用 ingress.namespaceSelector 字段,你可以对集群中特定或所有命名空间强制执行网络策略。例如,你可以创建特权/系统命名空间,即使默认策略是阻止流量,它们也可以与 Pod 通信。
- 限制特定端口的流量:使用 ingress.ports 字段,你可以指定策略要强制执行的端口号。如果你省略此字段,策略将默认匹配所有端口。例如,你可以使用此功能允许监控 Pod 仅查询应用的监控端口号。
- 单个策略上的多个入站规则 (Multiple ingress rules on a single policy):由于 spec.ingress 字段是一个数组,你可以使用同一个 NetworkPolicy 对象,通过不同的 Pod 选择器赋予对不同端口的访问权限。例如,一个 NetworkPolicy 可以有一个入站规则,授予标签为 kind: monitoring 的 Pod 访问端口 9000 的权限,并有另一个入站规则,授予标签为 app: foo 的 Pod 访问端口 80 的权限,而无需创建额外的 NetworkPolicy 资源。