如何解决 CloudFormation 中的模板验证错误或模板格式错误?
上次更新日期:2022 年 9 月 21 日
尝试创建 AWS CloudFormation 堆栈时收到错误消息。
简短描述
请根据收到的错误消息从下列解决方案中选择一种:
- 如果是“JSON not well-formed(JSON 格式不正确)”或“YAML not well-formed(YAML 格式不正确)”错误,请参阅验证模板语法部分。
- 如果是“Unresolved resource dependencies [XXXXXXXX] in the Resources block of the template(模板的资源数据块中未解析的资源依赖关系 [XXXXXXXX])”错误,请参阅验证逻辑 ID 和参数部分。
- 如果是“Unrecognized parameter type: XXXXXXXX(无法识别的参数类型:XXXXXXXX)”或“Invalid template parameter property 'XXXXXXXX'(无效的模板参数属性“XXXXXXXX”)”错误,请参阅验证参数定义部分。
- 如果是 "Every Condition member must be a string" 错误,见确认条件都已指定为字符串部分。
- 如果是 Unrecognized resource types: [XXXXXXXX](无法识别的资源类型:[XXXXXXXX])错误,请参阅验证资源类型的可用性部分。
- 如果是 The [environmental resource] 'XXXXXXXX' does not exist([环境资源]“XXXXXXXX”不存在)错误,请参阅验证资源是否存在于堆栈之外或验证同一堆栈中资源的依赖关系部分。
- 如果是 Invalid template property or properties [XXXXXXXX](无效的模板属性 [XXXXXXXX])错误,请参阅验证模板属性部分。
解决方法
注意:如果您在运行 AWS Command Line Interface (AWS CLI) 命令时收到错误,请确保您使用的是最新的 AWS CLI 版本。
验证模板语法
为了在您的 CloudFormation 模板中采用正确的 JSON 或 YAML 语法,请考虑以下方法:
- 使用 AWS CloudFormation Designer 创建堆栈。
- 使用文本编辑器或命令行工具(如 AWS CLI 模板验证器)验证 JSON 语法。
- 使用 aws cloudformation validate-template 命令验证 YAML 语法。
- 使用 GitHub 网站上的 AWS CloudFormation linter 验证 JSON 或 YAML 模板。
验证逻辑 ID 和参数
确认已在模板中定义资源逻辑 ID 和参数。
在以下 JSON 和 YAML 模板中,为 ImageId 属性引用了 test。但是,这两个模板都没有名为 test 的资源逻辑 ID 或参数。这些模板会返回以下错误:Unresolved resource dependencies [test] in the Resources block of the template(模板的资源数据块中未解析的资源依赖关系 [test])。 有关资源定义及其语法的更多信息,请参阅资源。
JSON 示例(不正确):
{
"Resources" : {
"EC2Instance01" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"ImageId" : {"Ref": "test"}
}
}
}
}
YAML 示例(不正确):
Resources:
EC2Instance01:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref test
要解决此问题,请添加名为 test 的资源逻辑 ID。或者,创建名为 test 的参数,其中引用将返回 imageId 值。以下 JSON 和 YAML 示例模板包含名为 test 的参数,并且其值为 imageId。
JSON 示例(正确):
{
"Parameters": {
"test": {
"Type": "String",
"Default": "ami-xxx"
}
},
"Resources" : {
"EC2Instance01" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"ImageId" : {"Ref": "test"}
}
}
}
}
YAML 示例(正确):
Parameters:
test:
Type: String
Default: ami-xxx
Resources:
EC2Instance01:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: !Ref test
验证参数定义
1. 将 Type(类型)设置为以下支持的属性之一:
- String(字符串)、Number(数字)、List
或 CommaDelimitedList - AWS 特定参数类型
- SSM 参数类型
2. 在您的 CloudFormation 模板中,确认参数仅包含以下允许的属性:
"Parameters" : {
"ParameterName" : {
"AllowedPattern" : "A regular expression that represents the patterns to allow for String types.",
"AllowedValues" : "An array containing the list of values allowed for the parameter",
"ConstraintDescription" : "A string that explains a constraint when the constraint is violated"
"Default" : "A value of the appropriate type for the template to use if no value is specified when a stack is created. If you define constraints for the parameter, you must specify a value that adheres to those constraints",
"Description" : "A string of up to 4000 characters that describes the parameter",
"MaxLength" : "An integer value that determines the largest number of characters you want to allow for String types",
"MaxValue" : "A numeric value that determines the largest numeric value you want to allow for Number types.",
"MinLength" : "An integer value that determines the smallest number of characters you want to allow for String types.",
"MinValue" : "A numeric value that determines the smallest numeric value you want to allow for Number types.",
"NoEcho" : "Whether to mask the parameter value when a call is made that describes the stack.
If you set the value to true, the parameter value is masked with asterisks (*****).",
"Type" : "The data type for the parameter (DataType)."
},
3. 在 CloudFormation 模板中,确认 Parameters(参数)部分不包含任何内置函数。
在以下 JSON 和 YAML 示例模板中,ParameterC 的默认值具有内置函数 Fn::Sub。此内置函数将导致验证错误:Every Default member must be a string(每个默认成员必须为字符串)。
JSON 示例(不正确):
{
"Parameters": {
"ParameterA": {
"Type": "String",
"Default": "abc"
},
"ParameterB": {
"Type": "String",
"Default": "def"
},
"ParameterC": {
"Type": "String",
"Default": {
"Fn::Sub": "${ParameterA}-${ParameterB}"
}
}
},
"Resources": {
"MyS3Bucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Ref": "ParameterC"
}
}
}
}
}
YAML 示例(不正确):
Parameters:
ParameterA:
Type: String
Default: abc
ParameterB:
Type: String
Default: def
ParameterC:
Type: String
Default: !Sub '${ParameterA}-${ParameterB}'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !Ref ParameterC
确认条件已指定为字符串
在 CloudFormation 模板中,将条件指定为字符串。
在以下 JSON 和 YAML 示例模板中,资源 EC2RouteA 中的条件被指定为字符串列表,而不是单个字符串。这些模板将产生以下验证错误:Every Condition member must be a string(每个条件成员必须为字符串)。
JSON 示例(不正确):
{
"Conditions": {
"ConditionA": {
"Fn::Not": [
{
"Fn::Equals": [
"",
"Sample"
]
}
]
},
"ConditionB": {
"Fn::Not": [
{
"Fn::Equals": [
"",
"Sample"
]
}
]
}
},
"Resources": {
"EC2RouteA": {
"Type": "AWS::EC2::Route",
"Condition": [
"ConditionA",
"ConditionB"
],
"Properties": {
...
}
}
}
}
YAML 示例(不正确):
Conditions:
ConditionA: !Not
- !Equals
- ''
- Sample
ConditionB: !Not
- !Equals
- ''
- Sample
Resources:
EC2RouteA:
Type: 'AWS::EC2::Route'
Condition:
- ConditionA
- ConditionB
Properties:
要解决此错误,请将 ConditionAandB 添加到模板的条件部分,然后将 ConditionAandB 用作 EC2RouteA 资源的条件。请参阅以下 JSON 和 YAML 示例模板。
JSON 示例(正确):
{
"Conditions": {
"ConditionA": {
"Fn::Not": [
{
"Fn::Equals": [
"",
"Sample"
]
}
]
},
"ConditionB": {
"Fn::Not": [
{
"Fn::Equals": [
"",
"Sample"
]
}
]
},
"ConditionAandB": {
"Fn::And": [
{
"Condition": "ConditionA"
},
{
"Condition": "ConditionB"
}
]
}
},
"Resources": {
"EC2RouteA": {
"Type": "AWS::EC2::Route",
"Condition": "ConditionAandB",
"Properties": {
...
}
}
}
}
YAML 示例(正确):
Conditions:
ConditionA:
Fn::Not:
- Fn::Equals:
- ''
- Sample
ConditionB:
Fn::Not:
- Fn::Equals:
- ''
- Sample
ConditionAandB:
Fn::And:
- Condition: ConditionA
- Condition: ConditionB
Resources:
EC2RouteA:
Type: AWS::EC2::Route
Condition: ConditionAandB
Properties:
验证资源类型的可用性
1. 验证您的资源在您的 AWS 区域中可用。
并非所有资源类型在每个 AWS 区域中都可用。如果模板中包含的资源类型在 AWS 区域中不可用,则会导致以下错误:Unrecognized resource types: [XXXXXXXX](无法识别的资源类型:[XXXXXXXX])。
2. 如果模板包含任何无服务器资源,请包含转换声明。请参阅以下 JSON 和 YAML 示例模板。
JSON 示例:
{
"Transform": "AWS::Serverless-2016-10-31", #Please make sure to include this.
"Resources": {
"MyServerlessFunctionLogicalID": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "index.handler",
"Runtime": "nodejs8.10",
"CodeUri": "s3://testBucket/mySourceCode.zip"
}
}
}
}
YAML 示例:
Transform: AWS::Serverless-2016-10-31 #Please make sure to include this.
Resources:
MyServerlessFunctionLogicalID:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs8.10
CodeUri: 's3://testBucket/mySourceCode.zip'
验证资源是否存在于堆栈之外或验证同一堆栈中资源的依赖关系
如果要将某个资源或存在于 CloudFormation 堆栈外部的资源的 Amazon Resource Name (ARN) 硬编码到其中一个堆栈资源,请验证以下内容:
- 资源名称或 ARN 正确。
- 资源存在。
- 资源与堆栈位于同一 AWS 区域中。请考虑一些资源接受跨 AWS 区域或跨账户的属性。
例如,堆栈中指定安全组 (sg-1234567890) 的 AWS::EC2::Instance 资源在以下情况下会失败:
- 安全组不存在。
- 堆栈的 AWS 区域中不存在安全组。
因此,您将收到此错误消息:The sg-1234567890 does not exist(sg-1234567890 不存在)。 请参阅以下示例:
LinuxInstance:
Type: AWS::EC2::Instance
Properties:
SubnetId: !Ref ServerSubnetID
KeyName: !Ref EC2KeyPairName
SecurityGroupIds: sg-1234567890 #<This resource must exist and be in the same AWS Region as the stack.>
验证模板属性
在 CloudFormation 模板中仅使用允许的模板属性。
在以下 JSON 和 YAML 示例模板中,存储桶资源与 Resources(资源)部分处于同一级别。这将返回以下错误:Template validation error: Invalid template property or properties [Bucket](模板验证错误:无效的模板属性 [存储桶])。 导致此错误的原因是,CloudFormation 模板验证程序将存储桶资源视为部分级别的规范。不允许将部分级别的规范作为模板属性。
JSON 示例(不正确):
{
"Resources": {
"WaitCondition": {
"Type": "AWS::CloudFormation::WaitCondition"
}
}, #<There is an extra '}' causing the Resources section to be closed off after the WaitCondition resource.>
"Bucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"Name": "BucketName"
}
}
}
YAML 示例(不正确):
Resources:
WaitCondition:
Type: AWS::CloudFormation::WaitCondition
Bucket: # <The spacing for the entire Bucket resource is incorrect and needs to be shifted 2 spaces to the right.>
Type: AWS::S3::Bucket
Properties:
Name: BucketName
要解决此问题,请改正格式,以便在 Resources(资源)部分中指定存储桶资源。请参阅以下格式正确的 JSON 和 YAML 示例模板。
JSON 示例(正确):
{
"Resources": {
"WaitCondition": {
"Type": "AWS::CloudFormation::WaitCondition"
},
"Bucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"Name": "BucketName"
}
}
}
}
YAML 示例(正确):
Resources:
WaitCondition:
Type: 'AWS::CloudFormation::WaitCondition'
Bucket:
Type: 'AWS::S3::Bucket'
Properties:
Name: BucketName