apacheのaccess_logをjson化しtd-agentで集約サーバへ収集する
apacheのaccess_logを構築した集約サーバへ収集する必要があり、そのついでに解析しやすいようjson化設定したのでメモ。
apacheログをjson化する要件が発生した場合汎用性がありそうなので、調査・対応を下記へ記載しておく。
apacheのconfファイルにjsonフォーマット指定追加
# vi http.conf // フォーマット指定 LogFormat "{\"timestamp\":\"%{%Y-%m-%dT%H:%M:%S}t.%{msec_frac}t%{%z}t\", \"remote_ip\":\"%a\", \"port\":%{local}p, \"local_ip\":\"%A\", \"httpHost\":\"%v\", \"reqTime\":\"%T\", \"reqStatus\":%>s, \"protocol\":\"%H\", \"bytes_sent\":%O, \"bytes_received\":%I, \"reqTime\":%D, \"file_path\":\"%f\", \"query\":\"%q\", \"method\":\"%m\", \"reqURL\":\"%U\", \"request\":\"%r\", \"ua\":\"%{User-Agent}i\", \"referrer\":\"%{Referer}i\"}" json //カスタムログにてログ出力 CustomLog /usr/local/apache2/logs/test.com_ssl_access.443.json.log json
以下td-agent2環境fluentd v0.12以降のバージョン
向けの設定例
# vi apache.access.conf <source> @id in_apache_http_com_json @type config_expander <config> @type tail path /usr/local/apache2/logs/test.com_ssl_access.443.json.log pos_file /var/log/td-agent/in.apache.com.access.443.json.pos read_from_head true keep_time_key true refresh_interval 1s format json time_key time time_format %Y-%m-%dT%H:%M:%S keep_time_key true tag test.apache.access @label @testserver </config> </source>
後は、上記ファイルをtd-agent.confで@includeし、送信設定(forward)すれば送信される。
※必要に応じてローテート設定行う
# vi /etc/logrotate.d/apache /usr/local/apache2/logs/*.log { daily rotate 30 compress missingok notifempty sharedscripts postrotate /usr/local/apache2/bin/apachectl graceful > /dev/null 2>/dev/null || true endscript }
ref)
shで日時バックアップscript
shellで日時バックアップ処理を行う必要があった為、設定時メモ。
- 以下構築条件
- デイリーバックアップ
- 圧縮必須
- suffixが日時のみ処理
- 開始・終了時刻が記載
本条件でshell scriptを書いた
#!/bin/sh set -e readonly SCRIPT_NAME=${0##*/} readonly HISTORY=/root/logrotate/history.log LOG_DATE_FORMAT(){ echo `date '+%Y/%m/%d %H:%M:%S %a'` } echo `LOG_DATE_FORMAT` `hostname -s` ${SCRIPT_NAME}[$$]: START >> ${HISTORY} #: "テスト" && { # echo 今日の日付 … $(date +'%Y-%m-%d %H:%M') # echo 更新日が1日以上過去のファイルを探す: && # find /data/td-agent/ -type f -mtime +0 -regextype posix-basic -regex ".*[0-9]\{4\}[0-9]\{1,2\}[0-9]\{1,2\}" # find /data/td-agent/ -not -name "*.gz" -type f -mtime +0 -regextype posix-basic -regex ".*[0-9]\{4\}[0-9]\{1,2\}[0-9]\{1,2\}.*" # echo 更新日が2日以上過去のファイルを探す: && # find /data/td-agent/ -not -name "*.gz" -type f -mtime +1 # echo 更新日が3日以上過去のファイルを探す: && # find /data/td-agent/ -not -name "*.gz" -type f -mtime +2 #} /bin/find /var/td-agent/store/ -not -name "*.gz" -type f -mtime +0 -regextype posix-basic -regex '.*[0-9]\{4\}[0-9]\{1,2\}[0-9]\{1,2\}' -exec gzip {} \; /bin/find /var/td-agent/store/ -name "*.gz" -type f -mtime +1 -exec rm {} \; echo `LOG_DATE_FORMAT` `hostname -s` ${SCRIPT_NAME}[$$]: STOP >> ${HISTORY} exit 0
後は、cronなりで起動設定すればバックアップされる。
td-agentのbuffer_path重複障害
td-agentを起動した場合、buffer_path指定でエラー発生し、嵌ったので設定時メモ。
sourceディレクティブが複数あり、各tagを指定してサーバへ送信している環境。
- 以下構築条件
- 各sourceディレクティブでtag指定
- sourceディレクティブでtag名重複は無い
- サーバ側で他へforwardする
- buffer_pathの出力先は他と共用は無い
- buffer_path出力先に{tag}.*を指定
■現象
本条件でtd-agent.logに以下エラーが発生する
2018-07-12 10:06:32 +0900 [error]: Cannot output messages with tag 'www.nginx.access.80-json' 2018-07-12 10:06:33 +0900 [error]: failed to configure sub output copy: Other 'secure_forward' plugin already use same buffer_path: type = secure_forward, buffer_path = /var/td-agent/buffer/secure-forward_www.nginx.access.80-json.*
tag名に重複無く「already use same buffer_path」となる原因不明。
■原因
td-agentの起動owner(td-agent
)に起因する事象
# ps aux|grep ruby td-agent 10382 0.0 0.6 217136 24136 ? Sl 18:36 0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid td-agent 10385 0.0 1.5 257184 59076 ? Sl 18:36 0:01 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
■対応
td-agentの起動owner(root
)を変更
#vi /etc/sysconfig/td-agent TD_AGENT_USER=root TD_AGENT_GROUP=root
td-agentの起動ownerを確認
# ps aux|grep ruby root 13127 0.0 0.6 217136 24156 ? Sl 15:07 0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group root --daemon /var/run/td-agent/td-agent.pid root 13130 0.2 2.4 306384 97564 ? Sl 15:07 0:12 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group root --daemon /var/run/td-agent/td-agent.pid
正常にownerが変更され、td-agent.logにエラー発生してない事を確認。
logに記載されている内容から原因調査→対応まで嵌ったのでここに記載しておく。
fluentdの複数sourceディレクティブで各label毎に特定record追加
fluent(td-agent)を使用したlabel切り分けで各label毎にrecord追加する対応が発生したので設定時でのメモ。
sourceディレクティブが複数あり、送信時に特定recordを追加して送りたい場合に有効。
汎用性がありそうな為、調査・対応を下記へ記載しておく。
- 以下構築要件
- sourceディレクティブを各label名にて割り当
- 各label毎に特定recordを追加
以下td-agent2環境fluentd v0.12以降のバージョン
向けの設定例
<source> @id in_redis_server @type tail @label @redis-server read_from_head true path /var/log/redis/redis.log pos_file /var/log/td-agent/redis.pos format none message_key log_line tag test.redis.log </source> <source> @id in_redis_sentinel @type tail @label @redis-sentinel read_from_head true path /var/log/redis/sentinel.log pos_file /var/log/td-agent/redis.sentinel.pos format none message_key log_line tag test.redis.log </source> <label @redis-server> <match> @type relabel @label @testlabel </match> </label> <label @redis-sentinel> <filter **> @type record_transformer <record> loginfo.subgroup testgroup input_tag ${tag} last_tag ${tag_parts[-1]} redis_type sentinel </record> </filter> <match> @type relabel @label @testlabel </match> </label>
■出力イメージ
2018-06-29T18:17:41+09:00 test.redis.log {"log_line":"testmessage","loginfo.subgroup":"testgroup","input_tag":"test.redis.log","last_tag":"log","redis_type":"sentinel","loginfo.hostname":"testhost","loginfo.group":"groupname"}
正常にrecord追加出来た。
条件分岐して、個別に情報追記を行う場合に便利に使えそうではある。
Zabbix で fluentd のbuffer・キュー等の項目を監視する
fluent(td-agent)サーバ構築時、buffer等の監視設定時のメモ。
Buffer溢れ、転送先サーバ接続不可などの検知に使用出来ればと考えた。
設定方法を下記へ記載しておく。
- 以下監視項目
- buffer_queue_length -> (バッファーに蓄積されているキューの数)buffer_queue_limitで設定した値を超えるとログデータがロストするので注意
- buffer_total_queued_size -> (バッファーに蓄積されている合計サイズ)buffer_queue_limit×buffer_chunk_limitの値を超えるとログデータがロストするので注意
- retry_count -> ( 再送を試みた回数)retry_limitで設定した回数を超えるとバッファーがリセットされるので注意
- dirused -> ( フォルダ容量)Bufferに指定されているフォルダ総容量
- bufnum -> ( フォルダファイル数)Bufferに指定されているフォルダファイル数
- filetime -> ( フォルダ日時)Bufferに指定されているフォルダに保存されているもっとも古いファイルスタンプ
■以下、zabbixのuserparameter設定
# cat /etc/zabbix/zabbix_agentd.d/userparameter_fluentd.conf ## # $1: 24220 or 24221 or 24222 # $2: buffer_queue_length or buffer_total_queued_size or retry_count # UserParameter=fluentd.queue.get[*],curl -s "localhost:$1/api/plugins.json" | /usr/bin/jq ".plugins[] | .$2" | sort -nr |grep -v null | head -n1 #UserParameter=fluentd.queue.get[*],/root/fluentd.queue.get.sh $1 $2 # cat /etc/zabbix/zabbix_agentd.d/userparameter_td-agent.conf UserParameter=td-agent.dirused[*],du -bs $1 | cut -f1 2>/dev/null UserParameter=td-agent.bufnum[*],ls -lt $1 2>/dev/null | wc -l UserParameter=td-agent.filetime[*],ls -trl --time-style='+%s' $1 | head -n2 | sed -e '1d' | sed -E 's/\s+/,/g' | cut -d, -f6 2>/dev/null UserParameter=td-agent.chunknum[*],ls /data/buffer/secure-forward_tag.* |wc -l
また、過去に別途shファイルを起動した形式でしたが上記にまとめた。
# cat /root/fluentd.queue.get.sh #!/bin/bash ## # $1: 24220 or 24221 or 24222 # PORT=$1 ## # $2: buffer_queue_length or buffer_total_queued_size or retry_count # VALUE=$2 curl -s "localhost:${PORT}/api/plugins.json" | /usr/bin/jq ".plugins[] | .${VALUE}"
後は、zabbixの管理画面でよしなに設定すれば監視される。
fluentdの一時的labelの書き換え
fluent(td-agent)を使用したlabel切り分けで一時的設定→送信時変更する対応が発生したので設定時でのメモ。
sourceディレクティブが複数あり、送信時にsubgroup化して送りたい場合に有効。
sourceディレクティブにsubgroup機能が無い為、送信時のlabelディレクティブ時に追加。
汎用性がありそうな為、調査・対応を下記へ記載しておく。
- 以下構築要件
- sourceディレクティブで一時的に送信時のグループ名をlabel割り当
- 一時的割り当てしたグループ名にtd-agent送信時のsubgroupを追加
- labelを本来設定する名称へ変更
以下td-agent2環境fluentd v0.12以降のバージョン
向けの設定例
<source> @id test_id @type config_expander <config> @type tail @label @testgroup read_from_head true path {log_path}.log pos_file {posfilepath}.pos format multiline format_firstline /^\[\d{4}.\d{2}.\d{2}/ format1 /^\[(?<time>\d{4}.\d{2}.\d{2}\s\d{2}:\d{2}:\d{2})\]\s(?<log_line>.*)/ message_key log_line tag testtag </config> </source> <label @testgroup> <filter **> @type record_transformer <record> loginfo.subgroup testgroup </record> </filter> <match> @type relabel @label @testlabel </match> </label>
後は、送信時のmatchディレクティブでよしなに設定すれば送信される。
ホスト側からリモートコマンド実行
ansibleのplaybookを使用し、ホスト側から配下内に複数クライアントへ特定コマンドを実行する
* 下記サンプルはmysqlのerror,slowに一括でコマンド実行しログ出力させる。
* td-agent等使用し、ログ収集行う場合のテスト出力で便利
# cat hosts [hostlist] hosta ansible_host=172.27.1.1 hostb ansible_host=172.27.1.2 hostc ansible_host=172.27.1.3 # cat test.yml --- - hosts: hostlist become: yes become_method: su become_user: root roles: - td-agent tasks: - name: check mysql errlog shell: echo "2018-04-05T01:10141.161639+09:00 0 [Warning] "tables_priv" entry "user mysql.session@localhost" ignored in --skip-name-resolve mode." >> /data/mysql/{{ inventory_hostname }}.errlog - name: check mysql slow shell: mysql -u[username] -p[passwd] -e "select sleep(2);"
■ 実行
* -C:テスト実行
* -l:hosts内の特定ホストのみ実行
# ansible-playbook -i hosts -u [username] -l hosta,hostb --ask-pass --ask-become-pass test.yml --diff -C