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
Loop over dates with bash in Linux
特定日時間でのループ処理
- start、endを指定
- daily処理
上記要件の場合の処理script
#!/bin/bash START=2017-10-22 END=2017-12-31 CURRENT=$START while true; do echo $CURRENT if [ "$CURRENT" = "$END" ]; then break fi CURRENT=`date -d "$CURRENT 1day" +%Y-%m-%d` done
たまにメンテナンスで使用するので便利
ref)
mongodb 2.6 クラスタ構成で過負荷対応
クラスタ構成環境のmongosで下記エラー発生。
調査・対応を下記へ記載しておく。
- エラー内容
対応方法
1.カーネル設定
vm.swappinessの設定をします。
vm.swappinessは、swap領域の扱いを制御するカーネルの設定です。
この設定値が小さければ小さいほどswapを抑制します。
デフォルトは、vm.swappiness=60です。
参考)Swappiness
vm.swappiness = 0 メモリが一杯になるまでスワップを利用しない
vm.swappiness = 60 規定値
vm.swappiness = 100 全体のパフォーマンスに影響しうるほど積極的にスワップ処理を行う
設定確認
# sysctl vm.swappiness vm.swappiness = 60
設定変更
# echo 10 > /proc/sys/vm/swappiness
設定確認
# sysctl vm.swappiness vm.swappiness = 10
sysctl.confに設定を追記
# vim /etc/sysctl.conf vm.swappiness = 10
2.logrotate設定
公式ドキュメントによると下記3パターンの設定方法がある。
mongo shell
- mongos> db.runCommand( { logRotate : 1 } )
- { "ok" : 1 }
-
- shell> kill -SIGUSR1
- shell> killall -SIGUSR1 mongod
Rotate Log Files — MongoDB Manual 2.6
bashを使用したローテーションが簡易で良いと考えたが、
実行した場合mongosが落ちるという事象が発生。
原因不明な為、mongo shellを使用したケースで対応。
### cat /root/mongologrotate.sh #/bin/sh # mongod log lotate mongo --quiet admin /root/MongoLogRotate.js # clear old olgs cd {/mongologdir} DELDAY=`date --date '30 days ago' '+%Y-%m-%d'` for LINE in `find -iname "mongod.log.$DELDAY*"` do echo "delete $LINE" rm -f $LINE done ### cat /root/MongoLogRotate.js db.auth("root", "******") db.runCommand( { logRotate : 1 } ) ### crontab -l 00 15 * * * /bin/sh /root/mongologrotate.sh
3.[slab | page]cache設定
上記2パターンを実行したケースにおいても現象改善されない状況。下記記事からcache設定。
UPDATE: It's fair that the memory usage looks high, which might lead to the conclusion it's another process. There's no other processes using any significant memory on the server; the memory appears to be consumed in the cache, but I'm not clear why that would be the case:
mongodb - Mongod resident memory usage low - Stack Overflow
OS側が保持している各cache設定を開放。
開放前のメモリー使用状況
### free -m total used free shared buffers cached Mem: 15951 15204 746 0 145 10355 -/+ buffers/cache: 4703 11248 Swap: 511 140 371 ### cat /proc/meminfo MemTotal: 16334048 kB MemFree: 764992 kB Buffers: 149060 kB Cached: 10604528 kB SwapCached: 7712 kB Active: 8825784 kB Inactive: 5337972 kB Active(anon): 2757160 kB Inactive(anon): 653428 kB Active(file): 6068624 kB Inactive(file): 4684544 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 524284 kB SwapFree: 380280 kB Dirty: 36 kB
OS保持の各cache開放
# free && sync && echo 3 > /proc/sys/vm/drop_caches && echo "" && free
開放後のメモリー使用状況
### free -m total used free shared buffers cached Mem: 15951 4908 11042 0 166 1183 -/+ buffers/cache: 3559 12392 Swap: 511 124 387 ### cat /proc/meminfo MemTotal: 16334048 kB MemFree: 11306796 kB Buffers: 170120 kB Cached: 1212012 kB SwapCached: 5716 kB Active: 3907484 kB Inactive: 99016 kB Active(anon): 2608944 kB Inactive(anon): 15848 kB Active(file): 1298540 kB Inactive(file): 83168 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 524284 kB SwapFree: 396408 kB Dirty: 40 kB Writeback: 0 kB AnonPages: 2618788 kB Mapped: 14892 kB Shmem: 424 kB Slab: 326744 kB SReclaimable: 84616 kB SUnreclaim: 242128 kB KernelStack: 410944 kB PageTables: 63036 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 8691308 kB Committed_AS: 28622200 kB VmallocTotal: 34359738367 kB VmallocUsed: 171952 kB VmallocChunk: 34359558216 kB HardwareCorrupted: 0 kB AnonHugePages: 1978368 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 10240 kB DirectMap2M: 16766976 kB
cache開放後、free領域がmongoに割り当てされれば問題ない為
mongo shell 起動し、物理メモリ(resident)領域がcache開放前後で増加しているか確認。
mongos> db.serverStatus().mem { "bits" : 64, "resident" : 3299, "virtual" : 29016, "supported" : true }
Zabbix API を使用してホストリストを取得する
zabbixに多数サーバ登録した場合、ホストリストの視認性に苦労する事がある。
※Webコンパネからポチポチしたくない・・
その場合、APIを使用しリスト化するのが便利そうなので実装した。
<?php // リクエストデータの作成 $request_ver = array( 'jsonrpc' => '2.0', 'method' => 'apiinfo.version', 'id' => 1, 'auth' => null, 'params' => array(), ); $request_token = array( 'jsonrpc' => '2.0', 'method' => 'user.login', 'params' => array( 'user' => '[userid]', 'password' => '[passwd]', ), 'id' => 1, 'auth' => null, ); $request_list = array( 'jsonrpc' => '2.0', 'method' => 'host.get', 'params' => array( 'output' => array('hostid', 'host'), 'selectGroups' => array('groupid', 'name'), 'selectParentTemplates' => array('templateid', 'name'), 'selectInterfaces' => array('interfaceid', 'ip'), ), 'id' => 1, 'auth' => '[auth_token]', ); // リクエストデータを JSON 形式に変換 //$request_json = json_encode($request_ver); // ver取得 //$request_json = json_encode($request_token); // auth_token取得 $request_json = json_encode($request_list); // ホストリスト取得 // HTTPストリームコンテキストの作成 $opts['http'] = array( 'method' => 'POST', 'header' => 'Content-Type: application/json-rpc', 'content' => $request_json, ); $context = stream_context_create($opts); // リクエストの実行 $url = 'http://[basic_auth_id]:[basic_auth_passwd]@localhost/zabbix/api_jsonrpc.php'; $response_json = file_get_contents($url, false, $context); // レスポンスの表示 $response = json_decode($response_json, true); //var_dump($response); // // ホストリスト取得する場合、下記コード有効化 // foreach((array)$response as $key => $value){ foreach((array)$value as $key1 => $value1){ echo 'hostid:' . $value1['hostid'] . "\t" . 'host:' . $value1['host'] ."\n"; foreach((array)$value1 as $key2 => $value2){ if ($key2 == 'groups'){ echo $key2 . "\n"; foreach((array)$value2 as $key3 => $value3){ echo 'groupid:' . $value3['groupid'] . "\t" . 'groupname:' . $value3['name'] ."\n"; } } if ($key2 == 'parentTemplates'){ echo $key2 . "\n"; foreach((array)$value2 as $key4 => $value4){ echo 'templateid:' . $value4['templateid'] . "\t" . 'templatename:' . $value4['name'] ."\n"; } } if ($key2 == 'interfaces'){ echo $key2 . "\n"; foreach((array)$value2 as $key5 => $value5){ echo 'interfaceid:' . $value5['interfaceid'] . "\t" . 'ip:' . $value5['ip'] ."\n"; } } } } }
上記実行時した場合の出力結果を示します。
hostid:1234 host:vm1234 groups groupid:11 groupname:DB servers groupid:19 groupname:groupA groupid:15 groupname:Staging servers parentTemplates templateid:10860 templatename:Template OS CentOS7 templateid:11303 templatename:Template App MySQL GroupReplication interfaces interfaceid:1183 ip:172.31.100.1
出力フォーマットの検討の余地があるが、箇条書きベースでリスト取得出来た。