【容器平台】Kubernetes网络策略101

Chinese, Simplified

什么是Kubernetes网络策略?

有几家公司正在将他们的整个基础设施转移到Kubernetes。Kubernetes的目标是抽象通常在现代IT数据中心中找到的所有组件。因此,pods表示计算实例,网络插件提供路由器和交换机,卷弥补SAN(存储区域网络),等等。但是,网络安全呢?在数据中心中,这由一个或多个防火墙设备处理。在Kubernetes中,我们有网络策略。

要在Kubernetes集群中应用NetworkPolicy定义,网络插件必须支持NetworkPolicy。否则,您应用的任何规则都是无用的。支持NetworkPolicy的网络插件包括Calico, Cilium, Kube-router, Romana和Weave Net。

大多数网络插件在OSI模型的网络层(第3层)上工作。然而,你可能会发现一些模型也在其他层上工作(例如,第4层和第7层)。

您是否需要在集群中定义NetworkPolicy资源?默认的Kubernetes策略允许pods接收来自任何地方的流量(这些被称为非隔离的pods)。因此,除非您处于开发环境中,否则肯定需要适当的NetworkPolicy。

您的第一个NetworkPolicy定义

NetworkPolicy资源使用标签来确定它将管理哪些pods。资源中定义的安全规则应用于pods组。这与云提供商用于在资源组上执行策略的安全组的工作原理相同。

在第一个示例中,我们将使用NetworkPolicy来定位具有app=backend 标签的pods。这些pods将被隔离在进入(进来)和出口(出去)流量一旦规则被应用。

该策略强制要求,在端口3000上,Pods可以接收来自相同名称空间(默认)的其他Pods的流量,只要:

  • Traffic is from IPs in block 182.213.0.0/16
  • The client pod is in a namespace that is labeled project=mywebapp.
  • The client pod is labeled app=frontend and it is in the same namespace (default).

所有其他进入流量将被拒绝。

允许在端口80上的IP范围为30.204.218.0/24。所有其他出口交通将被拒绝。

解决这些需求的NetworkPolicy定义文件如下所示:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-network-policy
  namespace: default
spec:
  podSelector:
	matchLabels:
  	app: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
	- ipBlock:
    	cidr: 182.213.0.0/16
	- namespaceSelector:
    	matchLabels:
      	project: mywebapp
	- podSelector:
    	matchLabels:
      	app: frontend
	ports:
	- protocol: TCP
  	port: 3000
  egress:
  - to:
	- ipBlock:
    	cidr: 30.204.218.0/24
	ports:
	- protocol: TCP
  	port: 80

下面是该网络策略的可视化。

kubernetes network policy example

如何使用选择器调整网络策略?

允许或拒绝来自特定或多个来源的通信流的情况有很多。对于您希望允许流量到达的目的地,情况也是如此。Kubernetes NetworkPolicy资源为您提供了一组丰富的选择器,您可以使用这些选择器按照您想要的方式保护您的网络路径。NetworkPolicy选择器可用于选择源连接(入口)和目标连接(出口)。它们是:

  • podSelector:选择相同名称空间中的pods,该名称空间在NetworkPolicy定义的元数据部分中定义。通过pod标签进行选择。
  • namespaceSelector:通过它的标签选择一个特定的名称空间。该名称空间中的所有pods都是匹配的。
  • podSelector与namespaceSelector组合:组合后,您可以在带有特定标签的名称空间中选择带有特定标签的pods。例如,假设我们希望将传入数据库(app=db)的流量限制为仅在一个名为env=prod的名称空间中的pods。此外,pod必须具有app=web。NetworkPolicy定义中用于实现此目的的入口部分如下:
ingress:
 - from:
    - namespaceSelector:
       matchLabels:
         env: prod
     podSelector:
       matchLabels:
         app: web

 

请注意

您可能想知道:Kubernetes是否将其规则与AND或or操作符结合?这取决于规则是在单个数组项中,还是在多个数组项中。无论定义是在YAML还是JSON中,这都是一样的。在本文中,我们将讨论YAML。因此,在上面的代码片段中,我们将namespaceSelector和podSelector都放在一个项中(在YAML中,数组项用破号' - '表示)。因此,Kubernetes将把这两个规则与AND操作符结合起来。换句话说,传入的连接必须匹配这两个规则才能被接受。

另一方面,如果我们将上面的代码段写成

ingress:
 - from:
    - namespaceSelector:
       matchLabels:
         env: prod
     podSelector:
       matchLabels:
         app: web

Kubernetes将把这两个规则与OR操作符结合起来。这意味着将允许名称空间中标记为“env=production”的任何pod。同样,在同一个NetworkPolicy命名空间中,任何标签为app=web的pod都是允许的。在定义NetworkPolicy规则时,这是一个非常重要的区别。

  • ipBock:在这里,您可以定义哪些IP CIDR块是所选pods连接的源或目的地。传统上,这些ip位于集群外部,因为pods的ip时间很短,随时都可能更改。

您应该知道,根据所使用的网络插件,在数据包被NetworkPolicy规则分析之前,源IP地址可能会改变。一个示例场景是云提供商的负载均衡器将包的源IP替换为它自己的。

ipBlock还可以用来阻止允许范围内的特定ip。这可以使用except关键字来完成。例如,我们可以允许来自182.213.0.0/16的所有流量,但是拒绝182.213.50.43。这种配置的代码片段如下:

- ipBlock:
      cidr: 182.213.0.0/16
      except:
      - 182.213.50.43/24

如您所见,您可以在excepted数组中添加多个IP地址甚至范围作为项。

常见的Kubernetes NetworkPolicy用例

本文的其余部分将讨论在集群中使用NetworkPolicy的一些常见用例。

拒绝没有规则的进入流量

有效的网络安全规则首先在默认情况下拒绝所有流量,除非明确允许。这就是防火墙的工作原理。默认情况下,Kubernetes认为任何没有被NetworkPolicy选择的pod都是“非隔离的”。这意味着所有进出交通都是允许的。因此,在默认情况下拒绝所有流量是一个很好的基础,除非NetworkPolicy规则定义了应该通过哪些连接。拒绝所有接入流量的NetworkPolicy定义如下:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: default
  name: ingress-default-deny
spec:
  podSelector: {}
  policyTypes:
  - Ingress

应用此策略的结果是,除非另一条规则允许,否则“默认”名称空间中的所有pods将不接受任何流量。可以通过NetworkPolicy的元数据部分根据需要更改名称空间。

请注意,这并不影响出口流量,出口流量必须通过其他规则进行控制,我们稍后将对此进行讨论。

否认没有规则的出口流量

我们也在做同样的事情,只是在出口交通上。以下NetworkPolicy定义将拒绝所有流出流量,除非另有规则允许:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-default-deny
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

您可以将这两种策略组合在一个定义中,该定义将拒绝所有进入和出口流量,如下所示:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: default
  name: ingress-egress-deny
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

只允许所有进口流量

您可能想要覆盖限制对pods通信的任何其他NetworkPolicy,也许是为了解决连接问题。这可以通过应用以下NetworkPolicy定义来实现:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ingress-default-allow
  namespace: default
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

这里唯一的区别是我们添加了一个没有任何规则的ingress对象。

但是请注意,此策略将覆盖同一名称空间中的任何其他隔离策略。

只允许所有出口交通

就像我们在入口部分所做的一样,有时您希望排他性地允许所有出口流量,即使其他一些策略拒绝它。以下网络策略将覆盖所有其他出口规则,并允许从所有吊舱到任何目的地的所有流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: default
  name: egress-default-allow
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

 

在所有情况下,您都可以使用前面讨论过的podSelector来修改允许-所有-否定-所有规则来匹配特定的pods。

TL;DR

Kubernetes使用NetworkPolicy资源来履行传统数据中心中常见的防火墙角色。NetworkPolicy很大程度上依赖于网络插件的功能。

NetworkPolicy定义可以在一个名称空间中的所有pods上工作,也可以使用选择器将规则应用到带有特定标签的pods上。

通过入口和出口规则,您可以定义从/到的传入或传出连接规则:

  • 带有特定标签的Pods (podSelector)
  • 属于具有特定标签的名称空间的Pods (namespaceSelector)
  • 结合这两种规则,将选择范围限制在带标签的名称空间中带标签的pods。
  • IP范围。通常,它们作为pods是外部ip。根据定义,ip是不稳定的。

网络策略选择的Pods被称为“隔离的”。那些不匹配的称为“非孤立”。Kubernetes允许非隔离舱接受所有的出口和入口交通。出于这个原因,建议对进出流量执行默认的“拒绝所有”策略,这样未被任何NetworkPolicy匹配的pods将被锁定,直到它们被匹配为止。

 

原文:https://www.magalix.com/blog/kubernetes-network-policies-101

本文:http://jiagoushi.pro/node/1189

讨论:请加入知识星球【首席架构师圈】或者加小号【jiagoushi_pro】或者QQ群【11107777】

SEO Title
Kubernetes Network Policies 101