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

如何调度EC2实例每小时启动并在Docker任务完成后停止以降本?

解决方案:按需启动EC2执行Docker任务后自动停止

这问题我之前帮朋友处理过,核心思路就是让EC2只在任务运行时段启动,执行完立刻停止,彻底避免闲置付费。结合EventBridge(原CloudWatch Events)、Lambda和EC2用户数据就能搞定,具体步骤拆解如下:

1. 配置EC2实例的启动自动执行脚本

在你的EC2实例(先处于停止状态)的**用户数据(User Data)**中添加启动脚本,让实例启动后自动完成:安装Docker(如果镜像没预装)、拉取你的镜像、运行容器,最后停止自身。

示例脚本(适配Amazon Linux 2,其他系统可调整包管理命令):

#!/bin/bash
set -e  # 遇到错误就退出,可选

# 安装Docker(如果实例镜像未预装)
yum update -y
amazon-linux-extras install docker -y
systemctl start docker
systemctl enable docker  # 确保重启后Docker自动启动
usermod -a -G docker ec2-user

# 拉取并运行你的Docker镜像(如果是私有镜像,要提前配置认证,比如ECR的IAM权限)
docker pull your-docker-repo/your-image:your-tag
docker run --rm your-docker-repo/your-image:your-tag

# 任务执行完成后,停止当前实例
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
aws ec2 stop-instances --instance-id $INSTANCE_ID --region us-east-1  # 替换为你的区域

注意:EC2实例需要关联一个IAM角色,该角色必须拥有ec2:StopInstances权限(遵循最小权限原则,别给全量EC2权限)。你可以在IAM控制台创建角色,附加自定义策略后关联到EC2实例。

2. 创建Lambda函数负责启动EC2

写一个简单的Lambda函数,用来触发EC2实例启动。用Python的话,代码如下:

import boto3

def lambda_handler(event, context):
    ec2_client = boto3.client('ec2', region_name='us-east-1')  # 替换为你的区域
    target_instance_id = 'i-xxxxxxxxxxxxxxxxx'  # 替换为你的EC2实例ID
    
    # 启动实例
    response = ec2_client.start_instances(InstanceIds=[target_instance_id])
    print(f"Successfully started instance {target_instance_id}, response: {response}")
    return {
        'statusCode': 200,
        'body': f"Started instance {target_instance_id}"
    }

同样,Lambda的执行角色需要拥有ec2:StartInstances权限,确保能调用启动实例的API。

3. 设置EventBridge定时触发Lambda

用EventBridge创建一个定时规则,每小时触发一次Lambda,自动启动EC2:

  • 进入EventBridge控制台,创建规则,选择计划类型
  • 选择cron表达式,输入0 * * * ? *(表示每小时整点触发)
  • 目标选择刚才创建的Lambda函数,完成配置

关键注意事项

  • 实例状态:确保EC2实例平时处于停止状态,这样Lambda启动时才会触发用户数据脚本(如果实例是运行中,启动命令不会触发用户数据)。
  • 私有镜像认证:如果你的Docker镜像存放在私有仓库(比如AWS ECR),要给EC2的IAM角色添加ecr:GetDownloadUrlForLayer、ecr:BatchGetImage等权限,或者在用户数据里添加登录命令。
  • 错误处理:如果Docker任务执行失败,你可以在脚本里加判断逻辑,比如发送SNS告警后再停止实例:
    if docker run --rm your-image:tag; then
        echo "Task completed successfully"
    else
        echo "Task failed! Sending alert..."
        aws sns publish --topic-arn arn:aws:sns:us-east-1:123456789012:your-alert-topic --message "Docker task failed on instance $INSTANCE_ID"
    fi
    
  • 成本优化:可以选择按需实例,或者如果任务允许中断,用Spot实例进一步降低成本,但按需实例更稳定,3分钟的运行成本几乎可以忽略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:24