3. 多租户隔离栈总体架构:控制平面 vs 租户平面
多租户隔离栈的核心设计理念在于将系统的管理职责与业务运行职责进行物理与逻辑上的分离。这种分离通过构建两个明确的平面来实现:控制平面与租户平面。控制平面负责全局资源调度、策略下发与监控告警;租户平面则承载每个租户独立的业务负载与数据。
核心原则:控制平面是“大脑”,租户平面是“四肢”。大脑负责决策与协调,四肢独立执行任务,互不干扰。
3.1 控制平面 vs 租户平面职责对比
| 维度 | 控制平面 | 租户平面 |
|---|---|---|
| 核心职责 | 全局资源管理、租户生命周期管理、策略下发、监控与告警聚合 | 运行租户业务应用、处理业务数据、提供业务API |
| 部署位置 | 独立的 Kubernetes 集群或高可用主机组 | 共享基础设施层上的独立 Docker Compose 栈 |
| 网络策略 | 对外暴露管理 API,对内连接所有租户平面 Agent | 默认隔离,仅通过反向代理或 API 网关暴露业务端口 |
| 数据存储 | 全局配置数据库、租户元数据、审计日志 | 租户私有数据库、文件存储、缓存 |
| 故障影响范围 | 影响新租户创建与全局监控,但不影响已有租户业务 | 仅影响单个租户,其他租户完全不受影响 |
3.2 共享基础设施层
共享基础设施层是支撑所有租户平面运行的底层资源池,包括计算、存储、网络三大核心资源。该层由控制平面统一管理,但租户平面通过资源配额与隔离机制实现安全共享。
- 计算资源池:由多台 Docker 主机组成,通过 Docker Swarm 或 Kubernetes Node 进行统一编组。控制平面根据租户规格动态分配 CPU 与内存配额。
- 存储资源池:采用分布式存储(如 Ceph、GlusterFS)或 NAS 共享存储。每个租户拥有独立的存储卷,通过 Docker Volume 驱动进行挂载与隔离。
- 网络资源池:使用 Overlay 网络(如 Docker Overlay、Calico)实现跨主机通信。每个租户拥有独立的网络命名空间与 IP 段,通过 iptables 或 eBPF 实现网络隔离。
调优建议:共享基础设施层建议预留 20% 的冗余资源用于突发流量与故障转移。存储层优先使用 SSD 缓存池,以降低租户数据库的 I/O 延迟。
3.3 每个租户独立 Compose 栈的设计模式
每个租户的完整业务栈被封装为一个独立的 Docker Compose 项目。这种设计模式确保了租户间的强隔离,同时保持了部署与运维的标准化。
3.3.1 独立 Compose 栈的组成要素
| 组件 | 说明 | 隔离方式 |
|---|---|---|
| 应用容器 | 租户的业务服务,如 Web 应用、API 服务、Worker 进程 | 独立容器、独立网络别名 |
| 数据库容器 | 租户私有数据库实例,如 MySQL、PostgreSQL、Redis | 独立数据卷、独立端口映射 |
| 消息队列容器 | 租户内部异步通信组件,如 RabbitMQ、Kafka | 独立容器、独立网络 |
| 反向代理容器 | 租户业务的入口网关,如 Nginx、Traefik | 独立端口映射、独立 SSL 证书 |
| 监控 Agent 容器 | 采集租户容器指标与日志,上报至控制平面 | 独立容器、共享控制平面网络 |
3.3.2 标准化 Compose 文件模板
控制平面通过模板引擎(如 Go Template、Jinja2)为每个租户生成 Compose 文件。以下是一个典型的多租户 Compose 栈模板片段:
version: '3.8'
services:
app:
image: {{ .TenantImage }}
container_name: "{{ .TenantID }}_app"
environment:
- DB_HOST=db
- DB_NAME={{ .TenantDBName }}
- REDIS_HOST=redis
networks:
- tenant_net
deploy:
resources:
limits:
cpus: '{{ .CPULimit }}'
memory: {{ .MemoryLimit }}
db:
image: mysql:8.0
container_name: "{{ .TenantID }}_db"
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_DATABASE={{ .TenantDBName }}
- MYSQL_USER={{ .TenantDBUser }}
- MYSQL_PASSWORD={{ .TenantDBPass }}
networks:
- tenant_net
redis:
image: redis:7-alpine
container_name: "{{ .TenantID }}_redis"
networks:
- tenant_net
nginx:
image: nginx:alpine
container_name: "{{ .TenantID }}_nginx"
ports:
- "{{ .ExternalPort }}:80"
volumes:
- ./nginx/{{ .TenantID }}.conf:/etc/nginx/conf.d/default.conf
networks:
- tenant_net
networks:
tenant_net:
driver: overlay
attachable: true
volumes:
db_data:
driver: local
关键注意点:每个租户的 Compose 项目必须使用独立的
project_name(通过 -p 参数指定),否则 Docker 会因资源名称冲突导致部署失败。建议使用租户 ID 作为项目名称前缀。
3.4 多租户隔离栈总体架构图
下图展示了控制平面与租户平面之间的逻辑关系,以及共享基础设施层如何支撑多个独立 Compose 栈的运行:
3.5 设计模式总结与最佳实践
模式总结:“控制平面统一管理 + 租户平面独立 Compose 栈”是一种经过生产验证的多租户隔离架构。它结合了集中管控的便利性与资源隔离的安全性,特别适合 SaaS 平台、DevOps 工具链、数据中台等场景。
- 资源配额硬限制:在 Compose 文件中使用
deploy.resources.limits为每个租户设置 CPU 与内存上限,防止单个租户资源滥用影响共享基础设施。 - 网络策略最小化:每个租户的 Compose 栈使用独立的 Overlay 网络,仅暴露必要的业务端口。控制平面通过独立的 API 网关与租户 Agent 通信。
- 存储卷生命周期管理:租户删除时,控制平面自动清理对应的 Docker Volume 与 Compose 项目,避免残留数据占用存储空间。
- 监控 Agent 标准化:每个租户栈内置监控 Agent(如 cAdvisor、Filebeat),将指标与日志推送至控制平面的聚合层,实现统一的可观测性。