tl;dr
- Amazon Aurora のスロークエリログを Logstash を使って Amazon ES に放り込みたい
- サーバーレスでやりたい場合には Lambda を利用する方法が既に紹介されている
- 今回はあえて logstash を使う
メモ
参考
- https://blog.theprogrammer.in/2014/11/aws-rds-mysql-slowquery-monitoring-on-kibana-using-logstash/
- http://dev.classmethod.jp/cloud/aws/rds-mysql-slowquerylog-to-es/
- https://www.elastic.co/guide/en/logstash/current/installing-logstash.html
- https://github.com/awslabs/logstash-output-amazon_es
ありがとうございますmm
Aurora のスロークエリログについて
ファイルに吐く場合に以下のような挙動となるようだ。
- slow_query_log を ON にすると一時間に一回 mysql-slowquery.log.YYYY-MM-DD.HH というログが生成される
- general_log を ON にすると mysql-slowquery.log というログが生成されてリアルタイムに確認出来る
今回は一時間に一回 cron でスロークエリログを API で取得して logstash 経由で Amazon ES に放り込むことにする。
試した構成
試す環境
$ cat /etc/redhat-release CentOS release 6.8 (Final) $ python -V Python 2.6.6 $ /opt/logstash/bin/logstash --version logstash 2.4.0 $ sudo /opt/logstash/bin/plugin list --installed --verbose logstash-output-amazon_es logstash-output-amazon_es (1.0)
logstash のインストール
$ sudo yum install -y java-1.8.0-openjdk.x86_64 $ sudo rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch $ sudo sh -c 'cat > /etc/yum.repos.d/logstash.repo [logstash-2.4] name=Logstash repository for 2.4.x packages baseurl=https://packages.elastic.co/logstash/2.4/centos gpgcheck=1 gpgkey=https://packages.elastic.co/GPG-KEY-elasticsearch enabled=1 EOT' $ sudo yum install -y logstash
logstash の Amazon ES プラグインの導入
$ cd /opt/logstash $ sudo bin/plugin install logstash-output-amazon_es
以下のように出力される。
The use of bin/plugin is deprecated and will be removed in a feature release. Please use bin/logstash-plugin. OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N Validating logstash-output-amazon_es Installing logstash-output-amazon_es Installation successful
SDK を利用してスロークエリログを取得する
#!/usr/bin/env python # -*- coding: utf-8 -*- import boto3 import sys import re from pytz import timezone from datetime import datetime # DB 名を指定 DBINSTANCEIDENTIFIER = 'oreno-aurora' # 不要な行 LINES = [ "/rdsdbbin/oscar/bin/mysqld, Version: 5.6.10-log (MySQL Community Server (GPL)). started with:", "Tcp port: 3306 Unix socket: /tmp/mysql.sock", "Time Id Command Argument" ] # 取得するログファイルの日付を生成 LOGDATETIME = datetime.now(timezone('UTC')).strftime("%Y-%m-%d.%H") # RDS への接続 rds = boto3.client('rds', region_name='ap-northeast-1') # ログの取得 try: body = rds.download_db_log_file_portion( DBInstanceIdentifier = DBINSTANCEIDENTIFIER, LogFileName = 'slowquery/mysql-slowquery.log.' + LOGDATETIME, )['LogFileData'] except Exception as e: print {'result': 'error', 'description': e} sys.exit (1) # 取得したログを一行ずつ展開(LINES に含まれる行と ^# Time: にマッチする行を削除) for line in body.split("\n"): if not line or line in LINES or re.match("^# Time:" , line): continue else: print line
EC2 に DownloadDBLogFilePortion ポリシーをアタッチする
既に適用済みの IAM role に DownloadDBLogFilePortion
ポリシーをアタッチする。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "RDSSlowLogDownloadPolicy", "Action": [ "rds:DownloadDBLogFilePortion" ], "Effect": "Allow", "Resource": "*" } ] }
試しにログを出力させてみる。
$ python rds-slow-log.py # User@Host: xxxxxxx[xxxxxxx] @ [xx.x.x.xxx] Id: 6 # Query_time: 7.000184 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0 SET timestamp=1477110716; SELECT SLEEP(7); (snip) # User@Host: xxxxxxx[xxxxxxx] @ [xx.x.x.xxx] Id: 48 # Query_time: 8.000187 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0 SET timestamp=1477112288; SELECT SLEEP(8); # User@Host: xxxxxxx[xxxxxxx] @ [xx.x.x.xxx] Id: 49 # Query_time: 11.000176 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0 SET timestamp=1477112330; SELECT SLEEP(11); # User@Host: xxxxxxx[xxxxxxx] @ [xx.x.x.xxx] Id: 50 # Query_time: 6.000193 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0 SET timestamp=1477112366; SELECT SLEEP(6);
logstash の設定
# input input { stdin { codec => multiline { pattern => "^# User@Host:" negate => true what => previous } } } # filter filter { grok { match => [ "message", "^# User@Host: %{USER:user}(?:\[[^\]]+\])?\s+@\s+\[%{IP:client}?\]\s+Id:\s+%{NUMBER:client_id:int}\n# Query_time: %{NUMBER:duration:float}\s*Lock_time: %{NUMBER:lock_wait:float}\s*Rows_sent: %{NUMBER:rows_sent:int}\s*Rows_examined: %{NUMBER:rows_examined:int}\nSET timestamp=%{NUMBER:timestamp};\n%{GREEDYDATA:sql_query};"] } date { match => [ "timestamp", "UNIX" ] } } # output output { # for Debug # stdout { codec => json } amazon_es { hosts => ["search-xxxxxxxxx.ap-northeast-1.es.amazonaws.com"] region => "ap-northeast-1" index => "rds_slow_log-%{+YYYY.MM.dd}" } file { path => "/path/to/rds_slow_log-%{+YYYY-MM-dd-HH}.json" } }
cron で実行
以下のようなラッパースクリプトを作成。
#!/usr/bin/env bash _LOG_DATE_TIME=$(date +%Y-%m-%d_%H) _DELETE_LOG_DATE=$(date --date '7 day ago' +%Y-%m-%d) _ROOT="/path/to/rds-slow-log" _LOGSTASH_CONF="rds-slow-log.conf" _LOGSTASH_LOG="rds-slow-log.log" ls ${_ROOT}/${_LOGSTASH_LOG}.${_DELETE_LOG_DATE}_* >/dev/null 2>&1 [ $? -eq 0 ] && rm -f ${_ROOT}/${_LOGSTASH_LOG}.${_DELETE_LOG_DATE}_* ${_ROOT}/bin/rds-slow-log.py | \ /opt/logstash/bin/logstash \ -f ${_ROOT}/conf/${_LOGSTASH_CONF} \ -l ${_ROOT}/log/${_LOGSTASH_LOG}.${_LOG_DATE_TIME}
cron は以下のように設定。
3 * * * * /path/to/rds-slow-log/bin/run.sh >/dev/null 2>&1
EC2 に Amazon ES へデータをポストする為のポリシーをアタッチする
既に適用済みの IAM role に ESHttpPost
ポリシーをアタッチする。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "es:ESHttpPost", "Resource": "arn:aws:es:*:*:*" } ] }
ダミーのクエリを仕込む
以下のようなスクリプトであえてスロークエリが発生するようにする。
while true; do sleep 30 TIME=`awk 'BEGIN{srand();print int(rand() * 15)}'` MYSQL_PWD="xxxxxxxxxxxx" mysql -udbadmin -h oreno-aurora-1.cluster-xxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com --execute "SELECT SLEEP(${TIME});" done
しばらくすると…
Kibana からスロークエリログが確認出来るようになる。
マッピングは適宜設定する必要がある。
以上
- メモでした
- 久し振りに Logstash を触った(改めて勉強し直したい)