タダです.
AWS 利用料のうち CloudWatch Logs への取り込みが高くかかっていました( DataProcessing-Bytes
という項目).そこで,下記のページを参照して調べてみたところ一番容量があったのが Aurora のログでした.そのログを CloudWatch Logs に出力せずダウンロードし,S3 などにアップロードしていけばコスト削減に繋がりそうです.この記事では,ダウンロードを Python でやってみた内容をまとめていきます.
Python で RDS ログダウンロードのための手段
boto3 のドキュメントを見てみたらログダウンロードをするのに, download_db_log_file_portion
があります.ただし,説明に記載のようにこの API では 1MB までのダウンロードになると記載があるため,別のアプローチを調べてみました.
Downloads all or a portion of the specified log file, up to 1 MB in size
調べてみたところ, DownloadCompleteLogFile
を使って REST API でのダウンロードであれば,容量制限もドキュメントに記載がなくダウンロードできそうなため,この手法を使ってみることにしました.
DownloadCompleteLogFile でのログダウンロードを試してみる
Python でログをダウンロードするコードを書いてみました.SigV4 署名での GET リクエストをダウンロードしたい DB インスタンスのログごとに実行します.そのため,download_rds_logfile
関数を実行する時に対象の DB インスタンスとファイルを get_db_instance_identifiers
と get_log_file_names_from_aurora
で抽出しています.また,デフォルトだとログファイル名を1000件しか取得できないため,Pagenation で全件取得するようにしています.ログダウンロードのリクエストを投げた後に tempfile に書き出しており,このファイルをそのまま S3 にアップロードしたりもできます.
import boto3 from botocore.awsrequest import AWSRequest import botocore.auth as auth import requests import tempfile region = 'ap-northeast-1' session = boto3.session.Session() rds_endpoint = 'rds.' + region + '.amazonaws.com' rds = boto3.client('rds') parser = argparse.ArgumentParser() parser.add_argument('aurora_cluster_name', type=str) args = parser.parse_args() aurora_cluster_name = args.aurora_cluster_name def get_db_instance_identifiers(aurora_cluster_name: str) -> list[str]: target_db_instance_identifiers = [] response = rds.describe_db_clusters(DBClusterIdentifier=aurora_cluster_name) members = response['DBClusters'][0]['DBClusterMembers'] for member in members: target_db_instance_identifiers.append(member['DBInstanceIdentifier']) return target_db_instance_identifiers def get_log_file_names_from_aurora(db_instance_identifier: str) -> list[str]: download_log_files = [] describe_db_log_files_pagenator = rds.get_paginator('describe_db_log_files') describe_db_log_files_page_iterator = describe_db_log_files_pagenator.paginate(DBInstanceIdentifier = db_instance_identifier) for describe_db_log_files_page in describe_db_log_files_page_iterator: for describe_db_log_file in describe_db_log_files_page['DescribeDBLogFiles']: download_log_files.append(describe_db_log_file['LogFileName']) def download_rds_logfile(db_instance_identifier:str, log_file_name:str, region:str, rds_endpoint:str) -> str: download_complete_logfile_url = 'https://' + rds_endpoint + '/v13/downloadCompleteLogFile/' + db_instance_identifier + '/' + log_file_name credential = session.get_credentials() awsreq = AWSRequest(method = 'GET', url = download_complete_logfile_url) sigv4auth = auth.SigV4Auth(credentials, 'rds', region) sigv4auth.add_auth(awsreq) res = requests.get(download_complete_logfile_url, stream=True, headers={ 'Authorization': awsreq.headers['Authorization'], 'X-Amz-Date': awsreq.context['timestamp'], 'X-Amz-Security-Token': credential.token }) log_file_content = res.text res.close return log_file_content def main(): db_instance_identifiers = get_db_instance_identifiers(aurora_cluster_name) for db_instance_identifier in db_instance_identifiers: log_file_names = get_log_file_names_from_aurora(db_instance_identifier) for log_file_name in log_file_names: with download_rds_logfile(db_instance_identifier, log_file_name, region, rds_endpoint) as log_file_content: with tempfile.NamedTemporaryFile(dir=".",mode='w') as fp: fp.write(log_file_content) fp.seek(0) if __name__ == '__main__': main()
まとめ
Python で Aurora の各種ログをダウンロードする処理を書く経験したのでまとめました.