多租户隔离与配置指南
当你的 coomia-dip 平台需要服务多个组织或部门时,多租户隔离变得至关重要。每个租户需要独立的数据空间、独立的 Ontology 定义、独立的权限体系,同时共享底层基础设施以降低运维成本。
“系列:S12 开发者教程 · 第 18 篇 | 难度:中级 | 阅读时间:15 分钟
多租户隔离与配置指南
#引言
当你的 coomia-dip 平台需要服务多个组织或部门时,多租户隔离变得至关重要。每个租户需要独立的数据空间、独立的 Ontology 定义、独立的权限体系,同时共享底层基础设施以降低运维成本。
coomia-dip 采用"逻辑隔离 + 物理共享"的混合模式:Ontology Schema、数据存储、权限策略在逻辑上完全隔离,但共享 Control Layer、Data Layer 和 Intelligence Layer 的计算资源。本教程将带你完成多租户平台的配置和管理。
#1. 多租户架构
#1.1 隔离模型
coomia-dip 的多租户隔离分为三个层次:
| 层次 | 隔离方式 | 实现机制 |
|---|---|---|
| Ontology 层 | 每租户独立 Schema | Namespace 前缀隔离 |
| 数据层 | 每租户独立 Database | Doris 多 Database |
| 权限层 | 每租户独立 RBAC | 租户级角色和策略 |
| 计算层 | 共享,资源配额限制 | K8s ResourceQuota |
| 网络层 | 共享,请求路由隔离 | 请求头 X-Tenant-ID |
#1.2 租户标识传播
每个 API 请求都必须携带租户标识。coomia-dip 支持两种方式:
# 方式 1:通过 Token 自动识别
# JWT Token 中包含 tenant_id claim
platform = OntoPlatform(
base_url="http://localhost:8080",
token="eyJ...", # 包含 tenant_id: "acme-corp"
)
# tenant_id 自动从 token 中提取
# 方式 2:显式指定
platform = OntoPlatform(
base_url="http://localhost:8080",
token="admin-token",
tenant_id="acme-corp", # 管理员可以切换租户
)
#2. 创建和管理租户
#2.1 创建租户
from ontology_sdk import OntoPlatform
admin = OntoPlatform(
base_url="http://localhost:8080",
token="super-admin-token",
)
# 创建新租户
tenant = admin.tenants.create(
tenant_id="acme-corp",
display_name="ACME Corporation",
config={
"max_object_types": 100,
"max_objects_per_type": 1_000_000,
"max_concurrent_queries": 50,
"data_retention_days": 365,
"features": {
"reasoning_engine": True,
"ai_functions": True,
"temporal_workflows": True,
"flink_cdc": False, # 未购买此功能
},
},
admin_user={
"username": "admin@acme.com",
"email": "admin@acme.com",
"role": "TENANT_ADMIN",
},
)
print(f"Tenant created: {tenant.tenant_id}")
#2.2 资源配额
admin.tenants.set_quota("acme-corp", {
"cpu_cores": 4,
"memory_gb": 16,
"storage_gb": 100,
"api_rate_limit": 1000, # 每分钟请求数
"concurrent_workflows": 20,
"max_users": 50,
})
#2.3 租户数据隔离
当创建租户时,coomia-dip 自动执行以下操作:
- 在 Doris 中创建独立 Database:
onto_acme_corp - 在 Kafka 中创建独立 Topic 前缀:
onto.acme-corp.* - 在 Ontology 注册表中创建独立 Namespace:
acme-corp - 初始化租户级 RBAC 策略
-- Doris 中的租户数据库
CREATE DATABASE IF NOT EXISTS onto_acme_corp;
-- 每个 Object Type 对应一张表
CREATE TABLE onto_acme_corp.order (
_rid VARCHAR(64) NOT NULL,
_created_at DATETIME NOT NULL,
_updated_at DATETIME NOT NULL,
_deleted BOOLEAN DEFAULT FALSE,
order_id VARCHAR(64),
customer_id VARCHAR(64),
total_amount DOUBLE,
status VARCHAR(32),
-- ...
) ENGINE=OLAP
UNIQUE KEY(_rid)
DISTRIBUTED BY HASH(_rid) BUCKETS 8;
#3. 租户级 Ontology 管理
#3.1 独立的 Object Type 定义
每个租户可以定义自己的 Object Type,互不影响:
# 以 acme-corp 租户身份操作
acme = OntoPlatform(
base_url="http://localhost:8080",
token="acme-admin-token",
)
# ACME 定义自己的 Order 类型
acme.ontology.create_object_type(
name="Order",
properties={
"orderId": {"type": "STRING", "primary_key": True},
"customerName": {"type": "STRING"},
"totalAmount": {"type": "DOUBLE"},
"internalCode": {"type": "STRING"}, # ACME 特有字段
},
)
# 另一个租户可以有完全不同的 Order 定义
beta = OntoPlatform(base_url="http://localhost:8080", token="beta-admin-token")
beta.ontology.create_object_type(
name="Order",
properties={
"orderId": {"type": "STRING", "primary_key": True},
"buyerEmail": {"type": "STRING"}, # Beta 特有字段
"currency": {"type": "STRING"}, # Beta 特有字段
"amount": {"type": "DOUBLE"},
},
)
#3.2 共享 Object Type 模板
平台管理员可以定义共享模板,租户可以基于模板创建并扩展:
# 管理员创建模板
admin.ontology.create_template(
name="StandardOrder",
properties={
"orderId": {"type": "STRING", "primary_key": True},
"customerId": {"type": "STRING"},
"totalAmount": {"type": "DOUBLE"},
"status": {"type": "STRING"},
"createdAt": {"type": "TIMESTAMP"},
},
description="Standard order object type template",
)
# 租户基于模板创建并扩展
acme.ontology.create_from_template(
template="StandardOrder",
name="Order",
additional_properties={
"internalCode": {"type": "STRING"},
"department": {"type": "STRING"},
},
)
#4. 跨租户数据共享
#4.1 数据共享协议
在某些场景下,租户之间需要共享部分数据(如供应链上下游):
# 创建数据共享协议
admin.tenants.create_sharing_agreement(
provider_tenant="acme-corp",
consumer_tenant="beta-inc",
shared_object_types=["Product"],
shared_properties=["productId", "productName", "category"], # 只共享部分字段
access_mode="READ_ONLY",
expiry="2026-12-31",
)
#4.2 联邦查询
# Beta 租户查询 ACME 共享的产品数据
beta_result = beta.oql.execute("""
SELECT p.productId, p.productName, p.category
FROM acme-corp::Product p
WHERE p.category = 'Electronics'
""")
#5. 租户监控与治理
#5.1 使用量监控
# 查看租户使用情况
usage = admin.tenants.get_usage("acme-corp")
print(f"Object Types: {usage.object_type_count} / {usage.quota.max_object_types}")
print(f"Total Objects: {usage.total_object_count}")
print(f"Storage: {usage.storage_used_gb:.1f} / {usage.quota.storage_gb} GB")
print(f"API Calls (today): {usage.api_calls_today}")
print(f"Active Users: {usage.active_users}")
#5.2 成本分摊
# 获取租户资源消耗报告
report = admin.tenants.get_cost_report(
tenant_id="acme-corp",
period="2025-03",
)
print(f"Compute hours: {report.compute_hours:.1f}")
print(f"Storage GB-months: {report.storage_gb_months:.1f}")
print(f"API calls: {report.api_calls}")
print(f"Estimated cost: ${report.estimated_cost:.2f}")
#5.3 租户生命周期
# 暂停租户(停止所有计算,保留数据)
admin.tenants.suspend("acme-corp", reason="Payment overdue")
# 恢复租户
admin.tenants.activate("acme-corp")
# 归档租户(冷存储,可恢复)
admin.tenants.archive("acme-corp")
# 删除租户(不可逆!需二次确认)
admin.tenants.delete("acme-corp", confirm_phrase="DELETE acme-corp PERMANENTLY")
#6. 安全最佳实践
#6.1 网络隔离
- 每个租户的 gRPC 请求通过
X-Tenant-IDHeader 路由 - 服务端验证 Token 中的 tenant_id 与请求的 tenant_id 一致
- 数据库查询自动注入租户过滤条件,防止跨租户数据泄漏
#6.2 审计日志
# 查看租户审计日志
logs = admin.tenants.get_audit_logs(
tenant_id="acme-corp",
event_types=["LOGIN", "DATA_ACCESS", "SCHEMA_CHANGE"],
from_time="2025-03-01",
to_time="2025-03-31",
)
for log in logs:
print(f"[{log.timestamp}] {log.user} - {log.event_type}: {log.details}")
#6.3 合规导出
# GDPR 数据导出
export = admin.tenants.export_data(
tenant_id="acme-corp",
format="JSON",
include_schema=True,
include_audit_logs=True,
)
print(f"Export ready: {export.download_url}")
#总结
本教程覆盖了 coomia-dip 多租户平台的完整管理流程:租户创建与配额设置、独立 Ontology 管理、跨租户数据共享、使用监控与成本分摊、安全审计与合规导出。多租户隔离是 coomia-dip 作为 PaaS 平台的核心能力,让你用一套基础设施安全地服务多个组织。
下一篇:[S12-19] 生产环境上线检查清单 上一篇:[S12-17] OSDK TypeScript 前端集成指南