Athena를 사용하여 Amazon S3 서버 액세스 로그를 분석하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2021년 12월 17일

Amazon Athena에서 Amazon Simple Storage Service(Amazon S3) 서버 액세스를 쿼리하는 방법은 무엇입니까?

해결 방법

Amazon S3에서는 서버 액세스 로그를 S3 버킷에 객체로 저장합니다. Athena를 사용하여 서버 액세스 로그를 빠르게 분석하고 쿼리할 수 있습니다.

1.    아직 활성화하지 않은 경우 S3 버킷에 대한 서버 액세스 로깅을 활성화합니다. Target bucket(대상 버킷)Target prefix(대상 접두사)의 값을 기록해 둡니다. Athena 쿼리에서 Amazon S3 위치를 지정하려면 이 두 개의 값이 모두 필요합니다.

2.    Amazon Athena 콘솔을 엽니다.

3.    쿼리 편집기에서 DDL 문을 실행하여 다음 데이터베이스를 생성합니다.
       참고: S3 버킷과 동일한 AWS 리전에 데이터베이스를 생성하는 것이 가장 좋습니다.

create database s3_access_logs_db

4.    데이터베이스에 테이블 스키마를 생성합니다. 다음 예에서 STRING BIGINT 데이터 형식 값은 액세스 로그 속성입니다. Athena에서 이 속성을 쿼리할 수 있습니다. [위치]에 1단계의 S3 버킷 및 접두사 경로를 입력합니다. 접두사 끝에 슬래시(/)를 포함해야 합니다(예: s3://doc-example-bucket/prefix/). 접두사를 사용하지 않는 경우 버킷 이름 끝에 슬래시(/)를 포함해야 합니다(예 s3://doc-example-bucket/).

CREATE EXTERNAL TABLE `s3_access_logs_db.mybucket_logs`(
  `bucketowner` STRING,
  `bucket_name` STRING,
  `requestdatetime` STRING,
  `remoteip` STRING,
  `requester` STRING,
  `requestid` STRING,
  `operation` STRING,
  `key` STRING,
  `request_uri` STRING,
  `httpstatus` STRING,
  `errorcode` STRING,
  `bytessent` BIGINT,
  `objectsize` BIGINT,
  `totaltime` STRING,
  `turnaroundtime` STRING,
  `referrer` STRING,
  `useragent` STRING,
  `versionid` STRING,
  `hostid` STRING,
  `sigv` STRING,
  `ciphersuite` STRING,
  `authtype` STRING,
  `endpoint` STRING,
  `tlsversion` STRING)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
  'input.regex'='([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$')
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://awsexamplebucket1-logs/prefix/'

5.    왼쪽 창의 [테이블]에서 테이블 이름 옆에 있는 메뉴 버튼의 [테이블 미리 보기]를 선택합니다. [결과(Results)] 창에 서버 액세스 로그의 데이터(예: bucketowner, bucketrequestdatetime)가 보이면 Athena 테이블을 성공적으로 생성한 것입니다. 이제 Amazon S3 서버 액세스 로그를 쿼리할 수 있습니다.

쿼리의 예

삭제된 객체에 대한 요청을 찾으려면 다음 쿼리를 사용합니다.

SELECT * FROM s3_access_logs_db.mybucket_logs WHERE
key = 'images/picture.jpg' AND operation like '%DELETE%';

403 Access Denied 오류를 발생시킨 요청에 대해 Amazon S3 요청 ID를 표시하려면 다음 쿼리를 사용합니다.

SELECT requestdatetime, requester, operation, requestid, hostid FROM s3_access_logs_db.mybucket_logs
WHERE httpstatus = '403';

특정 기간(키 및 오류 코드 포함)의 HTTP 5xx 오류에 대한 Amazon S3 요청 ID를 찾으려면 다음 쿼리를 실행합니다.

SELECT requestdatetime, key, httpstatus, errorcode, requestid, hostid FROM s3_access_logs_db.mybucket_logs
WHERE httpstatus like '5%' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:07:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-18:08:00:00','yyyy-MM-dd:HH:mm:ss');

객체를 삭제한 사람과 시간(타임스탬프, IP 주소 및 AWS Identity and Access Management(IAM) 역할)을 표시하려면 다음 쿼리를 사용합니다.

SELECT requestdatetime, remoteip, requester, key FROM s3_access_logs_db.mybucket_logs WHERE
key = 'images/picture.jpg' AND operation like '%DELETE%';

IAM 역할이 실행한 모든 운영을 표시하려면 다음 쿼리를 사용합니다.

SELECT * FROM s3_access_logs_db.mybucket_logs WHERE
requester='arn:aws:iam::123456789123:user/user_name';

특정 기간에 객체에 수행한 모든 운영을 표시하려면 다음 쿼리를 사용합니다.

SELECT SUM(bytessent) as uploadtotal,
SUM(objectsize) as downloadtotal,
SUM(bytessent + objectsize) AS total FROM s3_access_logs_db.mybucket_logs
WHERE remoteIP='1.2.3.4' AND 
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01','yyyy-MM-dd')
AND parse_datetime('2021-08-01','yyyy-MM-dd');

특정 기간 동안 IP 주소를 통해 전송한 데이터의 양을 표시하려면 다음 쿼리를 사용합니다.

SELECT SUM(bytessent) as uploadtotal,
SUM(objectsize) as downloadtotal,
SUM(bytessent + objectsize) AS total FROM s3_access_logs_db.mybucket_logs
WHERE remoteIP='1.2.3.4' AND 
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01','yyyy-MM-dd')
AND parse_datetime('2021-08-01','yyyy-MM-dd');

특정 기간에 수명 주기 규칙에 따라 수행한 모든 만료 운영을 표시하려면 다음 쿼리를 사용합니다.

SELECT *
FROM s3_access_logs_db.mybucket_logs
WHERE operation = 'S3.EXPIRE.OBJECT' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss');

특정 기간에 만료된 객체 수를 계산하려면 다음 쿼리를 사용합니다.

SELECT count(*) as ExpireCount
FROM s3_access_logs_db.mybucket_logs
WHERE operation = 'S3.EXPIRE.OBJECT' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss');

특정 기간에 수명 주기 규칙에 따라 수행한 모든 전환 운영을 표시하려면 다음 쿼리를 사용합니다.

SELECT * FROM s3_access_logs_db.mybucket_logs
WHERE operation like 'S3.TRANSITION%' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss');

서명 버전별로 그룹화된 모든 요청자를 표시하려면 다음 쿼리를 사용합니다.

SELECT requester, Sigv, Count(Sigv) as SigCount
FROM s3_access_logs_db.mybucket_logs
GROUP BY requester, Sigv;

특정 기간에 요청한 모든 익명 요청자를 표시하려면 다음 쿼리를 사용합니다.

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db.mybucket_logs
WHERE Requester IS NULL AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

특정 기간에 PUT 객체 요청을 보낸 모든 요청자를 표시하려면 다음 쿼리를 사용합니다.

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db
WHERE Operation='REST.PUT.OBJECT' AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

특정 기간에 GET 객체 요청을 보낸 모든 요청자를 표시하려면 다음 쿼리를 사용합니다.

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db
WHERE Operation='REST.GET.OBJECT' AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

특정 기간에 요청한 모든 익명 요청자를 표시하려면 다음 쿼리를 사용합니다.

SELECT Bucket, Requester, RemoteIP, Key, HTTPStatus, ErrorCode, RequestDateTime
FROM s3_access_logs_db.mybucket_logs
WHERE Requester IS NULL AND
parse_datetime(RequestDateTime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')

모든 요청자를 표시하려면 (특정 기간의 가장 높은 처리 시간을 기준으로 정렬됨) 다음 쿼리를 사용합니다.

SELECT * FROM s3_access_logs_db.mybucket_logs
NOT turnaroundtime='-' AND
parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2021-09-18:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-09-19:00:00:00','yyyy-MM-dd:HH:mm:ss')
ORDER BY CAST(turnaroundtime AS INT) DESC;

서버 액세스 로그 버킷의 수명 주기 정책을 생성하는 것이 가장 좋습니다. 주기적으로 로그 파일을 제거하도록 수명 주기 정책을 구성하십시오. 그러면 Athena에서 쿼리마다 분석하는 데이터의 양이 줄어듭니다.