通过编辑器创建可视化Kubernetes网络策略

实现网络策略是构建基于kubernetes的安全平台的关键部分,但是从简单的示例到更复杂的现实策略的学习曲线是陡峭的。不仅要使YAML语法和格式正确,而且更重要的是,在网络策略规范的行为中有许多微妙之处(例如默认允许/拒绝、名称空间、通配符、规则组合等)。即使是经验丰富的Kubernetes YAML-wrangler也可以轻松地通过高级网络策略用例进行思考。

在过去的几年里,当我们与你们中的许多人一起在Cilium社区中执行Kubernetes网络策略时,我们已经了解了许多关于网络策略挑战的知识。今天,我们很兴奋地宣布一个新的免费工具,用于社区,帮助您Kubernetes网络策略编写旅程:editor.cilium.io

Kubernetes网络策略编辑器帮助您构建、可视化和理解Kubernetes网络策略。

  • 教程:遵循辅助教程,从还没有使用网络策略到一个良好的安全态势。
  • 互动创建:以辅助和互动的方式创建策略。
  • 可视化和更新:上传现有的策略,以验证和更好地理解它们。
  • 安全性评分:检查策略的安全性评分,以了解它们添加到集群的安全性级别。
  • YAML下载:将策略作为YAML下载,以便在您最喜欢的CNI的集群中执行。
  • 共享:通过GitHub gist在团队之间共享策略,并创建链接来可视化您自己的网络策略。
  • 自动创建策略:上传哈勃流量日志,根据观察到的网络流量自动生成网络策略。

尝试网络策略编辑器

网络策略编辑器,真的有用吗?

为了更具体地说明这一点,让我们来探讨一下在使用网络策略时遇到的5个常见问题,无论是新手还是已经使用了一段时间的人。在每个错误的背后,你会在工具中找到一个简短(3-5分钟)的教程链接,引导你完成修复错误所需的每个步骤。

错误1:没有使用命名空间选择器

考虑这样一个场景:我们希望运行在monitoring命名空间中的集中式Prometheus实例能够从运行在default命名空间中的Redis Pod中获取度量数据。请看下面的网络策略,它应用于default名称空间中。它允许标签为app=prometheus的Pods从标签为app=redis的Pods中获取度量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress-from-prometheus
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: redis
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: prometheus

正如您在编辑器的可视化中所看到的,上面的网络策略只有在两个pod位于相同名称空间中时才有效。除非显式地使用namespaceSelector来选择其他名称空间,否则podSelector的作用域是策略的名称空间。

这样做是正确的吗?

一个常见的错误可能是使用podSelector创建一个入口规则,如当前策略所示。然而,正如您在可视化中看到的,这个网络策略只允许从默认名称空间的app=prometheus输入流量。为了创建一个跨命名空间允许规则,你必须添加namespaceSelector:{}

具体答案请点击:https://editor.cilium.io/?policy-tutorial=allow-cross-namespace

错误2:不可能是DNS…

通常情况下,工作负载必须被锁定以限制外部访问(即egress默认拒绝)。如果希望防止应用程序将通信发送到除同一名称空间中的Pods之外的任何地方,可以创建以下策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-kube-dns
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: foo
  egress:
    - to:
        - podSelector: {}

然而,一旦您部署了这个网络策略,您的应用程序连接可能会中断。为什么?Pod通常会通过服务的DNS名称到达其他Kubernetes服务(例如service1.tenant-a.svc.cluster.local),解析这个名称需要Pod将出口流量发送到在kube-system名称空间中标签为k8s-app=kube-dns的Pod。

如何修复这个问题呢?

策略将添加如下网络策略出口规则:

- to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP

注意:该规则明确地只允许对Kubernetes DNS进行DNS查询,它不允许出口DNS流量到Kubernetes以外的DNS服务器。这是防止DNS流量攻击的推荐方法。

具体答案请点击:https://editor.cilium.io/?policy-tutorial=allow-kube-dns

错误3:使用传统的网络结构

如果您使用传统的网络环境,那么使用32 CIDR规则允许流量到Pod的IP地址,如kubectl描述Pod的输出所示。例如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress-to-pod
spec:
  podSelector:
    matchLabels:
      app: foo
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.2.125/32

然而,Pod ip是短暂的和不可预测的,并且取决于网络插件的实现,ipBlock规则可能只允许出口流量到集群之外的目的地。Kubernetes文档建议仅对集群外的IP地址使用ipblock。

怎么解决这个问题呢?

使用podSelector和namespaceSelector来代替ipBlock:

  • 只允许特定Pod的进出
  • 允许同一命名空间内的所有出口通信
  • 允许集群内的所有出口流量

具体答案请点击:https://editor.cilium.io/?policy-tutorial=allow-egress-to-pod

错误4:网络规则如何结合使用

让我们看一下另一个出口策略示例,该示例试图允许标签为app=foo的Pods建立到端口443上IP为192.168.1.22的外部VM的出口连接

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: egress-to-private-vm-443
spec:
 podSelector:
    matchLabels:
      app: foo
 egress:
   - to:
       - ipBlock:
           cidr: 192.168.1.22/32
   - ports:
       - port: 443

等等……虽然这是有效的YAML和有效的网络策略,但YAML中的一个额外字符带来了巨大的不同,最终允许了比我预期更多的连接。端口前面的-被解释为两个不同的规则,一个允许所有流量到VM IP(在任何端口上),另一个允许所有流量到443端口(不管IP地址是什么)。网络策略规范规定规则在逻辑上是的(而不是),这意味着Pod工作负载具有比预期更多的连接。你如何防止这些错误? 请查看如下yaml:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-to-private-vm-443
spec:
  podSelector:
    matchLabels:
      app: foo
  egress:
    - to:
        - ipBlock:
            cidr: 192.168.1.22/32
      ports:
        - port: 443

具体答案请点击:https://editor.cilium.io/?policy-tutorial=combine-policy-rules

错误5:混淆了{}的不同用法

在网络策略中,空花括号(即{})在不同的上下文中有不同的含义,这导致了很多困惑。我们将用最后一个例子作为一个小测验。这两个看起来相似的网络策略规则都利用了{},它们之间的区别是什么?猜测一下,然后在下面的网络策略编辑器中查看每条规则,看看您是否正确。

乍一看,空花括号(例如:{})可能意味着匹配所有内容。然而,这并不总是正确的;

ingress:
  - {}

空花括号在规则级别使用,它们被转换为空规则。理论上,它应该匹配所有内容:同一名称空间中的所有pod,其他名称空间中的所有pod,甚至来自或来自集群外部的通信流。然而,实际上它们只匹配集群中的所有pod,并且有效地表示了以下策略规则:

ingress:
  - from:
    - podSelector: {}
      namespaceSelector: {}

注意:它不包括ipBlock,因此该规则不会匹配任何集群外的流量。

同时,下面的规则可能看起来几乎相同:

ingress:
  - from:
    - podSelector: {}

但是,它只在相同名称空间中的pods上匹配,而不会在来自其他名称空间的输入流量上匹配。

具体答案请点击:https://editor.cilium.io/?policy-tutorial=empty-selectors

总结

希望您觉得这些示例有用,如果您有其他常见的网络策略陷阱的例子或其他有趣的策略可以与社区分享,我们将非常乐意听取您的意见。您可以随意尝试制定自己的网络策略或删除现有的策略,以可视化方式检查它们是否执行您希望它们执行的操作。


另外,送福利了,最近我准备了关于各大厂的云原生技术最佳实践资料,请点击关注如下公众号,回复【云原生】获取

本文分享自微信公众号 - 云原生技术爱好者社区(programmer_java)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章