🚨Kubernetes安全警报!只知道Label就能保证服务安全吗? (深入解析Cilium网络策略)

大家好!今天我们将深入探讨Cilium的网络策略(Network Policy),这是一个在复杂Kubernetes环境中保护我们服务的强大工具。

在使用Kubernetes时,大量的Pod会相互通信。如果不明确控制“哪个Pod可以与谁通信”,那么安全性可能会变得脆弱,就像一栋所有门都敞开的公寓一样。😟

这时,网络策略就登场了!其中,Cilium的网络策略以其eBPF技术带来的强大性能和功能而自豪,它是如何运作的呢?核心就在于“Label”和“Selector”。


🌍 全局视角:为什么需要网络策略?

首先,让我们从宏观角度来看。在Kubernetes中,网络策略可以简单地理解为控制Pod组之间流量的防火墙规则。

默认情况下,Kubernetes集群中的所有Pod都可以自由地相互通信。然而,在实际运营服务时,这种配置是非常危险的。💣

例如,支付-API Pod需要与订单-服务 Pod通信,但完全不需要与不相关的登录-UI Pod通信。如果登录-UI Pod被黑客入侵,在没有网络策略的情况下,攻击者可以轻易地通过内部网络访问支付-API。

Cilium网络策略正是为了防止这种情况发生,它允许我们非常精细地定义允许哪些Pod(Endpoint)接收或发送哪些流量(Ingress/Egress)。


🎯 核心原理:如何选择“谁”?Label & Namespace Selectors

Cilium网络策略的核心在于“Selector(选择器)”机制,它决定了“将此策略应用于哪个Pod?”以及“允许来自哪个Pod/命名空间的流量?”

Cilium为此使用了两种主要的选择器。

1. endpointSelector:精确选择策略应用的目标

endpointSelector选择将应用此网络策略规则的Pod(Cilium中称之为端点)。这就像命令“此防火墙规则只应用于带有’class: backend’标签的服务器!”一样。

这里正是“Label Selector”发挥作用的地方。它可以根据Pod上附加的Label精确地选择策略目标。

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: backend-api-policy
spec:
  endpointSelector:
    matchLabels:
      app: backend
      tier: api
  # ... 现在为这些Pod定义规则。

在上面的示例中,同时具有app=backend和tier=api这两个标签的Pod将成为此策略的应用对象。

2. namespaceSelector:指定允许通信的“区域”(Namespace)

选择了要应用策略的Pod之后,接下来需要确定允许哪些流量,对吧?此时,如果想允许来自整个特定命名空间的流量,就可以使用“Namespace Selector”。

它用于ingress(入站)或egress(出站)规则中,可以创建诸如“我信任并接受来自带有’team: monitoring’标签的命名空间的所有流量!”之类的规则。

# ... (在endpointSelector之后)
  ingress:
  - fromEndpoints:
    - matchLabels:
        # 选择同一命名空间内的特定Pod
        app: frontend
  - fromCIDR:
    - "10.0.0.0/8"
  - toPorts:
    - ports:
      - port: "8080"
        protocol: TCP

上面的代码是ingress规则的一部分。它使用fromEndpoints来允许来自同一命名空间内带有app=frontend标签的Pod的流量。

如果想选择不同的命名空间怎么办?这时namespaceSelector就派上用场了。

# ... (在endpointSelector之后)
  ingress:
  - fromEndpoints:
    # 允许来自'monitoring'命名空间中所有Pod的流量
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: monitoring

此规则允许来自带有kubernetes.io/metadata.name=monitoring标签的命名空间,即“monitoring”命名空间中所有Pod的流量。


🛠️ 通过实际代码示例理解整体流程

现在,让我们通过一个同时利用两种选择器的完整策略示例来完美理解整个流程。

场景: default命名空间中的app=backend-db Pod只想允许来自带有app=api-server标签的Pod的6379/TCP端口流量。

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: db-access-policy
  namespace: default
spec:
  # 1. 选择策略应用目标 (Label Selector)
  # 将此策略应用于带有'app=backend-db'标签的Pod。
  endpointSelector:
    matchLabels:
      app: backend-db

  # 2. 定义入站(Ingress)规则
  ingress:
  - fromEndpoints:
      # 3. 选择允许的通信源 (Label Selector)
      # 只允许来自带有'app=api-server'标签的Pod的流量。
      - matchLabels:
          app: api-server
    # 4. 定义允许的端口和协议
    toPorts:
    - ports:
      - port: "6379"
        protocol: TCP

通过这一个YAML文件,我们就能以非常清晰和声明式的方式控制Pod之间的通信。


🤔 等等,为什么其他方法不行?

“为什么非要用复杂的Label?直接用Pod名称或IP指定不行吗?”

这是个好问题!但是,考虑到Kubernetes的动态环境,为什么必须使用Label就变得清晰了。

  • Pod名称 👎: Pod随时可能死亡并重新创建。(例如:部署、扩缩容、节点故障)每次Pod名称都会像backend-db-xxxx-yyyy一样改变。每次更改都修改策略几乎是不可能的。
  • IP地址 👎: Pod的IP也不是固定的。Pod重启后,大多数情况下会分配新的IP。基于IP管理策略不稳定,并且会损害Kubernetes的灵活性。

总而言之,**Label和Selector**是基于不变的“角色”和“属性”来识别目标,因此它们是Pod动态创建和销毁的云原生环境中最适合的方式。✨

Cilium网络策略的核心在于灵活运用这些**Label Selector**和**Namespace Selector**,以建立灵活而强大的安全策略。现在,您准备好将您的Kubernetes集群安全提升到一个新的水平了吗?


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注