Kubernetes Network 详解
Kubernetes Network
学习参考:网络策略
环境准备
root@master30:~# kubectl create ns network
root@master30:~# kubectl config set-context --current --namespace network
一、单主机网络通信
1.1 Docker 单机网络
-
Docker 的网络接口==默认使用虚拟接口,Linux在内核中进行数据复制来实现虚拟接口之间的数据转发,==不需要经过物理网卡,转发效率高。
-
默认创建
docker0Linux 网桥;使用 veth‑pair 成对虚拟网卡:一端在宿主机网桥,一端在容器内部。
-
docker0 配置 IP 与子网,实现==主机和容器互通==。
brctl 工具由
bridge‑utils软件包提供。
4.外部主机访问容器必须依靠端口映射。

1.2 Containerd 单机网络
网络原理和 Docker 类似,同样==使用虚拟接口 veth‑pair,==宿主机与容器分别生成**虚拟网卡成对连通。**
二、跨主机网络通信
2.1 跨主机网络通信架构

跨主机通信:不同节点上的 Pod / 容器互通。
- docker 原生的方案:overlay 和 macvlan。
- 第三方提供的方案:flannel 、calico、weave等。
| 方案 特性 | Flannel | Calico | macvlan | OpenVswitch | 直接路由 |
|---|---|---|---|---|---|
| 方案特性 | 通过虚拟设备flannel0实现对docker0的管理 | 基于BGP协议的纯三层的网络方案 | 基于Linux Kernel 的macvlan技术 | 基于隧道的虚拟路由器技术 | 基于Linux Kernel 的 vRouter 技术 |
| 对底层网络的要求 | 三层互通 | 三层互通 | 二层互通 | 三层互通 | 二层互通 |
| 配置难易程度 | 简单-基于etcd | 简单-基于etcd | 简单-直接使用宿主机网络,需要仔细规划IP地址 | 复杂-需手工配置个节点的bridge | 简单-使用宿主机vRoute功能,需要仔细规划每个Node的IP地址 |
| 网络性能 | host-gw > VxLAN | BGP 模式性能随时小、IPIP 模式较小 | 性能随时可忽略 | 性能随时较小 | 性能随时较小 |
| 网络连通性限制 | 无 | 在不支持BGP的网络环境下无法使用 | 基于macvlan的容器无法与宿主机网络通信 | 无 | 在无法实现大二层互通的网络环境下无法使用 |
2.2 跨主机网络通信方案
跨主机网络:将不同主机上的容器用同一个虚拟网络连接起来。
两种网络模型:
-
Underlay:直接使用底层物理网络转发 Pod 流量,无隧道封装,性能更高。
-
Overlay:在**宿主机网络之上构建虚拟隧道,数据包封装在 UDP 传输;会有封装开销**。
- 优势:支持更多二层网段,保护物理交换机 MAC 表。
1. Flannel
Flannel 提供两种主流工作模式:
- host-gw(Underlay)
- 原理:节点上添加静态路由,目标Pod网段下一跳指向目标宿主机IP;无任何报文封装。
- 流量:Pod原始IP包直接在底层网络传输。
- 约束:底层网络能够转发Pod网段路由;公有云大多不支持。
- 性能:高。
- VXLAN(Overlay)
- 原理:跨节点Pod报文封装UDP VXLAN包头,通过宿主机网络传输,到达对端解封装。
- 约束:仅要求宿主机之间IP连通,公有云通用。
- 性能:存在封包解包开销,低于host-gw。
Flannel仅负责连通,不提供网络策略NetworkPolicy。
2. Calico
- BGP 模式(Underlay)
- 节点间通过BGP交换Pod路由,无隧道封装,原生IP转发。
- 性能最优;前提:网络允许BGP协议发布路由。
- IPIP / VXLAN模式(Overlay)
- 底层不支持BGP时启用IP-in-IP隧道封装;数据包外层增加宿主机IP头。
- 适配公有云;封装带来性能损耗。
Calico最大亮点:原生支持 NetworkPolicy(Pod防火墙策略)。
3. Weave
默认采用 Overlay。
- 工作方式:节点之间建立UDP隧道,封装Pod流量;自动发现集群节点。
- 特色:
- 内置DNS;
- 支持NetworkPolicy;
- 可以混合运行加密隧道;
- 短板:
隧道封装持续占用CPU;大规模集群性能弱于Flannel VXLAN、Calico。
Weave也支持快速MAC路由优化,但主体模型仍然归类Overlay。
4. Macvlan
Macvlan 属于 Underlay 方案
-
原理:在宿主机物理网卡上虚拟多张独立网卡,每个Pod拥有独立MAC地址;Pod直接接入底层物理局域网。
-
流量:Pod报文直接在二层物理网络转发,不存在隧道封装。
✅ 优点:性能极高,Pod和物理机器同等地位,网络延迟极低。
❌ 限制:-
宿主机网卡不能开启桥接;
-
同一父网卡Macvlan子接口无法直接互通(同宿主机Pod互通缺陷);
-
网络规划复杂,传统虚拟化环境容易冲突。
-
典型场景:Pod 需要拿到局域网真实物理 IP,低延迟业务。
5. 网络模型比较
| CNI方案 | 可用网络模型 | 是否隧道封装 | 支持NetworkPolicy | 适用场景 |
|---|---|---|---|---|
| Flannel | host-gw(Underlay)、VXLAN(Overlay) | VXLAN封装;host-gw无封装 | ❌ 不支持 | 追求简单、不需要Pod访问控制;中小型集群 |
| Calico | BGP(Underlay)、IPIP/VXLAN(Overlay) | IPIP/VXLAN封装;BGP无封装 | ✅ 原生支持 | 需要网络策略、自建机房/公有云通用 |
| Weave Net | UDP隧道Overlay | UDP封装 | ✅ 支持 | 测试环境、小规模集群;部署简单,无需etcd |
| Macvlan | Underlay(二层直连物理网络) | ❌ 无任何封装 | 取决于配套CNI | Pod需要占用局域网独立IP、低延迟业务 |
2.3 跨主机网络通信模型
目的:把网络插件和容器平台解耦,适配多种容器运行时。
2.3.1 CNM 模型
CNM( Container Network Model,容器网络模型),由 Docker 公司提出,在 docker 项目下的 libnetwork 项目中被采用。按照该模型开发出的 driver 就能与 docker daemon 协同工作,实现容器网络。
- docker 原生的 driver 包括 none、bridge、overlay 和 macvlan。
- 第三方 driver 包括 flannel、weave、calico 等。

由以下三类组件组成:
-
Sandbox 是容器的网络栈,由 Linux Network Namespace 实现,保存网卡、路由、DNS。Sandbox 可以包含来自不同 Network 的 Endpoint。
-
Endpoint 的作用是将 Sandbox 接入 Network:veth‑pair 实现,把 Sandbox 接入网络;一个 Endpoint 只能属于一个网络、一个 sandbox。
-
Network 包含一组 Endpoint,同一 Network 的 Endpoint 可以直接通信。Network 的实现可以是 Linux Bridge、VLAN 等。
如图所示两个容器,一个容器一个 Sandbox,每个 Sandbox 都有一个 Endpoint 连接到 Network 1,第二个 Sandbox 还有一个 Endpoint 将其接入 Network 2.

下面我们以 docker bridge driver 为例讨论 libnetwork CNM 是如何被实现的。
- 两个 Network:默认网络 “bridge” 和自定义网络 “my_net2”。实现方式是 Linux Bridge:“docker0” 和 “br-5d863e9f78b6”。
- 三个 Enpoint,由 veth pair 实现,一端(vethxxx)挂在 Linux Bridge 上,另一端(eth0)挂在容器内。
- 三个 Sandbox,由 Network Namespace 实现,每个容器有自己的 Sanbox。
2.3.2 CNI 模型
CNI,全称 Container Network Interface,是 Google 和 **CoreOS **联合定制的网络标准,CNI 规范定义了容器和网络插件之间通信规范,实现多容器通信。各个网络厂商通过该接口实现互相通信。

一个容器可以被加入到被不同插件所驱动的多个网络之中。一个网络有自己对应的插件和唯一的名称。
CNI 模型包含2个概念:
-
容器: 独立的 linux 网络命名空间。
-
网络: 用于互联实体, 这些实体拥有各自独立且唯一的 IP 地址, 可以是容器, 物理机, 或者其他网络设备。
两类插件
- CNI Plugin:配置容器网络。
- IPAM Plugin:分配 Pod IP 地址。
不依赖守护进程,插件可替换;最小处理单元为 Pod。
2.3.3 模型比较
| 特点 | CNM | CNI |
|---|---|---|
| 标准规范 | Libnetwork | cni |
| 最小单元 | 容器 | POD |
| 对守护进程的依赖 | 依赖 dockerd | 不依赖任何守护进程 |
| 扩主机通信 | 依赖外部 KV 数据库 | 用本身的 KV 数据库 |
| 灵活程度 | 被 docker 绑定 | 插件可随意替换 |
三、K8s 中 Calico 网络
3.1 Calico 网络优势
Kubernetes 集群采用 Calico 网络通信方案优势:
-
支持 BGP 模式(Underlay)
- 节点间通过BGP交换Pod路由,无隧道封装,原生IP转发。
- 性能最优;前提:网络允许BGP协议发布路由。
-
支持IPIP / VXLAN模式(Overlay)
- 底层不支持BGP时启用IP-in-IP隧道封装;数据包外层增加宿主机IP头。
- 适配公有云;封装带来性能损耗。
-
支持 NetworkPolicy(Pod防火墙策略)。
3.2 Calico 隧道模式
Calico 支持两种隧道模式:IPIP 和VXLAN 。
3.2.1 ipipMode 隧道
- 协议:三层隧道,把内层IP包完整封装进外层IP包。
- 虚拟网卡:
tunl0。 - 封装结构:外层IP头(节点IP) + 内层IP头(Pod IP) + 应用数据。
- 只封装IP包,不携带二层帧(MAC)。
3.2.2 VXLAN 隧道
- 协议:二层隧道,UDP报文,默认端口
4789。 - 虚拟网卡:
vxlan.calico。 - 封装结构:外层IP+UDP头 + VXLAN头部(VNI) + 完整二层帧(MAC+IP+数据)。
- 保留完整二层,支持广播、组播。
| 项目 | IPIP | VXLAN |
|---|---|---|
| 隧道类型 | 三层IP隧道 | 二层UDP隧道 |
| 传输载体 | IP协议号4 | UDP 4789 |
| 是否带二层MAC | ❌ 不带 | ✅ 完整二层帧 |
| 包头开销 | 较小 | 更大(多VXLAN头部,MTU要更小) |
| 云厂商限制 | 很多公有云封禁协议号4,IPIP直接不通 | UDP端口一般放行,公有云兼容性更好 |
| 广播/组播 | 不支持 | 支持 |
| Calico配置 | ipipMode:Always,vxlanMode:Never | ipipMode:Never,vxlanMode:Always |
| 故障排查 | 抓包简单,只有内外两层IP | 包结构更复杂 |
| 适用场景 | 私有机房、底层网络允许IPIP协议 | 公有云、底层网络不允许IPIP |
3.2.3 隧道模式选择
选 IPIP 的场景
- 私有物理机房,底层网络不拦截IP协议号4
- 集群只需要单播Pod通信,不需要二层广播
- 想更小的包头开销,追求略高一点性能
缺点:公有云(阿里云/AWS等)默认会拦截IPIP协议,直接无法通信。
选 VXLAN 的场景
- 公有云环境(AWS、阿里云、腾讯云),云安全组屏蔽IPIP协议
- 需要二层广播能力(少数特殊业务)
- 底层网络不支持透传IP协议4号
缺点:封装头部更大,MTU需要调小;性能略低于IPIP。
3.3 Calico 工作模式
3.3.1 ipipMode 隧道
- Always(默认),所有跨节点Pod流量封装隧道包,路由下一跳指向
tunl0。节点只需要三层可达,不需要底层网络感知Pod网段。 - Never(BGP原生/Underlay),不封装IPIP,依靠BGP在节点之间同步Pod网段路由;路由下一跳是节点物理网卡。要求节点同子网L2互通。
- CrossSubnet(混合),同子网节点之间通信:不封装IPIP(BGP原生);跨子网节点之间通信:自动启用IPIP隧道封装。
无论是否开启IPIP,Calico都会运行BGP进程,BGP负责同步Pod网段;IPIP开关只决定数据包是否封装隧道。
3.3.2 VXLAN 隧道
vxlanMode 也支持三个取值:Never / Always / CrossSubnet,功能于 ipipMode 取值一致。
- Always,所有跨节点 Pod 流量全部封装 VXLAN 隧道(Overlay)。
- Never,不启用 VXLAN 隧道。
- CrossSubnet 混合模式,同子网节点之间通信不封装;跨子网节点之间通信启用VXLAN隧道封装。
3.3.3 工作模式选择
- 选 Never
-
没有隧道封装,性能优;
-
抓包可以直接观察Pod原生IP;
-
选 Always
-
节点分布在不同子网,节点之间无法二层互通;
-
公有云(阿里云/腾讯云/AWS)部署Calico;
-
不想依赖底层网络支持BGP。
-
-
选 CrossSubnet
- 企业机房,节点划分为多个子网;
- 同网段节点直接路由,跨网段节点自动走IPIP隧道。
3.4 查看工作模式
IPPool是Calico控制隧道模式的核心资源。
# 方法1:查看 IPPool 资源
root@master30:~# kubectl get ippool -o yaml|egrep 'ipip|vxlan'
ipipMode: Always
vxlanMode: Never
# 方法2:查看宿主机路由表
# 在任意节点执行
root@master30 ~# ip route | grep '/26 via'
10.224.19.0/26 via 10.1.8.31 dev tunl0 proto bird onlink
10.224.113.128/26 via 10.1.8.32 dev tunl0 proto bird onlink
# 路由条目末尾出现 `dev tunl0` → IPIP隧道模式(数据包走IPIP封装)
# 路由条目指向物理网卡 `dev ens32` → BGP原生路由模式
3.5 修改工作模式
⚠️ 风险提示:修改IPPool会立刻改变集群跨节点Pod转发行为,生产环境需要业务低峰操作,提前备份。
# 步骤1:备份原有IPPool配置
root@master30 ~# kubectl get ippool default-ipv4-ippool -o yaml > ippool-backup.yaml
# 步骤2:直接编辑 default-ipv4-ippool
root@master30 ~# kubectl edit ippool default-ipv4-ippool
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 10.224.0.0/16
# 修改 ipipMode
ipipMode: Never
...
配置下发等待30~60秒自动生效;长时间不生效,可以重启calico-node daemonset:
# 步骤3:验证路由表
root@master30 ~# ip route | grep '/26'
10.224.19.0/26 via 10.1.8.31 dev ens32 proto bird
10.224.113.128/26 via 10.1.8.32 dev ens32 proto bird
四、网络策略
4.1 网络策略介绍
- 前提条件:CNI 插件必须支持 NetworkPolicy,Calico 支持,Flannel 不支持。
- 默认集群所有 Pod、命名空间网络全部互通。
- NetworkPolicy 实现 Pod 级别白名单访问控制,没有拒绝规则,只做允许白名单;多条策略效果相加。
4.2 Ingress / Egress 核心规则
Pod 有两种隔离: 出口的隔离和入口的隔离。
- Ingress(入站):外部访问 Pod 默认全部放行;policyTypes 包含 Ingress,该 Pod 入站隔离,仅 ingress 白名单允许流量。
- Egress(出站):Pod 访问外部 默认全部放行;policyTypes 包含 Egress,该 Pod 出站隔离,仅 egress 白名单允许流量。
✅建立连接必须:源 Pod Egress 放行 AND 目标 Pod Ingress 放行,连接才可以建立。
网络策略是相加的,所以不会产生冲突。
**要允许从源 Pod 到目的 Pod 的连接,则源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。**如果任何一方不允许连接,建立连接将会失败。
示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
# 使用标签过滤限制哪些pod
podSelector:
matchLabels:
role: db
policyTypes:
# Ingress控制外部访问内部
- Ingress
# Egress控制pod访问外部
- Egress
ingress:
# from限制允许哪些主机可以访问pod
- from:
# 通过ip限制
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
# 限制namespace中pod
- namespaceSelector:
matchLabels:
project: myproject
# 限制同一namespace中pod
- podSelector:
matchLabels:
role: frontend
# 限制pod上哪些端口可以访问
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
-
必需字段:与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要
apiVersion、kind和metadata字段。 -
spec:NetworkPolicy 规约 中包含了在一个命名空间中定义特定网络策略所需的所有信息。
-
spec.podSelector:每个 NetworkPolicy 都包括一个
podSelector, 它对该策略所适用的一组 Pod 进行选择。示例中的策略选择带有 “role=db” 标签的 Pod。 空的podSelector选择命名空间下的所有 Pod。 -
spec.policyTypes:每个 NetworkPolicy 都包含一个
policyTypes列表,其中包含Ingress或Egress或两者兼具。policyTypes字段表示给定的策略是应用于进入所选 Pod 的入站流量还是来自所选 Pod 的出站流量,或两者兼有。 如果 NetworkPolicy 未指定policyTypes则默认情况下始终设置Ingress; 如果 NetworkPolicy 有任何出口规则的话则设置Egress。 -
spec.ingress:每个 NetworkPolicy 可包含一个
ingress规则的白名单列表。 每个规则都允许同时匹配from和ports部分的流量。示例策略中包含一条简单的规则: 它匹配某个特定端口,来自三个来源中的一个:- 第一个通过
ipBlock指定 - 第二个通过
namespaceSelector指定 - 第三个通过
podSelector指定。
- 第一个通过
-
spec.egress:每个 NetworkPolicy 可包含一个
egress规则的白名单列表。 每个规则都允许匹配to和port部分的流量。该示例策略包含一条规则, 该规则将指定端口上的流量匹配到10.0.0.0/24中的任何目的地。
4.3 to 和 from 选择器
可以在 ingress 的 from 部分或 egress 的 to 部分中指定四种选择器:
-
podSelector:此选择器将在与 NetworkPolicy 相同的命名空间中选择特定的 Pod,应将其允许作为入站流量来源或出站流量目的地。
-
namespaceSelector:此选择器将选择特定的命名空间,应将所有 Pod 用作其入站流量来源或出站流量目的地。
-
namespaceSelector 和 podSelector:指定
namespaceSelector和podSelector的to/from条目选择特定命名空间中的特定 Pod。示例:
... ingress: - from: - namespaceSelector: matchLabels: user: alice - podSelector: matchLabels: role: client ...在
from数组中包含两个元素,允许来自本地命名空间中标有role=client的 Pod 的连接,或来自任何命名空间中标有user=alice的任何 Pod 的连接。 -
ipBlock:此选择器将选择特定的 IP CIDR 范围以用作入站流量来源或出站流量目的地。 这些应该是集群外部 IP,因为 Pod IP 存在时间短暂的且随机产生。
集群的入站和出站机制通常需要重写数据包的源 IP 或目标 IP。 在发生这种情况时,不确定在 NetworkPolicy 处理之前还是之后发生, 并且对于网络插件、云提供商、
Service实现等的不同组合,其行为可能会有所不同。-
对入站流量而言,这意味着在某些情况下,你可以根据实际的原始源 IP 过滤传入的数据包, 而在其他情况下,NetworkPolicy 所作用的
源IP则可能是LoadBalancer或 Pod 的节点等。 -
对于出站流量而言,这意味着从 Pod 到被重写为集群外部 IP 的
ServiceIP 的连接可能会或可能不会受到基于ipBlock的策略的约束。
-
4.4 实施网络策略
准备实验环境
环境说明:
- namespace-web 中有3个 pod:web1、web2、test
- namespace-laoma 中有1个pod:test
- 如没有特别说明,默认namespace是web
root@master30:~# kubectl create ns web
root@master30:~# kubens web
# 创建 web1
root@master30:~# kubectl run web1 --image=hub.laoma.cloud/library/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=hub.laoma.cloud/library/nginx --image-pull-policy=IfNotPresent
root@master30:~# kubectl exec -it web2 -- bash -c 'echo Hello web2 > /usr/share/nginx/html/index.html'
# 创建service web1和web2
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
root@master30:~# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web1 NodePort 10.103.36.143 <none> 80:30790/TCP 11s
web2 NodePort 10.111.250.224 <none> 80:32686/TCP 7s
# 同一namespace中web1和web2互相访问
root@master30:~/network# kubectl run test --image=hub.laoma.cloud/library/nginx
root@master30:~/network# kubectl exec -it test -- curl -s web1
Hello web1
root@master30:~/network# kubectl exec -it test -- curl -s web2
Hello web2
# 在不同namespace-laoma中创建测试pod-test,访问web1和web2
root@master30:~# kubectl create ns laoma
root@master30:~# kubectl run test -n laoma --image=hub.laoma.cloud/library/nginx
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
Hello web1
root@master30:~# kubectl exec -n laoma test -- curl -s web2.web
Hello web2
# 集群内访问service web1和web2
root@master30:~# curl 10.103.36.143
Hello web1
root@master30:~# curl 10.111.250.224
Hello web2
# 集群外节点访问web1和web2
root@client:~# curl http://10.1.8.30:30790
Hello web1
root@client:~# curl http://10.1.8.30:32686
Hello web2
4.4.1 根据 pod 标签限定
根据pod标签限定:
- 限定同一ns中pod之间访问
- 所有其他ns中pod或者集群外主机都无法访问ns中pod
示例1:允许同一ns中具有标签run: test的pod,访问具有标签run: web1的pod 80端口。
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 80
# 创建network policy
root@master30:~# kubectl apply -f netpol.yaml
root@master30:~# kubectl get netpol
NAME POD-SELECTOR AGE
my-network-policy run=web1 4s
# 同一namespace中test可以访问web1,web2不可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1
# 不同 namespace 中pod,标签满足不可以访问
root@master30:~# kubectl exec test -n laoma -- curl -s --connect-timeout 3 web1.web
command terminated with exit code 28
# 修改现有标签,同一命名空间的test pod也无法访问了。
root@master30:~/network# kubectl label pod test run=web2 --overwrite
root@master30:~/network# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
test 1/1 Running 0 9m9s run=web2
web1 1/1 Running 0 13m run=web1
web2 1/1 Running 0 13m run=web2
# 超时退出
root@master30:~/network# kubectl exec test -- curl -s --connect-timeout 3 web1
command terminated with exit code 28
示例2:允许同一namespace中所有pod访问具有标签run: web1的pod 80端口。
设置podSelector: {},则针对namespace中所有pod。
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
ports:
- protocol: TCP
port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
# 同一namespace中所有pod都可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1
root@master30:~# kubectl exec web2 -- curl -s web1
Hello web1
# 不同namespace中pod不可以访问web1
root@master30:~# kubectl exec test -n laoma -- curl -s --connect-timeout 3 web1.web
command terminated with exit code 28
示例3:允许同一ns中具有标签run: test的pod,访问所有pod 80端口。
设置podSelector: {},则针对namespace中所有pod。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 80
4.4.2 根据 ns 标签限定
用于限定,来源于其他namespace中pod。
示例1:允许具有标签project: myproject的namespace中所有pod,访问当前ns中具有标签run: web1的pod 80端口。
root@master30:~# vim netpol.yaml
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
# 此时namespace-web中pod和namespace-laoma中pod都无法访问web1
root@master30:~# kubectl exec test -- curl -s web1
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
# 给namespace-laoma添加标签project=myproject,此时namespace-laoma中pod可以访问web1.web
root@master30:~# kubectl label namespaces laoma project=myproject
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
Hello web1
示例2:允许所有namespace中所有pod,访问当前ns中具有标签run: web1的pod 80端口。
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 80
# 创建network policy
root@master30:~# kubectl apply -f netpol.yaml
# 所有namespace中所有pod都可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
4.4.3 根据 pod IP 限定
示例1:允许网段172.17.0.0/16但不包括子网172.17.1.0/24中主机,访问具有标签run: web1的pod 80端口。
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: web
spec:
podSelector:
matchLabels:
run: web1
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
# 放行 网段10.1.8.0/24
cidr: 10.1.8.0/24
# 不放行网段
except:
- 10.1.8.128/26
ports:
- protocol: TCP
port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
# 访问失败
root@master30:~# kubectl exec test -- curl -s web1
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
root@client:~# curl http://10.1.8.30:30251
root@client:~# curl http://10.1.8.31:30251
# 访问成功失败
root@client:~# curl http://10.1.8.32:30251
Hello web1
# 理论上:10.1.8.0/24网段中主机都可以通过集群任意节点访问web1
# 实际测试:只可以通过pod所在主机的IP访问web1 (10.1.8.32:30790),不可以访问10.1.8.30:30790或10.1.8.31:30790
# 在worker31上也可以通过10.103.36.143访问pod-web1
root@master30:~# kubectl describe pod web1|grep Node:
Node: worker32.laoma.cloud/10.1.8.32
从实验测试结果来看,根据网段控制来源还不完善。
如果想放行所有主机,阻止部分主机,规则如下:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.1.8.0/26
4.4.4 限定所有端口
port参数不设置,代表限定所有端口。
root@master30:~# vim netpol.yaml
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
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml
root@master30:~# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test 1/1 Running 0 64m 10.224.193.70 worker32.laoma.cloud <none> <none>
web1 1/1 Running 0 82m 10.224.193.67 worker32.laoma.cloud <none> <none>
web2 1/1 Running 0 81m 10.224.41.132 worker31.laoma.cloud <none> <none>
# 此时满足条件的pod可以ping通pod地址
root@master30:~# kubectl run --rm -it ubuntu -l run=test --image ubuntu -- bash
root@ubuntu:/# apt update
root@ubuntu:/# 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
--- 10.224.193.67 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.831/0.831/0.831/0.000 ms
root@ubuntu:/# ping web1 -c1
PING web1.web.svc.cluster.local (10.96.144.145) 56(84) bytes of data.
--- web1.web.svc.cluster.local ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
root@ubuntu:/# exit
# 仍然 ping不通 service,因为service只开放80端口
4.4.5 限定端口范围
root@master30:~# vim netpol.yaml
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
4.4.6 多条件规则
只要有一个满足条件就可以访问pod。
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.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 80
# 创建network policy
root@master30:~# kubectl apply -f netpol.yaml
# namespace-web中pod-test可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1
4.5 默认策略
默认允许所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- {}
默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
此策略可以确保即使容器没有选择其他任何 NetworkPolicy,也仍然可以被隔离。 此策略不会更改默认的出口隔离行为。
默认允许所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {}
默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。 此策略不会更改默认的入站流量隔离行为。
默认拒绝所有入口和所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被 允许入站或出站流量。
4.6 无法完成的工作
-
特定于节点的策略。
-
基于名字的策略。
-
实现适用于所有命名空间或 Pods 的默认策略。
-
显式地拒绝策略的能力。NetworkPolicy 的模型默认采用拒绝操作, 其唯一的能力是添加允许策略。
-
**禁止本地回路或指向宿主的网络流量。**Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。
环境清理
root@master30:~# kubectl delete ns network web laoma
root@master30:~# kubectl delete ns web
root@master30:~# kubectl delete ns laoma
出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {}
默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。 此策略不会更改默认的入站流量隔离行为。
默认拒绝所有入口和所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被 允许入站或出站流量。
4.6 无法完成的工作
-
特定于节点的策略。
-
基于名字的策略。
-
实现适用于所有命名空间或 Pods 的默认策略。
-
显式地拒绝策略的能力。NetworkPolicy 的模型默认采用拒绝操作, 其唯一的能力是添加允许策略。
-
**禁止本地回路或指向宿主的网络流量。**Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。
环境清理
root@master30:~# kubectl delete ns network web laoma
root@master30:~# kubectl delete ns web
root@master30:~# kubectl delete ns laoma
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)