案例5

题目

某公司搭建了一个文件管理系统,用户上传文件到Amazon S3后,通过AWS Lambda函数将文件元数据(文件名、上传时间、大小)写入Amazon DynamoDB表。近期发现用户上传文件后,DynamoDB表中未新增数据,但S3桶中文件正常存储。请根据以下配置信息排查并解决问题。

相关配置信息

  1. S3存储桶配置

    • 桶名称:file - upload - bucket,启用了版本控制。
    • 事件通知配置:配置了Lambda触发器,事件类型为“所有对象创建事件”,目标Lambda函数为file - metadata - processor
    • 桶策略:
      {  
          "Version": "2012-10-17",  
          "Statement": [  
              {  
                  "Effect": "Allow",  
                  "Principal": {  
                      "Service": "lambda.amazonaws.com"  
                  },  
                  "Action": "s3:GetObject",  
                  "Resource": "arn:aws:s3:::file - upload - bucket/*"  
              }  
          ]  
      }  
      
  2. Lambda函数配置

    • 函数代码(Python):
      import boto3  
      import json  
      from datetime import datetime  
      
      dynamodb = boto3.resource('dynamodb')  
      table = dynamodb.Table('file - metadata - table')  
      
      def lambda_handler(event, context):  
          for record in event['Records']:  
              bucket = record['s3']['bucket']['name']  
              key = record['s3']['object']['key']  
              size = record['s3']['object']['size']  
              upload_time = datetime.now().isoformat()  
      
              table.put_item(  
                  Item={  
                      'FileName': key,  
                      'UploadTime': upload_time,  
                      'FileSize': size  
                  }  
              )  
          return {  
              'statusCode': 200,  
              'body': json.dumps('Metadata processed successfully')  
          }  
      
    • 执行角色:lambda - execution - role,策略如下:
      {  
          "Version": "2012-10-17",  
          "Statement": [  
              {  
                  "Effect": "Allow",  
                  "Action": "logs:CreateLogGroup",  
                  "Resource": "*"  
              },  
              {  
                  "Effect": "Allow",  
                  "Action": "logs:CreateLogStream",  
                  "Resource": "*"  
              },  
              {  
                  "Effect": "Allow",  
                  "Action": "logs:PutLogEvents",  
                  "Resource": "*"  
              }  
          ]  
      }  
      
  3. DynamoDB表配置

    • 表名:file - metadata - table,主键为FileName(字符串类型),无排序键。
    • 表的读写容量模式:按需模式(On - Demand)。

解题思路

1. 明确问题现象

  • 核心问题:S3文件上传后,DynamoDB表未写入元数据,但Lambda函数未报错(假设日志中无明显错误)。
  • 可能方向
    • S3事件通知未正确触发Lambda函数。
    • Lambda函数缺少DynamoDB写入权限。
    • 代码逻辑错误导致数据未写入。
    • S3桶策略或Lambda角色权限不足。

2. 排查S3事件通知配置

  • 检查点
    • 登录AWS控制台,进入S3桶file - upload - bucket的“事件通知”页面,确认:
      1. 事件类型是否为“所有对象创建事件”。
      2. 目标Lambda函数是否正确关联(file - metadata - processor)。
      3. 是否有错误提示(如Lambda函数ARN无效、权限不足)。
  • 发现问题
    事件通知配置正确,但S3桶策略中允许Lambda访问GetObject,但Lambda触发事件通知时,不需要GetObject权限(事件通知仅传递元数据,不读取文件内容),因此桶策略无直接问题,但需确认Lambda能否接收事件。

3. 排查Lambda函数权限

  • 关键分析
    Lambda函数需要向DynamoDB表file - metadata - table写入数据,对应操作是dynamodb:PutItem
    • 当前lambda - execution - role的策略仅包含CloudWatch日志权限,完全缺少DynamoDB相关权限,这是核心错误!
  • 修正角色策略
    lambda - execution - role添加DynamoDB写入权限:
    {  
        "Effect": "Allow",  
        "Action": "dynamodb:PutItem",  
        "Resource": "arn:aws:dynamodb:your - region:your - account - id:table/file - metadata - table"  
    }  
    
    (替换your - regionyour - account - id为实际值)

4. 检查代码逻辑

  • 潜在问题
    • S3事件通知的event结构中,record['s3']['object']['size']可能不存在?
      实际上,S3事件通知的“对象创建事件”中,size字段是可选的,若文件上传时未提供(如分块上传未完成),可能为null或缺失,导致代码报错。
    • 但题目中用户反馈“无数据写入”,且假设日志无报错,优先考虑权限问题。
  • 代码修正(可选)
    为避免size缺失导致错误,可添加默认值:
    size = record['s3']['object'].get('size', 0)  # 使用get()方法避免KeyError  
    

5. 验证S3事件触发和Lambda执行

  • 步骤1:重新上传文件
    上传一个测试文件到S3桶,观察Lambda函数是否被触发(可在Lambda控制台查看执行历史)。
  • 步骤2:检查Lambda日志
    进入CloudWatch Logs,查看Lambda函数的日志组,确认是否有权限错误:
    • 若出现AccessDeniedException,说明DynamoDB写入权限缺失(即步骤3未修复)。
    • 若日志显示正常执行但DynamoDB无数据,可能是代码逻辑问题(如FileName重复导致主键冲突)。
  • 步骤3:检查DynamoDB表
    使用DynamoDB控制台查询表file - metadata - table,确认是否有新写入的条目,或是否因主键重复导致写入失败(若文件名为唯一主键,重复上传同文件名会覆盖旧数据,而非新增)。

6. 额外检查:S3桶与Lambda的权限关联

  • Lambda函数要接收S3事件通知,需确保S3桶有权限调用Lambda(通过事件通知配置自动授予,一般无需额外策略)。
  • 若事件通知配置中提示“无法授权”,需在Lambda函数的“权限”页面,确保存在名为AWSServiceRoleForS3EventNotifications的权限策略(或手动添加lambda:InvokeFunction权限到S3桶的事件通知角色)。

总结

核心错误:Lambda函数缺少DynamoDB写入权限

  1. 权限缺失lambda - execution - role未包含dynamodb:PutItem权限,导致写入失败。
  2. 次要改进:代码中对S3事件字段的健壮性处理(如size可能缺失)。

解决步骤

  1. 为Lambda执行角色添加DynamoDB写入权限。
  2. 验证上传文件后Lambda是否正常执行并写入数据。

AWS排错核心:服务间的权限传递必须明确,每个服务(如Lambda、S3、DynamoDB)交互时,需确保执行角色具备目标服务的必要操作权限(如PutItemGetObject等),可通过服务控制台的错误日志快速定位权限缺失问题。

posted @ 2025-04-16 23:55  cat桑  阅读(64)  评论(0)    收藏  举报