我想在 AWS CloudFormation 中更新我的 Amazon Elastic Block Store (Amazon EBS) 卷。但是,我不想更换我的 Amazon Elastic Compute Cloud (Amazon EC2) 实例。
解决方法
为了防止实例更换,最佳做法是在 CloudFormation 中更新 EBS 卷时使用 AWS::EC2::Volume 资源类型。
当您在 AWS::EC2::Instance 和 AWS::EC2::Template 资源类型的 BlockDeviceMappings 属性中指定卷时,就会发生实例替换。在这种情况下,必须添加 retain DeletionPolicy 属性。
**重要事项:**如果您手动修改卷,例如由 gp2 修改为 gp3,则还必须修改附加到该实例的卷。确认该实例未处于 Optimizing(正在优化)或 Modifying(正在修改)状态。将卷修改为 gp3 之前,请确保遵循卷修改要求。
要避免在修改使用 BlockDeviceMappings 属性指定的卷时替换实例,请完成以下步骤。
向目标 AWS::EC2::Instance 模板资源添加 retain DeletionPolicy 属性
完成以下步骤:
-
拍摄卷快照以创建关键工作负载的备份。
-
在包含要更新的卷的实例的 CloudFormation 堆栈中将 DeletionPolicy 设置为 Retain。示例:
AWSTemplateFormatVersion: '2010-09-09'
Resources:
Myinstance:
Type: AWS::EC2::Instance
DeletionPolicy: Retain
Properties:
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp2
VolumeSize: 10
DeleteOnTermination: true
EbsOptimized: false
ImageId: ami-064ff912f78e3e561
InstanceInitiatedShutdownBehavior: stop
InstanceType: t2.micro
Monitoring: false
-
更新堆栈。
从其 CloudFormation 堆栈中移除资源并实施更改
完成以下步骤:
- 从模板中移除该实例以从 CloudFormation 堆栈中移除该实例,但不删除底层资源。然后,手动修改 EC2 实例。
**注意:**如果您的模板中只有一个资源,则必须创建一个替代资源,例如另一个实例。在将 EC2 实例重新导入模板后,您可以从模板中删除资源。
- 修改 EBS 卷属性。
将资源导回您的 CloudFormation 堆栈中
完成以下步骤:
-
打开 CloudFormation 控制台。
-
在导航窗格中,选择 Stack(堆栈)。
-
选择 Stack actions(堆栈操作),然后选择 Import resources into stack(将资源导入堆栈)。
-
输入更新的 CloudFormation 模板。示例:
AWSTemplateFormatVersion: '2010-09-09'
Resources:
Myinstance:
Type: AWS::EC2::Instance
DeletionPolicy: Retain
Properties:
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp3
VolumeSize: 100
DeleteOnTermination: true
EbsOptimized: false
ImageId: ami-064ff912f78e3e561
InstanceInitiatedShutdownBehavior: stop
InstanceType: t2.micro
Monitoring: false
**注意:**要导入资源,CloudFormation 模板必须描述该资源及其现有配置。
-
对于 Identifier(标识符),输入实例 ID。
-
选择 Import resource(导入资源)。
在 CloudFormation 将状态更新为 IMPORT_COMPLETE 后,该实例将成为堆栈的一部分。
您可能会收到以下错误消息:“创建此更改集时出错。在导入操作过程中,您无法修改或添加 [Outputs]”。要解决此问题,请验证最新 CloudFormation 模板的 Outputs(输出)部分是否与您的堆栈使用的模板相匹配。如果它们不相同,请更新最新的 CloudFormation 模板以匹配堆栈使用的模板的 Outputs(输出)部分中的值。然后,再次更新堆栈。