如何解决 AWS CloudFormation 中的模板验证错误或模板格式错误?

上次更新日期:2020 年 10 月 8 日

尝试创建 AWS CloudFormation 堆栈时收到错误消息。

简短描述

请根据收到的错误消息从下列解决方案中选择一种:

  • 如果是“JSON not well-formed”或“YAML not well-formed”错误,请参阅验证模板语法部分。
  • 如果是“Unresolved resource dependencies [XXXXXXXX] in the Resources block of the template”错误,请参阅验证逻辑和物理 ID 部分。
  • 如果是“Unrecognized parameter type: XXXXXXXX”或“Invalid template parameter property 'XXXXXXXX'”错误,请参阅验证参数定义部分。
  • 如果是“Every Condition member must be a string”错误,请参阅确认条件都已指定为字符串部分。
  • 如果是“Unrecognized resource types: [XXXXXXXX]”错误,请参阅验证资源类型的可用性部分。
  • 如果是“Encountered unsupported property XXXXXXXX”错误,请参阅验证属性、值和值类型部分。
  • 如果是“The [environmental resource] 'XXXXXXXX' does not exist”错误,请参阅验证资源是否存在于堆栈之外或验证同一堆栈中资源的依赖关系部分。
  • 如果是“At least one Resources member must be defined”错误,请参阅在模板中添加“资源”部分部分。
  • 如果是“Invalid template property or properties [XXXXXXXX]”错误,请参阅验证模板属性部分。

解决方法

注意:如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请确保您使用的是最新的 AWS CLI 版本

验证模板语法

为了在您的 AWS CloudFormation 模板中采用正确的 JSON 或 YAML 语法,请考虑以下方法:

验证逻辑和物理 ID

1.    确认在模板中定义了资源逻辑 ID。

2.    确认您的环境中存在资源物理 ID。

例如,在下面的 JSON 模板中,test 被引用为 ImageId 属性;而在下面的 YAML 模板中,它被引用为 ImageID 属性。这两个模板都没有一个名为 test 的资源逻辑 ID 或参数。

以下 JSON 和 YAML 模板中未正确定义资源 ID。这些模板返回以下错误:“Unresolved resource dependencies [test] in the Resources block of the template.” 有关资源定义及其语法的更多信息,请参阅资源

JSON:

{
  "Parameters" : { ... },
  "Resources" : {
    "EC2Instance01" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : {"Ref": "test"},
        ...
      }
    }
  }
}

YAML:

Parameters:
Resources:
  EC2Instance01:
    Type: AWS::EC2::Instance
    Properties:
      ImageID: !Ref: test

验证参数定义

1.    将类型设置为仅限以下属性之一:StringNumberList<Number>CommaDelimitedList

注意:这些属性包括特定于 AWS 的参数类型和 AWS Systems Manager 代理(SSM 代理)参数类型。

2.    在您的 AWS 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.    在您的 AWS CloudFormation 模板中,确认参数部分不包含任何内部函数

例如,下列 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

确认条件都已指定为字符串

在您的 AWS CloudFormation 模板中,将条件指定为字符串。

例如,资源 EC2RouteA 中的条件在下列 JSON 和 YAML 模板中指定为字符串列表,而不是单个字符串。这些模板会产生以下验证错误:“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 区域中都可用。例如,下列 JSON 和 YAML 模板中的资源类型 AWS::WAFRegional::IPSet 目前在 ap-south-1 中不可用。这些模板会产生以下错误:“Unrecognized resource types: [XXXXXXXX]”。

JSON:

{
  "IPSetlistA": {
    "Type": "AWS::WAFRegional::IPSet",
    "Properties": {
      "Name": "IPSet for IP addresses that are not allowed",
      "IPSetDescriptors": [
        {
          "Type": "IPV4",
          "Value": "x.x.x.x/x"
        },
        {
          "Type": "IPV4",
          "Value": "x.x.x.x/x"
        }
      ]
    }
  }
}

YAML:

IPSetlistA:
 Type: 'AWS::WAFRegional::IPSet'
 Properties:
  Name: IPSet for IP addresses that are not allowed
  IPSetDescriptors:
   - Type: IPV4
    Value: x.x.x.x/x
   - Type: IPV4
    Value: x.x.x.x/x

注意:AWS CloudFormation 模板是使用符合 JSON 或 YAML 标准的格式存储为文本文件。上面的 JSON 和 YAML 模板使用的模板相同,但格式不同。有关 YAML 支持的更多信息,请参阅了解模板基础知识AWS CloudFormation 更新 – YAML,跨堆栈引用、简化的替代

2.    如果您的模板包含任何无服务器资源,请包含转换声明。请参阅以下 JSON 和 YAML 示例。

JSON:

{
    "Transform": "AWS::Serverless-2016-10-31",
    "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
Resources:
  MyServerlessFunctionLogicalID:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      CodeUri: 's3://testBucket/mySourceCode.zip'

验证属性、值和值类型

使用模板部分和资源定义中有效的属性、值和值类型

验证资源是否存在于堆栈之外或验证同一堆栈中资源的依赖关系

如果要将 AWS CloudFormation 存在于堆栈外部的资源或资源的 Amazon 资源名称 (ARN) 硬编码为某种堆栈资源,请验证以下内容:

  • 资源名称或 ARN 正确。
  • 资源存在。
  • 资源与堆栈位于同一 AWS 区域中。请考虑一些资源接受跨 AWS 区域或账户的属性。

例如,如果在指定安全组 (sg-1234567890) 的堆栈中,不存在 AWS::EC2::Instance 资源的安全组,或在堆栈的 AWS 区域中不存在,则 AWS::EC2::Instance 资源将失败。您将收到以下错误消息:“The sg-1234567890 does not exist”。 请参阅以下示例:

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.>

在模板中添加“资源”部分

您必须在 AWS CloudFormation 模板中添加资源部分,否则会收到错误消息。

验证模板属性

在您的 AWS CloudFormation 模板中仅使用允许的模板属性

在以下 JSON 和 YAML 示例中,存储桶资源与资源部分处于同一级别。这将返回以下错误:“Template validation error: Invalid template property or properties [Bucket]”。 导致该错误的原因是,AWS CloudFormation 模板验证程序将存储桶资源视为部分级别的规范,不允许将其作为模板属性。

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

注意:在前面的 JSON 和 YAML 模板中,将 BucketName 替换为您的存储桶名称。</p


这篇文章对您有帮助吗?


您是否需要账单或技术支持?