3. 默认拒绝所有流量策略:配置方法、验证方式、常见误区

说实话,默认拒绝策略是K8s网络策略里最基础、也最容易翻车的一环。我见过太多团队,策略一配上去,vLLM服务直接断连,推理请求全挂。嗯,咱们今天就把这块掰开揉碎了讲清楚。

3.1 为什么需要默认拒绝?

K8s默认是“全通”的——所有Pod之间都能互相访问。这在开发环境还行,生产环境就有点吓人了。你想想看,一个恶意Pod只要进了集群,就能直接打到你的vLLM推理服务,这谁受得了?

默认拒绝策略,说白了就是“白名单机制”。先关掉所有入口,再一条一条放开必要的流量。我在项目中遇到过,有个团队没配默认拒绝,结果一个CI Job误打误撞把推理服务的GPU内存打爆了。从那以后,我养成了习惯:任何推理服务上线前,先配一条默认拒绝。

3.2 配置方法:两种姿势

默认拒绝策略分两种:入站(Ingress)拒绝出站(Egress)拒绝。vLLM服务通常只需要控制入站,但如果你有模型下载、日志上报等需求,出站也得管。

3.2.1 入站默认拒绝

这是最常用的。配置很简单,一个NetworkPolicy对象,selector匹配你的vLLM Pod,然后policyTypes只写Ingress,ingress留空。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
  namespace: inference
spec:
  podSelector:
    matchLabels:
      app: vllm-server
  policyTypes:
  - Ingress
  ingress: []  # 关键:空数组表示拒绝所有入站

注意这个ingress: [],它不是没写,而是明确写了一个空数组。K8s的语义是:如果ingress字段存在但为空,则拒绝所有入站流量。如果整个ingress字段都不存在,那策略就不生效。我曾经踩过这个坑,少写了一对中括号,结果策略根本没起作用。

3.2.2 出站默认拒绝

vLLM服务如果不需要访问外部,出站也可以锁死。但要注意,DNS解析需要放行,否则Pod连集群DNS都访问不了。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: inference
spec:
  podSelector:
    matchLabels:
      app: vllm-server
  policyTypes:
  - Egress
  egress: []  # 拒绝所有出站

我个人建议,出站策略先别急着配。先把入站搞明白,出站等业务稳定了再慢慢加。否则排查问题的时候,你都不知道是网络策略拦了,还是vLLM本身出了bug。

3.3 验证方式:三步走

策略配完,怎么知道它生效了?我一般分三步验证。

3.3.1 第一步:检查策略是否被应用

用kubectl看NetworkPolicy有没有创建成功,以及它匹配了多少个Pod。

kubectl get networkpolicy -n inference
kubectl describe networkpolicy deny-all-ingress -n inference

在describe的输出里,找PodSelector这一行,它会显示匹配的Pod数量。如果显示0,说明你的label写错了,策略根本没生效。

3.3.2 第二步:用测试Pod验证连通性

启动一个临时Pod,尝试访问vLLM服务。我习惯用busybox或者netshoot镜像。

kubectl run test-pod --image=busybox -n inference -- sleep 3600
kubectl exec -it test-pod -n inference -- wget -qO- http://vllm-server:8000/health

如果默认拒绝生效了,这个wget会卡住或者返回超时。如果还能通,说明策略没拦住——要么是selector没对上,要么是策略没应用到那个命名空间。

注意:测试Pod本身也要受网络策略影响。如果测试Pod所在的命名空间也有默认拒绝策略,那它可能连DNS都解析不了。建议在测试时,给测试Pod单独配一条允许策略,或者直接用hostNetwork模式。

3.3.3 第三步:检查审计日志

如果集群开启了网络审计日志(比如Cilium的Hubble或者Calico的FlowLogs),可以直接看被拒绝的流量记录。这是最靠谱的方式,因为测试Pod可能因为其他原因连不上,但审计日志能明确告诉你“这个包被NetworkPolicy拒绝了”。

# 以Cilium Hubble为例
hubble observe --namespace inference --verdict DROPPED

输出里会显示源IP、目标IP、端口,以及被哪条策略拒绝。嗯,这个信息在排查问题时特别有用。

3.4 常见误区:我踩过的坑

这部分我直接说重点,都是血泪教训。

误区一:默认拒绝策略会覆盖其他策略

很多人以为配了默认拒绝,其他放行策略就不用配了。其实不是。K8s网络策略是叠加生效的。默认拒绝只拒绝那些没有被其他策略显式允许的流量。如果你有一条策略允许某个来源访问,那默认拒绝不会拦它。

举个例子:

  • 策略A:拒绝所有入站
  • 策略B:允许来自监控命名空间的流量

最终效果:监控能访问,其他全拒绝。策略A和策略B是“与”的关系,不是“覆盖”。

误区二:默认拒绝策略只配一个方向就够了

vLLM服务通常只需要入站控制,但如果你有模型热加载、日志上报、指标采集等需求,出站也得考虑。我曾经遇到一个场景:vLLM服务需要从HuggingFace下载模型,但出站被默认拒绝了,结果Pod一直CrashLoopBackOff。排查了半天才发现是网络策略的问题。

所以我的建议是:入站默认拒绝必须配,出站按需配。不要一刀切。

误区三:策略配完就万事大吉

网络策略是动态的。你改了Pod的label,或者新增了服务,策略可能就不匹配了。我见过一个团队,vLLM服务升级时改了label前缀,结果所有策略都失效了,服务裸奔了三天才发现。

建议定期用工具(比如kube-iptables-tailer或者network-policy-validator)扫描一下,看看哪些Pod没有被任何策略覆盖。

小技巧:在vLLM的Deployment里加一个annotation,比如network-policy/version: v1,然后在NetworkPolicy的selector里匹配这个annotation。这样每次更新策略时,可以明确知道哪些Pod应该被覆盖。

3.5 核心逻辑图

下面这张图展示了默认拒绝策略的完整工作流程。从策略创建到流量拦截,再到验证放行,每一步都环环相扣。

默认拒绝策略工作流程 1. 创建NetworkPolicy podSelector + ingress: [] 2. 匹配目标Pod label匹配成功? 不匹配 → 策略不生效 3. 流量到达 入站请求 4. 策略引擎检查 是否有其他策略允许该流量? 放行 ✅ 允许策略优先级更高 拒绝 ❌ 默认拒绝生效 注意:默认拒绝只拦截未被其他策略显式允许的流量

3.6 总结

默认拒绝策略,说白了就是给vLLM服务加一道保险。配置不难,但细节很多。记住三点:

  • 入站必须配,出站按需配
  • 验证要到位,别光看kubectl get
  • 策略会叠加,不是覆盖

嗯,这块内容就这么多。下一节咱们聊聊如何精细控制vLLM的推理流量,包括如何只允许特定客户端访问、如何限制并发数等实战技巧。


专注资料整理