LoginSignup
1
0

More than 3 years have passed since last update.

AWS RDSのログファイルを高速にダウンロードするスクリプト

Posted at

RDSのインスタンスに保存されているログをダウンロードする方法として、ググると download_db_log_file_portion を使う方法がたくさん出てきます。しかし、問題がありましたので、 downloadCompleteLogFile というAPIを使うスクリプトを書きました。

download_db_log_file_portion の問題点:

  • awscliだと途中で途切れる(ページネーションしても途切れてしまう)
  • APIを直接叩くにも細かく分割が必要で、ダウンロードに時間がかかる
  • 文字化けする(日本語の含まれる場合に ? に置き換えられてしまう)

downloadCompleteLogFileであればいずれの問題も解消します。

downloadCompleteLogFileにアクセスするスクリプト

downloadCompleteLogFile にアクセスするには自力でSigV4署名する必要があります。IAMユーザまたはIAMロールが必要です。

このPythonスクリプトはダウンロードするcurlコマンドをSigV4署名して作成します。Pythonスクリプト自身はダウンロードを実行しませんので、作成されたcurlコマンドをあとから実行する使い方です。

~/.aws/config, ~/.aws/credentials に適切な権限の設定があることが前提です。

import boto3
from botocore.awsrequest import AWSRequest
import botocore.auth as auth
import urllib.request

import pprint

profile     = "default"
instance_id = "database-1"
region = "ap-northeast-1"

session = boto3.session.Session(profile_name = profile)
credentials = session.get_credentials()
sigv4auth = auth.SigV4Auth(credentials, "rds", region)

rds_client = session.client('rds')
files = rds_client.describe_db_log_files(DBInstanceIdentifier = instance_id)

for file in files["DescribeDBLogFiles"]:
    file_name = file["LogFileName"]

    # ファイル名からダウンロード除外を判定
    if not file_name.startswith("error/"):
        continue
    if file_name == "error/postgres.log":
        continue

    # downloadCompleteLogFileのAPIのURL
    remote_host = "rds." + region + ".amazonaws.com"
    url = "https://" + remote_host + "/v13/downloadCompleteLogFile/" + instance_id + "/" + file_name

    # SigV4署名
    awsreq = AWSRequest(method = "GET", url = url)
    sigv4auth.add_auth(awsreq)

    req = urllib.request.Request(url, headers = {
        "Authorization": awsreq.headers['Authorization'],
        "Host": remote_host,
        "X-Amz-Date": awsreq.context['timestamp'],
       })

    # ダウンロード進捗用のechoコマンド
    echo_cmd = "echo '" + file_name + "' >&2"
    print(echo_cmd)

    # curlコマンド
    header = " ".join(["-H '" + k + ": " + v + "'" for (k, v) in req.headers.items()])
    cmd = "curl " + header + " '" + url + "'"
    print(cmd)

このPythonは次のような出力をします。

echo 'error/postgresql.log.2020-11-05-23' >&2
curl -H 'Authorization: AWS4-HMAC-SHA256 Credential=AKIAXXXXXXXXXXXXXXXX/20201105/ap-northeast-1/rds/aws4_request, SignedHeaders=host;x-amz-date, Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -H 'Host: rds.ap-northeast-1.amazonaws.com' -H 'X-amz-date: 20201105T231307Z' 'https://rds.ap-northeast-1.amazonaws.com/v13/downloadCompleteLogFile/database-1/error/postgresql.log.2020-11-05-23'

これをBashで実行します。

$ python download-rds-log.py | bash > log.txt

curlコマンドを出力しているので、並列実行などに改良することも可能です。改良しなくてもdownload_db_log_file_portionを使うよりはずっと高速です。

リンク

SigV4署名については以下の記事にも書きました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0