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

能否基于SQS队列自动伸缩EC2实例?Terraform实现咨询

基于SQS队列实现EC2自动伸缩的可行性与Terraform实现方案

可行性分析

你的需求完全可以实现:

  • 缩容到0:利用CloudWatch监控SQS的ApproximateNumberOfMessagesVisible指标,当该指标连续60分钟保持为0时,触发Auto Scaling策略将实例数设为0,彻底停止不必要的实例开销。
  • 扩容到1台:通过CloudWatch的Change统计类型监控消息数变化,当待处理消息数连续2-3分钟没有下降(即变化量为0),说明当前没有实例在处理消息,触发扩容策略启动1台实例。

这种方案完全依托AWS原生服务,无需额外第三方工具,稳定性和可维护性都有保障。

Terraform实现步骤与代码示例

1. 基础资源定义

首先创建SQS队列、EC2实例所需的IAM权限和启动模板:

# 创建SQS工作队列
resource "aws_sqs_queue" "worker_queue" {
  name                      = "worker-queue"
  delay_seconds             = 0
  max_message_size          = 262144
  message_retention_seconds = 86400
  receive_wait_time_seconds = 20
}

# 实例角色:赋予SQS访问权限
resource "aws_iam_role" "worker_role" {
  name = "worker-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
  })
}

# 按需缩小权限范围,这里用全权限仅作示例
resource "aws_iam_role_policy_attachment" "worker_sqs_access" {
  role       = aws_iam_role.worker_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSQSFullAccess"
}

resource "aws_iam_instance_profile" "worker_instance_profile" {
  name = "worker-instance-profile"
  role = aws_iam_role.worker_role.name
}

# EC2启动模板:定义实例配置
resource "aws_launch_template" "worker_launch_template" {
  name_prefix   = "worker-launch-template"
  image_id      = "ami-0c55b159cbfafe1f0" # 替换为你的区域AMI ID
  instance_type = "t3.micro"
  iam_instance_profile {
    name = aws_iam_instance_profile.worker_instance_profile.name
  }
  # 替换为你的worker启动脚本,例如拉取SQS消息的处理逻辑
  user_data = base64encode("#!/bin/bash\necho 'Starting worker process...'")
}

2. 创建Auto Scaling组

配置允许缩容到0的Auto Scaling组:

resource "aws_autoscaling_group" "worker_asg" {
  name_prefix          = "worker-asg"
  min_size             = 0
  max_size             = 1
  desired_capacity     = 0
  vpc_zone_identifier  = ["subnet-0123456789abcdef0", "subnet-0abcdef1234567890"] # 替换为你的子网ID

  launch_template {
    id      = aws_launch_template.worker_launch_template.id
    version = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = "Worker-Instance"
    propagate_at_launch = true
  }
}

3. 定义伸缩策略与CloudWatch告警

缩容策略:消息数为0持续60分钟时缩容到0

# 缩容策略:直接设置期望实例数为0
resource "aws_autoscaling_policy" "scale_down_to_zero" {
  name                   = "scale-down-to-zero"
  scaling_adjustment     = 0
  adjustment_type        = "ExactCapacity"
  autoscaling_group_name = aws_autoscaling_group.worker_asg.name
}

# CloudWatch告警:监控消息数连续60分钟为0
resource "aws_cloudwatch_metric_alarm" "sqs_no_messages" {
  alarm_name          = "sqs-no-messages-for-60min"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods  = 60
  metric_name         = "ApproximateNumberOfMessagesVisible"
  namespace           = "AWS/SQS"
  period              = 60
  statistic           = "Average"
  threshold           = 0
  alarm_description   = "Trigger when SQS queue has no messages for 60 minutes"
  alarm_actions       = [aws_autoscaling_policy.scale_down_to_zero.arn]

  dimensions = {
    QueueName = aws_sqs_queue.worker_queue.name
  }
}

扩容策略:消息数停滞2-3分钟时扩容到1台

# 扩容策略:直接设置期望实例数为1
resource "aws_autoscaling_policy" "scale_up_to_one" {
  name                   = "scale-up-to-one"
  scaling_adjustment     = 1
  adjustment_type        = "ExactCapacity"
  autoscaling_group_name = aws_autoscaling_group.worker_asg.name
}

# CloudWatch告警:监控消息数连续3分钟无变化(若要2分钟则把evaluation_periods改为2)
resource "aws_cloudwatch_metric_alarm" "sqs_messages_stagnant" {
  alarm_name          = "sqs-messages-stagnant"
  comparison_operator = "EqualToThreshold"
  evaluation_periods  = 3
  metric_name         = "ApproximateNumberOfMessagesVisible"
  namespace           = "AWS/SQS"
  period              = 60
  statistic           = "Change"
  threshold           = 0
  alarm_description   = "Trigger when SQS message count stays the same for 3 minutes"
  alarm_actions       = [aws_autoscaling_policy.scale_up_to_one.arn]

  dimensions = {
    QueueName = aws_sqs_queue.worker_queue.name
  }
}

注意事项

  • 替换代码中的AMI ID、子网ID为你AWS环境的实际值。
  • 严格控制IAM权限,避免使用AmazonSQSFullAccess,仅授予实例所需的SQS操作权限(如sqs:ReceiveMessage、sqs:DeleteMessage等)。
  • 若需要更复杂的扩容逻辑(比如多实例),可以调整Auto Scaling组的max_size和扩容策略的调整值,但当前需求下1台足够。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:56:00