案例9
题目
某公司使用AWS构建了日志分析系统,架构如下:通过Amazon Kinesis Data Streams收集EC2实例的日志,Kinesis Data Firehose将数据流写入Amazon S3桶进行存储,同时触发AWS Lambda函数对日志进行实时分析并将结果写入Amazon DynamoDB表。近期发现DynamoDB表中无分析结果,但S3桶中存在日志文件。请根据以下配置信息排查并解决问题。
相关配置信息
-
Kinesis Data Streams配置
- 流名称:
ec2-logs-stream,分片数量为2,位于us-east-1区域。 - 启用了Kinesis Data Firehose自动捕获流数据,目标S3桶为
logs-storage-bucket。
- 流名称:
-
Kinesis Data Firehose配置
- 交付流名称:
logs-to-s3-firehose,目标S3桶配置正确,桶前缀为logs/。 - 错误处理:启用了重试,无数据转换。
- 交付流名称:
-
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" } ] }
- 函数代码(Python):
-
DynamoDB表配置
- 表名:
log-analysis-results,主键为LogTimestamp(字符串类型,ISO 8601格式),无排序键。 - 读写容量模式:按需模式,未启用加密或访问策略。
- 表名:
-
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作为实时分析目标:- 进入Firehose控制台,查看交付流的“转换”设置,确认已启用Lambda调用。
- 检查Lambda函数的“触发条件”,确认Kinesis Firehose事件源已正确关联。
6. 完整修复与验证
- 更新角色策略:
- 为
lambda-firehose-role添加dynamodb:PutItem权限。
- 为
- 修正代码Base64解码:
- 使用
base64.b64decode()替换弃用的decode('base64')。
- 使用
- 测试数据流入:
- 向Kinesis流发送测试日志数据,触发Firehose和Lambda。
- 检查Lambda日志,确认无权限错误和解析错误。
- 查询DynamoDB表,确认
LogTimestamp和ErrorCount已正确写入。
7. 补充检查:S3与DynamoDB的区域一致性
- 确保所有服务(Kinesis、S3、DynamoDB、Lambda)位于同一区域(题目中均为
us-east-1,假设正确)。
总结
核心错误:
- 权限缺失:Lambda角色缺少DynamoDB写入权限,导致无法写入数据。
- 代码过时:使用已弃用的Base64解码方法,导致数据解析失败(虽不直接导致权限错误,但需修正)。
解决步骤:
- 为Lambda角色添加必要的
dynamodb:PutItem权限。 - 更新代码中Base64解码逻辑,确保数据正确解析。
- 通过测试数据验证端到端流程,利用CloudWatch日志定位具体错误。
AWS排错要点:
- 权限优先:无服务器架构中,服务间调用的权限缺失是最常见问题,需严格检查IAM角色策略。
- 数据格式匹配:处理编码数据(如Base64)时,需使用语言对应的最新库函数,避免依赖过时语法。
- 事件源映射:确认触发关系(如Firehose→Lambda)正确配置,且事件结构符合函数预期。

浙公网安备 33010602011771号