Cloud & DevOps/AWS

Athena로 S3에 저장된 VPC flow logs 조회하기 - 2탄 (+ Glue Crawler)

백곰곰 2024. 2. 9. 00:15
728x90
반응형

지난 글에서 사용한 partition projection 방식에서 개선 필요한 점이 있어, 2탄을 작성합니다.

 

Athena로 S3에 저장된 VPC flow logs 조회하기

VPC flow logs를 Athena로 조회하기 위한 설정 방법을 소개합니다. VPC flow logs 설정 VPC flow logs를 S3에 저장할 때의 주요 설정 항목은 아래와 같습니다. 1.Log record format VPC flow logs에 포함될 필드를 저장합

popappend.tistory.com

 

Partition Projection을 사용하며 발견한 이슈

기존에 아래와 같이 partition projection을 사용한 DDL문을 사용하여 테이블을 생성한 뒤, 해당 테이블에 대해 쿼리를 실행했을 때, WHERE절에 accid 관련 조건이 제외되면 Amazon Athena experienced an internal error while executing this query... 와 같은 에러가 반복적으로 발생했습니다.

CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs_parquet (
  `version` int COMMENT '', 
  `account_id` string COMMENT '', 
  `interface_id` string COMMENT '', 
  `srcaddr` string COMMENT '', 
  `dstaddr` string COMMENT '', 
  `srcport` int COMMENT '', 
  `dstport` int COMMENT '', 
  `protocol` bigint COMMENT '', 
  `packets` bigint COMMENT '', 
  `bytes` bigint COMMENT '', 
  `start` bigint COMMENT '', 
  `end` bigint COMMENT '', 
  `action` string COMMENT '', 
  `log_status` string COMMENT '', 
  `vpc_id` string COMMENT '', 
  `subnet_id` string COMMENT '', 
  `instance_id` string COMMENT '', 
  `tcp_flags` int COMMENT '', 
  `type` string COMMENT '', 
  `pkt_srcaddr` string COMMENT '', 
  `pkt_dstaddr` string COMMENT '', 
  `az_id` string COMMENT '', 
  `sublocation_type` string COMMENT '', 
  `sublocation_id` string COMMENT '', 
  `pkt_src_aws_service` string COMMENT '', 
  `pkt_dst_aws_service` string COMMENT '', 
  `flow_direction` string COMMENT '', 
  `traffic_path` int COMMENT '')
PARTITIONED BY ( 
  `accid` string COMMENT '', 
  `region` string COMMENT '', 
  `year` string COMMENT '', 
  `month` string COMMENT '', 
  `day` string COMMENT '', 
  `hour` string COMMENT '')
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  's3://my-s3-arn/'
TBLPROPERTIES (
  'projection.accid.digits'='12', 
  'projection.accid.range'='000000000001,999999999999', # 문제가 되는 부분
  'projection.accid.type'='integer',
  'projection.region.type'='enum', 
  'projection.region.values'='ap-northeast-2,us-east-1',
  'projection.year.digits'='4', 
  'projection.year.range'='2024,3000', 
  'projection.year.type'='integer',
  'projection.month.digits'='2', 
  'projection.month.range'='01,12', 
  'projection.month.type'='integer', 
  'projection.day.digits'='2', 
  'projection.day.range'='01,31', 
  'projection.day.type'='integer', 
  'projection.hour.digits'='2', 
  'projection.hour.range'='00,23', 
  'projection.hour.type'='integer',
  'projection.enabled'='true', 
  'skip.header.line.count'='1', 
  'storage.location.template'='s3://my-s3-arn/AWSLogs/aws-account-id=${accid}/aws-service=vpcflowlogs/aws-region=${region}/year=${year}/month=${month}/day=${day}/hour=${hour}')

 

이 문제는 아래와 같은 제약사항 때문에 발생한 것으로 추측됩니다.

accid000000000001에서 999999999999 까지의 범위로 지정했는데, 실제 S3 버킷에 저장되는 account id는 몇개 되지 않아 너무 많은 파티션이 빈값으로 쿼리 성능에 이슈가 생긴 것입니다.

 

이를 개선하기 위해서는 projection.accid.range 대신에 projection.accid.values를 사용하여 실제 존재하는 account id를 지정하는 방법도 있지만, 새로운 AWS 계정이 추가되었을 때 별도로 업데이트가 필요하여 번거로운 점이 있습니다. 따라서 partition projection 대신에 Glue Crawler를 사용해보겠습니다.

 

Glue Crawler 사용하기

Crawler는 data store를 기반으로 테이블을 생성하거나 업데이트할 수 있습니다.

자동으로 파티션을 추가하는 역할도 합니다.

미리 생성된 테이블이 없는 경우에는 crawler가 자동으로 생성하는 테이블을 사용할 수 있지만, 원하는 이름의 테이블을 만들수가 없어서 먼저 Athena에서 테이블을 만든 다음에 crawler를 설정해보겠습니다.

 

1) Athena 테이블 생성

CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs_parquet (
  `action` string, 
  `az_id` string, 
  `bytes` bigint, 
  `dstaddr` string, 
  `dstport` int, 
  `end` bigint, 
  `flow_direction` string, 
  `instance_id` string, 
  `interface_id` string, 
  `log_status` string, 
  `packets` bigint, 
  `pkt_dst_aws_service` string, 
  `pkt_dstaddr` string, 
  `pkt_src_aws_service` string, 
  `pkt_srcaddr` string, 
  `protocol` int, 
  `region` string, 
  `srcaddr` string, 
  `srcport` int, 
  `start` bigint, 
  `sublocation_id` string, 
  `sublocation_type` string, 
  `subnet_id` string, 
  `tcp_flags` int, 
  `traffic_path` int, 
  `type` string, 
  `version` int, 
  `vpc_id` string)
PARTITIONED BY ( 
  `aws-account-id` string, 
  `aws-service` string, 
  `aws-region` string, 
  `year` string, 
  `month` string, 
  `day` string, 
  `hour` string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  's3://my-s3-arn/AWSLogs/'

 

2) Glue Crawler 생성

  • 이름 입력

  • 앞서 생성한 테이블 선택

  • IAM role 선택

 

IAM role에는 아래와 같은 권한이 있으면 됩니다.

  • AWSGlueServiceRole (AWS Managed Policy 연결)
  • S3 버킷 접근 권한
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::my-s3-arn/AWSLogs*",
            ]
        }
    ]
}

 

  • 스케쥴 설정
    새로운 파티션을 주기적으로 업데이트 해야하기 때문에 1시간에 한번 실행되게 설정합니다.

 

  • crawler 실행
    on-demand로 실행하여 파티션을 정상적으로 생성하는지 확인합니다.

      정상적으로 실행되었다면, 테이블에 아래와 같이 파티션이 추가된 것을 확인할 수 있습니다.

      또한, 기존에 생성한 테이블을 SHOW CREATE TABLE vpc_flow_logs_parquet 로 확인해보면, crawler를 통해 아래와 같은 부분이 추가된 것을 확인할 수 있습니다.

TBLPROPERTIES (
  'CrawlerSchemaDeserializerVersion'='1.0', 
  'CrawlerSchemaSerializerVersion'='1.0', 
  'UPDATED_BY_CRAWLER'='test-crawler', 
  'averageRecordSize'='10', 
  'classification'='parquet', 
  'compressionType'='none', 
  'objectCount'='178270', 
  'recordCount'='26606576091', 
  'sizeKey'='283571743323', 
  'transient_lastDdlTime'='1707404685', 
  'typeOfData'='file')

 

 

crawler를 통해 새로운 파티션이 주기적으로 업데이트되기 때문에, 새롭게 적재된 vpc flowlogs도 Athena를 통해 조회할 수 있습니다.

728x90