4. 允许同命名空间内通信:标签选择器配置、多Pod场景实践

同命名空间内的通信,说白了就是让一群Pod能互相打招呼。很多新手一上来就搞复杂的跨命名空间策略,结果基础没打牢,vLLM服务跑着跑着就断了。我个人习惯,先把同命名空间内的策略理清楚,再往外扩展。

4.1 为什么同命名空间通信需要策略?

你可能会问:同一个命名空间,默认不就该能通信吗?嗯,理论上是的。但一旦你开启了网络策略,默认就变成了「拒绝所有入站流量」。我遇到过不止一个团队,部署完vLLM后发现推理请求发不过去,排查半天——原来是忘了配允许同命名空间通信的策略。

所以记住一个原则:开启网络策略后,显式允许才是王道

4.2 标签选择器:你的通信白名单

标签选择器是K8s网络策略的核心。它不像IP段那样死板,而是基于Pod的标签动态匹配。说白了,你给Pod贴上标签,策略就自动找到它们。

举个例子,我的vLLM服务通常这样打标签:

apiVersion: v1
kind: Pod
metadata:
  name: vllm-server
  labels:
    app: vllm
    role: inference
spec:
  containers:
  - name: vllm
    image: vllm/vllm-openai:latest
    ports:
    - containerPort: 8000

然后我写一个网络策略,只允许带有 role: inference 标签的Pod访问它:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-inference-traffic
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: vllm
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: inference
    ports:
    - protocol: TCP
      port: 8000

这里有个坑:podSelector 匹配的是目标Pod(被访问方),而 from 下面的 podSelector 匹配的是源Pod(发起方)。我刚开始也搞反过,结果策略死活不生效。

4.3 多Pod场景:不只是vLLM自己

实际部署中,vLLM很少单打独斗。它通常需要跟其他服务配合,比如:

  • API网关:接收外部请求,转发给vLLM
  • 监控组件:Prometheus抓取指标
  • 日志收集器:Filebeat或Fluentd读取日志
  • 模型加载器:从存储拉取模型文件

每个服务都需要不同的访问权限。我建议用标签来区分角色:

服务 推荐标签 需要访问vLLM的端口
API网关 role: gateway 8000 (推理API)
Prometheus role: monitoring 8000 (/metrics)
模型加载器 role: model-loader 不需要直接访问vLLM

然后写一个更精细的策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: vllm-multi-service
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: vllm
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: gateway
    ports:
    - protocol: TCP
      port: 8000
  - from:
    - podSelector:
        matchLabels:
          role: monitoring
    ports:
    - protocol: TCP
      port: 8000
  - from:
    - podSelector:
        matchLabels:
          role: model-loader
    # 模型加载器不需要入站访问,所以不配端口

关键点:每个 from 块可以单独指定端口。这样API网关只能访问推理端口,监控组件只能访问指标端点,互不干扰。

4.4 避坑指南:我曾经踩过的雷

我曾经帮一个客户排查vLLM推理超时问题。他们的策略看起来没问题,标签也对了,但就是不通。折腾了两小时,最后发现——他们忘了给Pod打标签

嗯,你没看错。YAML里写了 matchLabels,但Pod本身没带那个标签。策略匹配不到任何Pod,相当于白写。

另一个常见坑是:多个策略叠加时的行为。K8s网络策略是「或」逻辑——只要有一个策略允许,流量就能通过。但如果你写了一个拒绝策略,它优先级更高。我建议刚开始时只写允许策略,别碰拒绝策略,等熟悉了再玩高级玩法。

警告:不要在生产环境直接应用未测试的网络策略。先在测试命名空间验证,确认标签和端口都正确,再推到生产。我曾经见过有人把整个命名空间锁死,所有Pod都无法通信,只能重建集群。

4.5 多Pod场景的实战配置

假设你有一个完整的AI推理服务栈:

  • vllm-server:标签 app: vllm, tier: backend
  • api-gateway:标签 app: gateway, tier: frontend
  • prometheus:标签 app: monitoring, tier: observability
  • redis-cache:标签 app: cache, tier: backend

vLLM需要访问Redis缓存推理结果,但Redis不应该被外部访问。策略可以这样写:

# 允许vLLM访问Redis
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-vllm-to-redis
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: cache
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: vllm
    ports:
    - protocol: TCP
      port: 6379

# 允许API网关访问vLLM
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-gateway-to-vllm
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: vllm
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: gateway
    ports:
    - protocol: TCP
      port: 8000

这样每个服务只暴露必要的端口给必要的调用方。你想想看,如果Redis被外部Pod随意访问,缓存数据泄露了怎么办?

4.6 验证策略是否生效

写完了策略,怎么知道它真的在工作?我一般用 kubectl exec 进到Pod里测试:

# 从API网关Pod测试能否访问vLLM
kubectl exec -it deploy/api-gateway -- curl http://vllm-server:8000/health

# 从Prometheus Pod测试能否抓取指标
kubectl exec -it deploy/prometheus -- wget -qO- http://vllm-server:8000/metrics

# 从任意Pod测试能否访问Redis(应该被拒绝)
kubectl run test-pod --image=busybox --rm -it -- sh
/ # telnet redis-cache 6379  # 应该超时或拒绝连接

小技巧:用 kubectl describe networkpolicy 查看策略的详细信息,确认 podSelector 匹配到了哪些Pod。如果显示 No resources found,说明标签没对上。

4.7 本章核心逻辑图

下面这张图展示了同命名空间内多Pod通信的策略设计思路:

命名空间: default vLLM Server app: vllm 端口: 8000 API网关 role: gateway Prometheus role: monitoring Redis缓存 app: cache 允许: 8000 允许: 8000/metrics 允许: 6379 拒绝 图例: API网关→vLLM Prometheus→vLLM vLLM→Redis 拒绝通信

从图上可以清楚看到:每个服务只开放必要的通信路径。API网关和Prometheus可以访问vLLM,vLLM可以访问Redis,但API网关和Prometheus之间不能直接通信。这就是标签选择器配合多策略实现的最小权限原则。

好了,同命名空间内的通信策略就这些。记住:标签要对、端口要准、策略要细。下次遇到跨命名空间通信,你会发现思路完全一样,只是多了个 namespaceSelector 而已。


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