为什么我会收到一个错误,提示存在未解析的 VPC 依赖项?

Why am I getting an error that there are unresolved VPC dependencies?

我正在尝试实施满足以下分配条件的配置管理:

https://s3.amazonaws.com/seis615/AnsiblePress.json

在文本编辑器中快速查看模板。请注意 mgmt1 实例的 UserData 属性 是如何配置的。当 CloudFormation 启动这个堆栈时,它会自动在管理服务器上安装和配置 Ansible 软件。使用少量脚本代码将 bootstrap 配置管理软件安装到新系统上是很常见的。安装 Ansible 后,它可用于安装和配置环境中的其他服务器。

CloudFormation 模板缺少一些您需要添加的资源:

逻辑名称为 webserverlb 的应用程序负载平衡器,它将 HTTP(端口 80)请求分发到 web1 和 web2 实例。负载均衡器的健康检查端点应该是根 (/) 目录。

一个 db.t2.micro RDS 数据库实例(不是集群)运行 一个名为 wordpress 的 MariaDB 10.2.21 数据库位于私有 VPC 子网中。为 CloudFormation RDS 资源使用逻辑名称 wordpressdb。 RDS 和 EC2 实例实际上早于 AWS 中 VPC 的到来,因此令人困惑的是有两种不同的方法来配置这些资源。您需要确保此数据库实例设计为 运行 在 VPC 内,并定义了正确的数据库子网组和安全组资源。

名为 WebserverLbSecurityGroup 的安全组允许来自 Internet 的传入 http 访问。

一个名为 WordpressDbSecurityGroup 的安全组允许从 WebServerSecurityGroup

在标准 MySQL 端口上进行传入访问

一个名为 DBName 的输入参数,它将定义要创建的数据库名称(默认为 wordpress)

名为 DBUser 的输入参数将用于数据库服务器用户名。

一个名为 DBPassword 的输入参数,将用于数据库服务器密码。

名为 wordpressDbEndpoint 的堆栈输出显示 MariaDB 实例端点地址。

名为 wordpressLbEndpoint 的堆栈输出显示了应用程序负载平衡器 URL。

我配置的 JSON(下方)给我以下模板格式错误,我不知道为什么:

模板格式错误:模板资源块中未解决的资源依赖关系[wordpressVPC]

    {"AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
      "SSMAccessRole": {
         "Type": "AWS::IAM::Role",
         "Properties": {
            "AssumeRolePolicyDocument": {
               "Version" : "2012-10-17",
               "Statement": [ {
                  "Effect": "Allow",
                  "Principal": {
                     "Service": [ "ec2.amazonaws.com" ]
                  },
                  "Action": [ "sts:AssumeRole" ]
               } ]
            },
            "Path": "/"
         }
      },
      "SSMRolePolicies": {
         "Type": "AWS::IAM::Policy",
         "Properties": {
            "PolicyName": "ssmProperties",
            "PolicyDocument": {
               "Version" : "2012-10-17",
               "Statement": [
                 {
                   "Effect": "Allow",
                   "Action": [
                     "ssm:DescribeParameters",
                     "ssm:PutParameter",
                     "ssm:GetParameters",
                     "ssm:DeleteParameter"
                   ],
                   "Resource": {
                     "Fn::Join" : [
                       "",
                       [
                         "arn:aws:ssm:",
                         { "Ref" : "AWS::Region" },
                         ":",
                         { "Ref" : "AWS::AccountId"},
                         {
                           "Fn::Join" : [
                             "",
                             [ ":parameter/", { "Ref": "AWS::StackName" }, ".*" ]
                           ]
                         }
                       ]
                     ]
                    }
                   }
                 ]
            },
            "Roles": [ { "Ref": "SSMAccessRole" } ]
         }
      },
      "SSMInstanceProfile": {
         "Type": "AWS::IAM::InstanceProfile",
         "Properties": {
            "Path": "/",
            "Roles": [ { "Ref": "SSMAccessRole" } ]
         }
      },
      "web1pem" : {
        "Type" : "AWS::SSM::Parameter",
        "Properties" : {
          "Name" : {
            "Fn::Join" : [
              "",
              [ { "Ref": "AWS::StackName" }, ".web1pem" ]
            ]
          },
          "Type" : "String",
          "Value" : "0",
          "Description": "web1 instance private key."
        }
      },
      "web2pem" : {
        "Type" : "AWS::SSM::Parameter",
        "Properties" : {
          "Name" : {
            "Fn::Join" : [
              "",
              [ { "Ref": "AWS::StackName" }, ".web2pem" ]
            ]
          },
          "Type" : "String",
          "Value" : "0",
          "Description": "web2 instance private key."
        }
      },
      "wordpressVpc": {
          "Type": "AWS::EC2::VPC",
          "Properties": {
              "EnableDnsSupport": "true",
              "EnableDnsHostnames": "true",
              "CidrBlock": "10.0.0.0/16",
              "Tags": [
                  {
                      "Key": "Environment",
                      "Value": "Test"
                  }
              ]
          }
      },
      "publicSubnet1": {
          "Type": "AWS::EC2::Subnet",
          "Properties": {
              "VpcId": {
                  "Ref": "wordpressVpc"
              },
              "CidrBlock": "10.0.0.0/24",
               "AvailabilityZone" : {
                  "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
                }
          }
      },
      "publicSubnet2": {
          "Type": "AWS::EC2::Subnet",
          "Properties": {
              "VpcId": {
                  "Ref": "wordpressVpc"
              },
              "CidrBlock": "10.0.1.0/24",
               "AvailabilityZone" : {
                  "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
                }
          }
      },
      "privateSubnet1": {
          "Type": "AWS::EC2::Subnet",
          "Properties": {
              "VpcId": {
                  "Ref": "wordpressVpc"
              },
              "CidrBlock": "10.0.2.0/24",
              "AvailabilityZone" : {
                  "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
                }
          }
      },
      "privateSubnet2": {
          "Type": "AWS::EC2::Subnet",
          "Properties": {
              "VpcId": {
                  "Ref": "wordpressVpc"
              },
              "CidrBlock": "10.0.3.0/24",
              "AvailabilityZone" : {
                  "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
                }
          }
      },
      "web1": {
          "Type": "AWS::EC2::Instance",
          "DependsOn": [
              "web1pem"
          ],
          "Properties": {
              "InstanceType": "t2.micro",
              "ImageId": {"Ref": "AMI"},
              "IamInstanceProfile": {
                "Ref": "SSMInstanceProfile"
              },
              "KeyName": {
                  "Ref": "KeyName"
              },
              "NetworkInterfaces": [
                  {
                      "GroupSet": [
                          {
                              "Ref": "WebServerSecurityGroup"
                          }
                      ],
                      "AssociatePublicIpAddress": "true",
                      "DeviceIndex": "0",
                      "DeleteOnTermination": "true",
                      "SubnetId": {
                          "Ref": "publicSubnet1"
                      }
                  }
              ],
              "Tags": [
                  {
                      "Key": "Name",
                      "Value": "web1"
                  }
              ],
              "UserData" : {
                "Fn::Base64" : {
                  "Fn::Join" : [
                    "", [
                      "#!/bin/bash -xe\n",
                      "ssh-keygen -f /home/ec2-user/.ssh/web1-key.pem -q -N \"\"\n",
                      "chown ec2-user:ec2-user /home/ec2-user/.ssh/web1-key.pem\n",
                      "chown ec2-user:ec2-user /home/ec2-user/.ssh/web1-key.pem.pub\n",
                      "PEMFILE=`cat /home/ec2-user/.ssh/web1-key.pem`\n",
                      "aws ssm put-parameter --name ", { "Ref" : "web1pem" }, " --type String --value \"${PEMFILE}\" --overwrite --region ", { "Ref" : "AWS::Region" },"\n",
                      "cat /home/ec2-user/.ssh/web1-key.pem.pub >> /home/ec2-user/.ssh/authorized_keys\n",
                      "# Signal the status from cfn-init\n",
                      "/opt/aws/bin/cfn-signal -e $? ",
                      "         --stack ",
                      {
                          "Ref": "AWS::StackName"
                      },
                      "         --resource web1 ",
                      "         --region ",
                      {
                          "Ref": "AWS::Region"
                      },
                      "\n"
                    ]
                  ]
                }
              }
          },
          "CreationPolicy": {
              "ResourceSignal": {
                  "Timeout": "PT5M"
              }
          }
      },
      "web2": {
          "Type": "AWS::EC2::Instance",
          "DependsOn": [
              "web1pem"
          ],
          "Properties": {
              "InstanceType": "t2.micro",
              "ImageId": {"Ref": "AMI"},
              "IamInstanceProfile": {
                "Ref": "SSMInstanceProfile"
              },
              "KeyName": {
                  "Ref": "KeyName"
              },
              "NetworkInterfaces": [
                  {
                      "GroupSet": [
                          {
                              "Ref": "WebServerSecurityGroup"
                          }
                      ],
                      "AssociatePublicIpAddress": "true",
                      "DeviceIndex": "0",
                      "DeleteOnTermination": "true",
                      "SubnetId": {
                          "Ref": "publicSubnet2"
                      }
                  }
              ],
              "Tags": [
                  {
                      "Key": "Name",
                      "Value": "web2"
                  }
              ],
              "UserData" : {
                "Fn::Base64" : {
                  "Fn::Join" : [
                    "", [
                      "#!/bin/bash -xe\n",
                      "ssh-keygen -f /home/ec2-user/.ssh/web2-key.pem -q -N \"\"\n",
                      "chown ec2-user:ec2-user /home/ec2-user/.ssh/web2-key.pem\n",
                      "chown ec2-user:ec2-user /home/ec2-user/.ssh/web2-key.pem.pub\n",
                      "PEMFILE=`cat /home/ec2-user/.ssh/web2-key.pem`\n",
                      "aws ssm put-parameter --name ", { "Ref" : "web2pem" }, " --type String --value \"${PEMFILE}\" --overwrite --region ", { "Ref" : "AWS::Region" },"\n",
                      "cat /home/ec2-user/.ssh/web2-key.pem.pub >> /home/ec2-user/.ssh/authorized_keys\n",
                      "# Signal the status from cfn-init\n",
                      "/opt/aws/bin/cfn-signal -e $? ",
                      "         --stack ",
                      {
                          "Ref": "AWS::StackName"
                      },
                      "         --resource web2 ",
                      "         --region ",
                      {
                          "Ref": "AWS::Region"
                      },
                      "\n"
                    ]
                  ]
                }
              }
          },
          "CreationPolicy": {
              "ResourceSignal": {
                  "Timeout": "PT5M"
              }
          }
      },
      "WebServerSecurityGroup": {
          "Type": "AWS::EC2::SecurityGroup",
          "Properties": {
              "VpcId": {
                  "Ref": "wordpressVpc"
              },
              "GroupDescription": "Allow access from HTTP and SSH traffic",
              "SecurityGroupIngress": [
                  {
                      "IpProtocol": "tcp",
                      "FromPort": "80",
                      "ToPort": "80",
                      "CidrIp": "0.0.0.0/0"
                  },
                  {
                      "IpProtocol": "tcp",
                      "FromPort": "22",
                      "ToPort": "22",
                      "CidrIp": {"Ref": "YourIp"}
                  }
              ]
          }
      },
      "WebServerSGIngressTCP22": {
        "Type": "AWS::EC2::SecurityGroupIngress",
        "Metadata": {
          "Comment": "SSH ingress security rule"
        },
        "Properties" : {
          "IpProtocol": "tcp",
          "FromPort": "22",
          "ToPort": "22",
          "SourceSecurityGroupId": { "Ref": "WebServerSecurityGroup" },
          "GroupId": { "Fn::GetAtt": ["WebServerSecurityGroup", "GroupId"]}
        }
      },
      "InternetGateway": {
          "Type": "AWS::EC2::InternetGateway",
          "Properties": {}
      },
      "AttachGateway": {
          "Type": "AWS::EC2::VPCGatewayAttachment",
          "Properties": {
              "InternetGatewayId": {
                  "Ref": "InternetGateway"
              },
              "VpcId": {
                  "Ref": "wordpressVpc"
              }
          }
      },
      "PublicRouteTable": {
          "Type": "AWS::EC2::RouteTable",
          "Properties": {
              "VpcId": {
                  "Ref": "wordpressVpc"
              }
          }
      },
      "PublicRoute": {
          "Type": "AWS::EC2::Route",
          "Properties": {
              "DestinationCidrBlock": "0.0.0.0/0",
              "RouteTableId": {
                  "Ref": "PublicRouteTable"
              },
              "GatewayId": {
                  "Ref": "InternetGateway"
              }
          },
          "DependsOn": [
              "InternetGateway", "AttachGateway"
          ]
      },
      "Public1RouteTableAssociation": {
          "Type": "AWS::EC2::SubnetRouteTableAssociation",
          "Properties": {
              "RouteTableId": {
                  "Ref": "PublicRouteTable"
              },
              "SubnetId": {
                  "Ref": "publicSubnet1"
              }
          }
      },
      "Public2RouteTableAssociation": {
          "Type": "AWS::EC2::SubnetRouteTableAssociation",
          "Properties": {
              "RouteTableId": {
                  "Ref": "PublicRouteTable"
              },
              "SubnetId": {
                  "Ref": "publicSubnet2"
              }
          }
      },
      "webserverlb": {
        "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
        "Properties": {
            "IpAddressType": "ipv4",
            "SecurityGroups": [
                {
                    "Ref": "webserverlbSecurityGroup"
                }
            ],
            "Subnets": [
                {
                    "Ref": "publicSubnet1"
                },
                {
                    "Ref": "publicSubnet2"
                }
            ],
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "webserverlb"
                }
            ]
        },
        "DependsOn": [
            "webserversSecurityGroup"
        ]
      },
    "webserverlbSecurityGroup": {
        "Type": "AWS::EC2::SecurityGroup",
        "Properties": {
            "VpcId": {
                "Ref": "wordpressVPC"
            },
            "GroupDescription": "Allows incoming requests from port 80 via HTTP.",
            "SecurityGroupIngress": [
                {
                    "IpProtocol": "TCP",
                    "FromPort": "80",
                    "ToPort": "80",
                    "CidrIp": "0.0.0.0/0",
                    "Description": "Allows 80 from Internet"
                }
            ]
        }
      },
    "wordpressdb": {
            "Type": "AWS::RDS::DBInstance",
            "Properties": {
                "VpcId": {
                    "Ref": "wordpressVPC"
                },
                "AvailabilityZone": "us-east-1a",
                "DBInstanceClass": "db.t2.micro",
                "DBName": "wordpress",
                "Engine": "mariadb",
                "EngineVersion": "10.2.21",
                "MultiAZ": 1,
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "wordpressdb"
                    }
                ]
            },
            "DependsOn": [
                "wordpressdbSecurityGroup"
            ]
      },
    "wordpressdbSecurityGroup": {
            "Type": "AWS::RDS::DBSecurityGroup",
            "Properties": {
                "VpcId": {
                    "Ref": "wordpressVPC"
                },
                "GroupDescription": "Enable access to the db via port 3306.",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "wordpressdbSecurityGroup"
                    }
                ],
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "TCP",
                        "FromPort": "3306",
                        "ToPort": "3306",
                        "Description": "Enable HTTP access."
                    }
                ]
            }
      }
    },
    "Parameters": {
        "KeyName": {
            "Description": "Name of your EC2 KeyPair to enable SSH access to the instances.",
            "Type": "AWS::EC2::KeyPair::KeyName",
            "ConstraintDescription": "must be the name of an existing EC2 KeyPair."
        },
        "YourIp": {
          "Description": "The current CIDR IP address of your workstation (x.x.x.x/32). http://checkip.amazonaws.com/",
          "Type": "String",
          "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-9]|3[0-2]))$",
          "ConstraintDescription": "Must be a valid IP CIDR range of the form x.x.x.x/x."
        },
        "AMI": {
          "Description": "The EC2 instance AMI",
          "Type": "String",
          "Default": "ami-00dc79254d0461090"
        },
        "DBName": {
            "Description": "Name of the database",
            "Type" : "String",
            "Default": "wordpress"
        },
        "DBUser": {
            "Default": "admin",
            "NoEcho": "false",
            "Description" : "The WordPress database admin account user name",
            "Type": "String",
            "MinLength": "1",
            "MaxLength": "16",
            "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*"
          },
        "DBPassword": {
            "NoEcho": "true",
            "Description" : "The password of the database.",
            "Type": "String",
            "MinLength": "1",
            "MaxLength": "16",
            "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*"
          }     
        },
    "Outputs": {
        "web1PublicIp": {
          "Value": {"Fn::GetAtt": ["web1","PublicIp"]},
          "Description": "web1 public IP"
        },
        "we2PublicIp": {
          "Value": {"Fn::GetAtt": ["web2","PublicIp"]},
          "Description": "web2 public IP"
        },
        "mgmt1PublicIp": {
            "Value": {"Fn::GetAtt": ["mgmt1","PublicIp"]},
            "Description": "mgmt1 public IP"
        }
    }
  }

因为 CloudFormation 区分大小写。您的 vpc 资源称为 wordpressVpc,但在某些地方您使用的是 wordpressVPC.

建议在创作模板以及自动完成和文档链接时尝试 CloudFormation Linter in VSCode 查看其中的一些内联错误:

E3005 DependsOn should reference other resources at Resources/webserverlb/DependsOn/0
E1012 Ref wordpressVPC not found as a resource or parameter
E1012 Ref wordpressVPC not found as a resource or parameter
E3002 Invalid Property Resources/wordpressdb/Properties/VpcId
E3003 Property DBSecurityGroupIngress missing at Resources/wordpressdbSecurityGroup/Properties
E1012 Ref wordpressVPC not found as a resource or parameter
E3002 Invalid Property Resources/wordpressdbSecurityGroup/Properties/VpcId
E3002 Invalid Property Resources/wordpressdbSecurityGroup/Properties/SecurityGroupIngress
E1010 Invalid GetAtt mgmt1.PublicIp for resource mgmt1PublicIp