Knowledge Center Monthly Newsletter - March 2025
Stay up to date with the latest from the Knowledge Center. See all new and updated Knowledge Center articles published in the last month and re:Post’s top contributors.
通过自定义终止策略,让AWS自动伸缩组(ASG)始终终止最旧的实例
本文利用AWS自动伸缩组(ASG)的自定义终止策略,一致地终止最旧的实例,解决了默认ASG设置中的限制,即实例在不同可用区的分布可能会覆盖最旧终止逻辑。文章介绍了一个解决方案,该方案集成了Lambda函数和CloudFormation,以简化部署和提高操作效率,确保缩容活动可预测且易于管理。
背景:
AWS自动伸缩组(ASGs)提供多种终止策略,包括旨在首先退役最旧实例的OldestInstance策略。然而,ASGs优先在各个可用区(AZ)之间平等分配实例。这种行为有时会导致某个AZ中的较新实例在另一个AZ中的较旧实例之前被终止。
需求:
有些客户希望始终一致地终止最旧的实例,不论AZ分布如何。
解决方案:
为了满足这一需求,本文提供了一个自定义Lambda函数来实施特定的终止策略。该函数利用EC2 DescribeInstances API准确识别ASG中最旧的实例。通过CloudFormation模板,该解决方案的部署得以简化,自动设置Lambda函数和必要的IAM权限。
CloudFormation YAML 文件内容 :
AWSTemplateFormatVersion: '2010-09-09' Resources: LambdaExecutionRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: 'sts:AssumeRole' Policies: - PolicyName: LambdaExecutionPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' Resource: 'arn:aws:logs:*:*:*' - Effect: Allow Action: - 'ec2:DescribeInstances' Resource: '*' MyLambdaFunction: Type: 'AWS::Lambda::Function' Properties: Handler: index.lambda_handler Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | import boto3 import logging logger = logging.getLogger() logger.setLevel(logging.INFO) ec2 = boto3.client('ec2') def lambda_handler(event, context): logger.info("Received event: " + str(event)) instance_ids = [instance['InstanceId'] for instance in event.get('Instances', [])] logger.info("Instance IDs: " + str(instance_ids)) if instance_ids: descriptions = ec2.describe_instances(InstanceIds=instance_ids) instances = [i for r in descriptions['Reservations'] for i in r['Instances']] oldest_instance = sorted(instances, key=lambda x: x['LaunchTime'])[0]['InstanceId'] logger.info("Oldest instance ID: " + oldest_instance) return {'InstanceIDs': [oldest_instance]} else: logger.info("No instances to process.") return {'InstanceIDs': []} Runtime: python3.9 Timeout: 30 LambdaInvokePermission: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !GetAtt MyLambdaFunction.Arn Principal: !Sub 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling'
部署CloudFormation模板的步骤:
- 保存模板:
- 将上述YAML内容保存为文件,比如 terminate_oldest_template.yaml 的文件。
- 访问AWS管理控制台:
- 登录您的AWS账户,并导航至AWS CloudFormation控制台。
- 创建新堆栈:
- 选择“创建堆栈” -> “使用新资源(标准)”。
- 选择“上传模板文件”,点击“选择文件”,并上传 terminate_oldest_template.yaml 文件。
- 点击“下一步”。
- 指定堆栈详细信息:
- 输入堆栈名称,例如 ASGTerminateOldestInstanceStack。
- 点击“下一步”。
- 配置堆栈选项:
- 配置任何必要的选项,如标签或权限。对于大多数情况,默认选项已足够。
- 点击“下一步”。
- 检查并启动:
- 检查所有设置以确保它们是正确的。
- 确认AWS CloudFormation可能会创建IAM资源,然后点击“创建堆栈”。
- 查看部署:
- 在CloudFormation控制台上查看堆栈的创建。等待状态变为“CREATE_COMPLETE”。
更改ASG终止策略来使用新的Lambda函数:
-
访问 https://console.aws.amazon.com/ec2/,打开 Amazon EC2 控制台,然后从导航窗格中选择 Auto Scaling Groups(Auto Scaling 组)。
-
选中并点击 Auto Scaling 组。
-
在 Details(详细信息)选项卡上,选择 Advanced configurations(高级配置)、Edit(编辑)。
-
对于 Termination policies(终止策略),选择 Custom termination policy(自定义终止策略),然后选择刚创建完成的 Lambda 函数。如果您已经为 Lambda 函数创建了版本和别名,则可以从 Version/Alias(版本/别名)下拉列表选择版本或别名。要使用您的 Lambda 函数的未发布版本,请保留 Version/Alias(版本/别名)设置为默认值。 参考此篇文档了解更多
免责声明:
此脚本已在受控实验环境中多次测试,并始终表现良好。然而,该脚本是“按原样”提供的,尽管我们已尽最大努力确保其可靠性,但我们无法保证其在其他环境中的准确性或功能。用户有责任在非生产环境中彻底评估和测试此脚本,然后再将其部署到生产环境中。使用此脚本的风险由用户自行承担,AWS 对因使用该脚本引起的任何损害或问题不承担任何责任。如需帮助或有任何疑问,请联系 AWS 支持团队。
参考资料:
相关内容
- AWS 官方已更新 1 年前
- AWS 官方已更新 1 年前
- AWS 官方已更新 2 年前