首页 / Kubernetes (k8s) 入门教程 / 网络策略 NetworkPolicy

Kubernetes (k8s) 入门教程

网络策略 NetworkPolicy

本教程共 65 篇 · 第 30 篇 · 更新于 2026-08-14 · 约 15 分钟阅读

KubernetesNetworkPolicy网络隔离网络策略东西向IngressEgress

本节目标:学会用 NetworkPolicy 给 Pod 之间的流量”上锁”。看懂入口/出口隔离、四种选择器怎么组合、默认拒绝策略怎么写,以及为什么它离不开支持策略的 CNI。

默认情况下,Kubernetes 集群里的网络是”全通”的。同一个命名空间里的 Pod 想连谁就连谁,跨命名空间也基本拦不住。这在测试环境无所谓,到了生产就成了大隐患:一个被攻破的前端 Pod,能直接摸到数据库。

NetworkPolicy(网络策略)就是用来关上这扇门的。

30-1 它工作在哪一层

NetworkPolicy 控制的是 OSI 第三层(IP)和第四层(端口)的流量,也就是 TCP、UDP、SCTP 这类。它管不了 HTTP 路径、域名这种七层东西——那是 Ingress 或服务网格的活。

它的思路是”以应用为中心”:你声明”某组 Pod 允许和哪些实体通信”,剩下的流量就被挡住。注意是被允许的才放行,不是被禁止的才拦——这是个白名单模型。

Note

NetworkPolicy 是白名单。写了一条策略后,没被明确允许的流量就会被拒绝。这点和写防火墙一样,先想清楚要放哪些。

30-2 前置条件:CNI 得支持

这是最关键的一点。NetworkPolicy 本身只是一份”声明”,真正去拦截、放行流量的,是底层的 CNI 网络插件。

如果你用的是纯 Flannel,哪怕写一百条 NetworkPolicy,流量照样全通——因为 Flannel 不实现策略处理。要用 NetworkPolicy,得选 Calico、Cilium 这类支持策略的实现。

Warning

光创建 NetworkPolicy 资源、底层却没支持的 CNI,等于贴了告示没人执行。先确认你的网络插件支持策略,否则写了也是摆设。

30-3 两种隔离:入口与出口

Pod 的隔离分两个方向:

  • 入口隔离(Ingress):控制谁能连进来。
  • 出口隔离(Egress):控制能连出去。

默认情况下,两个方向都是非隔离的,所有流量放行。一旦有某条 NetworkPolicy 选中了这个 Pod,且在 policyTypes 里写了 Ingress,那这个 Pod 的入口就被隔离了——只有策略 ingress 列表里允许的流量能进。

出口同理。而且多个策略是相加的,不会互相冲突。只要有一条允许,连接就成立;要彻底放行,源端出口策略和目的端入口策略都得放行。

30-4 一个完整的例子

下面这条策略把 default 命名空间里 role=db 的 Pod 同时做了入口和出口隔离:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - ipBlock:
            cidr: 172.17.0.0/16
            except:
              - 172.17.1.0/24
        - namespaceSelector:
            matchLabels:
              project: myproject
        - podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 6379
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978

它表达的意思是:

  • 只有这些来源能连 role=db 的 6379 端口:role=frontend 的 Pod、project=myproject 命名空间里的 Pod、以及除 172.17.1.0/24 外的 172.17.0.0/16 网段。
  • 这些数据库 Pod 只能往 10.0.0.0/24 的 5978 端口发起连接。
Tip

podSelector 不写任何 label(空选择器)就代表”选中该命名空间下的所有 Pod”。这是写默认策略的常用手法。

30-5 四种 from/to 选择器

ingress.fromegress.to 里,可以混用四种选择器挑”流量从哪来 / 到哪去”:

  1. podSelector:同命名空间内、带指定标签的 Pod。
  2. namespaceSelector:带指定标签的整个命名空间里的所有 Pod。
  3. podSelector + namespaceSelector 组合:某个命名空间里、带特定标签的 Pod。
  4. ipBlock:一组 IP CIDR,通常用于集群外部地址。

关于第 3 点有个经典坑。下面这段,namespaceSelectorpodSelector同一级的数组元素,意思是”来自 user=alice 命名空间 或 role=client 的 Pod”:

ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
    - podSelector:
        matchLabels:
          role: client

而下面这样把它们写进同一个元素,意思是更严格的”既在 user=alice 命名空间,又是 role=client 的 Pod”:

ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
      podSelector:
        matchLabels:
          role: client
Warning

缩进差一个层级,语义从”或”变成”且”。写多条件时务必用 kubectl describe 看 Kubernetes 怎么解读你的策略,别凭感觉。

30-6 默认拒绝:把门先关上

默认全通太危险,常见做法是先给命名空间上一个”默认拒绝所有入站”的策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
    - Ingress

podSelector: {} 选中所有 Pod,但 ingress 列表为空,于是没有任何入站被允许。哪怕别的策略没选中的 Pod,也被这道”兜底”挡住了。它对出口没影响。

反过来想要全放,也可以写一条允许所有入站:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
  namespace: default
spec:
  podSelector: {}
  ingress:
    - {}
  policyTypes:
    - Ingress

ingress 里一个空的 {} 表示”允许一切来源”。有了它,再叠加别的条件也不会把流量误杀。

Warning

默认拒绝所有出口会顺带把 DNS 流量也掐掉。如果你的工作负载要解析域名,必须额外写一条允许访问集群 DNS 服务的出口策略,否则 Pod 连名字都查不出来。

30-7 能精细到什么程度

NetworkPolicy 支持:

  • protocol(TCP/UDP/SCTP)区分。
  • 按端口号限制。
  • 入站、出站分别定义。
  • 多策略叠加(取并集)。

做不了的:

  • 七层内容过滤(URL、Header、域名)。
  • 对 Service VIP 做基于名字的复杂路由。
  • 加密、认证这类安全能力。

这些要靠服务网格(如 Istio、Linkerd)来补。NetworkPolicy 负责”通不通”,服务网格负责”怎么通、通得安不安全”。

30-8 调试小贴士

写完策略发现不通,先排查三件事:

  1. CNI 到底支不支持策略?(最常见的原因)
  2. 源端出口策略和目的端入口策略是否都放行了?
  3. podSelector/namespaceSelector 的标签是否真的对得上 Pod?
Tip

策略是白名单相加。连接失败往往是”有一端没放行”。用 kubectl describe networkpolicy 核对实际生效的选择器,比肉眼看 YAML 靠谱。

小结

NetworkPolicy 在三四层给 Pod 流量上白名单。它依赖支持策略的 CNI 才能真正拦流量。入口、出口两个方向独立隔离,多个策略取并集。

默认全通不安全,先用默认拒绝兜底,再逐条放行需要的流量。它管”通不通”,管不了七层细节——那是下一章南北向/东西向和服务网格的议题。