Lambda 不适用于具有自动缩放功能的 ec2

Posted

技术标签:

【中文标题】Lambda 不适用于具有自动缩放功能的 ec2【英文标题】:Lambda not working for ec2 with auto-scaling 【发布时间】:2021-04-28 02:37:43 【问题描述】:

遵循 AWS Lambda 正在按预期工作 [i.e. ec2 instance stop and start] 适用于不属于任何自动扩展组的 ec2 实例,但不适用于属于自动扩展组的 ec2 实例。

对于属于自动扩展组的 ec2 实例,ec2 实例将重新启动并再次运行。

AWS Lambda 代码如下;

import boto3

ec2 = boto3.client('ec2')


def lambda_handler(event, context):
    action_handler(event['action'])


def get_ec2_instances():
    ec2_int = ec2.describe_instances(
        Filters=[
            'Name': 'ops',
            'Values': [
                'cost-save'
            ]
        ]
    )
    return ec2_int


def action_handler(action):
    ec2_instances = get_ec2_instances()
    for reservation in ec2_instances['Reservations']:
        for ec2_instance in reservation['Instances']:
            if action == "stop":
                stop_ec2(ec2_instance)
            elif action == "start":
                start_ec2(ec2_instance)


def stop_ec2(ec2_int):
    if ec2_int['State']['Name'] == 'running':
        ec2.stop_instances(InstanceIds=[ec2_int['InstanceId']])


def start_ec2(ec2_int):
    if ec2_int['State']['Name'] == 'stopped':
        ec2.start_instances(InstanceIds=[ec2_int['InstanceId']])

您能帮忙解决这个问题吗?我想确保作为自动缩放一部分的 ec2 实例也必须停止和启动。

【问题讨论】:

这就是 asg 的工作原理。您无法停止 asg 中的实例。 @Marcin - 感谢您的快速回复。我可以理解,但是这个 lambda 是为了降低开发和测试环境中 ec2 实例的成本。所以,我从这个角度来看,寻找任何解决方法或技巧来阻止开发和测试环境中的 ec2。 如果您想“停止”而不是“终止”开发/测试实例,请不要将它们放在 Auto Scaling 组中。您可以从 Auto Scaling 组中暂时删除它们,然后停止它们,但这违背了使用 Auto Scaling 组的全部目的。可以终止并重新启动这些实例(在这种情况下使用 Scaling Policies 添加/删除实例),或者不使用 Auto Scaling 组。 【参考方案1】:

以下是一种解决方法。您可能需要根据您的设置重构一些代码。

import boto3

ec2 = boto3.client('ec2')

auto_scaling_group_client = boto3.client('autoscaling')
# TODO Refactor auto_scaling_group_processes list as per your setup
auto_scaling_group_processes = ['Launch',
                                'Terminate',
                                'HealthCheck',
                                'ReplaceUnhealthy',
                                'ScheduledActions',
                                'AddToLoadBalancer',
                                'AlarmNotification',
                                'AZRebalance']


def lambda_handler(event, context):
    action_handler(event['action'])


def get_ec2_instances():
    ec2_int = ec2.describe_instances(
        Filters=[
            'Name': 'ops',
            'Values': [
                'cost-save'
            ]
        ]
    )
    return ec2_int


def action_handler(action):
    ec2_instances = get_ec2_instances()
    auto_scaling_groups_to_resume = set()
    # TODO Can refactor logic added related to auto_scaling
    for reservation in ec2_instances['Reservations']:
        for ec2_instance in reservation['Instances']:
            auto_scaling_group_name = get_auto_scaling_group_name(ec2_instance['InstanceId'])
            if action == "stop":
                suspend_processes(auto_scaling_group_name)
                stop_ec2(ec2_instance)
            elif action == "start":
                auto_scaling_groups_to_resume.add(auto_scaling_group_name)
                start_ec2(ec2_instance)
    resume_auto_scaling_group_processes(auto_scaling_groups_to_resume)


def stop_ec2(ec2_int):
    if ec2_int['State']['Name'] == 'running':
        ec2.stop_instances(InstanceIds=[ec2_int['InstanceId']])


def start_ec2(ec2_int):
    if ec2_int['State']['Name'] == 'stopped':
        ec2.start_instances(InstanceIds=[ec2_int['InstanceId']])


def resume_processes(auto_scaling_group_name):
    if auto_scaling_group_name is not None:
        auto_scaling_group_client.resume_processes(
            AutoScalingGroupName=auto_scaling_group_name,
            ScalingProcesses=auto_scaling_group_processes
        )


# TODO Can refactor
def get_auto_scaling_group_name(ec_int_id):
    auto_scaling_group = auto_scaling_group_client.describe_auto_scaling_instances(
        InstanceIds=[
            ec_int_id
        ]
    )
    for auto_scaling_int in auto_scaling_group['AutoScalingInstances']:
        return auto_scaling_int['AutoScalingGroupName']


# TODO Can refactor
def resume_auto_scaling_group_processes(auto_scaling_groups):
    for auto_scaling_group in auto_scaling_groups:
        resume_processes(auto_scaling_group)


def suspend_processes(auto_scaling_group_name):
    if auto_scaling_group_name is not None:
        auto_scaling_group_client.suspend_processes(
            AutoScalingGroupName=auto_scaling_group_name,
            ScalingProcesses=auto_scaling_group_processes
        )

【讨论】:

以上是关于Lambda 不适用于具有自动缩放功能的 ec2的主要内容,如果未能解决你的问题,请参考以下文章

即使在我指定了自定义 VPC 之后,我的用于自动缩放组的 Cloudformation YAML 也会继续在默认 VPC 中创建 EC2 实例

AWS EC2 自动缩放 - 通过 ssh 在 EC2 上进行自定义设置

拖放不适用于缩放

使用 Lambda 函数覆盖 AWS Auto Scaling 策略

具有 cloudformation 的 AutoScaling ec2 实例

自定义缩放过渡不适用于模态演示