시작 전
- 이번엔 Zabbix에서 RDS의 CPU와 RAM 사용률, 가용률 모니터링이 필요했다.
- RDS는 MS-SQL DB를 설치해서 사용중이다.
- 모니터링에 사용되는 액세스키, 비밀키의 사용자는 ReadOnlyAccess 이상의 권한을 가져야한다.
- 사용된 모든 액세스 키 정보는 ReadOnlyAccess 권한만 가진 모니터링 전용 Server_moniroting 사용자이다.
작업
1. RDS의 CPU , RAM 정보 찾기
- 1) RDS의 CPU, RAM에 대한 정보를 boto3를 통해 가져오기 위해 구글링을 진행하던 중 RDS 확장 모니터링에 대한 문서를 찾았다.
- 2) DB 인스턴스 확장 모니터링 탭에서 MS-SQL 및 다양한 RDB의 정보를 CloudWatchLogs를 통해 제공하는 문서를 확인했다.
2. CloudWatchLogs를 활용하는 방법
- 1) RDS를 생성할 때 '모니터링' 옵션을 다음과 같이 체크한 경우 이미 CloudWatch Logs로 로그를 수집하고, 체크하지 않았다면 RDS 수정을 통해 체크하면 된다. (CloudWatch에 대한 소량의 비용이 발생할 수 있다.)
- 2) CloudWatch Logs에서 위 설정으로 아래 사진과 같은 로그 그룹이 자동 생성된다.
3. CloudWatch Logs Insight 에서 원하는 값을 쿼리할 수 있는지 확인
- 1) CloudWatch → 로그 → 인사이트에서 로그 그룹 'RDSOSMetrics'를 선택하고 쿼리를 실행한다.
- 2) 쿼리 코드 : disk 잔량 비율, memory 전체량, memory 잔량을 가장 최근 log 1개만 쿼리한다.
fields disks.0.availPc, memory.physTotKb, memory.physAvailKb, @timestamp | sort @timestamp desc | limit 1
- 3) 쿼리 결과 원하는 값들이 출력됐다. disks.0.availPc는 잔량 비율이기 때문에 바로 사용이 가능하고, 2개의 memory 값을 가공하여 RAM 비율 정보로 사용할 수 있을 것이다.
4. boto3와 python을 통해 CloudWatchLogs 쿼리하기
- 1) Logs Insight에서 쿼리한 값이 boto3를 통해서도 쿼리되는지 확인
#boto3 사용환경 필요하고 이 파일과 같은 위치에 get-pip.py 파일이 있어야한다. #!/usr/bin/python import boto3 import time from datetime import datetime, timedelta #boto3를 사용하기 위해 client 정보입력 client = boto3.client('logs', aws_access_key_id="[액세스 키]", aws_secret_access_key="[비밀 키]", region_name="ap-northeast-2") #CloudWatch Logs 쿼리 query = "fields disks.0.availPc, memory.physTotKb, memory.physAvailKb, @timestamp | sort @timestamp desc | limit 1" log_group = 'RDSOSMetrics' start_query_response = client.start_query( logGroupName=log_group, startTime=int(time.time()-3600), endTime=int(time.time()), queryString=query, ) query_id = start_query_response['queryId'] response = None while response == None or response['status'] == 'Running': time.sleep(1) response = client.get_query_results( queryId=query_id ) #쿼리 결과 출력 print(response.get('results')) #------------------------------구분선----------------------------------- #출력 결과 - 리스트 내부에 리스트 내부에 딕셔너리 형태로 쿼리 반환 [ [ {'field': 'disks.0.availPc', 'value': '99.88'}, {'field': 'memory.physTotKb', 'value': '8080988'}, {'field': 'memory.physAvailKb', 'value': '6170956'}, {'field': '@timestamp', 'value': '2021-01-26 02:30:39.000'}, {'field': '@ptr1-01-26 02:30:39.000'}, {'field': '@ptr', 'value': 'ClgKHQoZNjMwNTYzMTY3NTQ1OlJEU09TTWV0cmljcxAEEjcaGAIGAIlGRAAAAAAYZe6kAAYA9+YwAAACQiABKJixneTzLjCYsZ3k8y44AUCBPEje4AFQy6cBEAAYAQ=='} ] ]
- 1) Logs Insight에서 쿼리한 값이 boto3를 통해서도 쿼리되는지 확인
5. 쿼리 결과 중 원하는 값만 출력하기
- 1) 앞서 작성한 코드의 #쿼리 결과 출력 부분을 다음과 같이 변경 후 실행 및 결과
#쿼리 결과 출력 부분 변경 - 리스트 한겹 벗기기 datapoints = response.get('results') print(datapoints[0]) #------------------------------구분선----------------------------------- #결과 - 리스트 한겹 벗겨짐 [ {'field': 'disks.0.availPc', 'value': '99.88'}, {'field': 'memory.physTotKb', 'value': '8080988'}, {'field': 'memory.physAvailKb', 'value': '6173876'}, {'field': '@timestamp', 'value': '2021-01-26 04:04:39.000'}, {'field': '@ptr', 'value': 'ClgKHQoZNjMwNTYzMTY3NTQ1OlJEU09TTWV0cmljcxAFEjcaGAIF/54AawAAAABCWqI4AAYA+UVgAAADsiABKNjP9ebzLjDYz/Xm8y44AUD8O0ik4AFQkacBEAAYAQ=='} ]
- 2) 모니터링을 위해 정확히 원하는 값만 출력
#boto3 사용환경 필요하고 이 파일과 같은 위치에 get-pip.py 파일이 있어야한다. #!/usr/bin/python import boto3 import time from datetime import datetime, timedelta #boto3를 사용하기 위해 client 정보입력 client = boto3.client('logs', aws_access_key_id="[액세스 키]", aws_secret_access_key="[비밀 키]", region_name="ap-northeast-2") #CloudWatch Logs 쿼리 query = "fields disks.0.availPc, memory.physTotKb, memory.physAvailKb, @timestamp | sort @timestamp desc | limit 1" log_group = 'RDSOSMetrics' start_query_response = client.start_query( logGroupName=log_group, startTime=int(time.time()-3600), endTime=int(time.time()), queryString=query, ) query_id = start_query_response['queryId'] response = None while response == None or response['status'] == 'Running': time.sleep(1) response = client.get_query_results( queryId=query_id ) #쿼리 결과 정제 datapoints = response.get('results') rds_info1 = datapoints[0] for item in rds_info1: if item.get('field') == 'disks.0.availPc': #disk 사용률 CpuAvailRate = item.get('value') elif item.get('field') == 'memory.physTotKb': #memory 전체 용량 TotalMemory = float(item.get('value')) elif item.get('field') == 'memory.physAvailKb': #memory 남은 용량 AvailMemory = float(item.get('value')) #결과 출력 print(CpuAvailRate,TotalMemory,AvailMemory) #------------------------------구분선----------------------------------- #출력 화면 - 성공적으로 Zabbix에서 모니터링 할 형태의 값만 출력했다. 99.88 8080988.0 6180028.0
- 1) 앞서 작성한 코드의 #쿼리 결과 출력 부분을 다음과 같이 변경 후 실행 및 결과
6. 입력값에 따라 원하는 값만 출력하기
- 1) metric 옵션을 생성하여 원하는 값을 입력받고 출력하기
#!/usr/bin/python import boto3 import time from datetime import datetime, timedelta from optparse import OptionParser ##Connection## #옵션 값을 지정 parser = OptionParser() parser.add_option("-a", "--access-key", dest="access_key", help="AWS Access Key") parser.add_option("-k", "--secret-key", dest="secret_key", help="AWS Secret Access Key") parser.add_option("-r", "--region", dest="region", help="RDS region") parser.add_option("-m", "--metric", dest="metric", help="RDS cloudwatch metric") #옵션 값들을 options에 저장 (options, args) = parser.parse_args() #필수값 받기 if (options.metric == None): parser.error("-m RDS cloudwatch metric is required") #메트릭 옵션의 범위 지정 metrics = { "DiskAvailRate":{"type":"float", "value":None}, "DiskUsedRate":{"type":"float", "value":None}, "RAMAvailRate":{"type":"float", "value":None}, "RAMUsedRate":{"type":"float", "value":None} } # 액세스키가 있으면 not 1 -> 0 / 비밀키가 있으면 not 1 -> 0 # 즉 키가 모두있으면 0or0=0 -> use_roles=False / 키가 하나라도 없으면 use_roles=True if not options.access_key or not options.secret_key: use_roles = True else: use_roles = False #위의 use_roles 기반으로 키가 둘다있으면 client에 키값과 리전을 입력 if use_roles: client = boto3.client('logs', region_name=options.region) else: client = boto3.client('logs', aws_access_key_id=options.access_key, aws_secret_access_key=options.secret_key, region_name=options.region) #쿼리 query = "fields disks.0.availPc, memory.physTotKb, memory.physAvailKb, @timestamp | sort @timestamp desc | limit 1" log_group = 'RDSOSMetrics' start_query_response = client.start_query( logGroupName=log_group, startTime=int(time.time()-7200), endTime=int(time.time()), queryString=query, ) query_id = start_query_response['queryId'] response = None while response == None or response['status'] == 'Running': time.sleep(1) response = client.get_query_results( queryId=query_id ) #쿼리 결과 정제 datapoints = response.get('results') rds_info1 = datapoints[0] for item in rds_info1: if item.get('field') == 'disks.0.availPc': DskAvailRate = item.get('value') elif item.get('field') == 'memory.physTotKb': TotalMemory = float(item.get('value')) elif item.get('field') == 'memory.physAvailKb': AvailMemory = float(item.get('value')) #출력 형변환 및 소숫점 지정 RAR=round(float(AvailMemory/TotalMemory)*100,2) DAR=round(float(DskAvailRate),2) #옵션 입력값에 따라 출력하기 if options.metric in metrics.keys(): if options.metric == 'DiskAvailRate': print(DAR) elif options.metric == 'DiskUsedRate': print(100-DAR) elif options.metric == 'RAMAvailRate': print(RAR) elif options.metric == 'RAMUsedRate': print(100-RAR)
- 2) 실행 코드 및 출력 결과
python
test.py
"--metric" "RAMAvailRate" "--access-key" "액세스키" "--secret-key" "비밀키" "--region" "ap-northeast-2"
입력
- 1) metric 옵션을 생성하여 원하는 값을 입력받고 출력하기
7. 자빅스 서버에 파일 넣기
- 1) rds_disk_ram.py 이름으로
/usr/lib/zabbix/externalscripts/
경로에 넣어주기
- 2)
chown zabbix:root rds_disk_ram.py
명령으로 권한변경 (따로 zabbix 그룹이 없다면 root:root로 진행)
- 1) rds_disk_ram.py 이름으로
8. Zabbix 템플릿에 Item 추가
- 1) 템플릿에 이미 Key와 Region값이 들어가 있다. 아래 사진과 같이 입력 후 Item 생성
- 2) 결과 확인
에러
- 윈도우에선 출력되는데 Zabbix서버에서 에러가 나는 경우
- timestamp가 python 2. 버전을 지원하지 않아서 다른 함수로 startTime, endTime을 정의해줘야함 (time.time())
- 윈도우,리눅스에선 실행되는데 Zabbix에서 읽어오지 못하는경우 (to many arguments 오류)
#!/usr/bin/python
파이썬 파일 시작시 선언했는지 확인
- 윈도우에선 출력되는데 Zabbix서버에서 에러가 나는 경우
결과
- 기존 스크립트로 모니터링 하지 못한 지표도 boto3와 AWS에서 제공하는 지표를 토대로 Python 파일을 수정하여 모니터링이 가능하다.
- 개발자가 아니더라도 코드에 대한 기본적인 사용법을 익히면 엔지니어링, 모니터링, 솔루션과 같은 다양한 분야에서 편의성이 증가한다는 걸 체감했다. (원래도 머리로는 알고 있었는데 실제로 겪어보니 더 와닿는다.)
Uploaded by Notion2Tistory v1.1.0