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

S3、Lambda与EC2文件共享:Lambda访问EC2挂载EBS实现文件同步

解决方案:Lambda 间接访问 EC2 挂载的 EBS 卷

Lambda 无法直接挂载或访问 EC2 上的 EBS 卷(EBS 与特定 EC2 实例绑定,且 Lambda 运行在 AWS 托管的隔离环境中),必须通过 EC2 实例本身作为中间层完成文件检查与写入操作。以下是两种可行的实现方案:


方案 1:使用 SSM Run Command 触发 EC2 执行操作

这是最轻量化的方案,无需在 EC2 上额外部署服务,通过 AWS Systems Manager(SSM)让 Lambda 远程命令 EC2 完成文件处理。

前置准备

  • 给 Lambda 执行角色添加权限:允许 ssm:SendCommand 操作,以及访问目标 S3 桶的权限(s3:GetObject)。
  • 给目标 EC2 实例附加 IAM 角色:包含 AmazonEC2RoleforSSM 权限(确保 EC2 能被 SSM 管理)。
  • 确保 EC2 已安装并运行 SSM Agent(Amazon Linux 默认自带,其他系统需手动安装)。

Lambda 代码示例(Python)

import boto3

def lambda_handler(event, context):
    # 从 S3 Put 事件中提取文件信息
    s3_info = event['Records'][0]['s3']
    bucket = s3_info['bucket']['name']
    obj_key = s3_info['object']['key']
    file_name = obj_key.split('/')[-1]
    ebs_mount_dir = '/mnt/your-ebs-dir'  # 替换为你的 EBS 挂载目录

    # 初始化 SSM 客户端
    ssm = boto3.client('ssm')
    target_instances = ['i-xxxxxxxxx']  # 替换为目标 EC2 实例 ID

    # 构造要执行的 Shell 命令
    command = f"""
    if [ ! -f "{ebs_mount_dir}/{file_name}" ]; then
        aws s3 cp s3://{bucket}/{obj_key} "{ebs_mount_dir}/{file_name}"
    fi
    """

    # 发送 SSM 命令到 EC2
    response = ssm.send_command(
        InstanceIds=target_instances,
        DocumentName='AWS-RunShellScript',
        Parameters={'commands': [command]}
    )
    return {'command_id': response['Command']['CommandId']}

注意事项

  • 若 EC2 在私有子网,需配置 VPC 端点访问 SSM 和 S3,避免依赖公网。
  • 权限需最小化:限制 Lambda 只能向指定 EC2 实例发送命令,仅允许访问目标 S3 桶。

方案 2:使用 SQS 队列让 EC2 主动轮询处理

Lambda 将 S3 文件信息发送到 SQS 队列,EC2 运行脚本持续轮询队列,收到消息后执行文件检查与下载。

前置准备

  • 创建一个 SQS 标准队列。
  • 给 Lambda 角色添加 sqs:SendMessage 权限;给 EC2 角色添加 sqs:ReceiveMessage、sqs:DeleteMessage 以及 S3 访问权限。

Lambda 代码示例(Python)

import boto3
import json

def lambda_handler(event, context):
    s3_info = event['Records'][0]['s3']
    message = json.dumps({
        'bucket': s3_info['bucket']['name'],
        'object_key': s3_info['object']['key']
    })

    sqs = boto3.client('sqs')
    queue_url = 'https://sqs.your-region.amazonaws.com/123456789012/your-queue'  # 替换为你的队列 URL
    sqs.send_message(QueueUrl=queue_url, MessageBody=message)
    return {'status': 'message sent'}

EC2 轮询脚本示例(Bash)

将此脚本配置为 systemd 服务,确保开机自启、异常重启:

#!/bin/bash
QUEUE_URL="https://sqs.your-region.amazonaws.com/123456789012/your-queue"
EBS_DIR="/mnt/your-ebs-dir"

while true; do
    # 拉取 SQS 消息(长轮询,最长等待 20 秒)
    RESPONSE=$(aws sqs receive-message --queue-url $QUEUE_URL --max-number-of-messages 1 --wait-time-seconds 20)
    if [ -n "$RESPONSE" ]; then
        # 解析消息内容与句柄
        MESSAGE_BODY=$(echo $RESPONSE | jq -r '.Messages[0].Body')
        RECEIPT_HANDLE=$(echo $RESPONSE | jq -r '.Messages[0].ReceiptHandle')
        
        BUCKET=$(echo $MESSAGE_BODY | jq -r '.bucket')
        OBJECT_KEY=$(echo $MESSAGE_BODY | jq -r '.object_key')
        FILE_NAME=$(basename $OBJECT_KEY)
        
        # 检查文件是否存在,不存在则下载
        if [ ! -f "$EBS_DIR/$FILE_NAME" ]; then
            aws s3 cp s3://$BUCKET/$OBJECT_KEY "$EBS_DIR/$FILE_NAME"
        fi
        
        # 删除已处理的消息
        aws sqs delete-message --queue-url $QUEUE_URL --receipt-handle $RECEIPT_HANDLE
    fi
done

核心逻辑说明

EBS 卷是与特定 EC2 实例绑定的存储资源,仅能被挂载到同一可用区的 EC2 实例访问,Lambda 作为无服务器服务无法直接挂载。上述两种方案均通过 EC2 实例作为代理,间接完成 EBS 上的文件操作,符合你的需求(无需迁移现有 EBS 文件到 EFS)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:22:30