Cloudformation卡在UPDATE_ROLLBACK_FAILED

时间:2019-03-28 19:22:27

标签: amazon-cloudformation

请帮助克服这个问题。我必须输入3个逻辑ID才能回滚我的更新,但是cloudformation中的正则表达式不允许这样做,因为正则表达式似乎不允许使用逗号。但是AWS的继续ROLLBACK指令明确指出要使用逗号:

  

”要跳过资源,请输入逗号分隔逻辑列表   资源ID。仅包括阻止   回滚。”

但是cloudformation正则表达式不允许使用逗号吗????我在这里想念什么?我不能前进或后退。我的cloudformation堆栈卡住了。

我尝试回滚的错误:

  

回滚失败:1次验证   检测到错误:值'[rRoute10,rRoute192,rRoute172]'   'resourcesToSkip'无法满足约束:成员必须满足   约束:[成员必须满足正则表达式模式:   [a-zA-Z0-9] + | [a-zA-Z] [-a-zA-Z0-9] *。[a-zA-Z0-9] +]

我在cloudformation中的错误:

  

14:06:04 UTC-0400 UPDATE_FAILED AWS :: EC2 :: Route rRoute192网关   ID'vgw-0e7d969e316a7b5d5'不存在(服务:AmazonEC2;状态   代码:400;错误代码:InvalidGatewayID.NotFound;要求编号:   6d4cdb5f-31c5-4cf3-8777-3e3eb361d594)

     

14:06:04 UTC-0400 UPDATE_FAILED AWS :: EC2 :: Route rRoute10网关   ID'vgw-0e7d969e316a7b5d5'不存在(服务:AmazonEC2;状态   代码:400;错误代码:InvalidGatewayID.NotFound;要求编号:   315ecc3a-d70c-46b7-b1cd-05f4c6765edd)

     

14:06:04 UTC-0400 UPDATE_FAILED AWS :: EC2 :: Route rRoute172网关   ID'vgw-0e7d969e316a7b5d5'不存在(服务:AmazonEC2;状态   代码:400;错误代码:InvalidGatewayID.NotFound;要求编号:   2a6e20f0-4d41-4647-85f0-ffbfc0326680)

在后台,有人删除了我们的VPG并创建了另一个网关。他们还手动更新了路线。现在,我正在尝试使路由表上的堆栈同步。但是,堆栈无法更新,现在无法回滚。

截屏: enter image description here

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
    RDS

    SAM Template for creating an RDS in a secure Fault-Tolerant fashion...

Parameters:
  pDBName:
    Default: MyDatabase
    Description: The database name
    Type: String
    MinLength: '1'
    MaxLength: '64'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  pDBUser:
    NoEcho: 'true'
    Description: The database admin account username
    Type: String
    MinLength: '1'
    MaxLength: '16'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
    ConstraintDescription: must begin with a letter and contain only alphanumeric
      characters.
  pDBPassword:
    NoEcho: 'true'
    Description: The database admin account password
    Type: String
    MinLength: '1'
    MaxLength: '41'
    AllowedPattern: '[a-zA-Z0-9]+'
    ConstraintDescription: must contain only alphanumeric characters.
  pDBAllocatedStorage:
    Default: '20'
    Description: The size of the database (Gb)
    Type: Number
    MinValue: '20'
    MaxValue: '16384'
    ConstraintDescription: must be between 5 and 1024Gb.
  pDBInstanceClass:
    Description: The database instance type
    Type: String
    Default: db.t2.micro
    AllowedValues: [db.t1.micro, db.m1.small, db.m1.medium, db.m1.large, db.m1.xlarge,
      db.m2.xlarge, db.m2.2xlarge, db.m2.4xlarge, db.m3.medium, db.m3.large, db.m3.xlarge,
      db.m3.2xlarge, db.m4.large, db.m4.xlarge, db.m4.2xlarge, db.m4.4xlarge, db.m4.10xlarge,
      db.r3.large, db.r3.xlarge, db.r3.2xlarge, db.r3.4xlarge, db.r3.8xlarge, db.m2.xlarge,
      db.m2.2xlarge, db.m2.4xlarge, db.cr1.8xlarge, db.t2.micro, db.t2.small, db.t2.medium,
      db.t2.large]
    ConstraintDescription: must select a valid database instance type.

    # TODO - Future DBEngine allowed values: [aurora-mysql, aurora-postgresql, mariadb, oracle-ee, oracle-se2, sqlserver-ee, sqlserver-se, sqlserver-ex, sqlserver-web]
  pDBEngine:
    Description: The database type to create
    Type: String
    Default: oracle-se2
    AllowedValues: [aurora-mysql, oracle-ee, oracle-se2]
    ConstraintDescription: must select a valid database engine
  pDBEngineVersion:
    Description: The version of database to create
    Type: String
  pMultiAZ:
    Description: Multi-AZ master database
    Type: String
    Default: 'false'
    AllowedValues: ['true', 'false']
    ConstraintDescription: must be true or false.
  pDatabaseDeletionProtection:
    Description: Do we even allow a database to be deleted?
    Type: String
    Default: 'false'
    AllowedValues: ['true', 'false']
    ConstraintDescription: must be true or false.
  pDatabaseLicenseModel:
    Description: What licensing do we use?
    Type: String
    Default: "license-included"
    AllowedValues: ["license-included", "bring-your-own-license", "general-public-license"]
    ConstraintDescription: must be license-included or bring-your-own-license or general-public-license
  pDBParameterGroupName:
    Description: Use an existing parameter group in Amazon RDS - must match the database.
    Type: String
    Default: "default.aurora-mysql5.7"
  pStorageType:   # https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html
     Description: The type of storage to be used by the database.
     Type: String
     Default: 'standard'
     AllowedValues: ['standard', 'gp2', 'io1']
  pRDSVPC:
    Description: The vpc to use?
    Type: AWS::EC2::VPC::Id
  pCreateNewSubnets:
    Description: Set to true if we want new subnets for our databases
    Type: String
    Default: "true"
    AllowedValues: ['true', 'false']
    ConstraintDescription: must be true or false.    
  pExistingSubnetId1:
    Description: Use an id of an existing private subnet
    Type: String
    Default: "subnet-0455e1cfa66facd17"
  pExistingSubnetId2:
    Description: Use an id of a second existing private subnet
    Type: String
    Default: "subnet-0536176832ba42dfd"
  pSubnetCIDR1:
    Description: The cidrblock to use?
    Type: String
  pSubnetCIDR2:
    Description: The cidrblock to use?
    Type: String
  pGatewayID:
    Description: The virtual private gateway id for the vpc, to manage our databases.
    Type: String
    Default: "vgw-0e7d969e316a7b5d5"
  pOperatorEMail:
    Description: EMail address to notify if there are any operational issues
    Type: String
    AllowedPattern: >-
      ([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)
    ConstraintDescription: must be a valid email address.

# This next parameter is a hold-over from older pipelines.  It must exist, or there will be a cloudformation error.
  BuildBucket:
    Description: Unused in this template
    Type: String
    Default: ""


#  Warning, I haven't actually tested all these databases or these mappings - be ready to debug :-)
Mappings: 
  DBPortMap: 
    aurora-mysql: 
      port: 3306
    aurora-postgresql: 
      port: 5432
    mariadb: 
      port: 3306
    mysql: 
      port: 3306
    oracle-ee: 
      port: 1521
    oracle-se2: 
      port: 1521
    postgres: 
      port: 5432
    sqlserver-ee: 
      port: 1433
    sqlserver-se: 
      port: 1433
    sqlserver-ex: 
      port: 1433
    sqlserver-web: 
      port: 1433

Conditions: 
  CreateMultiAZ: !Equals [ !Ref pMultiAZ, "true" ]
  CreateNewSubnets: !Equals [ !Ref pCreateNewSubnets, "true" ]
  CreateAurora: !Or
    - !Equals [ !Ref pDBEngine, "aurora-mysql" ]
    - !Equals [ !Ref pDBEngine, "aurora-postgresql" ]
  CreateNonAurora: !Not [Condition: CreateAurora ]
  CreateAuroraMultiAZ: !And
    - Condition: CreateAurora
    - Condition: CreateMultiAZ

Resources:
  # TODO - SECURE THE PASSWARD PARAMETERS IN AWS PARAMETER STORE
  #   See: https://github.com/aws-samples/aws-aurora-cloudformation-samples/blob/master/cftemplates/Aurora-Postgres-DB-Cluster.yml 
  # TODO - DBClusterParameterGroups and DBParameterGroups are not auto-created.  


# Subnets
#
# Create one subnet if pCreateNewSubnets is true
# Create two new subnets if both pCreateNewSubnets and pMultiAZ are true...
# Otherwise, the user better have specified existing subnet(s) in pExistingSubnetId1 and pExistingSubnetId2
#
# Note that this template assumes we use Availability Zones 0 and 1.  Perhaps I should make those parameters?
#
  rDBSubnet1:
    Type: AWS::EC2::Subnet
    Condition: CreateNewSubnets
    Properties:
      VpcId: !Ref 'pRDSVPC'
      CidrBlock: !Ref 'pSubnetCIDR1'
      AvailabilityZone: !Select 
        - 0
        - !GetAZs 
          Ref: 'AWS::Region'
      Tags:
        - Key: "Name"
          Value: !Join [ "-", [!Ref "AWS::StackName", !Ref "AWS::Region", "RDS-AZA-SUBNET"] ]

  rDBSubnet2:
    Type: AWS::EC2::Subnet
    Condition: CreateNewSubnets
    Properties:
      VpcId: !Ref 'pRDSVPC'
      CidrBlock: !Ref 'pSubnetCIDR2'
      AvailabilityZone: !Select 
        - 1
        - !GetAZs 
          Ref: 'AWS::Region'
      Tags:
        - Key: "Name"
          Value: !Join [ "-", [!Ref "AWS::StackName", !Ref "AWS::Region", "RDS-AZB-SUBNET"] ]

# Route Table
#
# If we create new subnets, we need to use a route table.  I thought about reusing the existing route table for the 
# primary private subnet, but this is a different class of traffic.  I feel it is best practice to create new route tables.
#
  rCustomRouteTable:
    Type: AWS::EC2::RouteTable
    Condition: CreateNewSubnets
    Properties:
      VpcId: !Ref 'pRDSVPC'
      Tags:
        - Key: "Name"
          Value: !Join [ "-", [!Ref "AWS::StackName", !Ref "AWS::Region", "RTB-RDS"] ]

  rRoute10:
    Type: AWS::EC2::Route
    Condition: CreateNewSubnets
    Properties:
      RouteTableId: !Ref rCustomRouteTable
      DestinationCidrBlock: 10.0.0.0/8
      GatewayId: !Ref pGatewayID

  rRoute172:
    Type: AWS::EC2::Route
    Condition: CreateNewSubnets
    Properties:
      RouteTableId: !Ref rCustomRouteTable
      DestinationCidrBlock: 172.16.0.0/12
      GatewayId: !Ref pGatewayID

  rRoute192:
    Type: AWS::EC2::Route
    Condition: CreateNewSubnets
    Properties:
      RouteTableId: !Ref rCustomRouteTable
      DestinationCidrBlock: 192.168.0.0/16
      GatewayId: !Ref pGatewayID

 # attach route tables to our previously created subnets.
  rSubnetRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Condition: CreateNewSubnets
    Properties:
      SubnetId: !Ref rDBSubnet1
      RouteTableId: !Ref rCustomRouteTable

  rSubnetRouteTableAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Condition: CreateNewSubnets
    Properties:
      SubnetId: !Ref rDBSubnet2
      RouteTableId: !Ref rCustomRouteTable

# Security group.
#
# This is to make sure our databases only allow traffic on the correct port.
#
# Technically, we could be more specific than 0.0.0.0/0

  rDBEC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Open database for access
      VpcId: !Ref pRDSVPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: !FindInMap
        - DBPortMap
        - !Ref 'pDBEngine'
        - port
        ToPort: !FindInMap
        - DBPortMap
        - !Ref 'pDBEngine'
        - port
        CidrIp: 0.0.0.0/0
        Description: !Ref 'pDBEngine'
      Tags:
        - Key: "Name"
          Value: !Join [ "-", [!Ref "AWS::StackName", !Ref "AWS::Region", "RDS-SEC"] ]

# Subnet Groups
# 
# Here is the deal.  We don't attach subnets directly to databases.  Rather, we group subnets and attach the group to the 
# databases.  So, here is the complex "if" logic to determine which subnets to put into our database subnet group.
  rDBSubnetGroup: 
    Type: "AWS::RDS::DBSubnetGroup"
    Properties: 
      DBSubnetGroupDescription: "description"
      SubnetIds: 
        - !If [CreateNewSubnets, !Ref rDBSubnet1, !Ref pExistingSubnetId1 ]
        - !If [CreateNewSubnets, !Ref rDBSubnet2, !Ref pExistingSubnetId2 ]

# Database Builds...
#
# Aurora builds... first
  rDatabaseCluster:
    Type: AWS::RDS::DBCluster
    Condition: CreateAurora
    Properties:
      DatabaseName: !Ref 'pDBName'
      Engine: !Ref 'pDBEngine'
      EngineVersion: !Ref pDBEngineVersion
      MasterUsername: !Ref 'pDBUser'
      MasterUserPassword: !Ref 'pDBPassword'
      DBSubnetGroupName: !Ref rDBSubnetGroup
      DBClusterParameterGroupName: !Ref pDBParameterGroupName
      DeletionProtection: !Ref 'pDatabaseDeletionProtection'
      VpcSecurityGroupIds: [!GetAtt [rDBEC2SecurityGroup, GroupId]]

  rAuroraDB1:
    Type: AWS::RDS::DBInstance
    Condition: CreateAurora
    Properties:
      CopyTagsToSnapshot: true
      DBInstanceClass: !Ref 'pDBInstanceClass'
      DBClusterIdentifier: !Ref rDatabaseCluster
      DBSubnetGroupName: !Ref rDBSubnetGroup
      Engine: !Ref 'pDBEngine'
      EngineVersion: !Ref pDBEngineVersion
      DBParameterGroupName: !Ref pDBParameterGroupName
      PubliclyAccessible: false
      LicenseModel: !Ref 'pDatabaseLicenseModel'

  rAuroraDB2:
    Type: AWS::RDS::DBInstance
    Condition: CreateAuroraMultiAZ
    Properties:
      CopyTagsToSnapshot: true
      DBInstanceClass: !Ref 'pDBInstanceClass'
      DBClusterIdentifier: !Ref rDatabaseCluster
      DBSubnetGroupName: !Ref rDBSubnetGroup
      Engine: !Ref 'pDBEngine'
      EngineVersion: !Ref pDBEngineVersion
      DBParameterGroupName: !Ref pDBParameterGroupName
      PubliclyAccessible: false
      LicenseModel: !Ref 'pDatabaseLicenseModel'

# Now for the Non-Aurora builds...
  rMasterDB:
    Type: AWS::RDS::DBInstance
    Condition: CreateNonAurora
    Properties:
      AllocatedStorage: !Ref 'pDBAllocatedStorage'
      CopyTagsToSnapshot: true
      DBInstanceClass: !Ref 'pDBInstanceClass'
      DBName: !Ref 'pDBName'
      DBSubnetGroupName: !Ref rDBSubnetGroup
      Engine: !Ref 'pDBEngine'
      EngineVersion: !Ref pDBEngineVersion
      DBParameterGroupName: !Ref pDBParameterGroupName
      MasterUsername: !Ref 'pDBUser'
      MasterUserPassword: !Ref 'pDBPassword'
      MultiAZ: !Ref 'pMultiAZ'
      PubliclyAccessible: false
      StorageType: !Ref 'pStorageType'
      VPCSecurityGroups: [!GetAtt [rDBEC2SecurityGroup, GroupId]]
      LicenseModel: !Ref 'pDatabaseLicenseModel'
      DeletionProtection: !Ref 'pDatabaseDeletionProtection'

# Cloudwatch alarms
#
# Nothing too special here.  I just make sure the DB is operational.
  rAlarmTopic:
    Type: 'AWS::SNS::Topic'
    Properties:
      Subscription:
        - Endpoint: !Ref pOperatorEMail
          Protocol: email

  rCPUAlarmHighMasterDB:
    Type: 'AWS::CloudWatch::Alarm'
    Condition: CreateNonAurora
    Properties:
      EvaluationPeriods: 10
      Statistic: Average
      Threshold: 50
      AlarmDescription: >-
        Alarm if CPU too high or metric disappears indicating the RDS database
        instance is having issues
      Period: 60
      Namespace: AWS/RDS
      MetricName: CPUUtilization
      Dimensions:
        - Name: DBInstanceIdentifier
          Value: !Ref rMasterDB
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
        - !Ref rAlarmTopic
      InsufficientDataActions:
        - !Ref rAlarmTopic

  rCPUAlarmHighAuroraDB1:
    Type: 'AWS::CloudWatch::Alarm'
    Condition: CreateAurora
    Properties:
      EvaluationPeriods: 10
      Statistic: Average
      Threshold: 50
      AlarmDescription: >-
        Alarm if CPU too high or metric disappears indicating the RDS database
        instance is having issues
      Period: 60
      Namespace: AWS/RDS
      MetricName: CPUUtilization
      Dimensions:
        - Name: DBInstanceIdentifier
          Value: !Ref rAuroraDB1
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
        - !Ref rAlarmTopic
      InsufficientDataActions:
        - !Ref rAlarmTopic

  rCPUAlarmHighAuroraDB2:
    Type: 'AWS::CloudWatch::Alarm'
    Condition: CreateAuroraMultiAZ
    Properties:
      EvaluationPeriods: 10
      Statistic: Average
      Threshold: 50
      AlarmDescription: >-
        Alarm if CPU too high or metric disappears indicating the RDS database
        instance is having issues
      Period: 60
      Namespace: AWS/RDS
      MetricName: CPUUtilization
      Dimensions:
        - Name: DBInstanceIdentifier
          Value: !Ref rAuroraDB2
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
        - !Ref rAlarmTopic
      InsufficientDataActions:
        - !Ref rAlarmTopic
# 
# Consider adding JDBC string...
#
Outputs:
  Name:
    Description: Aurora Stack Name
    Value: !Ref AWS::StackName
    Export:
      Name: !Sub ${AWS::StackName}-Name
  RDSEndPointAddress:
    Description: Database Endpoint Address
    Value: !GetAtt [rMasterDB, Endpoint.Address]
    Export:
      Name: !Sub ${AWS::StackName}-RDSEndPointAddress
    Condition: CreateNonAurora
  RDSEndPointPort:
    Description: Database Endpoint port
    Value: !GetAtt [rMasterDB, Endpoint.Port]
    Export:
      Name: !Sub ${AWS::StackName}-RDSEndPointPort
    Condition: CreateNonAurora
  AuroraClusterId:
    Description: Aurora Cluster ID
    Value: !Ref rDatabaseCluster
    Export:
      Name: !Sub ${AWS::StackName}-AuroraClusterID
    Condition: CreateAurora
  AuroraEndPointAddress:
    Description: Database Endpoint Address
    Value: !GetAtt [rDatabaseCluster, Endpoint.Address]
    Export:
      Name: !Sub ${AWS::StackName}-AuroraDatabaseURL
    Condition: CreateAurora
  AuroraEndPointPort:
    Description: Database Endpoint port
    Value: !GetAtt [rDatabaseCluster, Endpoint.Port]
    Export:
      Name: !Sub ${AWS::StackName}-AuroraDatabasePort
    Condition: CreateAurora
  EndPointDBName:
    Description: Database Name
    Value: !Ref 'pDBName'
    Export:
      Name: !Sub ${AWS::StackName}-DBName
  JDBCConnectionString:
    Description: JDBC connection string for a mysql database
    Value: !Join ['', ['jdbc:mysql://', !GetAtt [rDatabaseCluster, Endpoint.Address], ':', !GetAtt [
          rDatabaseCluster, Endpoint.Port], /, !Ref 'pDBName']]
    Export:
      Name: !Sub ${AWS::StackName}-MySQLJDBCString
    Condition: CreateAurora

1 个答案:

答案 0 :(得分:2)

因此,经过一番挖掘之后,this似乎是最好的方法。
AWS CLI文档对此更加清楚,并且期望按照上面的链接使用此格式的逻辑ID语法:"string" "string" ...continue-update-rollback操作。