4. 租户隔离模型设计:多租户场景分类与隔离边界
多租户隔离模型的设计核心在于:识别租户的运行时载体,并针对每种载体定义清晰的隔离边界与威胁模型。在 Kubernetes 生态中,租户的载体形态主要分为三类:Pod、VM 和 Serverless。每种形态对 eBPF 的可见性、系统调用拦截能力和资源抽象层次都有不同的要求。
4.1 多租户场景分类
下表从资源抽象层次、隔离粒度、eBPF 挂载点三个维度对比三种典型场景:
| 场景 | 资源抽象层次 | 隔离粒度 | eBPF 典型挂载点 | 租户标识来源 |
|---|---|---|---|---|
| K8s Pod | 容器 cgroup + namespace | 进程组 / 容器 | tracepoint/syscall、cgroup hooks | cgroup id、pod label、container id |
| VM | Hypervisor + 独立内核 | 虚拟机 / 宿主机 | kprobe、tracepoint(宿主机侧) | VM ID、vCPU 调度上下文 |
| Serverless | 函数沙箱 / microVM | 单次调用 / 函数实例 | seccomp + eBPF 辅助(受限) | 请求 ID、函数 ARN、sandbox pid |
实践要点:在 Pod 场景中,eBPF 程序可以通过
bpf_get_current_cgroup_id() 直接获取租户上下文;而在 VM 场景中,宿主机 eBPF 程序通常只能看到 VM 进程(如 qemu),需要额外关联 VM 元数据。
4.2 隔离边界定义
隔离边界是指 eBPF 程序在数据采集、策略执行和资源消耗三个维度上的作用范围。定义清晰的边界是防止租户间信息泄露和资源抢占的前提。
- 数据边界:eBPF map 必须按租户分片,禁止跨租户读取。使用
BPF_MAP_TYPE_HASH_OF_MAPS或BPF_MAP_TYPE_ARRAY_OF_MAPS实现租户级 map 隔离。 - 执行边界:eBPF 程序通过 cgroup-bpf 或
BPF_PROG_TYPE_SK_LOOKUP绑定到特定 cgroup 层级,确保只处理目标租户的网络流量或系统调用。 - 资源边界:通过
BPF_MAP_TYPE_PERCPU_ARRAY和RLIMIT_MEMLOCK限制每个租户的 eBPF 内存开销,防止恶意租户耗尽内核资源。
边界定义公式:
隔离边界 = (数据域 ∩ 执行域) ∪ 资源配额
其中数据域由 map 分片策略决定,执行域由 cgroup 绑定路径决定,资源配额由内核 rlimit 和 map 大小上限共同约束。
隔离边界 = (数据域 ∩ 执行域) ∪ 资源配额
其中数据域由 map 分片策略决定,执行域由 cgroup 绑定路径决定,资源配额由内核 rlimit 和 map 大小上限共同约束。
4.3 威胁模型分析
针对三类场景,我们识别出以下核心威胁,并给出 eBPF 层面的缓解策略:
| 威胁编号 | 威胁描述 | 影响场景 | eBPF 缓解手段 |
|---|---|---|---|
| T1 | 跨租户 map 遍历 | Pod、VM | map 分片 + bpf_spin_lock 防止越界 |
| T2 | 系统调用侧信道 | Pod、Serverless | seccomp 白名单 + eBPF 过滤高频 tracepoint |
| T3 | eBPF 程序资源耗尽 | 全部 | cgroup 级别的 memlock 限制 + map 大小上限 |
| T4 | 宿主机内核信息泄露 | VM | 限制 kprobe 挂载点,仅允许 tracepoint 白名单 |
| T5 | 函数实例复用导致上下文残留 | Serverless | 每次调用前重置 per-packet map 状态 |
关键风险:在 VM 场景中,宿主机 eBPF 程序如果挂载了
kprobe/sys_open,理论上可以捕获所有 VM 的文件访问路径。必须通过 VM ID 白名单和 bpf_probe_read_str 的地址校验来限制数据可见性。
4.4 多租户隔离架构总览
下图展示了三种场景下 eBPF 隔离模型的统一架构:从底层内核资源到上层租户策略引擎的映射关系。
4.5 场景特化:Pod 与 VM 的隔离边界对比
Pod 和 VM 是当前最主流的两种多租户载体,它们的隔离边界在 eBPF 视角下存在本质差异。下图从系统调用可见性和网络隔离两个维度进行对比:
4.6 隔离模型设计原则
综合三类场景的威胁模型,我们提炼出以下设计原则,作为后续准入控制和架构实现的指导:
- 最小可见性:eBPF 程序只能访问其绑定的租户上下文数据,禁止全局 map 遍历。
- 资源硬限制:每个租户的 eBPF 内存、指令数、map 条目数必须在 cgroup 层面做硬配额。
- 上下文强绑定:所有 eBPF 事件必须携带租户标识(cgroup id / VM id / 请求 id),并在用户态做二次校验。
- 可审计性:所有跨租户操作(如 map 更新、程序加载)必须记录审计日志,支持回放。
- 场景自适应:同一套 eBPF 程序应能通过配置适配 Pod、VM、Serverless 三种场景,而非为每种场景重写。
设计原则落地检查清单:
- 是否每个 eBPF map 都包含租户 key 字段?
- 是否每个 eBPF 程序都通过 cgroup-bpf 或
- 是否每个租户的 memlock 上限都小于内核默认值?
- 是否在用户态实现了租户 map 的创建/销毁生命周期管理?
- 是否每个 eBPF map 都包含租户 key 字段?
- 是否每个 eBPF 程序都通过 cgroup-bpf 或
bpf_get_current_cgroup_id() 做了租户过滤?- 是否每个租户的 memlock 上限都小于内核默认值?
- 是否在用户态实现了租户 map 的创建/销毁生命周期管理?