kubernetes(K8s)学习笔记(第八期):集群治理与控制(上篇):网络策略——NetworkPolicy
kubernetes(K8s)学习笔记(第八期):集群治理与控制(上篇):网络策略——NetworkPolicy
本笔记为 Kubernetes 系列第八期,聚焦集群网络安全的核心机制——NetworkPolicy。涵盖:Kubernetes 网络基础(单主机/跨主机、CNM vs CNI)、网络策略规约详解、四种选择器、多个实战实验(Pod 标签/Namespace/IP 段限定)、默认策略配置。所有命令和 YAML 示例均已经过整理和注释。全文约 3200 字,包含 12 个 YAML 示例、30+ 命令示例 和 10 张对比表格,是 Kubernetes 网络安全的入门指南。
目录
- Kubernetes 网络基础
- 网络策略概述
- 网络策略规约详解
- 网络策略实战实验
- 默认策略
- 总结与知识点一览表
一、Kubernetes 网络基础
在理解网络策略之前,先回顾 Kubernetes 网络的基本原理。
1.1 单主机网络通信
无论是 Docker 还是 Containerd,容器网络接口默认都是虚拟接口。Linux 内核通过 veth pair(虚拟以太网对)技术,在宿主机和容器之间建立通信通道。
核心原理:数据包在宿主机内核中直接复制,不经过外部物理网络设备,因此转发效率极高。
以 Docker 为例:
- Docker 服务默认创建
docker0Linux 网桥 - 每个容器有一个虚拟接口(eth0)连接到网桥
- 宿主机和容器之间通过 veth pair 通信
Containerd 的网络模型与 Docker 类似,使用 nerdctl0 网桥。
1.2 跨主机网络通信
跨主机容器通信有两大方案:
| 方案 | 原理 | 代表技术 |
|---|---|---|
| Overlay 网络 | 建立主机间 VxLAN 隧道,封装数据包 | Flannel(vxlan)、Weave |
| Underlay 网络 | 依赖三层 IP 转发,不封装数据包 | Flannel(host-gw)、Calico |
性能对比:
- Underlay 网络性能优于 Overlay 网络(无需封装/解封装)
- Overlay 网络支持更多二层网段,避免物理交换机 MAC 表耗尽
选型建议:若追求性能且网络环境支持三层互通,优先选择 Calico(BGP 模式);若需要跨子网通信且对性能要求不高,Overlay 方案更灵活。
1.3 CNM vs CNI
容器网络模型经历了两个重要标准:
| 特点 | CNM(Container Network Model) | CNI(Container Network Interface) |
|---|---|---|
| 提出方 | Docker 公司 | Google + CoreOS |
| 最小单元 | 容器 | Pod |
| 守护进程 | 依赖 dockerd | 不依赖任何守护进程 |
| 扩展性 | 被 Docker 绑定 | 插件可随意替换 |
| 适用平台 | Docker | Kubernetes |
关键理解:Kubernetes 采用 CNI 标准,这也是为什么我们可以灵活选择 Calico、Flannel、Weave 等不同网络插件。
1.4 Kubernetes 网络模型核心要求
Kubernetes 对网络模型有四个基本要求(源自 CNI 规范):
- 所有 Pod 可以不经过 NAT 直接通信
- 所有节点可以不经过 NAT 直接与所有 Pod 通信
- Pod 看到的自身 IP 与其他 Pod 看到的一致
- 每个 Pod 拥有独立的 IP 地址
这些要求确保了网络行为的可预测性,也为 NetworkPolicy 的实现奠定了基础。
二、网络策略概述
2.1 默认网络行为
默认情况下,Kubernetes 集群的网络连通性是全开放的:
- 集群外部主机可以访问集群内部应用(通过 NodePort/LoadBalancer)
- 集群内部应用可以访问集群外部主机
- 各个 Namespace 之间没有做任何隔离策略
这意味着:任何 Pod 可以与集群中的任何其他 Pod 通信。这在生产环境中存在安全隐患。
2.2 什么是网络策略?
NetworkPolicy 是 Kubernetes 用于控制 Pod 之间网络通信的 API 对象。它允许你在 IP 地址或端口层面定义哪些流量被允许、哪些被拒绝。
- NetworkPolicy 是一种以应用为中心的结构
- 适用于一端或两端与 Pod 的连接
- 前提条件:必须使用支持 NetworkPolicy 的网络插件(如 Calico)
通俗理解:NetworkPolicy 就像 Pod 的“防火墙规则”——你告诉 Kubernetes“谁可以访问我、我可以访问谁”,Kubernetes 在网络层执行这些规则。
2.3 两种隔离类型
| 隔离类型 | 方向 | 默认行为 | 受 NetworkPolicy 影响后 |
|---|---|---|---|
| 入口隔离(Ingress) | 流入 Pod | 允许所有入站连接 | 仅允许策略中指定的连接 |
| 出口隔离(Egress) | 流出 Pod | 允许所有出站连接 | 仅允许策略中指定的连接 |
2.4 关键原则:策略是相加的
NetworkPolicy 是相加的,不会产生冲突。 如果多个策略适用于同一个 Pod,所有策略允许的连接的并集就是最终生效的规则。
重要:要允许从源 Pod 到目的 Pod 的连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。任何一方不允许,连接都会失败。
三、网络策略规约详解
3.1 完整 YAML 示例
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
3.2 核心字段详解
| 字段 | 说明 |
|---|---|
spec.podSelector |
策略适用的 Pod。{} 表示命名空间中的所有 Pod |
spec.policyTypes |
Ingress、Egress 或两者兼具。默认:有 Ingress 规则时自动包含 Ingress |
spec.ingress |
入站规则白名单。匹配 from 和 ports 的流量才被允许 |
spec.egress |
出站规则白名单。匹配 to 和 ports 的流量才被允许 |
3.3 四种选择器
| 选择器 | 作用 | 示例 |
|---|---|---|
| podSelector | 选择同一 Namespace 中的特定 Pod | role: frontend |
| namespaceSelector | 选择特定 Namespace 中的所有 Pod | project: myproject |
| namespaceSelector + podSelector | 选择特定 Namespace 中的特定 Pod | 组合使用 |
| ipBlock | 选择特定 IP CIDR 范围(通常用于集群外部 IP) | 172.17.0.0/16 |
组合示例:
ingress:
- from:
- namespaceSelector:
matchLabels:
user: alice
- podSelector:
matchLabels:
role: client
含义:允许来自任何 Namespace 中标有 user=alice 的 Pod 的流量,或来自本地 Namespace 中标有 role=client 的 Pod 的流量。
四、网络策略实战实验
4.1 实验环境准备
环境说明:
namespace-web:web1、web2、test 三个 Podnamespace-whisky:test 一个 Pod- 默认 Namespace 是
web
# 创建命名空间
root@master30:~# kubectl create ns web
root@master30:~# kubectl create ns whisky
root@master30:~# kubens web
# 创建 web1
root@master30:~# kubectl run web1 --image=nginx --image-pull-policy=IfNotPresent
root@master30:~# kubectl exec -it web1 -- bash -c 'echo Hello web1 > /usr/share/nginx/html/index.html'
# 创建 web2
root@master30:~# kubectl run web2 --image=nginx --image-pull-policy=IfNotPresent
root@master30:~# kubectl exec -it web2 -- bash -c 'echo Hello web2 > /usr/share/nginx/html/index.html'
# 创建 test(同一 Namespace)
root@master30:~# kubectl run test --image=busybox -- sleep 3600
# 在 whisky Namespace 创建 test(不同 Namespace)
root@master30:~# kubectl run test -n whisky --image=busybox -- sleep 3600
# 创建 Service(NodePort 用于外部访问验证)
root@master30:~# kubectl expose pod web1 --port=80 --target-port=80 --type=NodePort
root@master30:~# kubectl expose pod web2 --port=80 --target-port=80 --type=NodePort
4.2 实验一:根据 Pod 标签限定
目标:允许同一 Namespace 中具有标签 run: test 的 Pod 访问 web1 的 80 端口,其他 Pod 禁止。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
# 验证:test 可以访问 web1
root@master30:~# kubectl exec test -- wget -q -O- web1
Hello web1
# 验证:web2 无法访问 web1
root@master30:~# kubectl exec web2 -- wget -q -O- web1
wget: can't connect to remote host (10.103.36.143): Connection timed out
# 修改 test 的标签,使其不再匹配
root@master30:~# kubectl label pod test run=web2 --overwrite
# 再次验证:test 无法访问 web1
root@master30:~# kubectl exec test -- wget -q -O- web1
wget: can't connect to remote host (10.103.36.143): Connection timed out
关键理解:NetworkPolicy 通过标签选择器动态匹配 Pod。当 Pod 标签变更时,策略实时生效,无需重启 Pod 或重新应用策略。
4.3 实验二:根据 Namespace 限定
目标:允许具有标签 project: myproject 的 Namespace 中的所有 Pod 访问 web1。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
ports:
- protocol: TCP
port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
# 验证:web 命名空间中的 Pod 无法访问
root@master30:~# kubectl exec test -- wget -q -O- web1
wget: can't connect...
# 给 whisky 命名空间添加标签
root@master30:~# kubectl label namespace whisky project=myproject
# 验证:whisky 命名空间中的 Pod 可以访问
root@master30:~# kubectl exec -n whisky test -- wget -q -O- web1.web
Hello web1
4.4 实验三:根据 IP 段限定
目标:允许 10.1.8.0/24 网段(但不包括 10.1.8.128/26 子网)访问 web1。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 10.1.8.0/24
except:
- 10.1.8.128/26
ports:
- protocol: TCP
port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
# 验证:节点 IP 在允许范围内可以访问
root@client:~# curl http://10.1.8.30:30790 # 取决于 nodePort
Hello web1
⚠️ 注意:ipBlock 策略对集群外部访问 NodePort 的实际效果取决于流量来源 IP。实验中通过节点 IP 访问时,源 IP 会被 SNAT 转换,因此建议在验证时使用 Pod IP 直连测试。
4.5 实验四:限定所有端口
目标:允许特定 Pod 访问 web1 的所有端口(不限制端口范围)。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test
# 不指定 ports → 允许所有端口
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
# 验证:可以 ping 通 Pod IP(ICMP 协议不经过端口)
root@master30:~# kubectl get pod web1 -o wide
web1 1/1 Running 0 82m 10.224.193.67
root@master30:~# kubectl run --rm -it ubuntu -l run=test --image=ubuntu -- bash
root@ubuntu:/# apt update && apt install -y iputils-ping
root@ubuntu:/# ping -c1 10.224.193.67
PING 10.224.193.67 (10.224.193.67) 56(84) bytes of data.
64 bytes from 10.224.193.67: icmp_seq=1 ttl=62 time=0.831 ms
4.6 实验五:限定端口范围
目标:允许访问 web1 的 32000-32768 端口范围。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 32000
endPort: 32768
说明:
endPort支持指定端口范围,适用于 NodePort 等需要开放端口的场景。此特性需要 Kubernetes 1.24+ 版本支持。
五、默认策略
5.1 默认允许所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- {}
5.2 默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
5.3 默认允许所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {}
5.4 默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
5.5 默认拒绝所有入口和出口流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
生产推荐:在关键 Namespace 中部署 default-deny-all 策略,然后按需添加允许策略(白名单模式),实现零信任网络隔离。
六、总结与知识点一览表
6.1 NetworkPolicy 核心字段速查
| 字段 | 作用 | 示例 |
|---|---|---|
podSelector |
策略作用的 Pod 范围 | matchLabels: {role: db} |
policyTypes |
策略类型 | [Ingress, Egress] |
ingress.from |
允许的入站来源 | podSelector / namespaceSelector / ipBlock |
ingress.ports |
允许的入站端口 | {protocol: TCP, port: 80} |
egress.to |
允许的出站目标 | ipBlock: {cidr: 10.0.0.0/24} |
egress.ports |
允许的出站端口 | {protocol: TCP, port: 443} |
6.2 四种选择器对比
| 选择器 | 匹配范围 | 适用场景 |
|---|---|---|
podSelector |
同一 Namespace 的特定 Pod | 微服务间访问控制 |
namespaceSelector |
特定 Namespace 的所有 Pod | 多租户隔离 |
namespaceSelector + podSelector |
特定 Namespace 的特定 Pod | 精确控制 |
ipBlock |
特定 IP 段(含 except) | 集群外部来源控制 |
6.3 默认策略模板一览
| 场景 | 模板 |
|---|---|
| 允许所有入站 | ingress: [{}] |
| 拒绝所有入站 | 不指定 ingress |
| 允许所有出站 | egress: [{}] |
| 拒绝所有出站 | 不指定 egress |
| 完全隔离 | policyTypes: [Ingress, Egress],不指定规则 |
6.4 常见错误排查
| 错误现象 | 可能原因 | 解决方法 |
|---|---|---|
| 策略不生效 | 网络插件不支持 NetworkPolicy | 确认使用 Calico 等支持 NetworkPolicy 的插件 |
| Pod 无法访问 | 入口/出口策略未同时允许 | 检查源 Pod 出口策略和目的 Pod 入口策略 |
| ipBlock 不生效 | 流量来源 IP 被 SNAT | 检查实际来源 IP,使用 Pod IP 直连测试 |
| 策略冲突 | 误以为策略是拒绝的 | 记住策略是相加的,只能添加允许规则 |
6.5 生产环境最佳实践
- 启用网络策略前:确保使用支持 NetworkPolicy 的网络插件(如 Calico)
- 采用白名单模式:先部署
default-deny-all,再按需开放 - 命名空间级别隔离:在不同 Namespace 中部署不同的默认策略
- 监控策略影响:使用网络策略可视化工具(如 Calico Cloud 或 Cilium Hubble)
- 逐步推广:先在测试环境验证策略,再逐步应用到生产环境
下一期预告:kubernetes(K8s)学习笔记:集群治理与控制(下篇):调度与节点管理——Scheduler + 污点容忍 + 节点维护。涵盖:kube-scheduler 调度过程、nodeName/nodeSelector/亲和性控制 Pod 位置、污点与容忍度、cordon/drain 节点维护操作。
更多推荐

所有评论(0)