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
相关产品推荐
相关产品推荐

