Kubernetes集群安全通信

NetworkPolicy是Kubernetes的一个新特性,它负责配置Pod组如何与彼此和其他网络端点进行通信。换句话说,它在运行于Kubernetes集群上的Pod间创建防火墙。

该特性在Kubernetes 1.7版中已较为稳定。本文将阐述NetworkPolicy在理论与实践中分别是如何工作的。

使用NetworkPolicy你可以做些什么

默认情况下,Kubernetes没有限制集群内pod之间的通信。这意味着集群内任意Pod之间都可以像没有防火墙一样直接进行通信。NetworkPolicy让我们可以规定有哪些Pod可以连接到其余Pod。

这些Policy可以被描述的更为细节:你可以指定哪些命名空间可以进行通信,或者更具体地说,你可以选择要执行每个Policy的端口号。

目前你不能使用这一特性强制执行来自pod的外发(出口)流量的Policy。这在Kubernetes 1.8的规划中。

同时,Istio开源项目也是一个支持出口策略和其他更多功能的替代方案。

为什么说NetworkPolicy很酷

数十年来,NetworkPolicy是用来计算ACL(访问控制列表)的独特方式。这是Kubernetes在Pod之间进行ACL的方式。就像任何其他Kubernetes资源一样,NetworkPolicy通过声明式文件配置。它们是应用程序的一部分,你可以在源存储库中对它们进行修改,并随着应用程序部署到Kubernetes中。

NetworkPolicy几乎是实时应用的。如果你在Pod之间建立了连接,则应用组织连接的NetworkPolicy将会导致连接立即被终止。这种近乎实时的好处是使网络损耗非常小。

使用案例示例

以下是NetworkPolicy一般使用案例的简单清单。

阻断到应用程序的所有流量

限制到应用程序的流量

在命名空间中阻断所有非白名单的流量

阻断来自其他命名空间的所有流量

允许来自其他命名空间的流量

允许来自外部客户端的流量

NetworkPolicy如何执行

NetworkPolicy的实现不是Kubernetes的核心功能。即使你可以提交一个NetworkPolicy对象到Kubernetes主节点,如果你的网络插件不能实现网络策略,它也不会被实现。

Google Container Engine (GCE)通过在集群中预装Calico网络插件提供了对网络策略的支持。

网络策略适用于连接,而不是网络数据包。请注意,一个连接允许网络数据包的双向传输。例如,如果Pod A可以连接到Pod B,那么Pod B会在相同的连接中响应Pod A。这并不意味着Pod B可以启动与Pod A的连接。

NetworkPolicy的结构

NetworkPolicy只是Kubernetes API的另一个对象。你可以为一个集群创建许多NetworkPolicy。一个NetworkPolicy有两个主要部分:

  1. 目标Pod:哪些Pod有通过NetworkPolicy执行的ingress网络连接?这些Pod通过它们的标签被选择。
  2. Ingress规则:哪些Pod可以连接到目标Pod?这些Pod通过它们的标签或者命名空间被选择。

如下是一个NetworkPolicy更具体的例子:

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: api
  ingress:
  - from:
      - podSelector:
          matchLabels:
            app: bookstore
  - from:
      - podSelector:
          matchLabels:
            app: inventory

这个样例Policy允许拥有app=bookstore或app=inventory标签的Pod连接到拥有app=bookstore和role=api标签的Pod。你可以这样解读它:把bookstore应用程序访问的微服务指定给bookstore的API。

如何评价NetworkPolicy

NetworkPolicy的设计文档和API reference看起来比较复杂,我设法把它分解成几个简单的规则:

  1. 如果NetworkPolicy选择了一个Pod,那么到该Pod的流量将受到限制。
  2. 如果一个Pod没有NetworkPolicy,命名空间下的所有Pod都可以连接到此Pod。这意味着如果没有为一个Pod定义NetworkPolicy,就默认“允许所有”。
  3. 如果Pod A的流量被限制,但Pod B需要连接到Pod A,这应当至少有一个NetworkPolicy选择Pod A,且它具有选择Pod B的Ingress规则。

当包含跨命名空间网络时,事情就变得有些复杂了,简而言之,它是这样工作的:

  1. NetworkPolicy可以强制执行与部署在同一命名空间下的Pod的连接的规则。
  2. Ingress规则的podSelector只能选择部署NetworkPolicy的同一命名空间中的pod。
  3. 如果Pod A需要连接另一命名空间下的Pod B,并且Pod B的网络被强制执行,则需要在Pod B中有一个具有选择Pod A的namespaceSelector的Policy。

NetworkPolicy是否安全

NetworkPolicy限制Pod到Pod的网络,这是保护集群流量和应用程序的一部分。它们不是进行深度包检测的防火墙。

你不应该只依赖于NetworkPolicy保证集群pod间的安全通信。诸如TLS(传输层安全性)与相互认证的方法使你能够加密流量并在微服务之间进行身份验证。

本文译者:平凡, 微信公众号“容器时代”: CaaSOne

K8S中文社区微信公众号