SaaS 關鍵設計 - Multi-Tenancy - 探討真實世界的租賃關係
多租戶架構 (Mulit-Tenancy Architecture, 以下稱作 MTA)
是 SaaS (Software as a Service, 軟體及服務)
設計的核心議題,也是我過去幾年工作研究的題目之一,大部分的人針對這個題目討論的多是 K8s 的 Namespace 劃分、或者資料庫的拆分方式、使用 Single or Shared / Hybrid … 等策略。
多租戶架構背後需要討論的,除了這些技術架構的議題,更重要的是往前一步:
SaaS 的
多租戶
應該怎麼定義?以及能夠解決那些問題?
基於這些討論與實踐,最後我提出設計 MTA 的關鍵抽象概念,我把它稱為 Isolation Factor (隔離因子)
。
這篇文章嘗試解釋與探討 多租戶
背景與核心議題,同時用真實世界的租賃關係,剖析設計 SaaS 時必須要知道的概念,嘗試帶出 Isolation Factor 的重要性。
相關文章:
真實世界裡的租賃關係
在真實的世界中,有幾種角色關係:
房東 (Landlord)
:出租房子的人成為房東- 英文用詞:Landlord, Landlady
- 物件在法律上的資產擁有者,具備
擁有權
- 對於物件有
管理權
以及使用權
- 承租合約成立區間,不具備使用權
房客 (Lodger)
:指的是房子的承租者 (人) - 中文叫做租戶
、房客
、承租人
、或佃戶
- 英文用詞:Lodger、Tenant
- 承租對象的是房東提供的
承租物件
- 在雙方約定的時間範圍之內,房客
具備
承租物件的使用權
- 約定時間之內,非特定情境,房東
不具備
承租物件的使用權
承租物件 (Object)
:與租戶對應的房子稱為承租物件 (Object)
、出租處- 英文用詞:老美稱為 apartment、英國稱為 flat。
- 承租物件內部使用稱為使用權,物件以外稱為管理權
- 物件以外,在真實世界稱為公共空間、公共設施、公共區域 … etc.
合約 (Rental Agreements)
:指房東 / 租戶 雙方對於 承租物件 的使用權 承諾- 合約包含以下資訊:
房客 (who)
識別資訊,通常是個人身份、職業,目的是用來識別法律上的效益。- 允許使用的
時間範圍 (when)
- 對於承租物件的
權利與義務 (what)
- 更多參閱 Rental agreement
- 用詞:tenancy (租賃),通常用在房屋、土地等不動產的
- 合約包含以下資訊:
承租 (Lease, v)
:租戶向房東簽訂使用合約,整個動作稱為承租
使用權
: 泛指承租者 (房客) 在合約期限內,對於承租物件的使用範圍,其中包含承租物件本身以及公共區域的使用權管理權
: 承租物件內部與外部的管制與控制擁有權 (Ownership)
: 泛指資產在法律上賦予的擁有權
這些關係稱為 租賃 (Tenancy)
,概念如下圖所示:
了解基本租賃的幾個角色、關係之後,我想把主軸放在 房東
、承租物件
、房客
這三者的關係,然後套到的 SaaS 設計裡。
註:雖然房客 (Lodger) 的英文也可以是 Tenant 這個字,但是實際上中文口語上描述
租戶
的時候,可以意指人 (房客)
、或者是承租物件 (Object)
,通常要看前後文判斷,本文會直接使用 Object 直接代表承租房子,避免語意錯置。
其他專有名詞
- 垂直權限
- 水平權限
- 仿登入 (impersonate), 概念類似 sudo / run as xxx
- RBAC (Role-Based Access Control)
- ABAC (Role-Based Access Control)
背景探討:各種租賃組合
租賃關係的排列組合
Multi-Tenancy
這個字,中文翻譯成:多租戶
,字面上看似容易理解,但在設計與實作時,卻很容易做出有問題的設計。接下用 房東 (Landlord)
、承租物件 (Object)
、以及 房客 (Lodger)
,三者的數量關係,分別探討各種形式的租賃關係。
三個變動因子,每個變動因子都有 一個
或 多個
兩種選項,其排列組合列舉如下表:
探討過程,我會嘗試用真實世界的案例帶入,如果沒有舉例的,可能是我自己經歷不夠、想像力不足,或者是 … 排列組合根本就不合理。
首先先從 多租戶
這個詞的相對詞:單一租戶 Single Tenant
切入。
Case A: Single Tenant
Single Tenant
指的是 一個房東
可以提供 一個物件
給 一個房客
承租 ,完成 一個租賃合約
,這三者的關係如下圖:
這三者是一對一對一的關係:
房東:承租物件:房客 = 1:1:1
生活中常見的例子,像是一個大樓的 (一個) 房東,將一整棟大樓租賃給一家企業。
- 一個房東
- 一棟大樓
- 一家企業
Case B: Multiple Tenant
房東只有一個物件可以承租給房客?雖然有,但是不是普通鄉民會接觸的。
生活中更多的例子會是一個房東同時擁有多個物件可以出租,也就是 一個房東
可以提供 多個物件
給 多個房客
承租 ,完成 多個租賃合約
,這三者的關係如下圖:
這三者的關係是:
房東:承租物件:房客 = 1:N:N
注意,這裡描述 承租物件
與 房客
兩者是一對一關係,也就是每一個物件,只承租給一個客戶。不是一個物件,承租給多個客戶,這種結構在最後會描述。
在真實世界的租賃中,承租物件已經具備明確的 邊界 (Border)
,像是房屋都具備具象化的牆壁、隔間、房門等邊界,所以房內屬於私人區域、以外則公共區域,公私領域的邊界是清楚,且明確的。
而所謂的 多租戶
這個詞背後隱含的是:
相對於房東而言,也就是我們都是站在房東角度在論述。
這句話很重要,請留意思考的切入角度 (角色),本文全文的論述其實都是房東角度。
Case C
上述 Case A: Single Tenant
和 Case B: Multiple Tenant
是真實世界常見的例子,屬於正常、合理的例子。
接下來我們來探討第三個例子,其結構如下圖:
這三者關係是:
房東:承租物件:房客 = 1:N:1
這個意思是,一個房東,擁有 N 個物件,但是都租給同一個房客,會有這樣的案例?現實生活中,也許有吧?不曉得 … 貧窮限制我的想像啊。。。。
Case D
排列組合還有,繼續推演下一個狀況:
這三者關係是:
房東:承租物件:房客 = 1:1:N
這個狀況的意思是:
一個房東的其中一個物件,同時租給多個房客,背後有多個契約。
真實案例像是青年旅館,一個大通鋪,一堆人住一個晚上。在 IT 系統裡,有點像是一家公司申請一個 AWS Account,在裡面部署一套系統,這套系統,同時租賃給多個客戶使用。
探討
上一段整理了四個排列組合,真實世界的運作往往會比這些單一排列組合更複雜,更多的是複合式的組合。
我們就用這四個為基礎單位,探討真實世界的組合。
探討一:Case X1 = Case B + D
上述 Case B / D 有著很類似的概念,不過看到這裡的讀者可能腦袋也打結了 XD
重新整理這兩者的關係如下:
Case B:
房東:承租物件:房客 = 1:N:N
Case D
房東:承租物件:房客 = 1:1:N
把這兩個 Case 合併成 Case X1
如下圖:
用 AWS 的角度舉例說明,圖中的角色分別如下:
- Landlard: AWS
- Object: AWS Account
- Lodgers: AWS IAM 裡的 User
這個例子,如果用過 AWS 的人應該不難理解,不過要留意的是,每個 AWS Account 裡的資源彼此是看不到彼此的,像是:
User#A @ Object#A
是無法直接跟User#A @ Object#B
對話的Object#B
是無法得知Object#A
裡有哪些 UsersUser#A @ Object#A
不等於User#A @ Object#B
上面的描述,背後隱含的關鍵意義就是 Object 之間是 隔離
的,而且是強制性的隔離。
換 GCP 的例子:
- Landlard: GCP
- Object: GCP Project
- Lodgers: GCP Project IAM User
這個也不難理解,同樣可以舉例出 Object 之間隔離的概念,也完全與 AWS 一致。
GCP 與 AWS 的隔離概念稱為 垂直權限 (Vertical Authority)
繼續下一個例子是 K8s:
- Landlard: K8s Cluster
- Object: by Namespace
- Lodgers: Application or Developer
K8s 開始出現一個狀況,所謂的 Namespace 只是邏輯概念切割,也就是資源之間的並不是 強隔離
。
探討二:二房東 Case X2
上述 Case E 用 AWS / GCP / K8s 當例子,但更多時候企業在發展自己的業務狀況會是這樣:
把 Object#A
拆分,自己變成二房東,租一個物件,但是這個物件拆分成 N 個,每個再租給其他的使用者。
而如何把 Object#A 拆分的好與壞,就在於隔離的實作。
前面提到在真實世界的租賃中,承租物件已經具備明確的 邊界 (Border)
,但是承租 AWS 的企業,又把這個 SaaS 承租給他們的客戶,而對於 SaaS 客戶而言,邊界應該、必須要存在,而這個邊界則需要由 SaaS 公司在架構設計時,必須自己建立一道讓客戶以為的邊界,這個邊界,在本文中稱為 隔離 (Isolation)
。
隔離的核心議題: Isolation Factor (隔離因子)
本質上來講,隔離是透過一種 邊界 (Boundary)
方式,區分租戶彼此之間的空間範圍。
房子來講,區分彼此的空間範圍就是樑柱、牆壁、門、地板、天花板 … 等;以企業內部來講,就是各種辦公室的實體隔間、以及特定角色授權;以應用程式來說,就是使用者 A 能否看到使用 B 的資料而言。依照這樣的隔離概念,底下這些都是犯規:
- 企業大樓裡,未經授權的員工,進入機房
- 企業員工在 AWS 上開台機器,沒有認證授權,方便自己進出公司網域
- SRE 說:我的 Gmail 看到別人的信,就要把 Gmail shutdown! –> 相關報導
- 薩爾達傳說 - 王國之淚: 看我通天術 (這嚴重犯規 XDD)
實體隔離與邏輯隔離
在商業應用程式裡,隔離則因為 領域 (Domains)
不同,會用不同的方式,商業應用角度多半會以 邏輯隔離
為主。
邏輯隔離的例子,舉例常見的概念:
- Google 服務 (Gmail / Gmap / Docs …) 都是以 Gmail Account 為隔離單位
- GCP 以 Project 為隔離單位
- AWS 則以 Account 為單位
- Chrome 這個瀏覽器則以 Profile 為隔離概念
- 多租戶架構的電商平台,隔離則是以
店
為單位,像是 91APP 是開店平台 - 教育平台,則是以學校為單位,像是 Teachable 這個平台
- 開學校之後,每個學校都可以有自己的學生、自己的老師 .. 等角色定義
- 作業系統的隔離:Linux 的系統權限 user-group-anyone 本質上就是種隔離
- 資料庫的隔離:Database / Table / Row 都是隔離概念,更甚者則是交易過程的鎖。
上述的隔離,在權限系統稱為 垂直權限
,也就是透過 帳號 (通常)
隔離彼此。除了垂直權限,相對則是 水平權限
,概念如下圖:
但是當業務發展到一定程度之後,或者依照法規的需求,則很常會以期望實體隔離,也就是在實體的系統架構,就是 專用 (Dedicated)
資源,不與其他人共用。
不管是實體還是邏輯隔離,都需要一個關鍵因子來定義怎麼隔離?而這個隔離的關鍵因子我把它稱為 隔離因子 (Isolation Factor)
前面描述的手段與方法都是為了達到隔離:
- 權限:多租戶架構常用的方法是
垂直權限
- 相對於垂直權限,稱為
水平權限
,實踐方式有 RBAC、ABAC
- 相對於垂直權限,稱為
- 實體隔離 (physical isolation)
- 邏輯隔離 (logical isolation): 虛擬化 virtualization, VPC
AWS 服務的隔離因子
AWS 有很多服務,舉凡 EC2 / S3 / DynamoDB / CloudFront … etc. 這些服務在 AWS 裏面都需要計算隔離方式,但是每個服務本身的屬性不一樣,在設計的時候怎麼知道每個服務的隔離因子是什麼?底下列舉設計 AWS 服務要考慮的隔離因子:
- EC2: Instance
- S3: Bucket
- DynamoDB: Table
- CloudFront: Distribution
- VPC 本身就是個隔離單位
上述列舉的是這些服務的隔離因子例子,因為每個服務特性有所差異,要對應到 AWS Account 時,就要具體用一個單位對應隔離的想法,不然就會無法對應。
隔離沒做好會怎樣?
這是隔離背後要解決的關鍵痛點,最經典的案例是下圖:
Source: Google儲存SRE團隊負責人第一手經驗大公開, by ITHome, 20160421
另一個經典案例則是 VPC 的問題,底下截圖則是中國知名技術專家 陳皓 的部落格:
Source: 关于阿里云经典网络的问题, by Coolshell, 20200419
這都是別人的問題,而我面對過的問題則是之前在電商工作時,曾經出現的問題,我把它稱為 A-c-B event
,中文稱為 A 店跨 B 店
。也就是 B 店的使用者,看到 A 店的資料,不管是商品資料、還是訂單資料。
這三個例子,資安角度都是 垂直權限
的問題,背後實際問題就是隔離的設計與實踐。
updated 2023/09/29: 最近發生的 Google Bard臭蟲讓用戶對話出現在公開Google搜尋結果中 也屬於隔離沒做好造成的。
跨租戶問題常見的做法
雖然說跨租戶是不允許的,但是生活中還是有很多場景,需要跨租戶存取,例如我們信用卡掛失的時候,客服人員可以幫你調整信用卡的狀態。客服人員代替你調整信用卡的過程,就是個跨租戶操作,不管怎樣他要操作設定的時候,都要獲得你的允許,然後才能幫你調整狀態。這樣的過程,其實就是個身份暫時轉換,代理 (delegate) 執行的過程。
類似的做法,在作業系統已經都有很成熟的做法:
- Linux: sudo as XXX
- Windows: Run as XXXX
在系統實作時,專有名詞為 impersonate (v)
,也就是 User#A@Tanent#A as User#B@Tenant#B
,這是個需要授權程序的。
在 AWS 的設計,幾種常見的例子:
- 當 Account#A 要存取 Account#B 得時候,可以透過 STS 取得臨時授權
- 當網路要相互連線時,需要透過雙方授權才能連結,像是 VPC Peering
小結
下圖是一張網路梗圖:
Source: https://www.facebook.com/groups/it.humor.and.memes/posts/24452121121053675/
圖中在 Windows 裡裝了 VMWare,然後裡面裝了 Windows,裡面再裝 VMWare … 如此好幾層 … 這張圖表述了多租戶的核心概念,不過大家知道 VM 本身是模擬硬體,換言之實作的是實體隔離。相對於 VM 則是 Container,透過 Kernal 的特性 (cgroup, namespace … etc),時做出隔離的概念。
而應用程式如果要做出隔離概念,則必定要面對如何定義租戶的概念,租戶本質就是為了達到隔離,用來隔離的 隔離因子 (Isolation Factor)
,則是本文想帶出的概念。
多租戶架構因而衍生的相關議題:
- 水平權限系統,像是 RBAC / ABAC,也就是 AWS IAM
- 衍生的則是 API 認證授權與通訊協議,相關參閱 API 設計 - 摘要 API 通訊模式與協議
- 租戶與
功能
的訂閱市集 (Marketplace),背後本質是個 Pub/Sub 概念 - 帳務系統:延續租戶與功能訂閱而產生的議題,也就是使用狀況 (Usage) 與帳務資訊 (Billing)
- 功能系統的通訊架構,相關參閱 摘要 Eclipse 設計的啟發:當代 SaaS 分散式架構的關鍵設計
延伸閱讀
站內文章
參考資料
- Multitenancy
- Comparison of approaches to multitenancy in Rails apps
- Best practices for enterprise multi-tenancy - GKE
- General Design Concepts
- K8s 相關
- 資料庫相關
- AWS
- Architectural design patterns for multi-tenancy on AWS
- Configure Amazon Forecast for a multi-tenant SaaS application - AWS Machine Learning Blog, 20210325
- How to implement SaaS tenant isolation with ABAC and AWS IAM - AWS Security Blog, 20210609
- Ten tips for multi-tenant, multi-Region object replication in Amazon S3 - AWS Storage Blog, 20211101
- Build and load test a multi-tenant SaaS database proxy solution with Amazon RDS Proxy - AWS Database Blog, 20211113
- 在亚马逊云科技Marketplace上的SaaS架构设计——如何支持多产品使用单一账户中心 - 20210813
- Isolating SaaS Tenants with Dynamically Generated IAM Policies - AWS Partner Network (APN) Blog, 20200921
- How to secure multi-tenant applications with AppSync and Cognito