Skip to content

AWS

亚马逊云渠道代理商:如何利用Lambda 自动处理 EC2 异常告警?自动化运维实操

保障 Amazon Elastic Compute Cloud (Amazon EC2) 的高可用性是运维的核心任务。传统人工值守模式面对突发故障响应滞后,人力成本高。结合 Amazon CloudWatch + Amazon EventBridge + AWS Lambda,可以构建事件驱动的自动化自愈能力,实现 EC2 异常秒级响应,例如状态检查失败自动恢复、流量异常执行网络隔离。

边界说明:CloudWatch 告警自带原生 EC2 自愈动作(Reboot/Stop/Recover),适合简单场景;本文 Lambda 方案适合需要多条件判断、自定义逻辑、联动通知、复杂编排的生产场景。

前置重要提示:

  1. StatusCheckFailed_System 硬件故障,Reboot 重启无效,必须执行 StopStart 完成宿主机迁移;StatusCheckFailed_Instance 操作系统故障,使用 Reboot。示例脚本必须区分告警指标,否则硬件故障场景自愈失效AWS re:Pos…。
  2. EventBridge 事件为至少一次投递,未做幂等 / 冷却控制会发生循环反复重启实例,造成业务雪崩;生产务必增加状态判断、最大执行次数限制。
  3. EC2 状态检查指标默认 1 分钟采集,不需要开启付费详细监控;CPU 等性能指标才需要开启详细监控,避免产生额外 CloudWatch 账单AWS。
  4. 如果实例属于 Auto Scaling 伸缩组,stop/stopstart 会被 ASG 重新创建实例,自愈逻辑会失效。
  5. Lambda 如果部署在 VPC 内部,需要 NAT 网关,否则无法调用 EC2 公有 API。
  6. stopstart 操作会变更实例公网 IP,业务需要绑定 EIP 弹性 IP 防止 IP 变动影响业务访问。

 

本文面向云系统管理员、DevOps 工程师,完整讲解架构原理、权限配置、代码实现、排障与风险规避。

自动化值守的架构逻辑

  1. 传统运维 vs 事件驱动自动化 传统运维:告警通知人工,人工登录控制台执行恢复操作,MTTR 恢复时间长。 Lambda 自动化:CloudWatch 指标突破阈值产生告警,告警状态变更经由 EventBridge 投递事件,触发 Lambda 执行 Boto3 脚本,自动完成实例恢复、隔离、打标签,缩短故障恢复时间。
  2. 组件联动
  • 数据源:EC2 输出运行指标、状态检查指标
  • 监控层:CloudWatch 采集指标,达到阈值切换 ALARM 告警状态
  • 路由层:EventBridge 捕获「CloudWatch Alarm State Change」事件,过滤告警状态,投递到 Lambda
  • 执行层:Lambda 接收事件,执行重启、停止、安全组变更、打标签等自愈动作。

表 1:常见 EC2 异常监控指标与处理策略

监控指标 (CloudWatch Metric) 异常场景 自动化处理策略 (Lambda Action)
StatusCheckFailed_System 底层硬件、宿主机网络故障 StopStart(停止再启动,迁移至新物理主机)
StatusCheckFailed_Instance 操作系统内核崩溃、内存耗尽 Reboot 操作系统重启
CPUUtilization CPU 持续满载 可触发告警通知、打故障标签;谨慎自动重启,避免业务误杀
NetworkIn / NetworkOut 流量异常疑似攻击 修改安全组隔离(高危,建议仅测试环境验证)

前置条件准备

  1. 监控说明 EC2 的 StatusCheckFailed 状态检查指标默认即为 1 分钟粒度,无需开启付费详细监控; CPU、磁盘、网络等性能指标如果需要 1 分钟粒度,开启详细监控,会产生 CloudWatch 自定义指标费用。
  2. IAM 执行角色权限(遵循最小权限原则) 为 Lambda 执行角色配置策略,建议增加资源标签条件,限制仅处理带AutoRepair:true标签的 EC2 实例,防止误操作全部实例。 必需权限:
  • 日志:logs:CreateLogGroup、logs:CreateLogStream、logs:PutLogEvents,输出日志到 CloudWatch Logs
  • EC2:ec2:DescribeInstances、ec2:RebootInstances、ec2:StopInstances、ec2:StartInstances、ec2:DescribeInstanceStatus

提示:生产环境不要使用全托管粗粒度策略,通过 Tag 条件做权限约束。

  1. Lambda 基础配置
  • 运行时:x
  • 超时时间:建议设置 30s,避免 Boto3 调用 AWS API 超时。
  • 异步调用配置:配置 DLQ 死信队列 SNS/SQS,处理函数执行失败场景,推送人工告警。

实操步骤:构建异常处理脚本

代码重点:解析告警指标名称,区分 System/Instance 状态检查,做实例运行状态判断,简单防重复执行。

步骤一:编写 Lambda Python 函数

import boto3

import json

import logging

 

logger = logging.getLogger()

logger.setLevel(logging.INFO)

ec2_client = boto3.client(‘ec2’)

 

def lambda_handler(event, context):

logger.info(f”Receive EventBridge event: {json.dumps(event)}”)

try:

alarm_name = event[‘detail’][‘alarmName’]

alarm_state = event[‘detail’][‘state’][‘value’]

# 仅处理进入ALARM状态事件,忽略OK/INSUFFICIENT_DATA

if alarm_state != “ALARM”:

logger.info(f”当前告警状态 {alarm_state},跳过自愈处理”)

return {“statusCode”:200,”body”:”skip nonalarm state”}

 

instance_id = extract_instance_id(event)

metric_name = extract_metric_name(event)

if not instance_id:

logger.warning(“事件载荷未解析出InstanceId,直接退出”)

return {“statusCode”:400,”body”:”no instance id found”}

 

# 查询实例当前状态,避免重复执行自愈

resp = ec2_client.describe_instances(InstanceIds=[instance_id])

instance_state = resp[‘Reservations’][0][‘Instances’][0][‘State’][‘Name’]

if instance_state not in [“running”]:

logger.warning(f”实例 {instance_id} 当前状态 {instance_state},跳过自愈”)

return {“statusCode”:200,”body”:”instance not running, skip”}

 

# 根据指标选择动作

if metric_name == “StatusCheckFailed_System”:

logger.info(f”[{alarm_name}] System状态检查失败,执行StopStart迁移宿主机 {instance_id}”)

ec2_client.stop_instances(InstanceIds=[instance_id])

elif metric_name == “StatusCheckFailed_Instance”:

logger.info(f”[{alarm_name}] Instance状态检查失败,执行Reboot {instance_id}”)

ec2_client.reboot_instances(InstanceIds=[instance_id])

else:

logger.info(f”指标 {metric_name},仅记录日志,不执行自动恢复”)

 

return {“statusCode”:200,”body”:f”Processed {instance_id}, metric:{metric_name}”}

 

except Exception as e:

logger.error(f”自愈处理异常:{str(e)}”,exc_info=True)

raise e

 

def extract_instance_id(event):

“””从Alarm State Change事件解析InstanceId”””

cfg = event.get(‘detail’,{}).get(‘configuration’,{})

metrics = cfg.get(‘metrics’,[])

for m in metrics:

dims = m.get(‘metricStat’,{}).get(‘metric’,{}).get(‘dimensions’,[])

for d in dims:

if d.get(‘name’) == “InstanceId”:

return d.get(‘value’)

return None

 

def extract_metric_name(event):

cfg = event.get(‘detail’,{}).get(‘configuration’,{})

metrics = cfg.get(‘metrics’,[])

if metrics:

return metrics[0].get(‘metricStat’,{}).get(‘metric’,{}).get(‘metricName’)

return None

步骤二:创建 CloudWatch 告警

  1. CloudWatch 控制台进入「每实例指标」
  2. 针对目标 EC2 实例分别创建两条告警:
    • StatusCheckFailed_System:底层硬件故障告警
    • StatusCheckFailed_Instance:操作系统状态检查告警
  3. 阈值设置 >=1,评估周期设置连续 2 个数据点,规避瞬时抖动误报。

步骤三:配置 EventBridge 规则触发 Lambda

  1. EventBridge 控制台创建规则,事件模式选择CloudWatch Alarm State Change
  2. 增加过滤条件:状态仅匹配ALARM,过滤 OK、数据不足事件,减少无效调用。
  3. 目标类型选择 Lambda 函数,选择上面创建的自愈函数。
  4. 保存规则。

步骤四:部署完成后验证测试

  1. 给测试 EC2 打上AutoRepair:true标签;
  2. 可手动将告警强制设置为 ALARM 状态,观察 CloudWatch Logs 日志,确认 Lambda 被触发,动作按预期执行。

生产环境风险与最佳实践汇总

  1. 幂等与防循环重启EventBridge 为至少一次投递,同一个告警事件可能多次触发;建议增加 DynamoDB 记录实例最近自愈时间,设置冷却窗口(例如 15 分钟内不重复执行自愈),防止无限重启。
  2. Auto Scaling 组注意伸缩组内实例,不要使用 stop/stopstart 自愈,ASG 会直接终止重建实例;优先使用 ASG 本身健康检查替换故障实例。
  3. 高危动作管控流量异常自动修改安全组隔离属于高危操作,正式上线前充分测试,一旦逻辑错误会直接锁死业务实例。
  4. 备份兜底告警Lambda 配置 DLQ 死信队列,自愈脚本执行失败时,通过 SNS 发送邮件 / 短信通知人工介入,不能完全依赖自动化。
  5. stopstart 会改变公网 IP,业务实例务必绑定 EIP 弹性 IP。

常见排障对照表

现象 根因 解决方向
Lambda 被触发,但是拿不到 InstanceId EventBridge 事件解析路径不匹配告警类型 使用示例中的解析函数;优先测试验证告警事件载荷
StatusCheckFailed_System 告警触发,重启不能恢复业务 使用 Reboot 而不是 StopStart,不会迁移宿主机 System 故障必须 stop_instances,等待停机后 start_instances
实例反复不停重启 缺少冷却 / 幂等控制,持续 ALARM 状态反复触发 Lambda 增加自愈冷却窗口,DynamoDB 记录最近自愈时间
Lambda 执行报 EC2 API 访问拒绝 IAM 权限缺失,没有 ec2:DescribeInstances/reboot 等权限 补全执行角色权限,遵循最小权限
VPC 内部 Lambda 调用 EC2 API 超时 VPC 内 Lambda 没有出口访问公网 配置 NAT 网关,或者使用 VPCEndpoint 访问 EC2 接口

常见问题 (FAQ):

Q1:CloudWatch 原生告警就支持 Reboot/Stop 动作,为什么还要写 Lambda? A:原生告警动作适合简单固定恢复;Lambda 可以实现:区分不同指标执行不同动作、打故障标签、组合多指标判断、输出详细日志、对接第三方通知系统,适合复杂生产自愈场景。

Q2:StatusCheckFailed_System 为什么不能直接 Reboot? A:Reboot 只是操作系统重启,实例仍然运行在原有故障宿主机上;stopstart 会释放物理主机,重新调度到新宿主机,修复硬件层面故障。

Q3:整套自动化链路从异常发生到执行恢复,整体延迟大概多少? A:状态检查指标 1 分钟粒度,连续 2 个周期告警,从故障发生到触发 Lambda 大约 23 分钟;EventBridge 转发事件毫秒秒级别。

Q4:如何避免自动化自愈误操作线上核心业务? A:①IAM 使用标签条件限制仅处理带特定标签的实例;②先在测试实例完整验证;③配置死信队列兜底人工告警;④增加自愈冷却时间,短时间内禁止多次执行恢复动作。

Q5:EC2 实例属于 Auto Scaling 自动伸缩组,这套 Lambda 自愈方案还能用吗? A:不建议。stop/stopstart 动作会被 ASG 检测实例不健康直接终止重建。应该使用 ASG 自身健康检查策略,直接替换故障实例。

 

文章标签