Cloud & DevOps/AWS

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

백곰곰 2024. 2. 3. 12:30
728x90
반응형

VPC flow logs를 Athena로 조회하기 위한 설정 방법을 소개합니다.

 

VPC flow logs 설정

VPC flow logs를 S3에 저장할 때의 주요 설정 항목은 아래와 같습니다.

 

1.Log record format

VPC flow logs에 포함될 필드를 저장합니다. 모든 필드 저장 시 아래와 같이 log line format이 정해집니다.

 

${account-id} ${action} ${az-id} ${bytes} ${dstaddr} ${dstport} ${end} ${flow-direction} ${instance-id} ${interface-id} ${log-status} ${packets} ${pkt-dst-aws-service} ${pkt-dstaddr} ${pkt-src-aws-service} ${pkt-srcaddr} ${protocol} ${region} ${srcaddr} ${srcport} ${start} ${sublocation-id} ${sublocation-type} ${subnet-id} ${tcp-flags} ${traffic-path} ${type} ${version} ${vpc-id}

 

2.Log file format

Text/Parquet 중 선택할 수 있습니다. Parquet 선택 시 데이터 크기를 줄여 저장 비용을 절약할 수 있습니다.

 

3. Hive-compatible S3 prefix
Hive-compatible prefix는 아래와 같은 형태로 S3 오브젝트 prefix에 key=value 형태로 추가되는 것을 말합니다.

/aws-region=region/year=2024/month=02/day=03/...

 

      해당 형식이 요구되는 환경에서 활성화하여 사용하면 되고, Athena 에서는 이 형식도 지원합니다.

 

4. Partition logs by time

default 옵션 선택 시(Partition logs by time) S3에 저장되는 경로에는 년/월/일이 포함되지만, Every 1 hour 선택 시 년/월/일/시간 prefix를 포함하여 로그 저장이 가능합니다. VPC flow logs는 수집되는 데이터양이 많기 때문에 해당 옵션을 활성화하면 조금 더 세부적으로 파티셔닝이 가능해, 좁은 범위의 데이터를 스캔할 수 있습니다.

 

VPC flow logs 저장용 S3 버킷 설정

S3에 VPC flow logs 저장을 위해서는 아래 두개 권한 설정이 필요합니다.

  • IAM 권한
  • S3 버킷 policy 설정
    여러 계정의 로그를 하나의 버킷에 수집하기 아래처럼 S3 버킷 policy 설정이 필요합니다. 최근 S3 버킷 생성 시 기본적으로 ACL disabled 상태로 생성되기 때문에 ACL 관련 권한은 제외했습니다. 만약, ACL이 활성화된 버킷을 사용하는 경우에는 관련 설정도 필요합니다. 
    • 방법 1) account id 기반 허용
      허용 필요한 모든 account id를 기재해야합니다.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSLogDeliveryWrite",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetBucketAcl",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-s3-arn",
                "arn:aws:s3:::my-s3-arn/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [
                        "111111111111",
                        "222222222222",
                        "333333333333"
                    ]
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:logs:*:*:*"
                }
            }
        }
    ]
}

 

    • 방법 2) organization id 기반 허용
      organization에 속한 account들에서 로그를 저장할 수 있기 때문에 account id를 관리하지 않아도 됩니다.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSLogDeliveryWrite",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetBucketAcl",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-s3-arn",
                "arn:aws:s3:::my-s3-arn/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:SourceOrgID": "o-xxxxxxxx"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:logs:*:*:*"
                }
            }
        }
    ]
}

 

 

Athena 테이블 설정

위에 기재된 VPC flow logs 주요 설정을 아래와 같이 설정한 경우에 대해 Athena 테이블을 생성해보겠습니다.

1.Log record format : 모든 필드 활성화

2.Log file format : Parquet

3. Hive-compatible S3 prefix : Enable

4. Partition logs by time : Every 1 hour

 

위와 같이 설정 시 S3 버킷에는 아래와 같이 로그가 적재됩니다(별도 S3 prefix 미설정).

s3://my-s3-arn/AWSLogs/aws-account-id=111111111111/aws-service=vpcflowlogs/aws-region=ap-northeast-2/year=2024/month=02/day=03/hour=00/111111111111_vpcflowlogs_ap-northeast-2_fl-xxxxxxxxxxx_20240203T0000Z_xxxxxxxx.log.parquet

 

Athena 테이블 생성 시 오브젝트의 path를 고려하여 설정이 필요하기 때문에, 실제 path를 확인해야합니다.

또한, Log record format에 선택한 필드에 따라 Athena 테이블의 스키마 변경이 필요하기 때문에, 실제 체크한 필드를 반영해야합니다.

 

이제 해당 path에 적재된 로그를 조회하기 위한 Athena 테이블을 생성해보겠습니다.

  • 방법 1) 수동 파티션 관리
    • 테이블 및 파티션 업데이트
CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs_parquet (
  version int,
  account_id string,
  interface_id string,
  srcaddr string,
  dstaddr string,
  srcport int,
  dstport int,
  protocol bigint,
  packets bigint,
  bytes bigint,
  start bigint,
  `end` bigint,
  action string,
  log_status string,
  vpc_id string,
  subnet_id string,
  instance_id string,
  tcp_flags int,
  type string,
  pkt_srcaddr string,
  pkt_dstaddr string,
  region string,
  az_id string,
  sublocation_type string,
  sublocation_id string,
  pkt_src_aws_service string,
  pkt_dst_aws_service string,
  flow_direction string,
  traffic_path int
)
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/'
TBLPROPERTIES (
  'EXTERNAL'='true', 
  'skip.header.line.count'='1'
  )

  아래 명령어 실행 시 파티션 목록이 출력되면 정상 수행된 것입니다.

MSCK REPAIR TABLE vpc_flow_logs_parquet
SHOW PARTITIONS vpc_flow_logs_parquet

이 방법은 새로운 파티션 생성이 필요할 때마다(ex. 새로운 날짜 추가, account 추가 등) 파티션 로드 수행이 필요하다는 단점이 있습니다. 

  • 방법 2) 파티션 프로젝션
    위 방법의 단점을 해소하기 위해 자동 파티션 관리가 가능한 파티션 프로젝션을 사용하여 테이블을 생성해보겠습니다.
    해당 방식을 사용하면, 새로운 날짜에 데이터가 추가되어도 파티션 로드를 따로 하지 않아도 데이터 조회가 가능합니다.
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}')

 

accid에 실제 사용하는 계정만 설정하고 싶다면, range 대신 values로 설정할 수 있습니다.

참고로 해당 방식을 사용하면 별도로 테이블의 파티션이 보이지 않습니다.

728x90