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 |
这里有个容易踩的坑:namespaceSelector和podSelector同时使用时,默认是「与」的关系。什么意思呢?就是流量必须同时满足两个条件才能通过。我曾经见过有人以为这是「或」的关系,结果配了半天流量就是过不去。
我的建议:如果想让两个条件是「或」的关系,把它们分别写在不同的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字段决定了这条策略管哪类流量。它有两个可选值:Ingress和Egress。可以只选一个,也可以两个都选。
这里有个容易忽略的细节:
- 如果只写
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,再定策略类型,最后配具体规则。规则里又分四种匹配方式。记住这个流程,配策略时就不容易漏东西。
一句话总结:NetworkPolicy就是「选Pod → 定方向 → 配规则」三步走。别想复杂了。
公众号:蓝海资料掘金营,微信deep3321