我正在使用cloudformation来创建一个包含自动调整的ec2实例和S3存储桶的堆栈。对于S3存储桶,我将DeletionPolicy设置为Retain,工作正常,直到我想再次重新运行我的cloudformation脚本。由于在之前的运行中,脚本创建了S3存储桶,因此在后续运行中失败,说我的S3存储桶已经存在。当然也没有创建其他资源。我的问题是如何检查我的S3存储桶是否首先存在于cloudformation脚本中,如果存在,则跳过创建该资源。我已经查看了AWS中的条件,但它似乎都是基于参数的,我还没有找到一个从现有资源中检查的函数。
答案 0 :(得分:22)
除非您使用显式检查动态创建模板,否则没有明显的方法可以执行此操作。从同一模板创建的堆栈是独立的实体,如果您创建一个包含存储桶的堆栈,请在保留存储桶的同时删除堆栈,然后创建一个新堆栈(即使是一个具有相同名称的堆栈),这之间没有连接新堆栈和存储桶作为上一个堆栈的一部分创建。
如果要对多个堆栈使用相同的S3存储桶(即使一次只存在其中一个存储桶),该存储桶并不真正属于堆栈 - 在单独创建存储桶时更有意义堆栈,使用单独的模板(将桶URL放在"输出"部分),然后使用参数从原始堆栈引用它。
答案 1 :(得分:6)
只需在CloudFormation模板中添加一个输入参数即可指示应该使用现有的存储桶....除非您在使用该模板时尚未知道?然后,您可以根据参数值添加新资源。
答案 2 :(得分:1)
使用cloudformation可以使用Conditions 我创建了一个输入参数“ ShouldCreateBucketInputParameter”,然后使用CLI,您只需要设置“ true”或“ false”
Cloudformation json文件:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Description": "",
"Parameters": {
"ShouldCreateBucketInputParameter": {
"Type": "String",
"AllowedValues": [
"true",
"false"
],
"Description": "If true then the S3 bucket that will be proxied will be created with the CloudFormation stack."
}
},
"Conditions": {
"CreateS3Bucket": {
"Fn::Equals": [
{
"Ref": "ShouldCreateBucketInputParameter"
},
"true"
]
}
},
"Resources": {
"SerialNumberBucketResource": {
"Type": "AWS::S3::Bucket",
"Condition": "CreateS3Bucket",
"Properties": {
"AccessControl": "Private"
}
}
},
"Outputs": {}
}
然后(我正在使用CLI部署堆栈)
aws cloudformation deploy --template ./s3BucketWithCondition.json --stack-name bucket-stack --parameter-overrides ShouldCreateBucketInputParameter="true" S3BucketNameInputParameter="BucketName22211"
答案 3 :(得分:0)
如果你做了更新,(可能是堆栈中的堆栈,也就是嵌套堆栈),未更改的部分不会更新。 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html?icmpid=docs_cfn_console_designer
然后,您可以按照提及的方式设置策略以防止删除。 [记住'取消更新'回滚权限] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html
还可以通过将堆栈输出添加到堆栈输出来了解交叉堆栈输出。 http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html 演练... http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-crossstackref.html
然后你需要使用Fn :: ImportValue ... http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
这意味着可以使用网络堆栈名称参数。
不幸的是,当你在条件中试用它们时会出现这样的错误。
模板验证错误:模板错误:无法使用Fn :: ImportValue 在条件中。
或参数?
模板验证错误:模板格式错误:每个默认成员 必须是一个字符串。
尝试时也会发生这种情况......
模板格式错误:输出ExportOut格式错误。名称字段 Export不得依赖任何资源,导入值或 FN :: GetAZs。
因此,您无法停止从同一文件再次创建现有资源。仅在将其放入另一个堆栈并使用导出导入参考时。
但是如果你将两者分开,那么就会有一个依赖关系会停止和回滚,例如依赖关系的删除,这要归功于通过ImportValue函数的引用。
这里给出的例子是:
首先制作一个组模板
{
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {
"AWS::CloudFormation::Designer": {
"6927bf3d-85ec-449d-8ee1-f3e1804d78f7": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": -390,
"y": 130
},
"z": 0,
"embeds": []
},
"6fe3a2b8-16a1-4ce0-b412-4d4f87e9c54c": {
"source": {
"id": "ac295134-9e38-4425-8d20-2c50ef0d51b3"
},
"target": {
"id": "6927bf3d-85ec-449d-8ee1-f3e1804d78f7"
},
"z": 1
}
}
},
"Resources": {
"TestGroup": {
"Type": "AWS::IAM::Group",
"Properties": {},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "6927bf3d-85ec-449d-8ee1-f3e1804d78f7"
}
},
"Condition": ""
}
},
"Parameters": {},
"Outputs": {
"GroupNameOut": {
"Description": "The Group Name",
"Value": {
"Ref": "TestGroup"
},
"Export": {
"Name": "Exported-GroupName"
}
}
}
}
然后制作一个需要该组的用户模板。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {
"AWS::CloudFormation::Designer": {
"ac295134-9e38-4425-8d20-2c50ef0d51b3": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": -450,
"y": 130
},
"z": 0,
"embeds": [],
"isrelatedto": [
"6927bf3d-85ec-449d-8ee1-f3e1804d78f7"
]
},
"6fe3a2b8-16a1-4ce0-b412-4d4f87e9c54c": {
"source": {
"id": "ac295134-9e38-4425-8d20-2c50ef0d51b3"
},
"target": {
"id": "6927bf3d-85ec-449d-8ee1-f3e1804d78f7"
},
"z": 1
}
}
},
"Resources": {
"TestUser": {
"Type": "AWS::IAM::User",
"Properties": {
"UserName": {
"Ref": "UserNameParam"
},
"Groups": [
{
"Fn::ImportValue": "Exported-GroupName"
}
]
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "ac295134-9e38-4425-8d20-2c50ef0d51b3"
}
}
}
},
"Parameters": {
"UserNameParam": {
"Default": "testerUser",
"Description": "Username For Test",
"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."
}
},
"Outputs": {
"UserNameOut": {
"Description": "The User Name",
"Value": {
"Ref": "TestUser"
}
}
}
}
你会得到
找不到名为Exported-GroupName的导出。用户请求回滚。
如果运行没有找到组的用户已导出。
然后,您可以使用嵌套堆栈方法。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {
"AWS::CloudFormation::Designer": {
"66470873-b2bd-4a5a-af19-5d54b11f48ef": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": -815,
"y": 169
},
"z": 0,
"embeds": []
},
"ed1de011-f1bb-4788-b63e-dcf5494d10d1": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": -710,
"y": 170
},
"z": 0,
"dependson": [
"66470873-b2bd-4a5a-af19-5d54b11f48ef"
]
},
"c978f2d9-3fb2-4420-b255-74941f10a28a": {
"source": {
"id": "ed1de011-f1bb-4788-b63e-dcf5494d10d1"
},
"target": {
"id": "66470873-b2bd-4a5a-af19-5d54b11f48ef"
},
"z": 1
}
}
},
"Resources": {
"GroupStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://s3-us-west-2.amazonaws.com/cf-templates-x-TestGroup.json"
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "66470873-b2bd-4a5a-af19-5d54b11f48ef"
}
}
},
"UserStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://s3-us-west-2.amazonaws.com/cf-templates-x-TestUserFindsGroup.json"
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "ed1de011-f1bb-4788-b63e-dcf5494d10d1"
}
},
"DependsOn": [
"GroupStack"
]
}
}
}
不幸的是,您仍然可以删除用户堆栈,即使它是由MultiStack在此示例中制作的,但具有删除策略和其他可能有帮助的东西。
然后您只更新它创建的各种堆栈,如果您重新使用Bucket,则不会执行Multi Stack。
否则,您将以各种方式查看API和脚本。
答案 4 :(得分:0)
如果您想将一些现有资源合并到 CF 中,很遗憾这是不可能的。如果您只想将一组资源作为模板的一部分,取决于一些参数,你可以使用Conditions。但它们并没有改变CF本身的性质,只是确定需要哪些资源,而不是采取什么行动,也无法事先判断资源是否存在。
答案 5 :(得分:0)
没有明确说明的东西。如果您的第一次部署失败,除非您有 at 保留策略,否则资源将被删除。在这种情况下,手动删除相关资源是安全的。下一次部署将重新创建它,而不会产生资源已经存在的错误。