AWS에서 제공하는 Athena 서비스에 대해 간단히 알아보겠습니다. Athena는 파일에 저장된 텍스트 데이터를 SQL문으로 질의할 수 있도록 기능을 제공하는 AWS 서비스입니다.
“텍스트 파일의 내용을 조회할 때 DB Table 조회하듯이 SQL문을 사용해 검색을 하면 편리하지 않을까?”
현실에서는 보통 이러한 작업을 할 때 awk, sed등의 linux command를 이용하여 파일 내의 문자열을 파싱하거나 복잡한 경우 shell script, regular expression등을 조합하여 해당 작업을 수행하였을 것입니다.
그런데 이런식으로 구성된 대량의 파일을 여러가지 조건으로 분석해야 할 경우는 어떻게 해야 할까요?
대용량 DBMS를 구축하고 대용량의 파일을 읽어 저장하는 프로그램을 만들어야 할까요?
AWS에서 제공하는 Athena를 이용하면 이러한 요구조건을 쉽게 충족할 수 있습니다. Athena는 여러 가지 제약이 있지만 고정된 규칙의 형태로 저장된(예를 들면 csv같은) 대량의 파일에 대해서 분석이 필요할 경우 유용하게 사용할 수 있는 서비스입니다.
Athena 사용시 장점
- 파일에 저장된 데이터를 분석하기 위해 DBMS를 추가적으로 구축할 필요가 없습니다. 데이터가 저장되는 스토리지 비용+쿼리당 비용만 지불하면 되므로 RDBMS에 비해 훨씬 많은 비용을 절감할 수 있습니다.
- DBMS가 필요하지 않으므로 대용량 데이터를 다룰 인력과 인프라 관리에 필요한 시간 및 인적 자원을 아낄 수 있습니다.
- Athena는 기본적으로 s3에 업로드된 파일을 읽어 분석할 수 있으므로, 거의 무제한에 가까운 데이터에 대한 분석이 가능합니다.
- 데이터 파티셔닝을 제공하기 때문에 대용량 데이터에서 요청한 데이터를 빠른 시간안에 조회할 수 있습니다.
- athena를 사용하면 생성한 데이터베이스/테이블간에 Join을 통한 결과 조회가 가능합니다.
Athena 사용시 단점
- 질의 속도가 DBMS 보다는 느리므로 실시간 데이터를 다루는 Frontend에는 사용하기 어렵고 Backend에서 대용량 데이터 추출 및 분석하는 용도로 적합합니다.
- 대용량의 파일을 질의하는데 목적이 있으므로 SELECT, INSERT 기능만 사용가능하며 UPDATE, DELETE 기능은 제공하지 않습니다. 따라서 지속적으로 자주 변경되거나 삭제되는 데이터를 다루는데는 Athena가 적합하지 않습니다.
Athena 사용예시 – Accesslog 분석
alb log 활성화
aws elb를 사용중이라면 accesslog를 s3로 바로 보낼 수 있습니다.
EC2 – Loadbalancers : 활성화할 elb선택 후 Description 탭에서 Configure access logs를 선택하여 s3로 로그를 쌓도록 설정합니다.
위와 같이 생성을 하면 Interval 기간이 지난후에 s3의 아래위치에 데이터가 쌓인것을 확인할 수 있습니다.
s3://[bucketName]/AWSLogs/[AccountId]/elasticloadbalancing/[year]/[month]/[day]/[로그파일].log
athena database/table 생성
athena를 처음 사용하는 것이면 query result가 저장되는 s3 location을 지정해 줍니다.
s3 – Settings
Database 생성
기존에 생성되어 있는 default db를 사용해도 됩니다. 하지만 데이터의 구분을 위해 database를 아래 명령으로 생성합니다.
create database alb_db
Table 생성
CLB(Classic Load Balancer), ALB(Application Load Balancer)의 AccessLog 테이블 스키마가 다르므로 확인 후 테이블을 생성합니다.
CLB
https://docs.aws.amazon.com/ko_kr/athena/latest/ug/elasticloadbalancer-classic-logs.html
CREATE EXTERNAL TABLE IF NOT EXISTS alb_db.elb_logs ( timestamp string, elb_name string, request_ip string, request_port int, backend_ip string, backend_port int, request_processing_time double, backend_processing_time double, client_response_time double, elb_response_code string, backend_response_code string, received_bytes bigint, sent_bytes bigint, request_verb string, url string, protocol string, user_agent string, ssl_cipher string, ssl_protocol string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '1', 'input.regex' = '([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \\\"([^ ]*) ([^ ]*) (- |[^ ]*)\\\" (\"[^\"]*\") ([A-Z0-9-]+) ([A-Za-z0-9.-]*)$' ) LOCATION 's3://your_log_bucket/prefix/AWSLogs/AWS_account_ID/elasticloadbalancing/';
ALB
https://docs.aws.amazon.com/athena/latest/ug/application-load-balancer-logs.html
CREATE EXTERNAL TABLE IF NOT EXISTS alb_db.alb_logs ( type string, time string, elb string, client_ip string, client_port int, target_ip string, target_port int, request_processing_time double, target_processing_time double, response_processing_time double, elb_status_code string, target_status_code string, received_bytes bigint, sent_bytes bigint, request_verb string, request_url string, request_proto string, user_agent string, ssl_cipher string, ssl_protocol string, target_group_arn string, trace_id string, domain_name string, chosen_cert_arn string, matched_rule_priority string, request_creation_time string, actions_executed string, redirect_url string, lambda_error_reason string, target_port_list string, target_status_code_list string, classification string, classification_reason string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '1', 'input.regex' = '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) ([^ ]*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\s]+?)\" \"([^\s]+)\" \"([^ ]*)\" \"([^ ]*)\"') LOCATION 's3://your-alb-logs-directory/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<REGION>/';
조회(clb)
해당 월에 쌓인 로그 개수 확인
SELECT count(*) FROM "alb_db"."alb_logs" where year='2021' and month='07';
해당 월에 가장 많이 호출된 api 확인
SELECT request_verb, url_extract_path(url), count(*) FROM "alb_db"."alb_logs" where year='2021' and month='07' group by request_verb, url_extract_path(url) order by count(*) desc limit 10;
해당월에 응답 실패한 api 확인
SELECT request_verb, url_extract_path(url), elb_response_code, count(*) FROM "alb_db"."alb_logs" where year='2021' and month='07' and elb_response_code != '200' group by request_verb, url_extract_path(url), elb_response_code having count(*) > 1 order by count(*) desc limit 5;