You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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日志中无明确错误信息

排查步骤

  1. 检查Lambda网络访问权限

    • 默认Lambda运行在VPC外可直接访问公网,若配置了VPC,需确保Lambda所在子网有NAT网关/互联网网关,且安全组、网络ACL允许出站访问Slack的HTTPS端口(443)。
    • 可添加测试代码尝试访问https://www.google.com,验证公网请求能力。
  2. 验证环境变量正确性

    • 确认SLACK_WEBHOOK_URL与本地测试使用的URL完全一致,无多余空格或字符。
    • 临时添加日志打印URL(生产环境需删除),确认配置无误:print(f"Slack Webhook URL: {SLACK_WEBHOOK_URL}")
  3. 检查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层),兼容本地测试逻辑。
  4. 查看完整CloudWatch日志

    • 检查CloudWatch日志组的所有日志流,包括初始化日志和截断的错误信息,确认是否有遗漏的异常记录。
  5. 验证EventBridge事件格式

    • 核对打印的Received event日志,确认detail.state字段值是否与代码判断的running/stopped/terminated完全匹配,避免字段名或大小写差异。
  6. 检查Slack Webhook有效性

    • 确认Webhook未过期,对应Slack频道权限未变更,可重新生成URL测试。

内容的提问来源于stack exchange,提问作者Antham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:26:17