本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
向您的产品添加 CloudFormation 模板
AWS Marketplace 卖家可以使用 AWS CloudFormation 模板发布配送给 AWS Marketplace 买家的基于 AMI 的商品。在基于 AMI 的产品中添加 CloudFormation 模板后,您的买家无需手动配置资源和依赖关系即可部署您的解决方案。您可以使用这些模板定义集群或者产品的分布式架构,也可用于选择不同 AMI 组合或产品配置。单个 AMI 解决方案最多可以包含三个 CloudFormation 模板。
可以将 CloudFormation 模板配置为提供包含相关配置文件和 Lambda 函数的单个 Amazon 系统映像 (AMI)。此外,您必须为每个模板添加架构示意图。
准备 CloudFormation 模板
要构建 CloudFormation 模板,您必须满足模板的先决条件并提供所需的输入和安全参数。提交 CloudFormation 模板时,请使用以下各节中的指南。
模板先决条件
-
验证模板是否已通过 CloudFormation 控制台成功启动, AWS 区域 且已为您的产品启用所有功能。您可以使用该TaskCat 工具
来测试您的模板。 -
AMIs 您的 CloudFormation 模板中必须包含您要发布的产品的 AMI,或者是 AWS 托管的 AMI,例如最新的 Amazon Linux 2。请勿包含任何社区 AMI 或者您或任何其他第三方拥有和共享的 AMI。要使用 AWS 托管的 AMI,请使用 S AWS ystems Manager 参数存储中的公共参数,而不是硬编码 AMI。 IDs例如,在指定 AMI ID 的 CloudFormation 模板中,您可以使用动态引用
ImageId: '{{resolve:ssm:/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id}}'。 -
生成模板,使其不必依赖于使用特定可用区 (AZ)。并非所有客户都能访问所有账户 AZs, AZs 而且不同账户的映射方式也不同。
-
如果您在生成使用自动扩缩组的集群解决方案,我们建议您考虑到扩展事件。新节点应自动加入正在运行的集群。
-
对于单节点产品,我们建议使用自动扩缩组。
-
在解决方案涉及含多个实例的集群时,如果您希望在集群之间降低网络延迟时和/或提升网络吞吐量,请考虑使用置放群组。
-
为了便于 AWS Marketplace 团队审核并向买家透明,我们建议您在UserData栏目中添加评论。
AMI 详情要求
注意
如果您在卖家门户的服务器产品
在指定将 AMI 部署到 EC2 实例(例如AWS::EC2::InstanceAWS::AutoScaling::LaunchConfiguration、和AWS::EC2::LaunchTemplate资源)的资源的ImageId属性时,必须引用模板参数。参数类型必须是 AWS::EC2::Image::Id、AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> 或 String。
您可以将此模板参数命名为任何有效的参数名称。 AWS Marketplace 将您的模板复制到其自己的 Amazon S3 存储桶中,并将指定参数替换为AWS Systems Manager 参数存储参数。 AWS Marketplace 还会更新描述和约束文本,使部署模板的买家能够清楚地看到正确的值。当买家部署您的模板时,该参数会解析为已发布产品的 AWS 区域特定 AMI ID。
以下模板示例说明了使用内置函数 Ref 引用模板参数的 ImageId 属性。
YAML 示例:
Parameters: ImageId: Type: AWS::EC2::Image::Id Default: ami-example1234567890 Resources: MyInstance: Type: AWS::EC2::Instance Properties: ImageId: !Ref ImageId
JSON 示例:
{ "Parameters": { "ImageId": { "Type": "AWS::EC2::Image::Id", "Default": "ami-example1234567890" } }, "Resources": { "MyInstance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Ref": "ImageId" } } } } }
如果您在嵌套堆栈而不是根堆栈中部署 EC2 实例,则 AMI ID 必须从根堆栈动态继承其值。编辑您的根堆栈和嵌套堆栈,确保在根堆栈中设置模板参数的值时,能够覆盖此嵌套堆栈中使用的 AMI ID。
使用产品加载表单的 AMI 详情要求
AMIs 必须位于每个区域的映射表中。在 AMI 被克隆 IDs后, AWS Marketplace 团队会对其进行更新。您的源 AMI 必须位于 us-east-1 区域。其他区域可使用占位符。
YAML 示例:
Mappings: RegionMap: us-east-1: ImageId: ami-0123456789abcdef0 us-west-1: ImageId: ami-xxxxxxxxxxxxxxxxx eu-west-1: ImageId: ami-xxxxxxxxxxxxxxxxx ap-southeast-1: ImageId: ami-xxxxxxxxxxxxxxxxx Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: !FindInMap - RegionMap - !Ref AWS::Region - ImageId
对嵌套堆栈模板的要求
注意
本节仅适用于未使用产品加载表单的定价模式。对于使用产品加载表单的定价模式,嵌套堆栈 TemplateURL 属性只允许使用固定字符串。
如果您的模板包含嵌套堆栈,则嵌套堆栈资源的 TemplateURL 属性必须引用 Amazon S3 存储桶名称、存储桶区域和 Amazon S3 对象密钥前缀的模板参数。其中,存储桶名称的参数名称必须为 MPS3BucketName,存储桶区域必须为 MPS3BucketRegion,对象键前缀必须为 MPS3KeyPrefix。
将这些参数的默认值设置为与存储嵌套模板的 Amazon S3 存储桶相对应。所有嵌套模板必须可公开访问。当您提交模板进行发布时,会将您的模板 AWS Marketplace 复制到其自己的 Amazon S3 存储桶中,并修改这三个参数的属性,使其默认值和允许值设置为与副本的存储位置相对应。 AWS Marketplace 还会更新描述和约束文本,使部署模板的买家能够清楚地看到正确的值。
如果您有多个级别的嵌套堆栈,则必须配置所有创建其他嵌套堆栈的嵌套堆栈,以便 TemplateURL 属性动态继承根堆栈中的 Amazon S3 存储桶名称、Amazon S3 存储桶区域和 Amazon S3 对象键的值。请编辑您的根堆栈和嵌套堆栈,确保在根堆栈中设置模板参数 MPS3BucketName、MPS3BucketRegion 和 MPS3KeyPrefix 的值时,能够覆盖此嵌套堆栈中用于创建更多嵌套堆栈的 URL 中对应的值。
以下模板示例说明了使用内置函数 Fn::Sub 引用模板参数的 TemplateURL 属性。
YAML 示例:
AWSTemplateFormatVersion: '2010-09-09' Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: AWS Marketplace Parameters Parameters: - ImageId - MPS3BucketName - MPS3BucketRegion - MPS3KeyPrefix Parameters: ImageId: Type: AWS::EC2::Image::Id Default: ami-example1234567890 Description: The AMI that will be used to launch EC2 resources. MPS3BucketName: Type: String Default: sellerbucket Description: Name of the S3 bucket for your copy of the nested templates. MPS3BucketRegion: Type: String Default: us-east-1 Description: AWS Region where the S3 bucket for your copy of the nested templates is hosted. MPS3KeyPrefix: Type: String Default: sellerproductfolder/ Description: S3 key prefix that is used to simulate a folder for your copy of the nested templates. Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: !Ref ImageId NestedStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub https://${MPS3BucketName}.s3.${MPS3BucketRegion}.${AWS::URLSuffix}/${MPS3KeyPrefix}nested-template.yaml
JSON 示例:
{ "AWSTemplateFormatVersion": "2010-09-09", "Metadata": { "AWS::CloudFormation::Interface": { "ParameterGroups": [ { "Label": { "default": "AWS Marketplace Parameters" }, "Parameters": [ "ImageId", "MPS3BucketName", "MPS3BucketRegion", "MPS3KeyPrefix" ] } ] } }, "Parameters": { "ImageId": { "Type": "AWS::EC2::Image::Id", "Default": "ami-example1234567890", "Description": "The AMI that will be used to launch EC2 resources." }, "MPS3BucketName": { "Type": "String", "Default": "sellerbucket", "Description": "Name of the S3 bucket for your copy of the nested templates." }, "MPS3BucketRegion": { "Type": "String", "Default": "us-east-1", "Description": "AWS Region where the S3 bucket for your copy of the nested templates is hosted." }, "MPS3KeyPrefix": { "Type": "String", "Default": "sellerproductfolder/", "Description": "S3 key prefix that is used to simulate a folder for your copy of the nested templates." } }, "Resources": { "EC2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Ref": "ImageId" } } }, "NestedStack": { "Type": "AWS::CloudFormation::Stack", "Properties": { "TemplateURL": { "Fn::Sub": "https://${MPS3BucketName}.s3.${MPS3BucketRegion}.${AWS::URLSuffix}/${MPS3KeyPrefix}nested-template.yaml" } } } } }
注意
AWS::CloudFormation::Interface用于定义买家部署您的模板时如何在 AWS CloudFormation 控制台中对参数进行分组和排序。
模板输入参数
-
模板的输入参数不得包含 AWS Marketplace 客户的 AWS 凭证(例如密码、公钥、私钥或证书)。
-
对于密码等敏感输入参数,请选择
NoEcho属性并启用更严格的正则表达式。对于其他输入参数,设置最常见的输入以及相应的帮助文本。 -
如果可用,请使用 CloudFormation 参数类型进行输入。
-
使用
AWS::CloudFormation::Interface来分组和排序输入参数。 -
请勿为以下输入参数设置任何默认值:
注意
客户必须提供这些内容作为输入参数。
-
允许从公共互联网进入远程访问端口的默认 CIDR 范围
-
允许从公共互联网进入数据库连接端口的默认 CIDR 范围
-
用户或数据库的默认密码
-
网络和安全参数
-
确保默认 SSH 端口 (22) 或 RDP 端口 (3389) 未对 0.0.0.0 打开。
-
我们建议您使用适当的访问控制列表 () 和安全组来构建 VPC,而不是使用默认的虚拟私有云 (VPCACLs)。
-
您的模板无法向用户请求长期访问密钥,也无法创建这些密钥来访问 AWS 资源。如果您的 AMI 应用程序需要访问买家账户中的 AWS 服务,则它必须使用适用于 A mazon 的 IAM 角色 EC2。
-
将 IAM 角色和策略设置为授予最低权限,并且仅在绝对需要时启用写入访问权限。例如,如果您的应用程序只需要
S3:GET、PUT和DELETE操作,则仅指定这些操作。在这种情况下,我们不建议使用S3:*。
收到您的模板后,将 AWS Marketplace 验证产品配置和信息,并就所有必需的修订提供反馈。
架构示意图
您必须为每个模板提供架构示意图。要了解有关绘图的更多信息,请参阅什么是架构绘图?
示意图必须符合以下标准:
-
在上演示标准部署 AWS。
-
从逻辑上描述资源的部署位置。例如,像 Amazon EC2 实例这样的资源位于正确的子网中。
-
对通过 CloudFormation 模板 AWS 服务 部署的每个 AWS 产品使用最新的产品图标。要下载最新的架构图标集,请查看 AWS 架构图标
。 -
包括 CloudFormation 模板部署的所有服务的元数据。
-
包括 CloudFormation 模板部署的所有网络和子网。 VPCs
-
显示集成点,包括第三方资产 APIs 和本地混合资产。
-
图表大小必须为 1100 x 700 像素。保持原始图表比例,无需拉伸或裁剪。
转换现有产品的 CloudFormation 模板
注意
本部分适用于拥有现有 AMI 的卖家,其产品使用商品加载表发布了模板,但现在想在不使用商品加载表的情况下更新该模板。 CloudFormation 如果您要发布新产品,请参阅准备 CloudFormation 模板。
如果您在卖家门户网站的服务器产品
如果您想使用自助服务体验来更新以前使用产品加载表单发布的现有产品,则必须对现有 CloudFormation模板进行更改。
下表描述了使用产品加载表单和自助服务体验之间的区别:
| 产品加载表单 | 自助服务体验 | |
|---|---|---|
EC2资源ImageId财产的价值 |
引用您的 AMI ID 的映射表。有关更多信息,请参阅 使用产品加载表单的 AMI 详情要求。 | 引用您的 AMI ID 的模板参数。有关更多信息,请参阅 AMI 详情要求。 |
嵌套堆栈的 TemplateURL 属性的值 |
必须是固定字符串,不能使用内置函数。 | 可通过内置函数实现动态取值。必须引用一组模板参数。有关更多信息,请参阅 对嵌套堆栈模板的要求。 |
以下示例模板说明了使用产品加载表单发布模板的现有产品的示例。在此示例中,AMI ID 为 ami-example123456,嵌套模板存储在卖家的 S3 存储桶中,具体路径为 https://sellerbucket.s3.us-east-1.amazonaws.com/sellerproductfolder/nested-template.yaml。
使用产品加载表单发布的 YAML 示例:
AWSTemplateFormatVersion: '2010-09-09' Mappings: RegionMap: us-east-1: AMI: ami-example123456 Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: !FindInMap - RegionMap - !Ref AWS::Region - AMI NestedStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://sellerbucket.s3.us-east-1.amazonaws.com/sellerproductfolder/nested-template.yaml
使用产品加载表单发布的 JSON 示例:
{ "AWSTemplateFormatVersion": "2010-09-09", "Mappings": { "RegionMap": { "us-east-1": { "AMI": "ami-example123456" } } }, "Resources": { "EC2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Fn::FindInMap": [ "RegionMap", { "Ref": "AWS::Region" }, "AMI" ] } } }, "NestedStack": { "Type": "AWS::CloudFormation::Stack", "Properties": { "TemplateURL": "https://sellerbucket.s3.us-east-1.amazonaws.com/sellerproductfolder/nested-template.yaml" } } } }
以下模板示例说明了使用自助服务体验更新产品所需的更改。
通过自助服务体验发布的 YAML 示例:
AWSTemplateFormatVersion: '2010-09-09' Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: AWS Marketplace Parameters Parameters: - ImageId - MPS3BucketName - MPS3BucketRegion - MPS3KeyPrefix Parameters: ImageId: Type: AWS::EC2::Image::Id Default: ami-example123456 Description: The AMI that will be used to launch EC2 resources. MPS3BucketName: Type: String Default: sellerbucket Description: Name of the S3 bucket for your copy of the nested templates. MPS3BucketRegion: Type: String Default: us-east-1 Description: AWS Region where the S3 bucket for your copy of the nested templates is hosted. MPS3KeyPrefix: Type: String Default: sellerproductfolder/ Description: S3 key prefix that is used to simulate a folder for your copy of the nested templates. Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: !Ref ImageId NestedStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub https://${MPS3BucketName}.s3.${MPS3BucketRegion}.${AWS::URLSuffix}/${MPS3KeyPrefix}nested-template.yaml
通过自助服务体验发布的 JSON 示例:
{ "AWSTemplateFormatVersion": "2010-09-09", "Metadata": { "AWS::CloudFormation::Interface": { "ParameterGroups": [ { "Label": { "default": "AWS Marketplace Parameters" }, "Parameters": [ "ImageId", "MPS3BucketName", "MPS3BucketRegion", "MPS3KeyPrefix" ] } ] } }, "Parameters": { "ImageId": { "Type": "AWS::EC2::Image::Id", "Default": "ami-example123456", "Description": "The AMI that will be used to launch EC2 resources." }, "MPS3BucketName": { "Type": "String", "Default": "sellerbucket", "Description": "Name of the S3 bucket for your copy of the nested templates." }, "MPS3BucketRegion": { "Type": "String", "Default": "us-east-1", "Description": "AWS Region where the S3 bucket for your copy of the nested templates is hosted." }, "MPS3KeyPrefix": { "Type": "String", "Default": "sellerproductfolder/", "Description": "S3 key prefix that is used to simulate a folder for your copy of the nested templates." } }, "Resources": { "EC2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Ref": "ImageId" } } }, "NestedStack": { "Type": "AWS::CloudFormation::Stack", "Properties": { "TemplateURL": { "Fn::Sub": "https://${MPS3BucketName}.s3.${MPS3BucketRegion}.${AWS::URLSuffix}/${MPS3KeyPrefix}nested-template.yaml" } } } } }