AWS Lambda无法发送EC2状态变更通知至Slack求助
排查AWS Lambda无法向Slack发送EC2状态变更通知的问题
我们的需求是:当用户停止运行中的EC2实例、创建新实例或终止实例时,需向Slack频道发送通知。
本地测试验证
curl命令测试成功
curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX
Python代码测试成功
import requests import os # Define the data to send in the Slack message data = { "text": "Hi, This is a test from Local" } # Get the Slack webhook URL from environment variables webhook = os.environ.get("webhook_slack") # Send the POST request to Slack response = requests.post(webhook, json=data) # Check and print the response status for debugging print(f"Slack Response Status: {response.status_code}") print(f"Slack Response Text: {response.text}")
Lambda执行异常情况
AWS EventBridge可正常调用Lambda函数,但Lambda无法向Slack发送通知,Lambda代码如下:
import json import os import urllib3 SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL'] http = urllib3.PoolManager() def lambda_handler(event, context): # Log the entire event for debugging print("Received event:", json.dumps(event)) # Extract details from EventBridge event detail = event.get("detail", {}) instance_id = detail.get("instance-id") state = detail.get("state") region = event.get("region") # Log extracted details print(f"Instance ID: {instance_id}, State: {state}, Region: {region}") # Define message based on instance state if state == "running": message = f"🚀 EC2 Instance {instance_id} has been created and is now running in {region}." elif state == "stopped": message = f"🛑 EC2 Instance {instance_id} has been stopped in {region}." elif state == "terminated": message = f"💥 EC2 Instance {instance_id} has been terminated in {region}." else: print("State does not match expected values. Exiting.") return # Exit if the state is not relevant # Send notification to Slack slack_message = { "text": message } response = http.request( "POST", SLACK_WEBHOOK_URL, body=json.dumps(slack_message), headers={"Content-Type": "application/json"} ) # Log the HTTP response status and data for debugging print(f"Slack Response Status: {response.status}") print(f"Slack Response Data: {response.data}") if response.status != 200: raise ValueError( f"Request to Slack returned an error {response.status}, response is: {response.data}" ) return {"status": "Notification sent successfully"}
当前已配置内容
- 为Lambda角色配置了EC2只读访问权限与Lambda执行角色
- 已在Lambda配置中保存环境变量
SLACK_WEBHOOK_URL - Lambda日志中无明确错误信息
排查步骤
检查Lambda网络访问权限
- 默认Lambda运行在VPC外可直接访问公网,若配置了VPC,需确保Lambda所在子网有NAT网关/互联网网关,且安全组、网络ACL允许出站访问Slack的HTTPS端口(443)。
- 可添加测试代码尝试访问
https://www.google.com,验证公网请求能力。
验证环境变量正确性
- 确认
SLACK_WEBHOOK_URL与本地测试使用的URL完全一致,无多余空格或字符。 - 临时添加日志打印URL(生产环境需删除),确认配置无误:
print(f"Slack Webhook URL: {SLACK_WEBHOOK_URL}")
- 确认
检查urllib3使用细节
- urllib3默认需处理SSL证书,可临时添加
cert_reqs='CERT_NONE'测试(仅用于排查):response = http.request( "POST", SLACK_WEBHOOK_URL, body=json.dumps(slack_message), headers={"Content-Type": "application/json"}, cert_reqs='CERT_NONE' ) - 或替换为
requests库(需打包依赖或配置Lambda层),兼容本地测试逻辑。
- urllib3默认需处理SSL证书,可临时添加
查看完整CloudWatch日志
- 检查CloudWatch日志组的所有日志流,包括初始化日志和截断的错误信息,确认是否有遗漏的异常记录。
验证EventBridge事件格式
- 核对打印的
Received event日志,确认detail.state字段值是否与代码判断的running/stopped/terminated完全匹配,避免字段名或大小写差异。
- 核对打印的
检查Slack Webhook有效性
- 确认Webhook未过期,对应Slack频道权限未变更,可重新生成URL测试。
内容的提问来源于stack exchange,提问作者Antham
相关产品推荐
相关产品推荐

