使用模块封装及重复使用资源配置 - AWS CloudFormation
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用模块封装及重复使用资源配置

模块是一种供您以透明、易管理和可重复的方式打包资源配置以便跨堆栈模板实现包含的方法。模块可以将常见服务配置和最佳实践封装为模块化、可自定义的构建数据块,供您包含在堆栈模板中。模块使您能够将包含最佳实践、专家领域知识和可接受的指南(例如安全性、合规性、治理和行业法规)在内的资源配置纳入模板中,而无需深入了解资源实施的复杂性。

例如,网络领域专家可以创建一个包含遵守安全指南的内置安全组和入口/出口规则的模块。然后,您可以将该模块纳入到模板中,以便在堆栈中预置安全的网络基础架构,而无需花费时间弄清楚 VPC、子网、安全组和网关的工作方式。此外,由于模块具有版本控制,因此如果安全指南随时间而发生变化,模块作者可以创建包含这些更改的新版本模块。

在模板中使用模块的特点包括:

  • 可预测性:模块必须遵守其在 CloudFormation 注册表中注册的架构,这样在您将模块纳入到模板中后,您就知道该模块可以解析到哪些资源。

  • 可重用性:您可以在多个模板和账户中使用同一模块。

  • 可追溯性:CloudFormation 可以保留堆栈中的哪些资源是从模块预置的知识,使您能够轻松了解资源变化的来源。

  • 可管理性:注册模块后,您可以通过 CloudFormation 注册表对其进行管理,包括版本控制以及账户和区域可用性。

模块可以包含:

  • 要从模块配置的一个或多个资源以及任何关联的数据,例如输出数据或条件。

  • 使您能够在使用模块时指定自定义值的任何模块参数

有关开发模块类型的信息,请参阅 CloudFormation 命令行界面用户指南中的开发模块类型

在模板中使用模块

要使用模块,请确保该模块已在要在其中使用它的账户和区域中注册。您在 CloudFormation 注册表中将模块注册为私有扩展。然后,将其作为单个资源进行处理:

  • 将其纳入到模板的 Resources 部分中。

  • 为模块指定任何必要的属性。

当您启动堆栈操作时,CloudFormation 会生成一个已处理的模板,该模板将所有包含的模块解析为适当的资源。在实际执行堆栈操作之前,使用更改集预览要添加或更新的资源。

参阅以下示例:您有一个包含资源和模块的模板。模板包含一个单独的资源 ResourceA 和一个模块 ModuleParent。而模块包含两个资源(ResourceBResourceC),以及一个嵌套模块 ModuleChildModuleChild 包含一个资源,即 ResourceD。如果您使用此模板创建堆栈,CloudFormation 会处理模板并将模块解析为适当的资源。最终创建的堆栈具有四个资源:ResourceAResourceBResourceCResourceD


                在堆栈操作期间,CloudFormation 会将堆栈模板中包含的两个模块解析为适当的四个资源。

CloudFormation 会跟踪堆栈中的哪些资源是从模块创建而成的。您可以在给定堆栈的事件资源偏差选项卡上查看此信息,更改集预览中也包含此信息。

模块与模板中的资源可以区别开来,因为它们遵循以下四部分命名约定,而不是资源所用的典型的三部分命名约定:

organization::service::usecase::MODULE

使用参数指定模块值

模块可以包含模块参数。与模板参数非常相似,模块参数使您能够将自定义值从包含自定义值的模板(或模块)输入到模块中。然后,模块可以使用这些值来设置其所包含的资源的属性。

您还可以定义模板参数,这些参数反过来会设置模块属性,以便用户可以输入在堆栈操作时传递给模块的值。有关定义模板参数的详细信息,请参阅参数

同样,如果模块含有包含模块参数的嵌套模块,则您可以:

  • 直接在父模块中为嵌套模块的参数指定值。

  • 在父模块中定义相应的模块参数,使嵌套模块的参数能够由包含父模块的模板(或模块)来设置。

使用模板参数指定模块参数值

以下示例展示了如何定义将值传递给模块的模板参数。

此处,包含 My::S3::SampleBucket::MODULE 的模板定义了模板参数 BucketName,该参数使用户能够在堆栈操作期间指定 S3 存储桶名称。

// Template containing My::S3::SampleBucket::MODULE { "Parameters": { "BucketName": { "Description": "Name for your sample bucket", "Type": "String" } }, "Resources": { "MyBucket": { "Type": "My::S3::SampleBucket::MODULE", "Properties": { "BucketName": { "Ref": "BucketName" } } } } }

在父模块中指定子模块中资源的属性

以下示例展示了如何在嵌套在另一个模块中的模块中指定参数值。

第一个模块 My::S3::SampleBucketPrivate::MODULE 将是子模块。该模块定义了两个参数:BucketNameAccessControl。为这些参数指定的值用于指定模块所包含的 AWS::S3::Bucket 资源的 BucketNameAccessControl 属性。以下为 My::S3::SampleBucketPrivate::MODULE 的模板片段。

// My::S3::SampleBucketPrivate::MODULE { "AWSTemplateFormatVersion": "2010-09-09", "Description": "A sample S3 Bucket with Versioning and DeletionPolicy.", "Parameters": { "BucketName": { "Description": "Name for the bucket", "Type": "String" }, "AccessControl": { "Description": "AccessControl for the bucket", "Type": "String" } }, "Resources": { "S3Bucket": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { "Ref": "BucketName" }, "AccessControl": { "Ref": "AccessControl" }, "DeletionPolicy": "Retain", "VersioningConfiguration": { "Status": "Enabled" } } } } }

接下来,上一个模块嵌套在父模块 My::S3::SampleBucket::MODULE 中。父模块 My::S3::SampleBucket::MODULE 通过以下方式设置子模块参数:

  • 其将 My::S3::SampleBucketPrivate::MODULE 的 AccessControl 参数设置为 Private

  • 对于 BucketName,其定义了一个模块参数,该参数将允许存储桶名称在包含 My::S3::SampleBucket::MODULE 的模板(或模块)中进行指定。

// My::S3::SampleBucket::MODULE { "AWSTemplateFormatVersion": "2010-09-09", "Description": "A sample S3 Bucket. With Private AccessControl.", "Parameters": { "BucketName": { "Description": "Name for your sample bucket", "Type": "String" } }, "Resources": { "MyBucket": { "Type": "My::S3::SampleBucketPrivate::MODULE", "Properties": { "BucketName": { "Ref": "BucketName" }, "AccessControl" : "Private" } } } }

为模块参数指定约束

模块参数不支持类型或约束强制执行。要对模块参数执行类型或约束检查,请创建具有所需约束的模板参数,然后在模块参数中引用该模板参数。

引用模块中的资源

模块中的资源可以通过逻辑名称进行引用。模块中包含的资源的完全限定逻辑名称可以通过将以下名称相结合来构成:

  • 在包含模板(或包含模块)中为模块指定的逻辑名称。

  • 模块中指定的资源的逻辑名称。

通过这种方式,您可以使用 GetAttRef 内部函数来访问模块资源上的属性值。

在以下示例中,模板引用模块中的属性来为模板本身的资源设置相应属性。

假设 My::S3::SampleBucket::MODULE 模块包含逻辑名称为 S3Bucket 的资源 AWS::S3::Bucket。要使用 Ref 内部函数引用此资源的存储桶名称,将模板中给定模块的逻辑名称 MyBucket 与模块中资源的逻辑名称 S3Bucket 相结合,从而获得资源的完全限定逻辑名称:MyBucketS3Bucket

模块中包含的资源的逻辑名称在模块的架构中指定。您可以通过以下方式访问该架构:

  • 在 CloudFormation 注册表中查找模块。架构选项卡显示了模块架构。

  • 使用 DescribeType API 返回模块详细信息,其中包括架构。

// Template that uses My::S3::SampleBucket::MODULE { "Parameters": { "BucketName": { "Description": "Name for your sample bucket", "Type": "String" } }, "Resources": { "MyBucket": { "Type": "My::S3::SampleBucket::MODULE", "Properties": { "BucketName": { "Ref": "BucketName" } } }, "someQueueToMakeItExciting" : { "Type" : "AWS::SQS::Queue", "Properties": { "QueueName": { "Fn::GetAtt" : [ "MyBucketS3Bucket", "BucketName" ] } } } } }

使用模块时的注意事项

  • 使用模块不收取任何额外费用。您只需为模块解析到堆栈中的资源付费。

  • CloudFormation 配额(例如堆栈中允许的最大资源数或模板正文的最大大小)适用于处理过的模板,无论该模板中包含的资源是否来自模块。有关更多信息,请参阅 AWS CloudFormation 配额

  • 您在堆栈级别指定的标签将分配给派生自模块的各个资源。

  • CloudFormation 处理模板时,在模块级别指定的帮助程序脚本不会传播到模块中包含的各个资源。

  • 模块中指定的输出将在模板级别传播到输出。

    将为每个输出分配一个逻辑 ID,该 ID 是模块逻辑名称和模块中定义的输出名称的拼接。有关输出的详细信息,请参阅输出

  • 模块中指定的参数不会传播到模板级别的参数。

    但是,您可以创建引用模块级参数的模板级参数。有关详细信息,请参阅使用参数指定模块值

模块注册和版本控制

您可以使用 CloudFormation 注册表注册及管理账户和区域中的模块。有关更多信息,请参阅使用 AWS CloudFormation 注册表

您可以在给定账户和区域注册同一模块的多个版本。请注意以下事项:

  • 必须在要在其中使用模块的账户和区域中注册模块。

  • 在堆栈操作期间,CloudFormation 会使用当前在执行堆栈操作的账户和区域中注册为默认版本的模块版本。包括嵌套在其他模块中的模块。

    因此,请注意,如果您在不同账户或区域中将同一模块的不同版本注册为默认版本,则使用同一个模板可能会导致不同的结果。

    有关详细信息,请参阅指定要使用的扩展版本

  • 在堆栈操作期间,CloudFormation 会使用当前在执行堆栈操作的账户和区域中注册为默认版本的资源版本。这包括通过纳入模块生成的资源。

  • 更改模块的默认版本不会启动任何堆栈更新操作。但是,在您下次使用包含该模块的任何模板执行堆栈操作(例如堆栈更新)时,CloudFormation 将在操作中使用新的默认版本。

    但在指定了使用以前的模板选项的情况下执行堆栈更新时例外,如下所述。

  • 对于堆栈更新操作,如果您指定使用以前的模板选项,则 CloudFormation 会使用先前处理过的模板进行堆栈更新,不会针对您可能对模块作出的任何更改重新处理模块。

  • 为了保证结果统一,如果要在堆栈模板中纳入模块以用于堆栈集,则应确保在计划部署堆栈实例的所有账户和区域中将相同版本的模块设置为默认版本。这包括嵌套在其他模块中的模块。有关堆栈集的更多信息,请参阅使用堆栈集

有关注册模块新版本或更改模块的默认版本的更多信息,请参阅使用 AWS CloudFormation 注册表