AWS CDK项目蓝图 - 建模和组织(第1/2部分)
一个关于如何建模、结构和组织你的基础设施即代码AWS CDK项目的样本。从头开始构建,直到CI/CD管道组成,所有的云组件资源,和AWS云的服务。
作为系统/软件工程师,学习一个新的工具或框架有时并不是我们 "技术生活 "中最困难的部分。我们可能需要适应一些新的概念,以及关于这个工具/框架的术语,当然,还要学习如何使用它。我们通常很快就能完成这部分工作。但是,在那之后,我们开始想......好吧,现在我知道如何使用它了,那么......我如何用这个新工具组织我的项目?我应该使用这个还是那个结构?有没有一些已经存在的实践/模式?
总而言之,在我们的环境中,在我们的现实中,如何最好地利用这个工具,使它的帮助多于它带来的问题?
所以,没有别的办法,有更多的工作要做......开始研究,检查社区的经验、做法(好的和坏的)、建议、结果,所有的一切收集数据和处理,以适应我们的需求(环境),我们开始建立我们自己的工作方式与这个 "新 "的工具/框架。
这就是我这两部分文章系列的目的:建立一个蓝图模型,展示如何使用AWS-CDK框架对我们的基础设施即代码项目进行建模、组织和结构。所以,让我们从第一部分开始。
关于AWS云计算开发工具包(AWS CDK)的快速简介
这是一套库,被认为是一个框架,用于在代码中定义基础设施并通过AWS CloudFormation进行配置。AWS CDK最吸引人的优点之一是,你可以使用(你的)"真正的 "语言,利用循环、函数、条件、参数、类、继承、组合......我们通常用来构建软件的一切,我们都可以用来构建我们的基础设施。此外,你可以选择最适合你的编程语言,AWS CDK有以下语言。TypeScript、JavaScript、Python、Java、C#/.Net和Go(这背后是jsii)-- 它给AWS CDK带来的能力是,用同样的源代码提供一个多语言库)。在这里,我们将使用Python。
对于那些沉迷于Terraform的人,不要担心,它也会来的,就是CDKTF。
我们可以设计被称为 "结构 "的可重复使用的组件,然后定义我们的基础设施,把它们组合成堆栈和应用程序。这里的目的是建立我们的AWS CDK蓝图模型,所以,非常快速和简短地介绍一下涉及AWS CDK的几个概念:
- 构造:AWS CDK应用程序的基本构件,它代表了一个 "云组件",具有由AWS CloudFormation创建的资源/服务。AWS CDK包括它们的集合,适用于每个AWS服务(被称为AWS构造库)。此外,还可以查看Construct Hub,这是一个帮助你发现来自AWS、第三方和开源CDK社区的额外构造的好地方。
- 堆栈:它们是部署单元,一个堆栈中的所有资源都作为一个单元进行配置。
- App:它代表整个CDK应用(也被认为是一个构造),通常是应用的根构造。
- 阶段:代表一个抽象的应用建模,它将由应该一起部署的Stack组成。然后,我们多次创建这个Stage的实例,每个实例都由我们需要部署应用程序的不同环境。
好吧,我同意只读这个有点无聊,这些概念在我们通过蓝图样本项目,即实践部分后会更加清晰。
解决方案、建模和组织
这个解决方案被称为AWS技能图谱,它显示了一个专业人员在每个AWS服务中的经验水平。
我们这里有两个项目,一个是简单的AngularJS项目(应用--上图),另一个是AWS CDK Python项目(基础设施即代码--IaC)。AWS CDK项目将负责为这个AngularJS应用程序的部署和运行构建环境。除了在AWS云中创建所需的资源和服务,AWS CDK项目还将为应用程序的部署创建一个CI/CD管道(CodePipeline, Codebuild)。
AWS CDK项目的建模
这是我们IaC AWS CDK项目的设计模型。我们定义了三个逻辑单元,在分离的云组件(Constructs)中组成了我们的应用程序。API、数据库和WebSite。然后,我们创建了一个阶段(一个抽象的应用程序),我们把它分成两个独立的堆栈。有状态和无状态。这样我们就可以把那些我们可能关注数据的组件,即有状态的组件(如s3,数据库),与另一个可能更容易复制的组件(如API,MQ,SNS,lambda)分开。
IaC AWS SDK设计模型
舞台(继承了aws_cdk.Stage的Python类,有两个aws_cdk.Stacks。有状态和无状态)将被实例化,并为每个不同的阶段加载不同的配置/环境信息。Dev和Pre prod。
AWS CDK项目结构
让我们来看看我们的AWS CDK项目的结构和组织,它将遵循我们已经看到的定义的设计模型。
该结构最相关的部分在上面的图片中被分为三个部分。在第一部分 (1),我们有实际建立云组件、资源和服务的代码,我们需要为应用程序的每个逻辑单元提供这些服务。例如,在API文件夹中(API逻辑单元),我们有我们的aws_cdk.Construct(一个名为Apache的Python类)。构造(一个名为ApiAwsSkillsMapping的Python类),它创建的API网关和Lambda函数已经相互连接,这样我们就创建了一个由其他两个构造组成的更高级别的构造。同时,在运行时子文件夹中,我们保留了这个LU的必要资产,即Lambda函数代码。
在第二部分 (2),我们将所有信息配置外化为YAML文件,按阶段划分,还有一个额外的文件用于管道。下面是其内容的一个例子。
在default.yml文件中,我们保留了所有的通用值(如bucket-prefix),并在其各自的文件中保留了特定的阶段(如bucket-suffix-name)。稍后,在我们的实践中,我们将把Dev和Pre prod阶段部署到同一个AWS账户,但在不同的AWS区域 (Dev/eu-west-3/Paris和Preprod/eu-west-1/Ireland)。当创建AngularJS应用程序CI/CD的管道时,让我们创建一个批准步骤,就在Dev的部署之后,但在Pre prod的部署之前。在pipeline.yml文件中告知需要批准Preprod部署的团队和电子邮件。
最后,在我们项目结构的第三部分 (3) ,我们对一些最相关的Python类进行了简短的描述,它们是构成我们AWS CDK项目的所有代码的一部分。
AWS跨区域的依赖关系
对于同一AWS账户/区域的堆栈之间的依赖关系,CDK会识别它们的存在,并能够自行处理。例如,看看我们的AWS CDK项目的设计模型,我们可以看到DynamoDB和Lambda在不同的堆栈中(DynamoDB是有状态的,而Lambda是无状态的),我们需要Lambda函数被授予读取DynamoDB表的授权。
在这种情况下,我们可以在代码中直接引用它们,或者利用aws_cdk.CfnOutput("NAME")在一个栈中导出,然后cdk.Fn.import_value("NAME")在另一个栈中导入。回顾一下,对于每个AWS账户,出口名称在一个区域内必须是唯一的。
现在,在另一个更棘手的情况下,我们需要采取不同的策略。在我们的例子中,问题是这样的......在管道堆栈中,当创建Codebuild项目时,我们需要为每个阶段(开发和预生产)生成API网关URL (https://{restapi_id}...),以便正确构建AngularJS应用程序(见下面的侧记)。
注意!我 们使用S3静态网站来托管我们的AngularJS示例项目,我们没有 "注入 "环境变量的选项,以便在运行时使用,因为S3是一个静态对象存储,而不是一个动态内容服务器,所以没有 "服务器运行时 "这样的东西(在这种情况下)。这就是为什么我们必须为每个环境设置一个Build Stage的原因,为了给每个环境设置不同的变量值,我们必须在 "Build time "配置它们。此外,记住,AngularJS是纯粹的客户端代码(它在浏览器中运行)。
在Pre prod的案例中,拥有API网关的堆栈位于eu-west-1(爱尔兰),而拥有管道的堆栈位于eu-west-3(巴黎)AWS区域。那么,我们如何在不同AWS区域的两个堆栈之间分享这些信息呢? 对于这种情况,我们使用AWS系统管理员的服务参数存储,(见下图)。首先 (1),在第一个堆栈(有依赖关系的源头),我们在它自己的AWS区域的参数存储中保存该信息,然后 (2),在另一个堆栈(依赖它的那个),我们在存储它的AWS区域的参数存储中读取它。
注意,在这种情况下,显然,我们需要注意我们部署堆栈的顺序,以适当的顺序处理它们,首先是创建参数的那个,然后是读取参数的那个。
结论(第一部分)
好了,现在让我们到此为止,回顾一下,到此为止,我们已经见到了样本应用程序,看到了我们的AWS CDK项目的设计模型,知道了这个AWS CDK项目中实现的结构、组织和外部配置。此外,我们还看到了一些细节,我们如何处理位于不同AWS区域的AWS CDK堆栈之间的依赖关系。
在本文的下一部分(也是最后一部分),有趣的部分来了,我们将进入实践,部署所有的资源,看到AngularJS应用程序在两个阶段,即开发和预开发中运行。很快就会见到你。