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通信的策略设计思路:
从图上可以清楚看到:每个服务只开放必要的通信路径。API网关和Prometheus可以访问vLLM,vLLM可以访问Redis,但API网关和Prometheus之间不能直接通信。这就是标签选择器配合多策略实现的最小权限原则。
好了,同命名空间内的通信策略就这些。记住:标签要对、端口要准、策略要细。下次遇到跨命名空间通信,你会发现思路完全一样,只是多了个 namespaceSelector 而已。
公众号:蓝海资料掘金营,微信deep3321