多租戶 SaaS 部署
概觀
SaaS 公司為大量租戶營運解決方案。AWS 邊緣服務的多租戶部署 (例如 CloudFront、AWS WAF 等) 需要仔細的設計決策,才能滿足靈活性、成本、可擴展性及營運開銷等業務需求。
架構決策
使用 CloudFront 設計多租戶解決方案時,請考慮下列架構決策:
- 您是為所有租戶使用相同的主機名稱 (例如 saas.com/tenant1、saas.com/tenant2) 還是單獨的主機名稱? 如果使用相同的主機名稱,則可以選擇使用單一 CloudFront 發布部署。
- 如果使用單獨的主機名稱,您是使用相同的網域名稱 (例如 tenant1.saas.com、tenant2.saas.com) 還是單獨的網域名稱 (例如 tenant1.com、tenant2.com)? CloudFront 發布可以與單一 TLS 憑證相關聯,該憑證可以託管多個主機名稱 (SAN 憑證)。如果您使用相同的網域名稱,您可選擇按租戶部署 CloudFront 發布,或為所有租戶部署具有萬用字元 CNAME 及 TLS 憑證 (*.saas.com) 的單一發布。如果網域不同,您可以選擇按租戶部署 CloudFront 發布,或部署多個發布,每個發布都具有最多可託管 100 個不同網域的 SAN 憑證。但是,附加到同一個 TLS 憑證的網域越多,TLS 憑證授權過程的摩擦就越大。
- 誰來控制網域名稱? 如果租戶控制其網域,則需要額外的步驟來將其主機名稱作為 CNAME 新增至 CloudFront 發布。基於安全原因,CloudFront 要求您透過附加涵蓋主機名稱的有效 TLS 憑證來證明您對網域的所有權。租戶需要共用自己的 TLS 憑證,您將該憑證上傳到 ACM,或讓您使用 ACM 代表他們發行 TLS 憑證。對於第二種方法,ACM 要求他們在 DNS 建立 CNAME 權杖,以證明他們對該網域的所有權。
- 租戶是共用相同的內容還是使用不同的內容? 如果他們共用相同的內容,請考慮將共用內容託管在可供不同租戶使用的單一網域。這樣可以提高共用內容的快取命中率。
- 如果您要為多個租戶使用一個 CloudFront 發布,您是在相同的來源還是在不同來源託管租戶? 如果您使用相同的來源 (例如單一 S3 儲存貯體或單一 ALB),則可以透過 URL 路徑或主機標頭區分租戶。如果您選擇此區分租用者的方法,請將主機標頭新增至快取金鑰。如果您使用不同的來源 (例如,每個租戶一個 S3 儲存貯體,或在 ALB 叢集對租戶進行分割),則需要在來源請求事件使用 Lambda@Edge 將流量路由到正確的來源。請注意,如果您使用路徑來區分租戶 (例如 saas.com/tenant1、saas.com/tenant2),您可使用 CloudFront 快取行為將不同租戶原生路由到其來源,但您可以針對每個 CloudFront 發布的行為數量來配額。
- 您的設計是否遵守每個 AWS 服務及每個 AWS 帳戶的 AWS 配額?
在您的設計考慮以下的差異。請注意,您可以針對多層次產品實作差異化權衡。例如,在您控制網域名稱的基本層,所有租戶都會共用相同的 CloudFront 發布。您的頂級租戶將擁有一個專用的 CloudFront 發布,其中包含自訂網域及使用 AWS WAF 的安全保護。
每個租戶都託管在專用的 CloudFront 發布 | 在同一 CloudFront 發布託管多個租戶 | |
可觀測性 | 每個租戶可以原生使用 | 在發布層級可用,需要額外努力使用日誌來提取每個租戶的指標 |
影響範圍 | 變更僅影響一個租戶 | 單一變更會影響所有租戶 |
營運開銷 | 需要大規模自動化,透過大量推出以避免 CloudFront API 層級的限流 | 低 |
自訂 | 每個租戶都可以有自己的不同組態 | 所有租戶都具有相同的組態。當啟用 WAF 時,所有請求都會收費 |
效能 | 每個 CloudFront 發布都需要單獨透過流量進行預熱 (例如與來源的連接) | 所有租戶都受益於溫暖的 CloudFront 發布 |
CloudFront 發布可以連接到單一 AWS WAF WebACL。相同的 WebACL 可以在多個 CloudFront 發布使用。除了以下內容之外,前面提到的衡量也適用於 WAF 部署:
每個租戶使用一個 WebACL | 針對多個租戶使用相同的 WebACL | |
價格 | WebACL/規則成本與租戶數量成線性比例 | WebACL/規則成本與租戶數量無關 |
誤報 | 規則更新可能只會導致單一租戶出現誤報 | 規則更新可能會導致許多單一租戶出現誤報 |
常用案例
每個租戶的子網域
在這種情況下,您可以為每個租戶建立子網域 (tenant1.saas.com)。Route 53 使用萬用字元別名記錄 (*.saas.com) 設定至 CloudFront 發布,也使用萬用字元 CNAME (*.saas.com) 設定,主機標頭包含在快取金鑰。提供動態請求的 ALB 來源原生使用主機標頭來區分租戶。請注意,在此情況下,單一內容失效將適用於所有租戶,因為 CloudFront 失效與快取金鑰的標頭部分 (例如主機標頭) 無關。提供靜態內容的 S3 儲存貯體需要在檢視器請求事件設定的 CloudFront 函數來讀取主機標頭,並將 URL 重寫到 S3 的租戶目錄 (例如 tenant1.saas.com/index.html-> s3://bucket:arn/tenant1/index.html)。如果您從 S3 向所有租戶提供相同的內容,例如相同的單頁應用程式,但使用 API 區分租戶,請考慮這個簡單的解決方案。
如果您託管不同來源的租戶,則需要根據來源請求事件設定的 Lambda@Edge 函數,來將租戶請求路由到託管租戶的來源。若要深入瞭解此實作,請參閱下列案例研究:
擁有自己網域的租戶
在這種情況下,請為每個租戶專用一個 CloudFront 發布,並將程序自動化 (例如,使用 Amazon Certificate Manager 建立發布並發布 TLS 憑證)。請務必事先提高相關配額 (例如每個帳戶分配數、TLS 憑證數量)。在某些情況下,您需要將 CloudFront 發布跨多個 AWS 帳戶分割。
終止伺服器的 TLS
如果 CloudFront 無法滿足您的需求規模,請考慮建立反向 Proxy 機群 (例如以 NLB 及 EC2 為基礎) 以終止 TCP/TLS 連線,並透過 Global Accelerator 來達成更好的安全性與效能。請注意,在這種情況下,您需要在反向 Proxy 達成快取 (如果需要)。