17.10.4 RBAC与多租户隔离策略
RBAC与多租户隔离在Prometheus生态中通常通过“入口控制+数据隔离+操作审计”共同实现。Prometheus本身缺少内置细粒度RBAC,需要借助反向代理、授权网关或多实例拆分来满足多租户需求。多租户隔离的目标包括:查询与可视化隔离、告警规则隔离、写入与远程存储隔离,以及对元数据与目标发现的控制。
原理草图(入口鉴权 + 多租户查询)#
RBAC实现路径#
- 反向代理授权:在Prometheus与Grafana前端通过Nginx/Envoy接入OIDC/LDAP,基于用户组映射到读/写/管理员角色。
- 查询层控制:使用Thanos Query Frontend、Cortex/Mimir或自建API网关,在查询请求中注入租户标识(如
X-Scope-OrgID),并基于租户策略限制PromQL与时间范围。 - 规则管理控制:将告警规则、记录规则存储在Git仓库,使用GitOps与CI审批流程控制变更权限,运行时由不同租户的Ruler实例加载。
多租户隔离策略#
- 物理隔离:每个租户独立Prometheus与Alertmanager实例,资源与数据完全隔离,适合合规要求高的场景。
- 逻辑隔离:共享后端存储,通过租户ID或标签进行隔离,依赖Cortex/Mimir/Thanos等组件实现。
- 标签隔离约束:统一约定
tenant/team等标签,强制在采集配置和告警规则中注入,配合网关进行标签强制校验与重写。
告警与通知隔离#
- Alertmanager多实例或路由隔离:按租户维度设置接收器与路由,禁止跨租户的告警转发与合并。
- Webhook权限控制:为每个租户配置独立的Webhook密钥与回调地址,限制告警模板可访问的标签范围。
安全边界与运维规范#
- 最小权限原则:读写分离,限制查询时间范围与高基数标签查询,防止资源滥用。
- 变更审计:所有RBAC策略与规则变更必须有审计记录,包含操作者、时间、变更内容与回滚方案。
- 配额与限流:对每租户的查询频率、并发、告警数量设定配额,防止单租户影响整体稳定性。
典型落地方案示例#
- 入口使用OIDC登录,映射
viewer/editor/admin角色。 - Prometheus通过反向代理统一鉴权,Grafana使用组织与文件夹隔离视图。
- 远程存储采用Mimir,按租户ID隔离指标,Alertmanager路由按租户分组。
示例:Nginx反向代理实现基础RBAC + 租户头注入#
目标:为不同用户注入X-Scope-OrgID,限制访问Prometheus与Thanos Query Frontend。
安装Nginx(示例)#
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y nginx apache2-utils
# CentOS/RHEL
sudo yum install -y nginx httpd-tools
创建用户与租户映射文件#
# 生成基础认证用户
sudo htpasswd -c /etc/nginx/htpasswd prom_viewer
sudo htpasswd /etc/nginx/htpasswd prom_admin
Nginx配置(/etc/nginx/conf.d/prometheus_rbac.conf)#
map $remote_user $tenant_id {
default "public";
prom_viewer "team-a";
prom_admin "team-admin";
}
server {
listen 80;
server_name prom.example.com;
# 基础认证
auth_basic "Prometheus RBAC";
auth_basic_user_file /etc/nginx/htpasswd;
# Prometheus只读
location / {
proxy_pass http://prometheus:9090;
proxy_set_header X-Scope-OrgID $tenant_id;
proxy_set_header X-Forwarded-User $remote_user;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Thanos Query Frontend
location /thanos/ {
proxy_pass http://thanos-query-frontend:10902/;
proxy_set_header X-Scope-OrgID $tenant_id;
proxy_set_header X-Forwarded-User $remote_user;
}
}
生效与验证#
sudo nginx -t
sudo systemctl reload nginx
# 验证用户访问与头注入
curl -u prom_viewer:密码 -I http://prom.example.com/
curl -u prom_admin:密码 -H "X-Scope-OrgID:team-admin" -I http://prom.example.com/thanos/
关键参数说明
- auth_basic_user_file: 指定账号密码文件。
- map $remote_user $tenant_id: 将用户映射为租户ID。
- X-Scope-OrgID: 多租户查询头,Cortex/Mimir/Thanos支持。
示例:Grafana组织与文件夹隔离#
目标:不同租户只看到自己的仪表盘与告警规则。
Grafana组织与权限(命令行或API)#
# 创建组织
curl -X POST -H "Content-Type: application/json" \
-u admin:admin \
-d '{"name":"team-a"}' \
http://grafana:3000/api/orgs
# 为组织添加用户
curl -X POST -H "Content-Type: application/json" \
-u admin:admin \
-d '{"loginOrEmail":"user_a","role":"Viewer"}' \
http://grafana:3000/api/orgs/2/users
预期效果:team-a 用户只能访问自己的组织、文件夹与仪表盘。
示例:Prometheus采集强制租户标签#
目标:所有采集目标自动注入tenant标签,便于规则与查询隔离。
prometheus.yml#
global:
scrape_interval: 15s
scrape_configs:
- job_name: "node"
static_configs:
- targets: ["node1:9100", "node2:9100"]
labels:
tenant: "team-a"
验证(PromQL)#
up{tenant="team-a"}
预期效果:查询仅返回team-a租户的目标。
示例:Alertmanager按租户路由#
目标:不同租户告警只发到自己接收器。
alertmanager.yml#
route:
group_by: ["alertname", "tenant"]
receiver: "default"
routes:
- match:
tenant: "team-a"
receiver: "team-a-webhook"
- match:
tenant: "team-b"
receiver: "team-b-webhook"
receivers:
- name: "default"
- name: "team-a-webhook"
webhook_configs:
- url: "https://webhook.example.com/team-a?token=xxx"
- name: "team-b-webhook"
webhook_configs:
- url: "https://webhook.example.com/team-b?token=yyy"
预期效果:tenant=team-a的告警不会发送到team-b。
排错清单(常见问题与定位)#
-
访问被拒绝(401/403)
- 检查/etc/nginx/htpasswd是否包含用户
-nginx -t是否通过,查看/var/log/nginx/error.log -
租户隔离失效(看到其他租户数据)
- 检查是否注入X-Scope-OrgID
- 检查后端是否启用多租户模式(Cortex/Mimir) -
Grafana看到其他组织仪表盘
- 检查用户角色(Viewer/Editor/Admin)
- 确认组织切换权限和文件夹权限 -
告警跨租户发送
- 检查告警规则是否写入tenant标签
-Alertmanager的group_by是否包含tenant
练习#
- 反向代理练习:新增用户
prom_team_b,映射tenant_id为team-b,验证X-Scope-OrgID是否生效。 - 规则隔离练习:为
team-a编写一条告警规则,只匹配tenant="team-a"的目标。 - Grafana隔离练习:创建
team-b组织和文件夹,验证team-a用户无法访问。 - 故障注入:临时移除
tenant标签,观察告警路由是否出现跨租户发送并恢复配置。