3. 平台设计原则:面向租户的多租户架构、数据隔离策略、权限模型(RBAC/ABAC)设计

在自助服务可观测性平台中,多租户架构是支撑企业级规模化运营的基石。平台需要同时服务于多个业务团队(租户),每个租户拥有独立的资源视图、数据边界和操作权限。设计核心在于平衡资源共享效率与租户隔离安全性。

3.1 多租户架构模型

多租户架构通常分为三种模式,每种模式在隔离性、成本和运维复杂度上各有取舍:

模式 隔离粒度 资源效率 运维复杂度 适用场景
独立实例(Silo) 每个租户独占一套完整服务实例 低(资源重复) 高(实例管理) 金融、合规要求极高的租户
共享实例(Pool) 所有租户共享同一套服务实例 高(资源复用) 低(统一运维) 内部开发测试环境、SaaS 标准版
混合模式(Bridge) 核心服务共享,数据存储按租户分区 中(平衡) 中(需路由逻辑) 大多数企业级可观测性平台
推荐实践:采用混合模式作为默认架构。将计算层(查询引擎、告警引擎)共享以降低成本,存储层(时序数据库、日志索引)按租户物理或逻辑分区,确保数据安全。
多租户混合架构(Bridge 模式) 租户 A(业务线 1) 租户 B(业务线 2) 租户 C(业务线 3) 共享接入层(API Gateway / 认证中心) 共享计算层(查询引擎 / 告警引擎 / 聚合服务) 租户 A 存储分区 租户 B 存储分区 租户 C 存储分区

3.2 数据隔离策略

数据隔离是多租户设计的核心安全防线。根据可观测性数据类型(指标、日志、链路),隔离策略需分层实施:

  • 物理隔离:租户使用独立的数据库实例或独立的索引集群。隔离性最强,但成本最高,适用于合规敏感租户。
  • 逻辑隔离:共享同一存储集群,通过租户 ID(tenant_id)字段进行数据分区。成本低,但需确保查询路由层强制注入租户上下文。
  • 混合隔离:热数据(近期高频查询)采用逻辑隔离以降低成本;冷数据(历史归档)采用物理隔离以满足合规要求。
关键设计点:所有数据写入和查询路径必须经过租户上下文拦截器。该拦截器从认证 中提取租户 ID,自动附加到 SQL 查询、PromQL 查询或日志搜索请求中,防止跨租户数据泄露。
数据隔离策略对比 物理隔离 租户 A 独立集群 租户 B 独立集群 租户 C 独立集群 隔离性:★★★★★ 成本:高 运维:复杂 逻辑隔离 共享存储集群 tenant_id 分区 查询强制过滤 租户上下文拦截器 隔离性:★★★☆☆ 成本:低 运维:简单 混合隔离 热数据:逻辑隔离 冷数据:物理隔离 自动数据迁移策略 隔离性:★★★★☆ 成本:中 运维:中等

3.3 权限模型设计:RBAC 与 ABAC

权限模型决定了租户内用户能看到什么和能做什么。可观测性平台通常采用 RBAC(基于角色的访问控制)作为基础,并在精细场景下引入 ABAC(基于属性的访问控制)。

3.3.1 RBAC 核心设计

RBAC 通过“用户 → 角色 → 权限”的映射关系简化授权管理。在可观测性平台中,建议预定义以下角色:

角色 权限范围 典型操作
租户管理员 租户内全部资源 管理用户、配置告警规则、管理数据保留策略
运维工程师 指定服务/环境 查看仪表盘、查询日志、创建临时告警
只读用户 指定仪表盘/视图 查看预置仪表盘、查看告警通知
审计员 操作日志与访问记录 查看用户操作审计、导出审计报告

3.3.2 ABAC 扩展场景

当权限控制需要更细粒度时,ABAC 基于用户属性、资源属性和环境条件动态计算权限。典型场景包括:

  • 时间窗口限制:仅允许在工作时间(09:00-18:00)执行高危操作(如删除数据源)。
  • 环境属性过滤:开发工程师只能查看 environment=dev 或 environment=staging 的指标,不能访问生产环境。
  • 数据标签匹配:用户只能访问带有 team=payment 标签的仪表盘和告警。
设计陷阱:ABAC 策略引擎会增加查询延迟(每次请求需计算策略)。建议将 ABAC 用于数据行级过滤(如标签过滤),而将功能级权限(如能否创建告警)保留在 RBAC 中,避免性能瓶颈。

3.4 权限模型与数据隔离的协同

多租户架构、数据隔离和权限模型三者必须协同工作,形成完整的访问控制链路:

  1. 认证阶段:用户登录后,平台从 中解析出 tenant_id 和 user_id。
  2. 授权阶段:RBAC 引擎根据用户角色判定是否允许执行请求的操作(如查询、创建、删除)。
  3. 数据过滤阶段:ABAC 引擎(如启用)根据资源标签和用户属性进一步过滤返回的数据行。
  4. 存储隔离阶段:查询路由层将 tenant_id 注入到存储查询中,确保只访问该租户的数据分区。
// 伪代码:权限与隔离协同流程
function handleRequest(user, request) {
    // 1. 认证
    tenantId = extractTenantFromToken(user.);
    
    // 2. RBAC 授权
    if (!rbacEngine.authorize(user.role, request.action, request.resource)) {
        return 403 Forbidden;
    }
    
    // 3. ABAC 数据过滤(可选)
    filterExpr = abacEngine.buildFilter(user.attributes, request.resource.attributes);
    
    // 4. 注入租户隔离条件
    query = request.query + " WHERE tenant_id = " + tenantId;
    if (filterExpr) {
        query += " AND " + filterExpr;
    }
    
    // 5. 执行查询
    return storageEngine.execute(query);
}
最佳实践:在平台设计初期,将 tenant_id 作为所有数据模型的必选标签。无论是指标、日志还是链路数据,写入时强制注入租户 ID,查询时强制过滤。这是防止数据泄露最有效的一行代码。