ECS on EC2集群CDK栈:如何优雅无停机更新实例AMI?
问题:EC2集群ECS栈无停机轮换实例至最新AMI的CDK/CFN方案
在EC2类型的ECS集群中,需要实现无停机轮换实例到最新AMI,但CDK+CloudFormation的组合在更新Auto Scaling Group(ASG)的AMI时遇到问题:
直接更新ASG的AMI配置(代码如下),CDK可以正常合成模板,但CloudFormation变更集会失败——能创建新的启动配置,却无法完成ASG的更新。
InstanceType: awsec2.NewInstanceType(jsii.String(envProps.AsgInstanceType)), MachineImage: awsec2.MachineImage_GenericLinux(&imageMap, &awsec2.GenericLinuxImageProps{}), //DesiredCapacity: jsii.Number(envAsgSize), //Don't set for prod and probably others Vpc: vpc, Role: instanceRole,
尝试过手动流程:编辑启动配置(但CDK会生成带随机名称的新配置,无法覆盖)→ 执行ASG更新替换实例→ 同步CDK/CFN状态,但流程繁琐,希望找到更优的适配CDK的方案,不希望用Lambda这类过于复杂的实现。
可行方案
方案1:利用ASG实例刷新+CDK自动生成启动配置
CDK每次更新AMI时必然会创建新的启动配置(这是设计特性,无法修改),但可以通过配置ASG的实例刷新能力,让CloudFormation在创建新启动配置后自动触发实例替换:
- 在CDK中给ASG添加实例刷新配置:
const asg = new autoscaling.AutoScalingGroup(this, 'EcsAsg', { // 原有配置... instanceType: awsec2.InstanceType.of(awsec2.InstanceClass.T2, awsec2.InstanceSize.MEDIUM), machineImage: awsec2.MachineImage.genericLinux(imageMap), vpc, role: instanceRole, // 添加实例刷新配置 instanceRefresh: { strategy: autoscaling.InstanceRefreshStrategy.ROLLING, minHealthyPercentage: 70, // 根据集群容量调整,保证业务无停机 instanceWarmup: Duration.minutes(5), // 匹配ECS实例注册到集群的预热时间 }, });
- 当通过CDK更新AMI并部署时,CloudFormation会创建新启动配置,然后触发ASG的实例刷新,逐步替换旧实例为新AMI的实例,全程无停机。
- 注意:需要确保ASG的
minCapacity和desiredCapacity设置合理,避免刷新过程中容量不足;同时ECS服务的部署策略要设置为ROLLING_UPDATE,保证容器在实例替换时平滑迁移。
方案2:用Launch Template替代Launch Configuration
Launch Template是Launch Configuration的升级版,CloudFormation对ASG使用Launch Template的更新支持更友好:
- 将原有的启动配置替换为Launch Template:
const launchTemplate = new ec2.LaunchTemplate(this, 'EcsLaunchTemplate', { instanceType: awsec2.InstanceType.of(awsec2.InstanceClass.T2, awsec2.InstanceSize.MEDIUM), machineImage: awsec2.MachineImage.genericLinux(imageMap), role: instanceRole, // 其他配置如安全组、用户数据等 }); const asg = new autoscaling.AutoScalingGroup(this, 'EcsAsg', { vpc, launchTemplate: launchTemplate, minCapacity: 2, maxCapacity: 5, // 同样配置实例刷新 instanceRefresh: { strategy: autoscaling.InstanceRefreshStrategy.ROLLING, minHealthyPercentage: 70, }, });
- 更新AMI时,CDK会创建Launch Template的新版本,CloudFormation会自动关联ASG到新版本,再通过实例刷新完成实例替换。相比Launch Configuration,Launch Template支持版本化管理,更适配CDK的声明式更新模型。
方案3:手动触发ASG实例刷新(适配已有CDK栈)
如果不想修改现有CDK代码结构,可以按以下步骤操作:
- 通过CDK更新AMI并部署,此时CloudFormation会创建新的启动配置但不会更新ASG
- 进入AWS控制台,找到目标ASG,手动触发实例刷新,选择使用最新的启动配置
- 等待实例刷新完成后,CDK的状态会自动同步(因为新启动配置已经被CDK创建并记录在模板中)
这种方式不需要修改代码,适合临时的AMI更新场景,但长期来看还是推荐方案1或2的自动化方式。
内容的提问来源于stack exchange,提问作者Trevor Griffiths
相关产品推荐
相关产品推荐

