案例9

题目

某公司使用AWS构建了日志分析系统,架构如下:通过Amazon Kinesis Data Streams收集EC2实例的日志,Kinesis Data Firehose将数据流写入Amazon S3桶进行存储,同时触发AWS Lambda函数对日志进行实时分析并将结果写入Amazon DynamoDB表。近期发现DynamoDB表中无分析结果,但S3桶中存在日志文件。请根据以下配置信息排查并解决问题。

相关配置信息

  1. Kinesis Data Streams配置

    • 流名称:ec2-logs-stream,分片数量为2,位于us-east-1区域。
    • 启用了Kinesis Data Firehose自动捕获流数据,目标S3桶为logs-storage-bucket
  2. Kinesis Data Firehose配置

    • 交付流名称:logs-to-s3-firehose,目标S3桶配置正确,桶前缀为logs/
    • 错误处理:启用了重试,无数据转换。
  3. Lambda函数配置

    • 函数代码(Python):
      import boto3  
      import json  
      
      dynamodb = boto3.resource('dynamodb')  
      table = dynamodb.Table('log-analysis-results')  
      
      def lambda_handler(event, context):  
          for record in event['Records']:  
              log_data = json.loads(record['kinesis']['data'].decode('base64'))  
              # 简单分析:统计日志中的"ERROR"次数  
              error_count = log_data['message'].count('ERROR')  
              table.put_item(  
                  Item={  
                      'LogTimestamp': log_data['timestamp'],  
                      'ErrorCount': error_count  
                  }  
              )  
          return { 'statusCode': 200 }  
      
    • 执行角色:lambda-firehose-role,策略如下:
      {  
          "Version": "2012-10-17",  
          "Statement": [  
              {  
                  "Effect": "Allow",  
                  "Action": "logs:PutLogEvents",  
                  "Resource": "*"  
              },  
              {  
                  "Effect": "Allow",  
                  "Action": "dynamodb:DescribeTable",  
                  "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/log-analysis-results"  
              }  
          ]  
      }  
      
  4. DynamoDB表配置

    • 表名:log-analysis-results,主键为LogTimestamp(字符串类型,ISO 8601格式),无排序键。
    • 读写容量模式:按需模式,未启用加密或访问策略。
  5. S3桶配置

    • 桶名:logs-storage-bucket,启用了版本控制,桶策略允许Kinesis Firehose写入。

解题思路

1. 明确问题边界

  • 现象
    • S3桶有日志文件(Firehose写入正常),但Lambda未写入DynamoDB。
    • 可能原因:Lambda权限不足、代码解析错误、事件源配置问题。

2. 排查Lambda函数权限

  • 核心分析
    Lambda需要调用dynamodb:PutItem写入数据,但当前策略仅包含dynamodb:DescribeTable(查看表结构)和日志权限,缺少写入权限
  • 错误日志线索
    CloudWatch日志会显示AccessDeniedException,指出缺少dynamodb:PutItem权限。
  • 修正角色策略
    添加DynamoDB写入权限:
    {  
        "Effect": "Allow",  
        "Action": "dynamodb:PutItem",  
        "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/log-analysis-results"  
    }  
    

3. 检查Kinesis事件数据格式

  • 代码逻辑问题
    Kinesis Data Firehose传递给Lambda的event结构中,record['kinesis']['data']是Base64编码,需使用base64.b64decode()而非decode('base64')(Python 3中已弃用decode('base64'),应使用base64模块)。
  • 修正代码
    import base64  
    log_data = json.loads(base64.b64decode(record['kinesis']['data']).decode('utf-8'))  
    

4. 验证DynamoDB主键类型匹配

  • 潜在问题
    代码中log_data['timestamp']需为字符串类型,与表主键LogTimestamp(字符串类型)匹配。若日志中的timestamp为数字或格式错误,会导致类型不匹配错误。
  • 检查点
    确保日志数据中的timestamp字段是ISO 8601格式的字符串(如"2023-10-01T12:34:56Z")。

5. 排查Lambda事件源映射

  • 配置验证
    确认Kinesis Data Firehose已正确配置Lambda作为实时分析目标:
    1. 进入Firehose控制台,查看交付流的“转换”设置,确认已启用Lambda调用。
    2. 检查Lambda函数的“触发条件”,确认Kinesis Firehose事件源已正确关联。

6. 完整修复与验证

  1. 更新角色策略
    • lambda-firehose-role添加dynamodb:PutItem权限。
  2. 修正代码Base64解码
    • 使用base64.b64decode()替换弃用的decode('base64')
  3. 测试数据流入
    • 向Kinesis流发送测试日志数据,触发Firehose和Lambda。
    • 检查Lambda日志,确认无权限错误和解析错误。
    • 查询DynamoDB表,确认LogTimestampErrorCount已正确写入。

7. 补充检查:S3与DynamoDB的区域一致性

  • 确保所有服务(Kinesis、S3、DynamoDB、Lambda)位于同一区域(题目中均为us-east-1,假设正确)。

总结

核心错误

  1. 权限缺失:Lambda角色缺少DynamoDB写入权限,导致无法写入数据。
  2. 代码过时:使用已弃用的Base64解码方法,导致数据解析失败(虽不直接导致权限错误,但需修正)。

解决步骤

  • 为Lambda角色添加必要的dynamodb:PutItem权限。
  • 更新代码中Base64解码逻辑,确保数据正确解析。
  • 通过测试数据验证端到端流程,利用CloudWatch日志定位具体错误。

AWS排错要点

  • 权限优先:无服务器架构中,服务间调用的权限缺失是最常见问题,需严格检查IAM角色策略。
  • 数据格式匹配:处理编码数据(如Base64)时,需使用语言对应的最新库函数,避免依赖过时语法。
  • 事件源映射:确认触发关系(如Firehose→Lambda)正确配置,且事件结构符合函数预期。
posted @ 2025-04-17 00:03  cat桑  阅读(48)  评论(0)    收藏  举报