2. NetworkPolicy基础概念:Pod选择器、Ingress/Egress规则、策略类型

聊到K8s网络策略,我见过不少团队第一反应就是「哦,就是那个防火墙嘛」。嗯,这么说也没错,但K8s的NetworkPolicy跟传统防火墙有个本质区别——它不关心IP,只关心标签。说白了,它是面向Pod的,不是面向网段的。

我个人习惯把NetworkPolicy理解成「Pod之间的门禁系统」。你想想看,在物理世界里,门禁卡只认人,不认你穿什么颜色的衣服。NetworkPolicy也一样,它只认Pod的标签,不认Pod的IP地址。这个设计理念,其实挺巧妙的。

2.1 Pod选择器:策略的「门禁卡」

Pod选择器(podSelector)是NetworkPolicy的核心。它决定了这条策略管哪些Pod。我记得刚接触K8s网络策略时,总以为策略是配给Namespace的,后来才发现——策略是配给Pod的。

来看一个最简单的例子:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-only-api
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: vllm-server
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api-gateway

这段配置的意思是:只有打了app: api-gateway标签的Pod,才能访问打了app: vllm-server标签的Pod。其他Pod?统统拦在外面。

关键点:podSelector如果不写,默认匹配Namespace下所有Pod。但我不建议你这么干——太粗放了,容易误伤。

我在项目中遇到过一个问题:有个团队给vLLM服务配了NetworkPolicy,但忘了给Pod打标签。结果策略配上去后,所有流量都被拒绝了。排查了半天,最后发现是标签没对上。嗯,这种坑踩过一次就记住了。

2.2 Ingress规则:谁可以进来

Ingress规则控制「入站流量」——也就是谁可以访问你的Pod。对于vLLM推理服务来说,通常只有API网关和监控系统需要访问它。

Ingress规则支持四种来源匹配方式:

匹配方式 作用范围 典型场景
podSelector 同Namespace 允许API网关访问vLLM
namespaceSelector 跨Namespace 允许monitoring命名空间的Prometheus抓取指标
ipBlock 外部IP 允许特定CIDR的客户端访问
混合匹配 组合使用 同时限制Namespace和Pod

这里有个容易踩的坑:namespaceSelectorpodSelector同时使用时,默认是「与」的关系。什么意思呢?就是流量必须同时满足两个条件才能通过。我曾经见过有人以为这是「或」的关系,结果配了半天流量就是过不去。

我的建议:如果想让两个条件是「或」的关系,把它们分别写在不同的from条目里。每个from条目内部是「与」,条目之间是「或」。

2.3 Egress规则:可以出去找谁

Egress规则控制「出站流量」——也就是你的Pod可以访问谁。对于vLLM服务来说,它可能需要访问模型存储(比如S3)、日志服务、DNS等。

我曾经遇到一个案例:vLLM服务启动后一直报错,说模型加载失败。排查了半天,发现是Egress规则把访问S3的流量给拦了。嗯,这种问题其实挺常见的——大家往往只关注入站规则,忘了出站规则也会卡脖子。

一个典型的Egress配置长这样:

spec:
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8
        except:
        - 10.96.0.0/12  # 排除ClusterIP网段
    ports:
    - protocol: TCP
      port: 443
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

这个配置允许vLLM访问内网HTTPS服务(443端口),以及kube-system命名空间下的DNS服务(53端口)。其他出站流量?全部拒绝。

避坑指南:我曾经见过有人把Egress规则配得太死,结果Pod连DNS都解析不了。记住:如果启用了Egress规则,一定要把DNS服务放行,否则Pod连域名都解析不了。

2.4 策略类型:Ingress、Egress还是两者都要

policyTypes字段决定了这条策略管哪类流量。它有两个可选值:IngressEgress。可以只选一个,也可以两个都选。

这里有个容易忽略的细节:

  • 如果只写policyTypes: [Ingress],那这条策略只管入站流量
  • 如果只写policyTypes: [Egress],那这条策略只管出站流量
  • 如果两个都写,或者不写(默认两个都生效),那就都管

我个人习惯是显式声明policyTypes,哪怕默认值是对的。为什么?因为代码可读性。你想想看,半年后你回来看这段配置,显式声明比靠猜默认值要靠谱得多。

2.5 默认策略:你不配,我就全放行

K8s的默认行为是「没有NetworkPolicy时,所有流量都放行」。但一旦给某个Pod配了NetworkPolicy,没被显式允许的流量就会被拒绝。

这个设计其实挺合理的——默认开放,按需收紧。但我在生产环境中见过太多因为忘记配策略导致的安全事故。所以我的建议是:

最佳实践:给每个Namespace配一条「默认拒绝所有入站流量」的策略,然后再按需放行。这样即使忘了配具体策略,也不会裸奔。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}  # 匹配所有Pod
  policyTypes:
  - Ingress
  # 没有ingress规则,默认拒绝所有入站流量

2.6 本章知识体系

下面这张图总结了NetworkPolicy的核心逻辑,我画出来方便你理解:

NetworkPolicy 核心逻辑 Pod选择器 策略类型 Ingress规则 控制谁可以访问我的Pod Egress规则 控制我的Pod可以访问谁 podSelector namespaceSelector ipBlock 混合匹配 默认行为:没有NetworkPolicy时,所有流量放行

这张图把NetworkPolicy的核心逻辑串起来了:先选Pod,再定策略类型,最后配具体规则。规则里又分四种匹配方式。记住这个流程,配策略时就不容易漏东西。

一句话总结:NetworkPolicy就是「选Pod → 定方向 → 配规则」三步走。别想复杂了。


公众号:蓝海资料掘金营,微信deep3321