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 大小上限共同约束。

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 隔离模型的统一架构:从底层内核资源到上层租户策略引擎的映射关系。

多租户 eBPF 隔离架构总览 多租户 eBPF 隔离架构总览 租户层 租户 A (Pod) | 租户 B (VM) | 租户 C (Serverless) eBPF 策略引擎 map 分片 | cgroup 绑定 | 资源配额 | 白名单过滤 cgroup-bpf 钩子 syscall / sock / cgroup per-租户 cgroup 路径 eBPF map 分片 hash_of_maps / per-cpu 租户 key 隔离 资源限制层 memlock / map 上限 per-租户 quota Pod 运行时 containerd / crio VM 运行时 qemu / cloud-hypervisor Serverless 沙箱 gVisor / Firecracker 架构说明: 1. 租户层通过 cgroup id / VM id / 请求 id 映射到策略引擎。 2. 策略引擎将隔离规则下发给内核层的三个子模块,实现数据、执行、资源三维隔离。 3. 运行时载体负责执行实际的计算任务,eBPF 程序在宿主机内核中完成监控与阻断。

4.5 场景特化:Pod 与 VM 的隔离边界对比

Pod 和 VM 是当前最主流的两种多租户载体,它们的隔离边界在 eBPF 视角下存在本质差异。下图从系统调用可见性和网络隔离两个维度进行对比:

Pod 与 VM 隔离边界对比 Pod 与 VM 隔离边界对比(eBPF 视角) Pod 场景(共享内核) 系统调用可见性: - eBPF 可捕获 Pod 内所有 syscall(open/exec/connect) - 通过 cgroup-bpf 按 cgroup id 过滤 网络隔离: - 共享宿主机网络栈,eBPF 可拦截 Pod 间流量 - 使用 BPF_MAP_TYPE_SK_LOOKUP 做透明代理 威胁暴露面: - 高:侧信道、容器逃逸、内核漏洞 - eBPF 需做细粒度 syscall 白名单 VM 场景(独立内核) 系统调用可见性: - 宿主机 eBPF 只能看到 VM 进程(如 qemu) - VM 内部 syscall 对宿主机不可见 网络隔离: - 通过 vhost/virtio 虚拟化,eBPF 可拦截 VM 网卡流量 - 需要关联 VM ID 与网络包元数据 威胁暴露面: - 低:VM 内部攻击无法直接触及宿主机内核 - eBPF 主要防御 VM 间网络攻击和资源滥用 结论:Pod 场景需要更强的 eBPF 内省能力来补偿共享内核带来的安全风险;VM 场景则更依赖宿主机侧的流量和资源监控。

4.6 隔离模型设计原则

综合三类场景的威胁模型,我们提炼出以下设计原则,作为后续准入控制和架构实现的指导:

  1. 最小可见性:eBPF 程序只能访问其绑定的租户上下文数据,禁止全局 map 遍历。
  2. 资源硬限制:每个租户的 eBPF 内存、指令数、map 条目数必须在 cgroup 层面做硬配额。
  3. 上下文强绑定:所有 eBPF 事件必须携带租户标识(cgroup id / VM id / 请求 id),并在用户态做二次校验。
  4. 可审计性:所有跨租户操作(如 map 更新、程序加载)必须记录审计日志,支持回放。
  5. 场景自适应:同一套 eBPF 程序应能通过配置适配 Pod、VM、Serverless 三种场景,而非为每种场景重写。
设计原则落地检查清单:
- 是否每个 eBPF map 都包含租户 key 字段?
- 是否每个 eBPF 程序都通过 cgroup-bpf 或 bpf_get_current_cgroup_id() 做了租户过滤?
- 是否每个租户的 memlock 上限都小于内核默认值?
- 是否在用户态实现了租户 map 的创建/销毁生命周期管理?