3. 资源模型设计原则:面向租户的CPU、内存、网络带宽资源抽象
在多租户云原生环境中,eBPF网络观测系统必须建立一套清晰的资源模型,将底层物理资源抽象为租户可感知、可配额、可审计的逻辑单元。本章定义面向租户的CPU、内存、网络带宽三大资源的抽象原则,为后续准入控制与调度策略奠定基础。
3.1 资源抽象的三层架构
资源模型采用“物理资源 → 虚拟资源池 → 租户视图”的三层抽象架构,每一层解决不同的关注点:
| 抽象层 | 关注点 | 典型对象 | eBPF观测点 |
|---|---|---|---|
| 物理资源层 | 节点容量、硬件拓扑 | CPU核心、NUMA节点、内存条、网卡 | perf_event、kprobe/sched_switch |
| 虚拟资源池层 | 资源切片、隔离域 | cgroup、CPU份额、内存上限、带宽限速 | cgroup BPF、tc BPF |
| 租户视图层 | 配额管理、用量计量 | 租户ID、资源预留、突发上限 | BPF map(租户维度聚合) |
设计原则:每一层只关注本层职责,下层向上层提供标准化接口。eBPF程序在物理层和虚拟资源池层采集原始数据,在租户视图层完成聚合与记账。
3.2 CPU资源抽象原则
CPU资源抽象的核心目标是:按租户分配计算时间片,并确保观测开销不干扰业务负载。
- 时间片配额(CPU Quota):基于CFS调度器的
cpu.cfs_quota_us与cpu.cfs_period_us,为每个租户设定周期内可使用的CPU时间上限。eBPF通过sched_switchtracepoint采集实际运行时间,与配额对比生成告警。 - 权重分配(CPU Shares):使用
cpu.shares实现弹性竞争,权重高的租户在资源争抢时获得更多时间片。eBPF观测sched_wakeup事件,统计各租户的唤醒延迟。 - 核心绑定(CPU Pinning):对延迟敏感型租户,允许将特定CPU核心独占绑定。eBPF通过
sched_migrate_task跟踪任务迁移,确保绑定策略不被违反。
// eBPF CPU时间采集核心逻辑(伪代码)
struct cpu_account {
u64 runtime_ns;
u64 period_ns;
u64 quota_ns;
};
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, u32); // 租户ID
__type(value, struct cpu_account);
} tenant_cpu_map SEC(".maps");
SEC("tracepoint/sched/sched_switch")
int trace_sched_switch(struct trace_event_raw_sched_switch *ctx) {
u32 tenant_id = get_current_tenant_id();
struct cpu_account *acc = bpf_map_lookup_elem(&tenant_cpu_map, &tenant_id);
if (acc) {
u64 now = bpf_ktime_get_ns();
acc->runtime_ns += now - prev_runtime; // 累加运行时间
}
return 0;
}
3.3 内存资源抽象原则
内存资源抽象强调硬限制与软限制结合,避免OOM影响跨租户稳定性。
| 抽象维度 | cgroup参数 | eBPF观测事件 | 租户视图指标 |
|---|---|---|---|
| 物理内存上限 | memory.max |
cgroup_oom、mm_page_alloc |
当前用量、OOM次数 |
| 内存+交换上限 | memory.swap.max |
vmscan_* 回收事件 |
交换使用率、回收延迟 |
| 内存软限制 | memory.high |
memcg_stat 水位线 |
高压持续时间、throttle次数 |
| NUMA亲和性 | cpuset.mems |
numa_hit/numa_miss |
本地内存访问比例 |
实践建议:内存资源模型应优先使用
memory.high软限制配合eBPF水位线告警,避免硬限制触发OOM Killer导致租户进程被强制终止。仅在关键生产租户上启用memory.max硬限制。
3.4 网络带宽资源抽象原则
网络带宽抽象是eBPF网络观测的核心场景,需要同时覆盖入方向、出方向、连接数、吞吐量四个维度。
- 带宽限速(Bandwidth Shaping):基于
tc BPF或XDP实现每租户流量整形。出方向使用HTB队列,入方向通过ifb设备或XDP限速。 - 连接数限制(Connection Limit):通过
BPF_MAP_TYPE_HASH跟踪每租户活跃连接数,超过阈值时丢包或重置。 - 吞吐量记账(Throughput Accounting):在
XDP或tc BPF入口处统计字节数,按租户ID聚合到BPF map中。
// eBPF网络带宽限速与记账(tc BPF出口方向)
struct bpf_elf_map {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 4096);
__type(key, u32); // 租户ID
__type(value, struct rate_limit);
} tenant_rate_map SEC("maps");
struct rate_limit {
__u64 bytes_quota; // 周期内允许字节数
__u64 bytes_used; // 已使用字节数
__u64 last_update; // 上次更新时间戳
};
SEC("tc")
int tc_egress(struct __sk_buff *skb) {
u32 tenant_id = skb->cb[0]; // 从skb控制块获取租户ID
struct rate_limit *rl = bpf_map_lookup_elem(&tenant_rate_map, &tenant_id);
if (!rl) return TC_ACT_OK;
__u64 now = bpf_ktime_get_ns();
if (now - rl->last_update > 1000000000) { // 每秒重置
rl->bytes_used = 0;
rl->last_update = now;
}
if (rl->bytes_used + skb->len > rl->bytes_quota) {
return TC_ACT_SHOT; // 超过配额,丢包
}
__sync_fetch_and_add(&rl->bytes_used, skb->len);
return TC_ACT_OK;
}
注意:网络带宽抽象必须区分“承诺速率(CIR)”和“突发速率(PIR)”。eBPF限速程序应使用令牌桶算法,允许短时突发但长期平均不超过承诺值。直接丢包会导致TCP重传风暴,建议配合ECN标记进行拥塞通知。
3.5 资源模型协同关系图
下图展示CPU、内存、网络带宽三种资源在eBPF观测视角下的协同关系:
3.6 资源模型设计检查清单
在实际落地资源模型时,建议对照以下清单逐项验证:
- 完备性:是否覆盖CPU、内存、网络带宽三大核心资源?是否遗漏磁盘IO或GPU?
- 可观测性:每种资源的eBPF观测点是否明确?采集频率是否可控?
- 可配额性:租户能否通过API查询当前配额和已用量?
- 隔离性:一个租户的资源耗尽是否会影响其他租户的观测数据?
- 性能开销:eBPF程序在资源采集路径上的CPU开销是否低于1%?
- 可扩展性:新增资源类型(如eBPF map大小)是否需要修改核心模型?
核心结论:面向租户的资源模型不是简单的“配额+监控”,而是通过eBPF在底层实现细粒度观测,在上层提供统一的租户视图。CPU、内存、网络带宽三种资源虽然抽象方式不同,但都遵循“物理→虚拟→租户”的三层架构,并通过BPF map实现跨资源的数据关联。