跳转到主要内容
Chinese, Simplified

 

Created by Tabby Ward (AWS), Susmitha Reddy Gankidi (AWS), Vijai Anand Ramalingam (AWS), and Danil Ko (AWS)

Code repository:

Environment: PoC or pilot

Technologies: Modernization; Cloud-native; SaaS; DevOps

Workload: Open-source

AWS services: AWS CloudFormation; Amazon DynamoDB; Amazon DynamoDB Streams; AWS Lambda; Amazon API Gateway

总结

软件即服务(SaaS)应用程序可以使用各种不同的架构模型构建。筒仓模型是指为租户提供专用资源的体系结构。

SaaS应用程序依赖于一个无摩擦的模型来将新租户引入其环境。这通常需要协调多个组件,以成功地调配和配置创建新租户所需的所有元素。在SaaS架构中,这个过程被称为租户入职。对于每个SaaS环境,应通过将基础设施用作入职流程中的代码来实现入职完全自动化。

此模式将指导您完成一个创建租户并在Amazon Web Services(AWS)上为租户提供基本基础设施的示例。该模式使用C#和AWS云开发工具包(AWS CDK)。

因为这种模式会产生计费警报,所以我们建议在美国东部(北弗吉尼亚州)或美国东部1号AWS地区部署堆栈。有关更多信息,请参阅AWS文档。

先决条件和限制

先决条件

  • 活跃的AWS帐户。
  • 具有足够AWS身份和访问管理(IAM)访问权限的用户,可以为此模式创建AWS资源。有关详细信息,请参阅IAM角色。
  • 具有编程访问密钥的用户。有关更多信息,请参阅在AWS帐户中创建IAM用户。
  • Amazon命令行界面(AWS CLI)。
  • 下载并安装了Visual Studio 2022或下载并安装Visual Studio代码。
  • AWS Toolkit for Visual Studio安装。
  • .NET Core 3.1或更高版本(C#AWS CDK应用程序需要)
  • 已安装Amazon.Lambda.Tools。

局限性

  • AWS CDK使用AWS CloudFormation,因此AWS CDK应用程序受CloudFormation服务配额限制。有关更多信息,请参阅AWS CloudFormation配额。
  • 租户CloudFormation堆栈是使用CloudFormation服务角色创建的,该角色位于CloudFormation角色之下,在操作(sns*和sqs*)上使用通配符,但资源锁定到租户集群前缀。对于生产用例,请评估此设置,并仅提供对此服务角色所需的访问权限。InfrastructureProvisionLambda函数还使用通配符(cloudformation*)来配置cloudformation堆栈,但资源锁定到租户集群前缀。
  • 此示例代码的docker构建使用--platform=linux/amd64强制使用基于linux/adm64的映像。这是为了确保最终图像伪影适合Lambda,默认情况下使用x86-64架构。如果您需要更改目标Lambda架构,请确保同时更改Dockerfile和AWS CDK代码。有关更多信息,请参阅将AWS Lambda函数迁移到基于Arm的AWS Graviton2处理器的博客文章。
  • 堆栈删除过程不会清理堆栈生成的CloudWatch日志(日志组和日志)。您必须通过AWS管理控制台Amazon CloudWatch控制台或通过API手动清理日志。

此模式是作为示例设置的。对于生产用途,请评估以下设置并根据您的业务需求进行更改:

  • 本例中的AWS Simple Storage Service(AmazonS3)存储桶没有启用版本控制以简化操作。根据需要评估和更新设置。
  • 为了简单起见,本示例设置了AmazonAPI网关REST API端点,而无需验证、授权或限制。对于生产用途,我们建议将系统与业务安全基础设施集成。评估此设置并根据需要添加所需的安全设置。
  • 对于这个租户基础设施示例,Amazon Simple Notification Service(Amazon SNS)和Amazon Simple Queue Service(Amazon SQS)只有最低设置。每个租户的AWS密钥管理服务(AWS KMS)向账户中的Amazon CloudWatch和Amazon SNS服务开放,以便根据AWS KMS密钥策略进行消费。设置只是一个示例占位符。根据您的业务用例,根据需要调整设置。
  • 整个设置(包括但不限于API端点和使用AWS CloudFormation进行的后端租户配置和删除)仅涵盖基本的快乐路径情况。根据您的业务需要,使用必要的重试逻辑、其他错误处理逻辑和安全逻辑来评估和更新设置。
  • 在编写本文时,使用最新的cdk-nag对示例代码进行了测试,以检查策略。未来可能会实施新政策。这些新策略可能需要您根据建议手动修改堆栈,然后才能部署堆栈。检查现有代码以确保其符合您的业务需求。
  • 该代码依赖于AWS CDK生成随机后缀,而不是依赖于大多数创建资源的静态分配物理名称。此设置旨在确保这些资源是唯一的,并且不会与其他堆栈冲突。有关更多信息,请参阅AWS CDK文档。根据您的业务需求进行调整。
  • 此示例代码将.NET Lambda工件打包到基于Docker的映像中,并使用Lambda提供的容器映像运行时运行。容器映像运行时在标准传输和存储机制(容器注册表)和更准确的本地测试环境(通过容器映像)方面具有优势。您可以将项目切换为使用Lambda提供的.NET运行时,以减少Docker映像的构建时间,但随后需要设置传输和存储机制,并确保本地设置与Lambda设置相匹配。调整代码以符合用户的业务需求。

产品版本

  • AWS CDK 2.45.0版或更高版本
  • Visual Studio 2022

架构

技术堆栈

  • Amazon API网关
  • AWS云形成
  • 亚马逊CloudWatch
  • 亚马逊动态数据库
  • AWS身份和访问管理(IAM)
  • AWS公里
  • AWS Lambda公司
  • 亚马逊S3
  • 亚马逊SNS
  • 亚马逊简单队列服务

架构

下图显示了租户堆栈创建流程。有关控制平面和租户技术堆栈的更多信息,请参阅附加信息部分。

租户堆栈创建流程

  1. 用户向AmazonAPI网关托管的REST API发送一个POST API请求,其中包含JSON格式的新租户负载(租户名称、租户描述)。API网关处理请求并将其转发到后端Lambda租户登录功能。在此示例中,没有授权或身份验证。在生产设置中,此API应与SaaS基础设施安全系统集成。
  2. 租户登机功能验证请求。然后,它尝试将租户记录(包括租户名称、生成的租户通用唯一标识符(UUID)和租户描述)存储到AmazonDynamoDB租户登录表中。
  3. 在DynamoDB存储记录后,DynamoDB流启动下游的Lambda Tenant Infrastructure功能。
  4. Tenant Infrastructure Lambda函数基于接收到的DynamoDB流进行操作。如果流用于INSERT事件,则函数使用流的NewImage部分(最新更新记录,租户名称字段)调用CloudFormation,以使用存储在S3存储桶中的模板创建新的租户基础结构。CloudFormation模板需要租户名称参数。
  5. AWS CloudFormation基于CloudFormation模板和输入参数创建租户基础设施。
  6. 每个租户基础设施设置都有CloudWatch警报、计费警报和警报事件。
  7. 报警事件变成一条指向SNS主题的消息,该主题由租户的AWS KMS密钥加密。
  8. SNS主题将收到的报警消息转发到SQS队列,SQS队列由租户的AWS KMS加密密钥。

其他系统可以与AmazonSQS集成,以根据队列中的消息执行操作。在本例中,为了保持代码的通用性,传入消息保留在队列中,需要手动删除。

租户堆栈删除流程

  1. 用户将一个带有JSON格式的新租户负载(租户名称、租户描述)的DELETE API请求发送到由Amazon API Gateway托管的REST API,后者将处理该请求并转发到租户登录功能。在此示例中,没有授权或身份验证。在生产设置中,此API将与SaaS基础设施安全系统集成。
  2. 租户登记功能将验证请求,然后尝试从租户登记表中删除租户记录(租户名称)。
  3. DynamoDB成功删除记录(记录存在于表中并被删除)后,DynamoDB流启动下游Lambda Tenant Infrastructure功能。
  4. Tenant Infrastructure Lambda函数基于接收到的DynamoDB流记录进行操作。如果流用于REMOVE事件,则该函数使用记录的OldImage部分(记录信息和租户名称字段,在最新更改之前,即删除)根据该记录信息启动现有堆栈的删除。
  5. AWS CloudFormation根据输入删除目标租户堆栈。

工具

AWS服务

  1. Amazon API网关可帮助您创建、发布、维护、监控和保护任何规模的REST、HTTP和WebSocket API。
  2. AWS云开发工具包(AWS CDK)是一个软件开发框架,可帮助您在代码中定义和配置AWS云基础设施。
  3. AWS CDK工具包是一个命令行云开发工具包,可帮助您与AWS云开发工具包(AWS CDK)应用程序交互。
  4. AWS命令行界面(AWS CLI)是一个开源工具,可帮助您通过命令行shell中的命令与AWS服务交互。
  5. AWS CloudFormation帮助您设置AWS资源,快速、一致地提供资源,并在AWS客户和地区的整个生命周期中对其进行管理。
  6. AmazonDynamoDB是一个完全管理的NoSQL数据库服务,提供快速、可预测和可扩展的性能。
  7. AWS身份和访问管理(IAM)通过控制谁经过身份验证和授权使用AWS资源,帮助您安全地管理对AWS资源的访问。
  8. AWS密钥管理服务(AWS KMS)帮助您创建和控制加密密钥,以帮助保护数据。
  9. AWS Lambda是一种计算服务,它可以帮助您运行代码,而无需配置或管理服务器。它只在需要时运行您的代码,并自动缩放,因此您只需支付所使用的计算时间。
  10. 亚马逊简单存储服务(Amazon S3)是一种基于云的对象存储服务,可帮助您存储、保护和检索任意数量的数据。
  11. 亚马逊简单通知服务(Amazon SNS)帮助您协调和管理发布者和客户之间的消息交换,包括web服务器和电子邮件地址。
  12. 亚马逊简单队列服务(Amazon SQS)提供了一个安全、持久和可用的托管队列,帮助您集成和分离分布式软件系统和组件。
  13. AWS Toolkit for Visual Studio是Visual Studio集成开发环境(IDE)的插件。Visual Studio工具包支持开发、调试和部署使用AWS服务的.NET应用程序。

其他工具

  • Visual Studio是一个IDE,它包括编译器、代码完成工具、图形设计器和其他支持软件开发的功能。

Epics

史诗

Set up AWS CDK

Task Description Skills required

Verify Node.js installation.

To verify that Node.js is installed on your local machine, run the following command.  

node --version
AWS administrator, AWS DevOps

Install AWS CDK Toolkit.

To install AWS CDK Toolkit on your local machine, run the following command.

npm install -g aws-cdk

If npm is not installed, you can install it from the Node.js site.

AWS administrator, AWS DevOps

Verify the AWS CDK Toolkit version.

To verify that the AWS CDK Toolkit version is installed correctly on your machine, run the following command.  

cdk --version
AWS administrator, AWS DevOps

Set up AWS credentials.

To set up your AWS credentials, run the aws configure command and follow the prompts.    

$aws configure AWS Access Key ID [None]: AWS Secret Access Key [None]: your_secret_access_key Default region name [None]: Default output format [None]:
AWS administrator, AWS DevOps

Review the code for the tenant onboarding control plane

Task Description Skills required

Clone the repository.

Clone the repository, and navigate to the \tenant-onboarding-in-saas-architecture-for-silo-model-apg-example folder.

In Visual Studio 2022, open the \src\TenantOnboardingInfra.sln solution. Open the TenantOnboardingInfraStack.cs file and review the code.

The following resources are created as part of this stack:

  • DynamoDB table

  • S3 bucket (Upload the CloudFormation template to the S3 bucket.)

  • Lambda execution role

  • Lambda function

  • API Gateway API

  • Event source to Lambda function

AWS administrator, AWS DevOps

Review the CloudFormation template.

In the \tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\template folder, open infra.yaml, and review the CloudFormation template. This template will be hydrated with the tenant name retrieved from the tenant onboarding DynamoDB table.

The template provisions the tenant-specific infrastructure. In this example, it provisions the AWS KMS key, Amazon SNS , Amazon SQS, and the CloudWatch alarm.

App developer, AWS DevOps

Review the tenant onboarding function.

Open Function.cs, and review the code for the tenant onboarding function, which is created with the Visual Studio AWS Lambda Project (.NET Core- C#) template with the .NET 6 (Container Image) blueprint.

Open the Dockerfile, and review the code. The Dockerfile is a text file that consists of instructions for building the Lambda container image.

Note that the following NuGet packages are added as dependencies to the TenantOnboardingFunction project:

  • Amazon.Lambda.APIGatewayEvents

  • AWSSDK.DynamoDBv2

  • Newtonsoft.Json

App developer, AWS DevOps

Review the Tenant InfraProvisioning function.

Navigate to \tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\src\InfraProvisioningFunction.

Open Function.cs, and review the code for the tenant infrastructure provisioning function, which is created with the Visual Studio AWS Lambda Project (.NET Core- C#) template with the .NET 6 (Container Image) blueprint.

Open the Dockerfile, and review the code.

Note that the following NuGet packages are added as dependencies to the InfraProvisioningFunction project:

  • Amazon.Lambda.DynamoDBEvents

  • AWSSDK.DynamoDBv2

  • AWSSDK.Cloudformation

App developer, AWS DevOps

Deploy the AWS resources

Task Description Skills required

Build the solution.

To build the solution, perform the following steps:

  1. In Visual Studio 2022, open the \tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\src\TenantOnboardingInfra.sln solution. 

  2. Open the context (right-click) menu for the solution, and choose Build solution.

Note: Make sure that you update the Amazon.CDK.Lib NuGet package to the latest version in \tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\src\TenantOnboardingInfra project before you build the solution.

App developer

Bootstrap the AWS CDK environment.

Open the Windows command prompt and navigate to the AWS CDK app root folder where the cdk.json file is available (\tenant-onboarding-in-saas-architecture-for-silo-model-apg-example). Run the following command for bootstrapping.

cdk bootstrap

If you have created an AWS profile for the credentials, use the command with your profile.

cdk bootstrap --profile <profile name>
AWS administrator, AWS DevOps

List the AWS CDK stacks.

To list all the stacks to be created as part of this project, run the following command.

cdk ls cdk ls --profile <profile name>

If you have created an AWS profile for the credentials, use the command with your profile.

cdk ls --profile <profile name>
AWS administrator, AWS DevOps

Review which AWS resources will be created.

To review all the AWS resources that will be created as part of this project, run the following command.

cdk diff

If you have created an AWS profile for the credentials, use the command with your profile.

cdk diff --profile <profile name>
AWS administrator, AWS DevOps

Deploy all the AWS resources by using AWS CDK.

To deploy all the AWS resources run the following command.

cdk deploy --all --require-approval never

If you have created an AWS profile for the credentials, use the command with your profile.  

cdk deploy --all --require-approval never --profile <profile name>

After the deployment is complete, copy the API URL from the outputs section in the command prompt, which is shown in the following example.  

Outputs: TenantOnboardingInfraStack.TenantOnboardingAPIEndpoint42E526D7 = https://j2qmp8ds21i1i.execute-api.us-west-2.amazonaws.com/prod/
AWS administrator, AWS DevOps

Verify the functionality

Task Description Skills required

Create a new tenant.

To create the new tenant, send the following curl request.  

curl -X POST <TenantOnboardingAPIEndpoint* from CDK Output>tenant -d '{"Name":"Tenant123", "Description":"Stack for Tenant123"}'

Change the place holder <TenantOnboardingAPIEndpoint* from CDK Output> to the actual value from AWS CDK, as shown in the following example.  

curl -X POST https://j2qmp8ds21i1i.execute-api.us-west-2.amazonaws.com/prod/tenant -d '{"Name":"Tenant123", "Description":"test12"}'

The following example shows the output.

{"message": "A new tenant added - 5/4/2022 7:11:30 AM"}
App developer, AWS administrator, AWS DevOps

Verify the newly created tenant details in DynamoDB.

To verify the newly created tenant details in DynamoDB, perform the following steps.

  1. Open AWS Management Console, and navigate to the Amazon DynamoDB service.

  2. In the left navigation, choose Explore items, and choose the TenantOnboarding table.

    Note: The tenant name will be prepended with tenantcluster-. For more information, see the Additional information section.

  3. Verify that a new item is created with the tenant details.

App developer, AWS administrator, AWS DevOps

Verify the stack creation for the new tenant.

Verify that the new stack was successfully created and provisioned with infrastructure for the newly created tenant according to the CloudFormation template.

  1. Open the CloudFormation console.

  2. In the left navigation, choose Stacks, and verify that a stack with the tenant name was successfully created.

  3. Choose the newly created tenant stack, and then choose the Resources tab. Note the alarm resource and the Amazon SQS resource.

  4. Open a new terminal with AWS credentials configured, and point to the correct Region. To raise a test alarm, enter the following code, replacing <alarm resource name> with the alarm resource name noted in step 3.  

    aws cloudwatch set-alarm-state --alarm-name <alarm resource name> --state-value ALARM --state-reason 'Test setup'

    The following example shows the code with an alarm resource name.  

    aws cloudwatch set-alarm-state --alarm-name tenantcluster-tenant123-alarm --state-value ALARM --state-reason 'Test setup'
  5. Open the console and navigate to the Amazon SQS console. Choose the Amazon SQS resource name identified in step 3. Follow the AWS documentation instructions to receive and delete the test message from the alarm that was raised in step 4.

App developer, AWS administrator, AWS DevOps

Delete the tenant stack.

To delete the tenant stack, send the following curl request.

curl -X DELETE <TenantOnboardingAPIEndpoint* from CDK Output>tenant/<Tenant Name from previous step>

Change the place holder <TenantOnboardingAPIEndpoint* from CDK Output> to the actual value from AWS CDK, and change <Tenant Name from previous step> to the actual value from the previous tenant creation step, as shown in the following example.  

curl -X DELETE https://j2qmp8ds21i1i.execute-api.us-west-2.amazonaws.com/prod/tenant/Tenant123

The following example shows the output.  

{"message": "Tenant destroyed - 5/4/2022 7:14:48 AM"}
App developer, AWS DevOps, AWS administrator

Verify the stack deletion for the existing tenant.

To verify that the existing tenant stack got deleted, perform the following steps:

  1. Open console and navigate to the CloudFormation console.

  2. In the left navigation, verify that the existing stack with the tenant name is no longer in console (if the CloudFormation console is set up to show only Active stacks) or is in the process of being deleted. If the stack is no longer in the CloudFormation console, use the dropdown list to change the console's setting from Active to Deleted to see the deleted stack and verify that the stack was deleted successfully.

App developer, AWS administrator, AWS DevOps

Clean up

Task Description Skills required

Destroy the environment.

Before the stack clean up, ensure the following:

  • All records in DynamoDB are removed either through the previous tenant deletion operation or through the DynamoDB console or API. Each tenant record deletion will initiate the cleanup of its AWS CloudFormation counterpart. 

  • All tenant-based AWS CloudFormation stacks are cleaned up (in case the DynamoDB trigger cleanup logic fails) on the AWS CloudFormation console.

After testing is done, AWS CDK can be used to destroy all the stacks and related resources by running the following command.  

cdk destroy --all;

If you created an AWS profile for the credentials, use the profile.

Confirm the stack deletion prompt to delete the stack.

AWS administrator, AWS DevOps

Clean up Amazon CloudWatch Logs.

The stack deletion process will not clean up CloudWatch Logs (log groups and logs) that were generated by the stack. Manually clean up the CloudWatch resources by using the CloudWatch console or the API.

App developer, AWS DevOps, AWS administrator

相关资源

其他信息

控制平面技术堆栈

  • 用.NET编写的CDK代码用于提供控制平面基础结构,该基础结构由以下资源组成:

API网关

  • 用作控制平面堆栈的REST API入口点。

承租人登机Lambda功能

此Lambda函数由API网关使用m方法启动。

POST方法API请求导致(租户名称、租户描述)插入到DynamoDB租户登录表中。

在这个代码示例中,租户名称也用作租户堆栈名称和该堆栈中资源名称的一部分。这是为了使这些资源更容易识别。此租户名称在整个安装过程中必须是唯一的,以避免冲突或错误。IAM角色文档和限制部分解释了详细的输入验证设置。

只有在表中的任何其他记录中未使用租户名称时,对DynamoDB表的持久化过程才会成功。

在本例中,租户名称是此表的分区键,因为只有分区键可以用作PutItem条件表达式。

如果以前从未记录过租户名称,则记录将成功保存到表中。

但是,如果表中的现有记录已经使用了租户名称,则操作将失败并启动DynamoDB ConditionalCheckFailedException异常。该异常将用于返回失败消息(HTTP BadRequest),指示租户名称已存在。

DELETE方法API请求将从租户登录表中删除特定租户名称的记录。

即使记录不存在,本例中的DynamoDB记录删除也将成功。

如果目标记录存在并被删除,它将创建一个DynamoDB流记录。否则,不会创建下游记录。

启用Amazon DynamoDB Streams的DynamoDB上的租户

这将记录租户元数据信息,任何记录保存或删除都将向下游的tenant Infrastructure Lambda函数发送一个流。

租户基础设施Lambda功能

此Lambda函数由上一步骤中的DynamoDB流记录启动。如果记录是针对INSERT事件的,它将调用AWS CloudFormation,使用存储在S3存储桶中的CloudFormation模板创建新的租户基础设施。如果记录用于REMOVE,它将根据流记录的Tenant Name字段启动现有堆栈的删除。

S3 桶

这用于存储CloudFormation模板。

每个Lambda功能的IAM角色和CloudFormation的服务角色

每个Lambda函数都有其独特的IAM角色,只有最低权限才能完成其任务。例如,Tenant On-boarding Lambda函数具有对DynamoDB的读/写访问权限,Tenant Infrastructure Lambda函数只能读取DynamoDB流。

为租户堆栈配置创建自定义CloudFormation服务角色。此服务角色包含CloudFormation堆栈配置的其他权限(例如,AWS KMS密钥)。这将在Lambda和CloudFormation之间划分角色,以避免对单个角色(基础架构Lambda角色)的所有权限。

允许强大操作(例如创建和删除CloudFormation堆栈)的权限被锁定,并且仅允许在以tenantcluster-开头的资源上使用。AWS KMS例外,因为它的资源命名约定。从API中获取的租户名称将在前面加上tenantcluster,以及其他验证检查(仅带破折号的字母数字,并且限制为少于30个字符,以适合大多数AWS资源命名)。这确保租户名称不会意外导致核心基础架构堆栈或资源中断。

租户技术堆栈

CloudFormation模板存储在S3存储桶中。该模板提供租户特定的AWS KMS密钥、CloudWatch警报、SNS主题、SQS队列和SQS策略。

AWS KMS密钥用于Amazon SNS和Amazon SQS对其消息进行数据加密。AwsSolutionsSNS2和AwsSolutions-SQS2的安全实践建议您使用加密设置Amazon SNS和Amazon SQS。然而,当使用AWS托管密钥时,CloudWatch警报不适用于Amazon SNS,因此在这种情况下必须使用客户托管密钥。有关更多信息,请参阅AWS知识中心。

SQS策略用于AmazonSQS队列,以允许创建的SNS主题将消息传递到队列。如果没有SQS政策,访问将被拒绝。有关更多信息,请参阅Amazon SNS文档。

 

原文地址
https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html?did=pg_card&trk=pg_card
本文地址
Article

微信

知识星球

微信公众号

视频号