跳到正文
复制成功
请遵守本站许可
报告
章节_文章 // 现场报告

文章编号: RL-NETWORKP

2026.09.28

NetworkPolicy 网络策略

Chavy
Chavy
#Kubernetes#NetworkPolicy#网络安全
档案

摘要:使用 NetworkPolicy 限制 Pod 入站和出站流量,理解 Pod 与命名空间选择器、默认拒绝、规则叠加、DNS 放行及网络插件的能力边界。

这一节开始学习 Kubernetes 网络安全。

核心问题是:如何限制 Pod 之间的通信,只允许经过授权的应用访问指定服务?

例如,一个典型的三层应用:

  • 前端 Pod:对外提供 Web 服务。
  • 后端 Pod:提供业务 API。
  • 数据库 Pod:保存业务数据。

我们希望实现:

  1. 只有前端可以访问后端。
  2. 只有后端可以访问数据库。
  3. 其他 Pod 不能随意访问数据库。
  4. 必要的 DNS 查询仍然可以正常工作。

这就是 NetworkPolicy 的主要用途。

一、为什么需要 NetworkPolicy?#

假设集群中有三个应用:

flowchart TB
    N0["Frontend Pod<br/>前端应用 · 8080"]
    N1["Backend Pod<br/>业务 API · 8080"]
    N2["Database Pod<br/>数据库 · 5432"]
    N3["其他 Pod<br/>没有授权时,不应直接访问数据库。"]
    N0 -->|"允许访问"| N1
    N1 -->|"允许访问"| N2
    N3 --x|"禁止访问"| N2

在许多 Kubernetes 网络插件的默认配置下,同一集群中的 Pod 可以直接通过 Pod IP 通信。Service 并不是强制经过的安全网关。

这意味着,即使你只给数据库创建了 ClusterIP Service,其他具有网络连通性的 Pod 仍可能直接访问数据库 Pod IP。

因此,Service 负责提供服务入口,NetworkPolicy 负责声明网络访问规则,两者解决的问题不同。

二、NetworkPolicy 的工作原理#

NetworkPolicy 是 Kubernetes 的网络策略 API,使用标签选择器指定受保护的 Pod,并定义允许哪些入站或出站流量。

它有三个核心概念:

  • PodSelector:选择哪些 Pod 应用这条策略。
  • Ingress:控制进入所选 Pod 的流量。
  • Egress:控制从所选 Pod 发出的流量。

例如,下面这条策略选择所有 app=database 的 Pod,并禁止它们接收未被其他策略允许的入站流量。

PRTCL // YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-deny-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress: []

这条策略的含义是:

  • 保护 default Namespace 中带有 app=database 标签的 Pod。
  • 不允许任何入站连接,除非有其他适用策略也允许该流量。
  • 不会限制这些 Pod 的出站流量。

注意,NetworkPolicy 只是策略声明,真正执行规则需要支持 NetworkPolicy 的网络插件。常见的 Calico 和 Cilium 都支持这类策略,但具体能力和行为应以实际部署为准。

三、入站策略:只允许前端访问后端#

我们先实现一个常见的生产需求:

只有 app=frontend 的 Pod 可以访问 app=backend 的 Pod 的 TCP 8080 端口。

假设 Pod 已经带有以下标签:

PRTCL // YAML
# 前端 Pod 标签
app: frontend
# 后端 Pod 标签
app: backend

创建策略:

PRTCL // YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080

逐字段理解#

配置含义
podSelector选择被保护的后端 Pod
policyTypes: Ingress声明该策略控制入站流量
from定义允许的来源
podSelector允许来源必须具有 app=frontend 标签
ports只允许 TCP 8080 端口

应用配置:

PRTCL // BASH
Terminal window
kubectl apply -f backend-ingress.yaml
kubectl describe networkpolicy backend-ingress
kubectl get networkpolicy

假设前端和后端位于同一个 Namespace,这条策略会产生以下效果:

流量与结果:

flowchart LR
    N0["前端 Pod"]
    N1["后端 TCP 8080"]
    N2["其他普通 Pod"]
    N3["后端 TCP 9090"]
    N0 -->|"允许"| N1
    N2 --x|"默认拒绝"| N1
    N0 --x|"默认拒绝"| N3

后端 Pod 的出站流量:不受这条策略限制。

这里的“默认拒绝”有一个前提:后端 Pod 已经因为这条策略而受到入站隔离,而且没有其他策略允许相应流量。

重要:同一个 Pod 可以同时匹配多条 NetworkPolicy。对标准 NetworkPolicy 而言,适用策略的允许规则通常是累加的,而不是后创建的规则覆盖先创建的规则。

因此,如果另一条策略允许所有 Pod 访问后端 8080,那么上面这条策略并不能单独阻止其他 Pod 的访问。

四、跨 Namespace 如何限制访问?#

实际集群往往有多个 Namespace,例如:

flowchart TB
    N0["frontend-ns"]
    N1["frontend Pod"]
    N2["backend-ns"]
    N3["backend Pod"]
    N4["database-ns"]
    N5["database Pod"]
    N0 --> N1
    N2 --> N3
    N4 --> N5

如果你希望只允许 frontend-ns 中的前端访问 backend-ns 中的后端,就需要同时匹配来源 Namespace 和 Pod 标签。

例如,在 backend-ns 中创建:

PRTCL // YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-cross-namespace
namespace: backend-ns
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend-ns
podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080

这里有一个非常重要的 YAML 细节。

namespaceSelector 和 podSelector 写在同一个 from 条目中,表示两个条件必须同时满足:

  1. 来源 Pod 所在的 Namespace 是 frontend-ns。
  2. 来源 Pod 具有 app=frontend 标签。

如果把它们拆成两个独立的 from 条目,语义就变成满足其中任意一个条件即可,可能会放宽访问范围。

五、出站策略:控制 Pod 能访问什么#

前面控制的是谁可以访问后端,现在控制一个 Pod 可以主动访问哪些目标。

例如,只允许后端访问数据库的 TCP 5432 端口:

PRTCL // YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-egress
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432

这条策略的含义:

  • 选择 app=backend 的 Pod。
  • 将它们的出站流量纳入策略隔离。
  • 允许访问同一 Namespace 中 app=database 的 Pod 的 TCP 5432 端口。
  • 其他出站流量默认不允许,除非有其他适用策略允许。

但是,这条策略还有一个实际问题:DNS 可能会被阻断。

如果后端应用使用 database.default.svc.cluster.local 访问数据库,就需要确保它能够访问集群 DNS 服务。

为什么 DNS 会失效?#

启用出站隔离后,Pod 的 DNS 查询也属于出站流量。

如果没有允许访问 DNS 的规则,应用可能出现:

PRTCL // TEXT
Could not resolve host
Temporary failure in name resolution

这时即使数据库本身正常运行,应用仍可能因为无法解析 Service 名称而连接失败。

你可以根据实际 CoreDNS Service 的标签、Namespace 和端口,增加 DNS 出站规则。常见示例是:

PRTCL // YAML
egress:
- to:
- podSelector:
matchLabels:
k8s-app: kube-dns
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432

这是一个需要结合现有策略合并使用的 egress 规则示例,不是完整的 NetworkPolicy 资源。

还需要注意:

  • CoreDNS 的实际标签可能不同,需要通过 kubectl get pods -n kube-system --show-labels 检查。
  • 部分集群的 DNS 请求可能经过 NodeLocal DNSCache,流量路径和策略匹配需要结合具体部署分析。
  • UDP 53 和 TCP 53 都应该考虑,尤其是 DNS 响应较大或需要 TCP 回退的情况。
  • 如果应用需要访问外部 HTTPS API,还要明确添加相应的出站允许规则。

生产环境建议先盘点应用依赖,再逐步启用出站隔离,避免直接使用全拒绝策略导致业务中断。

六、默认拒绝策略:构建真正的网络隔离#

如果你想让某个 Namespace 中的所有 Pod 默认拒绝入站流量,可以创建:

PRTCL // YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
ingress: []

podSelector: {} 表示选择该 Namespace 中的所有 Pod。

如果还要默认拒绝所有出站流量,可以使用:

PRTCL // YAML
policyTypes:
- Ingress
- Egress
ingress: []
egress: []

这是一种常见的“默认拒绝,再逐项放行”的安全设计。

但请特别注意:如果直接对整个 Namespace 应用默认拒绝入站和出站策略,DNS、外部 API、监控探针以及服务之间的通信都可能中断。应该先规划允许规则,再逐步实施。

七、NetworkPolicy 与 Service 有什么关系?#

这是一个容易混淆的地方。

组件解决的问题
Service提供稳定的服务访问入口
EndpointSlice维护服务关联的网络端点
CNI提供 Pod 网络连接及相关网络能力
NetworkPolicy声明允许和拒绝哪些 Pod 网络流量
Ingress / Gateway管理外部 HTTP/HTTPS 流量路由

例如,后端有一个 ClusterIP Service:

PRTCL // TEXT
backend.default.svc.cluster.local:8080

前端通过 Service 访问后端时,仍然需要满足适用的网络策略。即使其他 Pod 绕过 Service,直接访问后端 Pod IP,也不应因此绕过正确实施的 NetworkPolicy。

标准 NetworkPolicy 主要描述 L3/L4 访问控制,并不直接提供基于 HTTP URL、请求头或用户身份的细粒度授权。如果需要这些能力,通常还需要网关、服务网格或应用层身份认证与授权机制。

八、本节总结#

本节需要掌握的核心知识:

  • NetworkPolicy 使用标签选择器定义流量访问规则。
  • Ingress 控制进入目标 Pod 的流量,Egress 控制目标 Pod 发出的流量。
  • 默认拒绝策略可以建立网络隔离基础,但需要显式规划必要的放行规则。
  • 多条标准 NetworkPolicy 的允许规则通常是累加关系。
  • 网络策略是否生效,取决于底层网络插件的支持和实际配置。
  • DNS、监控、探针及外部依赖都需要纳入策略设计。
归档于 2026.09.28
// 档案结束
Classified
章节_06
协议编号: CC-BY-NC-SA-4.0

NetworkPolicy 网络策略

作者:Chavy发布日期:2026.09.28

基于 CC BY-NC-SA 4.0

© 2026 Chavy
Powered by Astro