【容器平台】Kubernetes网络策略101
什么是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 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】
- 42 次浏览