멀티 테넌트 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 배포는 여러 호스트 이름(SAN 인증서)을 호스팅할 수 있는 단일 TLS 인증서와 연결할 수 있습니다. 동일한 도메인 이름을 사용하는 경우 테넌트별로 CloudFront 배포를 배포하거나 모든 테넌트에 대해 와일드카드 CNAME 및 TLS 인증서(*.saas.com)가 포함된 단일 배포를 배포하도록 선택할 수 있습니다. 도메인이 서로 다른 경우 테넌트별로 CloudFront 배포를 배포하거나 각각 최대 100개의 서로 다른 도메인을 호스팅할 수 있는 SAN 인증서가 있는 여러 배포를 배포할 수 있습니다. 하지만 동일한 TLS 인증서에 더 많은 도메인을 연결할수록 TLS 인증서 발급 프로세스에 마찰이 가중됩니다.
- 도메인 이름은 누가 관리하나요? 테넌트가 도메인을 제어하는 경우 CloudFront 배포에 호스트 이름을 CNAME으로 추가하려면 추가 단계가 필요합니다. 보안상의 이유로 CloudFront에서는 호스트 이름을 포함하는 유효한 TLS 인증서를 첨부하여 도메인 소유권을 증명해야 합니다. 테넌트는 ACM에 업로드할 자체 TLS 인증서를 공유하거나 사용자가 ACM을 사용하여 테넌트를 대신해 TLS 인증서를 발급하도록 허용해야 합니다. 두 번째 접근 방식을 사용하는 경우 ACM은 도메인의 소유권을 증명하기 위해 DNS에 CNAME 토큰을 생성하도록 요구합니다.
- 테넌트가 동일한 콘텐츠를 공유하나요, 아니면 다른 콘텐츠를 공유하나요? 공통 콘텐츠를 공유하는 경우 서로 다른 테넌트가 사용할 수 있는 단일 도메인에 공유 콘텐츠를 호스팅하는 것을 고려해 보세요. 이를 통해 공유 콘텐츠의 캐시 적중률이 향상됩니다.
- 여러 테넌트에 대해 CloudFront 배포를 사용하는 경우 동일한 오리진에서 테넌트를 호스팅하나요, 아니면 다른 오리진에서 테넌트를 호스팅하나요? 동일한 오리진을 사용하는 경우(예: 단일 S3 버킷 또는 단일 ALB) URL 경로 또는 호스트 헤더별로 테넌트를 구분할 수 있습니다. 테넌트를 구별하는 데 이 방법을 선택하는 경우 캐시 키에 Host 헤더를 추가하세요. 다른 오리진을 사용하는 경우(예: 테넌트당 하나의 S3 버킷 또는 ALB 클러스터의 샤딩 테넌트) 트래픽을 올바른 오리진으로 라우팅하려면 오리진 요청 이벤트에 Lambda@Edge가 필요합니다. 참고로 경로를 사용하여 테넌트를 구분하는 경우(예: saas.com/tenant1, saas.com/tenant2), CloudFront 캐시 동작을 사용하여 기본적으로 서로 다른 테넌트를 오리진으로 라우팅할 수 있지만 CloudFront 배포당 동작 수에 대한 할당량이 있습니다.
- 설계가 AWS 서비스 및 AWS 계정별 AWS 할당량을 준수하나요?
설계 시 다음과 같은 절충점을 고려하세요. 멀티 티어 제품에 대한 차별화된 절충안을 구현할 수 있습니다. 예를 들어 도메인 이름을 제어하는 기본 계층에서는 모든 테넌트가 동일한 CloudFront 배포를 공유합니다. 프리미엄 테넌트는 각각 사용자 지정 도메인과 AWS WAF를 사용한 보안 보호 기능을 갖춘 전용 CloudFront 배포를 갖게 됩니다.
각 테넌트는 전용 CloudFront 배포에서 호스팅됩니다. | 여러 테넌트는 동일한 CloudFront 배포에서 호스팅됩니다. | |
관찰성 | 테넌트당 기본적으로 사용 가능 | 배포 수준에서 사용할 수 있으며, 로그를 사용하여 테넌트당 지표를 추출하려면 추가 작업이 필요합니다. |
영향 범위 | 변경은 하나의 테넌트에만 영향을 미칩니다. | 한 번의 변경으로 모든 테넌트에 영향을 미칩니다. |
운영 오버헤드 | CloudFront API 수준에서의 제한을 피하기 위해 일괄 롤아웃을 통해 대규모 자동화가 필요합니다. | 낮음 |
사용자 지정 | 각 테넌트는 자체적으로 다른 구성을 가질 수 있습니다. | 모든 테넌트에 동일한 구성. WAF를 활성화하면 모든 요청에 대해 요금이 청구됩니다. |
성능 | 각 CloudFront 배포는 트래픽에 의해 개별적으로 준비되어야 합니다(예: 오리진과의 연결). | 모든 테넌트는 강화된 CloudFront 배포의 이점을 활용할 수 있습니다. |
CloudFront 배포는 단일 AWS WAF WebACL에 연결할 수 있습니다. 동일한 WebACL을 여러 CloudFront 배포에서 사용할 수 있습니다. 앞서 언급한 장단점은 다음 사항 외에도 WAF 배포에도 적용됩니다.
테넌트당 WebACL 사용 | 여러 테넌트에 동일한 WebACL 사용 | |
요금 | WebACL/규칙 비용은 테넌트 수에 따라 선형적으로 규모 조정됩니다. | WebACL/규칙 비용은 테넌트 수와 무관합니다. |
오탐 | 규칙 업데이트는 단일 테넌트에서만 오탐을 일으킬 수 있습니다. | 규칙 업데이트는 많은 단일 테넌트에서 오탐을 일으킬 수 있습니다. |
일반 사용 사례
테넌트당 하위 도메인
이 시나리오에서는 모든 테넌트에 대해 하위 도메인(tenant1.saas.com)을 생성합니다. Route 53은 CloudFront 배포에 와일드카드 별칭 레코드(*.saas.com)로 구성되며, 캐시 키에 Host 헤더가 포함된 와일드카드 CNAME(*.saas.com)으로도 구성됩니다. 동적 요청을 제공하는 ALB 오리진은 Host 헤더를 사용하여 기본적으로 테넌트를 구별합니다. 이 시나리오에서는 단일 콘텐츠 무효화가 모든 테넌트에 적용됩니다. CloudFront 무효화는 Host 헤더와 같은 캐시 키의 헤더 부분에 영향을 받지 않기 때문입니다. 정적 콘텐츠를 제공하는 S3 버킷에는 Host 헤더를 읽고 S3의 테넌트 디렉터리에 URL을 다시 쓰기 위해 최종 사용자 요청 이벤트에 구성된 CloudFront Function가 필요합니다(예: tenant1.saas.com/index.html -> s3://bucket:arn/tenant1/index.html). S3의 모든 테넌트에 동일한 콘텐츠를 제공하지만(예: 동일한 단일 페이지 애플리케이션) API로 테넌트를 차별화하는 경우 이 간단한 솔루션을 고려해 보세요.
다른 오리진에서 테넌트를 호스팅하는 경우, 테넌트 요청을 테넌트를 호스팅하는 오리진으로 라우팅하려면 오리진 요청 이벤트에 구성된 Lambda@Edge 함수가 필요합니다. 이 구현에 대해 자세히 알아보려면 다음 사례 연구를 읽어보세요.
- OutSystems는 Lambda@Edge를 사용하여 NLB 클러스터 간에 테넌트를 라우팅하여 OutSystems가 NLB 클러스터 전체에 이 라우팅을 구현한 방법을 알아봅니다.
- Arc XP는 Lambda@Edge를 사용하여 S3 버킷 간에 테넌트를 라우팅합니다.
자체 도메인이 있는 테넌트
이 시나리오에서는 각 테넌트에 대해 전용 CloudFront 배포를 지정하고 프로세스를 자동화합니다(예: Amazon Certificate Manager를 사용하여 배포 생성 및 TLS 인증서 발급). 사전에 관련 할당량(예: 계정당 배포 수, TLS 인증서 수)을 늘려야 합니다. 경우에 따라 여러 AWS 계정 간에 CloudFront 배포를 샤딩해야 합니다.
서버에서 TLS 종료
CloudFront에서 요구 사항의 규모를 충족할 수 없는 경우, TCP/TLS 연결을 종료하기 위한 리버스 프록시 플릿(예: NLB 및 EC2 기반)을 구축하고, 보안 및 성능 향상을 위해 프론트 Global Accelerator를 구축하는 것을 고려해 보세요. 참고로 이 시나리오에서는 필요한 경우 리버스 프록시에 캐싱을 구현해야 합니다.