SaaS架构:多租户管理
不少小伙伴对Saas多租户管理,按需部署等感兴趣,极特收集了下小伙伴们的提问,总结下大概关心的有以下几块:租户管理、资源隔离、弹性部署和全方位监控。
今天,极特跟大家一起详细拆解这四大支柱的架构设计与落地实践,一起学习探讨。
租户管理
租户管理是SaaS的起点,定义了如何识别、隔离和服务客户。
租户识别
多租户Saas应用需要准确地识别请求来自哪个租户。常见租户识别方式有四种,适用于不同场景。
URL路径 (saas.com/tenant1)
最简单直接的方式,租户ID明确地写在URL里。
- 实现逻辑:在 URL 路径中,截取租户 ID 作为tenant_id。
// 伪代码 tenant_id = request.path.split('/')[1]; - 优点:实现简单,成本低,不用复杂的DNS配置。
- 缺点:URL不够美观,品牌感弱。
子域名 (tenant1.saas.com)
最主流、体验最好的方式。每个租户都拥有专属的二级域名。
- 实现逻辑:从请求头中解析出子域名部分作为tenant_id。
// 伪代码 host = request.headers['Host']; // "tenant1.saas.com" tenant_id = host.split('.')[0]; - 进阶(自定义域名):需要自定义域名的客户,可以将客户自己的域名 CNAME 到 SaaS 平台指定地址。网关层映射Host和tenant_id,实现动态路由。
HTTP头 (X-Tenant-ID: tenant1)
适合程序间的API调用。
- 怎么做:客户端在每次请求的HTTP头里,都加上一个类似 X-Tenant-ID: tenant1的字段。网关或应用中间件拿到这个值,就知道是谁来了。
- 优点:对URL没有影响,看起来很清爽,很适合后端服务之间的通信。
- 缺点:需要调用方配合,不适合普通用户通过浏览器访问的场景。
JWT令牌
这是一种将身份认证和租户识别合二为一的聪明做法。
- 怎么做:用户登录成功后,服务端返回的JWT令牌里,除了包含用户信息,再额外塞一个tenant_id字段。之后用户的每次请求都会带上这个令牌,服务端解开一看,用户身份和所属租户就都清楚了。
- 优点:安全、无状态,一次登录解决了两个问题,效率很高。
- 缺点:依赖登录,无Token,则无租户。
这些方式也可以组合使用,提供统一的租户解析服务,按 子域名 -> JWT -> Header 的优先级顺序进行识别,适应各种复杂的业务场景。

这几种方式的实现难度和灵活性各不相同,但核心都是识别租户,然后路由。其中自定义域名对后端的动态SSL证书处理能力要求最高,这正是我们下一节要解决的问题。
SSL自动化
工程师的注意力是生产资源,不该消耗在证书续期这种问题上。这种重复、没有创造力、又极易出错的劳动,必须100%自动化。
在K8s中,cert-manager就是你的自动化大厨:
- 安装大厨:在集群中部署
cert-manager。 - 告知菜谱:配置一个
ClusterIssuer,告诉它去哪家菜市场(如Let’s Encrypt)买食材(证书)。 - 下单:为租户的
Ingress加上一个注解,相当于下个订单。
之后,这位大厨会自动帮你买菜、洗菜、炒菜、上菜,甚至盘子脏了还会自动洗(证书到期自动续签),你只需坐享其成。

租户生命周期管理
除了识别租户,我们还需要一套完整的流程来管理租户从注册到注销的全过程。这套流程的自动化程度,直接决定了你的运维成本和客户体验。
- 开通 (Provisioning):新租户注册时,系统需要自动准备好一切:创建独立的数据库或Schema、初始化默认配置和权限、分配存储空间等。实现客户拎包入住。
- 配置 (Configuration):不同租户有不同需求。需要提供一个管理后台,让租户可以自定义功能、界面主题,或者对接自己公司的SSO。
- 状态管理 (State Management):租户的状态不是非黑即白的。除了“启用/禁用”,还应该有更丰富的状态,比如
TRIAL(试用中)、ACTIVE(活跃)、SUSPENDED(因欠费暂停)、ARCHIVED(已归档)。每种状态都对应不同的功能限制和数据保留策略,实现精细化运营。 - 销户 (Deprovisioning):客户决定离开时,提供清晰、体面的流程。一般不会立即删除数据,会先将租户置为ARCHIVED状态,保留数据一段时间(如30天)。宽限期过后,再通过自动化脚本彻底清理,既对客户数据负责,也可以回收资源。
资源隔离
做SaaS,本质是做数字房东。不能光收租,物业管理也要做好。最怕什么?某个租户疯狂用水,全楼水流就骤减。
做好资源隔离,是SaaS服务的生命线。
怎么做?
Kubernetes 就是最好的物业工具箱。其中两样工具最关键:requests 和 limits。
- requests(资源预留):基础水压。保证每家住户正常洗漱做饭的最低供应。
- limits(资源上限):总阀门。硬性规定每户用水上限,超了立即限制,保护整栋系统。
CPU和内存的超限处理不同:
- CPU limits:超了,服务变慢(节流),但不中断。
- 内存 limits:超了,服务会被立刻掐断,然后重启。不这么做的话,整个节点的蓄水池(内存)都会被用光,大家都没水用。
# 典型的Pod资源配置示例
apiVersion: v1
kind: Pod
metadata:
name: tenant-b-pod
spec:
containers:
- name: app
image: my-saas-app
resources:
requests:
memory: "256Mi" # 基础水量:256 Mebibytes内存
cpu: "250m" # 基础水压:0.25个CPU核心
limits:
memory: "512Mi" # 用水上限:内存上限512 Mebibytes
cpu: "500m" # 水流上限:CPU上限0.5个CPU核心
不同的限制配置与要 SaaS 服务不同套餐挂钩,就是商业模式在技术上的落地。付多少钱,用多少水,公平合理。
按需部署
按需部署,就是当且仅当有需求时才使用资源。核心就一个词:缩容到零 (Scale to Zero)。
从HPA到KEDA
最基础的弹性工具是HPA (Horizontal Pod Autoscaler)。像个勤奋的保安,看到人多了(CPU/内存升高)就多开几个门,人少了就关掉几个。
但HPA有个局限:它至少得留一个门开着。它无法做到在空无一人时,把所有门都锁上。
这时候,KEDA (Kubernetes-based Event-Driven Autoscaling)登场了。
KEDA 不再关心人多人少,而是关心有没有事要做。监听各种事件源:消息队列里有没有新消息?数据库里有没有新订单?是不是到了凌晨两点该跑批处理了?
- 有事做:KEDA立刻从零启动一个或多个服务来处理。
- 没事做:处理完毕,所有服务立刻原地解散,缩容到零,不占用一分钱的计算资源。
KEDA跟走廊的声控灯类似,有人走过才亮,人走了就灭。而HPA,更像是一盏必须24小时开着的小夜灯。
# 一个使用Kafka作为事件源的KEDA ScaledObject示例
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: kafka-consumer-scaler
spec:
scaleTargetRef:
name: report-generator-deployment # 需要伸缩的Deployment
minReplicaCount: 0 # 关键:允许缩容到零
maxReplicaCount: 10
triggers:
- type: kafka
metadata:
# ... kafka配置 ...
lagThreshold: "5" # 队列里积压了5条消息,就开始扩容
GitOps
GitOps 的核心思想就一句话:Git仓库是描述你整个系统最终状态的唯一真理之源。
别再手动敲kubectl了,那是原始人的做法。
现代化的SaaS部署流程应该是这样:
- 新租户注册-> 自动生成一套部署蓝图(YAMLs) -> 提交到Git仓库。
- ArgoCD/Flux-> 像一个永不疲倦的监工,时刻盯着蓝图。
- 蓝图变更-> 监工立刻在集群里施工,让现实与蓝图保持绝对一致。
结果是什么?每一次变更都是一次commit,每一次回滚都是一次revert。你得到了完美的审计日志和掌控时间的能力。这才是管理一个SaaS帝国的正确姿势。
全方位监控
没有监控,SaaS系统就是个黑盒子。客户比你先发现问题,你就输了。监控,就是让你拥有上帝视角的工具。它由三块拼图组成:Metrics, Logging, Tracing。
Metrics:仪表盘
- 它是什么?系统的生命体征。CPU、内存、QPS、延迟…这些数字告诉你系统是健康还是亚健康。
- 抓手是什么?Prometheus+ Grafana。
- 唯一原则:所有指标都必须打上 tenant_id标签。没有这个,你的多租户监控就是个笑话。
PromQL查询示例 (找出最活跃的5个租户):topk(5, sum(rate(http_requests_total{job=”my-saas-app”}[5m])) by (tenant_id))
Logging:行车记录仪
- 它是什么?事故发生后的现场录像。每一行日志都可能是破案的关键线索。
- 抓手是什么?Loki或 EFK。
- 唯一原则:所有日志必须是JSON格式,并且必须包含 tenant_id字段。否则,在海量日志里找一个特定租户的问题,无异于大海捞针。
Tracing:GPS导航
- 它是什么?一次请求的完整旅行地图。它告诉你请求经过了哪些服务,在每一站停留了多久。
- 抓手是什么?Jaeger或 SkyWalking。
- 唯一原则:在链路的起点,就把 tenant_id作为关键标签(Tag)钉上去。
- 有了它,发现请求慢的时候,不用再对着整个城市的地图发呆,马上调出专属路径图,问题马上就能定位。

写在最后
打造一个成功的SaaS产品,是一场精细的平衡艺术。
我们常常被新功能的需求所驱动,但真正支撑这座大厦不倒的,是那些看不见的地基——租户管理、资源隔离、按需部署和全方位监控。
将这四大支柱打磨好,我们才能在快速变化的市场中,拥有持续交付价值的底气和从容。
最后编辑:Jeebiz 更新时间:2025-10-19 11:12