k8s中Network Policy的实现原理

188 阅读4分钟

在 Kubernetes 中,Network Policy 是一种用于控制 Pod 之间网络流量的机制。它允许你定义哪些流量可以进入或离开某个 Pod,从而在网络层面上进行细粒度的流量控制。Kubernetes 本身并不直接实现 Network Policy,而是依赖于网络插件(如 CalicoCiliumWeave 等)来实施这些策略。

Network Policy 的基本原理

  1. 网络插件支持

    • Kubernetes 的网络策略由网络插件实现。不同的插件有不同的实现方式,但所有插件都遵循 Kubernetes 提供的 NetworkPolicy API 规范。
    • 例如,Calico、Cilium 和 Weave 都支持 Network Policy,并在其内部实现了策略的拦截和执行。
  2. 选择器(Selector)

    • Pod Selector:Network Policy 使用标签选择器(Label Selector)来选择应用此策略的 Pod。通常使用 matchLabelsmatchExpressions 来定义目标 Pod。
    • Namespace Selector:除了 Pod 选择器,Network Policy 还可以选择基于命名空间的流量。例如,可以指定来自特定命名空间的流量。
    • 通过这些选择器,Network Policy 确定哪些 Pod 允许或拒绝流量。
  3. 入站(Ingress)和出站(Egress)规则

    • Ingress:指定哪些流量可以进入匹配的 Pod。Ingress 规则定义了允许从哪些源 IP 地址或 Pod 进入 Pod。
    • Egress:指定哪些流量可以从匹配的 Pod 出去。Egress 规则定义了允许 Pod 向哪些目的地址或 Pod 发送流量。
    • 这些规则允许对流量进行细粒度控制,可以基于源地址、目标地址、端口等进行限制。
  4. 允许和拒绝规则

    • 默认情况下,所有 Pod 都能与集群中的其他 Pod 通信,但如果定义了 Network Policy,它会显式地控制哪些流量可以进出 Pod。
    • 允许:可以通过 Network Policy 允许某些流量。
    • 拒绝:Network Policy 允许通过选择器指定的规则拒绝流量。如果没有匹配到规则的流量,将被拒绝。

Network Policy 的工作流程

  1. 定义 Network Policy

    • Network Policy 通常通过 YAML 配置文件来定义。它包括 Ingress 和 Egress 规则,以及匹配标签选择器(selectors)来选择 Pod。

    示例 Network Policy YAML:

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-nginx
      namespace: default
    spec:
      podSelector:
        matchLabels:
          app: nginx
      ingress:
      - from:
        - podSelector:
            matchLabels:
              app: frontend
      egress:
      - to:
        - podSelector:
            matchLabels:
              app: backend
      policyTypes:
      - Ingress
      - Egress
    

    这个示例表示:

    • 只有带有标签 app: nginx 的 Pod 可以接受来自标签为 app: frontend 的 Pod 的流量。
    • 这些 Pod 也可以向标签为 app: backend 的 Pod 发送流量。
  2. 插件拦截和实施

    • 网络插件通过在节点上配置

      iptables

      eBPF

      规则来实现 Network Policy 的功能。

      • iptables:某些插件(如 Calico)使用 iptables 来拦截和过滤网络流量,根据 Network Policy 定义的规则进行控制。
      • eBPF:现代的网络插件(如 Cilium)可能会使用 eBPF(扩展的 BPF,Berkley Packet Filter)技术,以更高效的方式处理流量。
  3. 策略传播和执行

    • 当网络策略(Network Policy)被创建或更新时,网络插件会立即重新计算流量规则并将其应用到相应的网络接口或路由表上。
    • 网络插件会根据规则在 网络层 对 Pod 的流量进行控制,允许符合条件的流量进入或离开 Pod,同时阻止不符合条件的流量。
  4. 默认行为

    • 如果集群没有任何 Network Policy,则所有 Pod 默认是 无约束的,即 Pod 之间的通信是完全开放的。
    • 一旦应用了任何 Network Policy,默认的行为变为 拒绝所有流量,除非显式地允许流量。这意味着如果没有规则指定某些流量,可以访问某个 Pod,则该流量将被拒绝。

例子:如何使用 Network Policy

假设我们有以下场景:

  1. Pod A:标签 app=frontend
  2. Pod B:标签 app=backend

我们希望 frontend Pod 可以与 backend Pod 通信,但 backend Pod 不允许与 frontend 以外的 Pod 通信。

定义 Network Policy:

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

这个策略做了以下事情:

  • 允许标签为 app: frontend 的 Pod 向标签为 app: backend 的 Pod 发送流量。
  • 除了 frontend Pod,其他 Pod 都无法访问 backend Pod。

网络策略的关键点总结

  1. 默认拒绝所有流量:没有 Network Policy 时,Pod 之间默认是开放的;有 Network Policy 后,默认拒绝所有流量,除非显式允许。
  2. 支持细粒度控制:可以基于 Pod 标签、命名空间标签、IP 地址等来定义流量控制规则。
  3. 网络插件依赖:Network Policy 的实际执行是依赖于 Kubernetes 集群中使用的网络插件,插件负责将策略转化为底层的网络规则(如 iptableseBPF)。
  4. 策略类型:可以定义 IngressEgress 策略来分别控制入站和出站流量。

结论

Kubernetes 中的 Network Policy 提供了灵活、细粒度的网络流量控制,能够在集群内部有效地隔离不同 Pod 和服务的通信。它通过网络插件将高层定义的策略转化为底层的网络配置,从而实现流量控制。