一文吃透K8s 网络策略 NetworkPolicy !别再裸奔了!

837 阅读3分钟

一、为什么你需要 NetworkPolicy?

Kubernetes 默认情况下,Pod 与 Pod 之间的网络是完全开放的。这虽然利于通信,但从安全的角度来看极其危险,特别是在以下场景中:

  • 多租户集群,不同业务线之间需要隔离;
  • 防止横向移动攻击(Lateral Movement);
  • 金融/政企场景有合规要求(如等保三级);
  • 需要精细控制哪些 Pod 能访问数据库等敏感服务。

NetworkPolicy 就是 K8s 提供的“东向流量控制机制” ,能精细控制网络访问权限,防止“Pod 裸奔”。


二、NetworkPolicy 是什么?

NetworkPolicy 是一种 Kubernetes 资源,用来控制:

  • 哪些 Pod 可以访问其他 Pod;
  • 哪些命名空间或 IP 范围可以访问特定 Pod;
  • 控制入站(Ingress)和出站(Egress)网络流量。

重要前提:需要网络插件支持(如 Calico、Cilium、Weave Net)。K8s 原生并不强制执行 NetworkPolicy


三、语法结构详解

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-app-access
spec:
  podSelector:       # 选中“被访问”的 Pod
    matchLabels:
      role: db
  policyTypes:
    - Ingress
  ingress:           # 定义“谁可以访问”
    - from:
        - podSelector:
            matchLabels:
              role: api

逐项解释:

  • podSelector:选中哪些 Pod 受本策略保护;
  • policyTypes:定义策略类型,常见为 Ingress(进入)或 Egress(出去);
  • ingress.from:指定允许哪些来源访问该 Pod。

四、实战场景一:只允许特定 Pod 访问数据库

目标:只有 role=api 的 Pod 能访问 role=db 的 Pod。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-only-api
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: api

效果:非 API Pod 将无法访问 DB,即使在同一命名空间。

注意:一旦为某 Pod 应用了 NetworkPolicy,没有明确“允许”的来源,其余访问会被默认拒绝


五、实战场景二:跨命名空间访问控制

目标:允许来自 namespace: team-a 的 role=frontend 访问 namespace: team-b 的 role=backend。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: team-b
spec:
  podSelector:
    matchLabels:
      role: backend
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: team-a
          podSelector:
            matchLabels:
              role: frontend

用法要点:

  • namespaceSelector 控制跨 NS;
  • podSelector 控制具体 Pod;
  • 必须部署在目标命名空间(即被访问方所在 NS)。

六、实战场景三:禁止 Pod 访问外网(Egress)

目标:防止某些 Pod 访问公网,只允许访问内网资源(如内部 API)。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-egress
spec:
  podSelector:
    matchLabels:
      app: secure-service
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/8  # 仅允许访问内网

无此策略时,Pod 可随意访问公网!这在金融、运营商行业中风险极大。


七、测试 NetworkPolicy 的正确姿势

✅ 推荐使用以下方式测试是否生效:

  1. 使用 busybox 容器作为 curl 测试器:
kubectl run curl --rm -it --image=busybox:1.28 --restart=Never -- sh
  1. 进入容器内部:
wget --spider http://myservice.default.svc.cluster.local
  1. 根据返回的连接结果判断策略是否生效。

八、常见误区与最佳实践

误区/问题正确做法
忽略网络插件是否支持使用如 Calico、Cilium 这类支持 NetworkPolicy 的插件
写了策略没生效确认是否选择了正确的 podSelector 和 namespaceSelector
想“禁止所有访问”却放开了默认值一旦启用策略,需要显式写出所有允许的访问规则
将 NetworkPolicy 写在错误命名空间策略必须部署在被保护 Pod 所在命名空间
使用 subnet IP 而不是服务名尽量使用 K8s Service 名称作为目标而非裸 IP,避免漂移

九、总结:掌握 K8s 网络策略的核心要点

维度建议实践
启用网络插件使用支持 NetworkPolicy 的 CNI 插件
最小权限原则只允许必要的通信,默认拒绝其他访问
Ingress + Egress 配合使用控制内外流量,提升安全性
多策略组合一组 Pod 可匹配多个策略,注意覆盖顺序
版本控制与 GitOps 管理推荐将 NetworkPolicy 纳入版本控制