본문 바로가기

Monitoring/R&D

percona rds-exporter AWS API throttling issue

1. 배경

현재 재직 중인 회사에서는 오픈소스인 percona 사의 rds-exporter (https://github.com/percona/rds_exporter) 를 이용하여 RDS 의 enhanced monitoring 지표 (OS 지표) 를 수집하고 있다.

하지만 하나의 account + region 에 종속된 instance 가 많아질수록 API throttling 에러가 발생하며 지표 수집에 실패하는 빈도가 잦아졌다.

 

그래서 해당 이슈에 대한 원인 파악과 함께 대응 방안을 수립하기 시작했다.

 

 

2. 기존 방식의 문제점

1) API throttling 이 발생한 원인 

rds-exporter 는 CloudWatch Logs 에 속한 Log stream 중 하나인 "RDSOSMetric" 을 FilterLogEvents API 를 이용하여 call 한다.

API 이용 방식에는 문제가 없지만, 문제는 각 instance 별로 parallel 하게 call 을 한다는 것이다. 

 

AWS CloudWatch Logs 의 quota 와 관련된 manual 상 ap-northeast-2(아시아 서울) region 의 경우  "10 requests per second in the following Regions" 라고 명시되어있다.

이 지정된 10 requests per second 를 초과했기때문에 API Throttling 이 발생하고 있었다.

* CloudWatch Logs qouta document : https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html

 

2) CloudWatch Logs API quota 상향 불가

앞서 설명했듯이 rds-exporter 에서는 CloudWatch Logs 의 filterLogEvents API 를 이용한다.

하지만 CloudWatch Logs 에서 FilterLogEvents 를 포함한 지표를 스크랩할 수 있는 API 전부, AWS 측에 요청하여도 limitation 을 늘릴 수 없는 내부 프로그램에 명시된 hard limitation 이다. (상향 할 수 있는 API 는 간단한 정보들을 확인할 수 있는 describe 와 관련된 API 들이다.)

결국 AWS 측에서 이 qouta 를 상향시켜주지않는 한, 한 account + region에 종속된 instance 가 많아질수록 Throttling 현상을 구조적으로 회피할 수 없다.

 

3) 수집을 못해 발생하는 더 큰 문제

수집을 못하는 기간동안은 지표의 변동은 안생기겠지만, grafana 같은 visualizing 에 문제가 되지는 않는다.

하지만 가장 큰 문제는 수집에 실패한 기간에 CPU usage 같은 OS 지표가 critical 한 수치까지 올라가게되면 최대한 빠르게 대응을 해야하는데, 이 수치까지 올라갔는지에 대한 trigger 를 발생시킬 수 없다는 점이다.

수집을 못한 시점동안의 지표를 놓칠 수 있다는 점은 둘째치고, 가장 큰 문제는 문제 상황에 대한 빠른 인지가 안된다는 점이다.

 

 

3. 개선 시 고려할 점

1)

Enhanced monitoring 지표는 CloudWatchLogs 에 속한 Log Stream 인 "RDSOSMetric" 에만 남으니, CloudWatch Logs 의 API 만을 이용해야한다.

또한 기존 방식의 근본적 문제점인 동시에 여러 개의 API 를 call 하는 현상을 만들지말아야한다.

2)

현재 metric 을 수집하고 있는 DB 를 prometheus (혹은 victorimaMetrics) 와 같은 시계열 DB 를 이용하고 있다.

따라서 prometheus 의 API 규격에 맞춰 metric 을 endpoint 에 업로드해야한다.

3)

Agent 는 항상 최신의 metrics 를 endpoint 에 올려두고 있어야한다.

key 값 (instance + metric) 에 대한 value 가 주기적으로 최신화 되어야한다. (내부 설정 주기에 맞춰서 지속적으로 데이터를 업데이트 해야함)

4)

사용 패턴이 다양할 수 있으니, 기존의 pull 방식 외에도 exporter 에서 직접 time series database 로 push 할 수 있는 방식을 도입한다.

 

4. 구현 방식

리서치 중 CloudWatch Logs 기능 중의 하나인 "Logs Insights queries"  라는 기능을 확인했고 위와 같은 고려할 점들을 다 수용하는 방식으로 판단했다.

StartQuery API 는 요약하면, 특정 LogSteam 에 특정 time range 와 특정 조건을 명시하여 query 를 한다. 

https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_StartQuery.html

 

StartQuery 를 통해 API 를 실행하게되면 Query ID 를  result set 을 주게되는데, 이 Query ID 를 이용하여 GetQueryResult API 를 수행하게되면 실제 query 가 수행한 결과 값을 볼 수 있다.

https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_GetQueryResults.html

$ aws logs start-query --log-group-name RDSOSMetrics --start-time 1659608469000 --end-time 1659608529000 --query-string "fields @message"
{
    "queryId": "cbb85d23-21fe-42f9-98eb-e7c8c5583cc8"
}

$ aws logs get-query-results --query-id cbb85d23-21fe-42f9-98eb-e7c8c5583cc8
{
    "status": "Complete",
    "statistics": {
        "recordsMatched": 196.0,
        "recordsScanned": 493.0,
        "bytesScanned": 4972327.0
    },
    "results": [
        [
            {
                "field": "@message",
                "value": "{\"engine\":\"Aurora\",\"instanceID\":\"instancename\",\"instanceResourceID\", ...
...
...
...
            }
         ]
    ]
}

 

 

5. 새로운 구현 방식의 장점

1) API call 빈도 저하

기존 방식의 API Call 은 매 스크랩주기마다 instance 대수만큼 호출해야한다. 

하지만 새로운 방식은 매 스크랩 주기에 하나의 account + region 별로 start query 1번과 get query result 1번만 수행하면 된다.

따라서 API throttling 에 대한 제약에서 완전히 벗어날 수 있다.

 

2) API call 비용

manual 상에서 seoul region 의 경우 $0.0076 per GB of data scanned 의 price 를 확인할 수 있다. (https://aws.amazon.com/cloudwatch/pricing/?nc1=h_ls)

위 예제처럼 196대의 instance 를 수집했을 때,  "bytesScanned": 4972327.0 대략 4.7MB 정도를 스캔하는 것을 확인할 수 있다.

이는 기존의 비용에 비해 현저하게 적은 비용을 사용하게 된다.

 

수집 주기를 scrap interval 15초 정도로 설정하였을 때, 하루에 5760번 호출을 한다. 

하루에 instance 200대를 기준으로 5MB * 5760 = 28800MB 정도를 스캔을 할 것이고, 

28GB * 0.0076$ = 0.2128$ 

대략적으로 하루에 약 0.2~0.3$ 를 사용하게된다. 

 

3) 편리한 관리 방식

하나의 account + region 에 대해 1개의 agent 만 실행하면 된다. 

즉 기존에는 하나의 account + region 이라도, 200대의 instance 가 존재하면 200대의 agent 를 띄워야하는 방식이었다면 이 방식에서는 1대만 띄우면 된다.

결국 관리해야할 agent 의 총 대수는 "관리하고 있는 account + region 대수" 와 동일하다.

 

 

6. Architecture

 

 

7. Project source

https://github.com/wooseok22/rds-enhanced-exporter