[AWS/Athena] 如何使用分区投影创建用于 WAF 日志分析的表

介绍

大家好!
我是Mikoto,从七月份开始担任基础设施工程师到现在已经一年了。正式进入第二年也已经四个月了,我即将迈入第三年。

我最近尝试Athena分析 WAF 日志分区投影,所以我决定写一篇文章来解决这个问题。

*请注意,本文不适合不熟悉 Athena 使用方法或不了解表格概念的人士阅读。

 

什么是亚马逊雅典娜?

这与希腊智慧和战争女神无关!
Amazon Athena一项查询服务,可让您直接分析存储在 S3 中的数据。

例如,即使您已使用 Elastic Load Balancer、Cloud Front、WAF 等启用了日志输出到 S3,但当您想要从大量日志中识别每分钟的请求数或特定的访问源 IP 地址时,下载文本文件并在本地进行分析可能会很麻烦,对吗?

在这种情况下,如果您使用 Amazon Athena,在控制台上运行查询即可分析日志,而
如需了解更多信息,请阅读文档

 

关于执行环境

这次查询使用以下配置执行。
请注意,
稍后指定的会根据配置而变化

所使用的S3层级结构如下:

 

创建表格

这次以此创建一个表格
如上所述,CloudFront 位于第一行,因此 S3 路径包含 /cloudfront。

创建外部表 `waf_logs_partition_projection`( `timestamp` bigint, `formatversion` int, `webaclid` string, `terminatingruleid` string, `terminatingruletype` string, `action` string, `terminatingrulematchdetails` array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>, `httpsourcename` string, `httpsourceid` string, `rulegrouplist` array<struct<rulegroupid:string,terminatingrule:struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>>,nonterminatingmatchingrules:array<struct<ruleid:string,action:string,overriddenaction n:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>,excludedrules:string>>,`ratebasedrulelist` array<struct<ratebasedruleid:string,limitkey:string,maxrateallowed:int>>,`nonterminatingmatchingrules` array<struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>, `requestheadersinserted` array<struct<name:string,value:string>>, `responsecodesent` string, `httprequest` struct<clientip:string,country:string,headers:array<struct<name:string,value:string>>,uri:string,args:string,httpversion:string,httpmethod:string,requestid:string,fragment:string,scheme:string,host:string>, `labels` array<struct<name:string>>, `captcharesponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, `challengeresponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, `ja3fingerprint` string, `ja4fingerprint` string, `oversizefields` string, `requestbodysize` int, `requestbodysizeinspectedbywaf` int) PARTITIONED BY ( `log_time` string ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://{WAF TBLPROPERTIES( 'projection.enabled' = 'true', 'projection.log_time.type' = 'date', 'projection.log_time.range' = '2025/11/01/00/00,NOW', 'projection.log_time.format' = 'yyyy/MM/dd/HH/mm', 'projection.log_time.interval' = '1', 'projection.log_time.interval.unit' = 'minutes', 'storage.location.template' = 's3://{WAF 日志输出存储桶}/AWSLogs/{账户 ID}/WAFLogs/cloudfront/{目标 CF}/${log_time}')

*请注意,如果您将此配置应用于区域资源(例如 ALB),则此处应填写区域名称,例如 /ap-northeast-1/(代表东京地区)。
*在此结构中,yyyy/MM/dd/HH/mm ,但根据您的 S3 层级结构,可能需要进行更改。如果时间格式为yyyy/MM/dd/HH 则需要将projection.log_time.interval.unit

 

关于分区投影

本文的主题是分区投影它是一种自动执行分区管理以提高查询性能的功能。

(^ω^) <日语可以

别摆出那副表情,
我这就解释。

以下是一个创建表的查询示例。
此查询指定从 2025 年 11 月 1 日至今的日志。

按 (`log_time` 字符串) 分区 ~省略~ TBLPROPERTIES( 'projection.enabled' = 'true', 'projection.log_time.type' = 'date', 'projection.log_time.range' = '2025/11/01/00/00,NOW', 'projection.log_time.format' = 'yyyy/MM/dd/HH/mm', 'projection.log_time.interval' = '1', 'projection.log_time.interval.unit' = 'minutes', 'storage.location.template' = 's3://{WAF 日志输出目标存储桶}/AWSLogs/{账户 ID}/WAFLogs/cloudfront/{目标 CF}/${log_time}')

S3 存储桶中的日志文件是按层级结构排列的,例如年/月/日/小时/分钟,对吧?这称为分区
通常,您需要定期运行命令,将分区位置注册到AWS Glue 数据目录

┌[ ∵]┐ <新增数据?数据位于何处?

每次使用胶水都必须经过这个过程。

通过预先向 Athena 提供分区层次结构,Athena将根据接收到的层次结构信息自动计算日志数据的存储位置

这样,新添加的分区将被自动识别,从而无需在每次要分析的日志数据范围增加时都读取 AWS Glue 数据目录。

└[ ∵]┘ <如果数据存储在此层次结构中,则新日志将出现在这里。

它看起来是这样的。
这叫做分区投影

 

如何写作


我们将解释如何编写它,假设您了解它的实际工作原理

按 (`log_time` 字符串) 分区 ~省略~ TBLPROPERTIES( 'projection.enabled' = 'true', 'projection.log_time.type' = 'date', 'projection.log_time.range' = '2025/11/01/00/00,NOW', 'projection.log_time.format' = 'yyyy/MM/dd/HH/mm', 'projection.log_time.interval' = '1', 'projection.log_time.interval.unit' = 'minutes', 'storage.location.template' = 's3://{WAF 日志输出目标存储桶}/AWSLogs/{账户 ID}/WAFLogs/cloudfront/{目标 CF}/${log_time}')

如前所述,我们主要使用两个子句: PARTITIONEDTBLPROPERTIES

分区:
指定分区键。
这里我们使用名为 log_time 的键,但您可以设置其他键。
如果键与现有列名重叠,Athena 可能会出错并抛出错误,因此最好将其设置为原始日志数据中不存在的名称。

TBLPROPERTIES:
指定是否启用分区投影以及指定键的格式详细信息。
在本例中,我们将对 log_time 中包含的信息进行排序,并将其提供给 Athena。

  • projection.enabled :声明“我将使用分区投影!”
  • 类型:数据类型(在本例中为日期,因此为日期)
  • range :数据范围,从“开始”到“结束”。使用 NOW 函数非常有用,因为它会将范围设置为查询执行时为止。
  • 格式:S3 文件夹名称的格式(例如 yyyy/MM/dd)
  • 间隔:数据添加的间隔(每分钟添加 1 个数据)
  • storage.location.template :将计算值应用到 S3 路径的位置。${log_time} 是 Athena 计算出的日期。

请注意,如果PARTITIONEDTBLPROPERTIES不同,将会出现以下错误,因此请务必确保它们匹配。

INVALID_TABLE_PROPERTY: 表 {{数据库名称}}.{{表名称}} 配置为分区投影,但投影配置中缺少以下分区列:[year, month, day, hour]

除非查询语句中另有限定,否则此查询将针对“{{数据库名称}}”数据库执行。请将错误信息发布到我们的论坛或联系客户支持,并提供查询 ID:XXXX。

*当时我学习不够,所以写了一些不同的值,结果卡住了。

此外,本文中, storage.location.template在使用 CloudFront 时指的是路径。
请注意,如果 WAF 已链接到负载均衡器,则路径将如下所示:

LOCATION 's3://{WAF 日志输出目标存储桶}/AWSLogs/{账户 ID}/WAFLogs/ap-northeast-1(区域)/{目标 WAF}/' ~省略~ 'storage.location.template' = 's3://{WAF 日志输出目标存储桶}/AWSLogs/{账户 ID}/WAFLogs/${区域}/{目标 WAF}/${日志时间}')

 

执行查询

创建表的说明到此结束。最后,让我们使用创建的表!
我们使用之前指定的分区键的 log_time 来扫描数据。

SELECT from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST, * FROM waf_logs_partition_projection WHERE log_time BETWEEN '2025/11/16/00/00' AND '2025/11/16/00/59';

*如果格式为yyyy/MM/dd/HH/ 则将其更改为2025/11/16/00/。

如果此处输出日志数据,则设置完成🎉🎉
如果执行此操作时没有获得任何值,请检查以下内容!

  • 分区键设置是否正确?
  • storage.location.template中指定的路径是否有错误

 

结论

你觉得怎么样?
虽然日志分析查询本身没有问题,但我创建表的时候遇到了很多麻烦,所以我深入研究了一下,并写了一篇文章来说明。

我通过慢慢阅读文档,并记下我操作的步骤,同时向我的前辈和人工智能寻求建议,并将这些内容发布在我的博客上,从中学习到了很多东西!

希望这篇文章对您有所帮助。
感谢您一直以来的支持!

参考


分区
功能在 Amazon Athena 中使用分区投影。使用
分区投影在 Athena 中创建用于存储 AWS WAF S3 日志的表。
如何选择分区键。

如果您觉得这篇文章有用,请点击【点赞】!
1
加载中...
1票,平均分:1.00/11
9
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者

御琴

我是一名基础设施工程师,2024年4月从文科院校毕业后加入公司。
我当时想不出昵称,所以就选了我妈妈常用的一个。
鲸头鹳是不是很可爱?