ELK 維護的一些點
來自: http://www.wklken.me/posts/2016/02/16/elk-about-upgrade.html
去年入職新公司之后, 負責維護平臺的elk
這套東西是2013年搭建的, 年久失修, 所以做了個方案, 開始了批量升級
將logstash從1.3升級到2.1, 將elasticsearch從1.4.1升級到2.0
期間踩了很多坑, 搞了一個多月, 總算搞完
從純手工落后隔三差五有人找查問題的自行車, 改成自動化最新版本新架構運維便捷上了兩個月無人反饋的, 額, 小汽車:) - 繼承安裝包/shell腳本/fabric實現部署/升級/增刪/加黑名單等等功能
每天日志量大概10G上下, 幾十個采集端, 兩個redis, 兩個indexer, 兩臺es機器扛起
以下, 不那么嚴謹地, 記錄一些遇到的問題
1. logstash升級策略
logstash1.3到2.x, 變化點還是很多的
所以, 首先第一步要去閱讀官方文檔, 將所有change log過一遍, 對一些關鍵性的東西進行了解, 比如, 干掉了哪些語法(舊的功能需要如何實現), 哪些語法有變更, 新增了哪些特性等.
然后, 將線上不同類型agent的配置文件拉下來, 先, 歸類, 然后, 開始改-測-改-測-直到測試通過
bin/logstash agent -t -f test.conf
直到, 語法驗證通過
現在要做的是, 驗證數據正確性
從線上拉取對應日志, 啟動, 查看輸出
output { stdout{ debug => true } }
這里需要驗證的是, 1. 過濾, 該過濾的過濾了 2. 轉換, 該轉換的轉換了 3.新增, 新增字段
注意, 測試時, 使用邏輯分支覆蓋到所有配置文件中的分支即可.
然后, 可以挑一臺機器, 停老的服務, 部署新的服務進行測試
建議, 部署agent的時候, 如果讀的是文件, 建議配置 sincedb_path 這樣假設下次升級, 就可以從老的服務最后讀取的位置開始了
input { file { path => ["/data/logs/*.log"] sincedb_path => "/data/LogNew/logstash/sincedb/celery.sincedb" } }
2. elasticsearch升級的策略
elasticsearch從1.4到2.0, 部署上變化不大, 變化最大的是存儲doc的schema變了......
使用原來的語法查詢, 發現查不到, 因為字段名以及嵌套層級完全不一樣了, 這里, 要修改查詢端, 兼容新老版本的格式
{'from': 0, 'query': {'filtered': {'filter': {'bool': {'must': [{'bool': {'should': [{'term': {'type': 'app'}}, {'term': {'@type': 'app'}}]}}, {'bool': {'should': [{'term': {'log_level': u'error'}}, {'term': {'@fields.log_level': u'error'}}]}}, {'range': {'@timestamp': {'gt': 'now-5h'}}}, {'bool': {'should': [{'term': {'log_type': u'celery'}}, {'term': {'@fields.log_type': u'celery'}}]}}]}}}}, 'size': 100, 'sort': [{'@timestamp': 'desc'}]}
另一個是, 取到數據進行解析的時候, 發現解析邏輯跪了, 沒辦法, 返回的json也完全變了, 這里, 要修改解析邏輯, 兼容新老版本格式
for hit in log_hits: try: source = hit.get('_source') if '@fields' in source: log = source.get('@fields', {}) else: log = source
為了讓用戶感覺不到集群升級, 首先要做的就是上面兩個變更
然后, 搭建新的集群, 最好找新的機器搭建(我在新的機器搭完才發現媽蛋硬盤才100G, 坑死, 無奈在老集群上搭新的集群, 硬盤1t)
ready, 所有節點起好維護好, 然后, 改indexer, 將同一份日志灌到兩個集群
output { elasticsearch { hosts => ["10.1.1.1:9100", "10.1.1.2:9100"] } elasticsearch { hosts => ["10.1.1.1:9110", "10.1.1.2:9110"] } }
簡單測試下, 沒問題就放著甭管了, 等數據攢齊了....
數據夠了, 就, 停indexer, 停老集群, 挺新集群, 改新集群端口, 起來....同時去掉indexer只輸出到新的集群, 起來......測試, 切換完畢, 收工吧.
優化點: 集成安裝包和supervisord
額, logstash和es, 如果要配置節點, 其實還是挺蛋疼的
要做的, 就是, logstash+不同類型配置文件+運維腳本, 達成一個包
然后, 如果要部署一臺機器, 扔上去一鍵執行安裝, 測試, 啟動即可
例如, 運維腳本 logstashd.sh
#!/bin/bashBASEDIR=$(dirname $0) cd $BASEDIR CURRENT_DIR=
pwd
function help_msg() { echo "===================== usage =====================" echo "./logstashd.sh - enter command line" echo "./logstashd.sh status - show all configured process" echo "./logstashd.sh start ${name} - start program" echo "./logstashd.sh stop ${name} - stop program" echo "./logstashd.sh restart ${name} - restart program" echo "./logstashd.sh reread && ./logstashd.sh update - update config and just update the modified programs" echo "./logstashd.sh reload - reload config files and restart all programs(stopeed not included)" echo "=================================================" echo "" }
if [ "${1}" = "-h" -o "${1}" = "--help" ] then help_msg exit 0 fi
SUPERVISORCTL='/data/LogNew/python27/bin/supervisorctl'
CONFIG_FILE_PATH="${CURRENT_DIR}/conf/supervisord.conf"
$SUPERVISORCTL -c $CONFIG_FILE_PATH $@</pre>
使用
./logstashd.sh ===================== usage ===================== ./logstashd.sh - enter command line ./logstashd.sh status - show all configured process ./logstashd.sh start - start program ./logstashd.sh stop - stop program ./logstashd.sh restart - restart program ./logstashd.sh reread && ./logstashd.sh update - update config and just update the modified programs./logstashd.sh reload - reload config files and restart all programs(stopeed not included)
111_indexer RUNNING pid 27058, uptime 1:25:10 indexer RUNNING pid 24731, uptime 1:31:29 supervisor> restart indexer</pre>
這里, 我引入了 stackless python (獨立), 然后裝pip/supervisord, 使用supervisord對logstash/es進程進行管理
使用supervisord管理進程, 有個注意點
默認supervisord相關的文件在
/tmp/supervisor*而線上, 存在tmp被刪/清理了情況, 導致要進行進程啟停操作才發現,媽蛋找不到
處理方式 => 放到集成安裝包的run目錄下
注意點: logstash存在兩個output時, 必須要保證二者的可用性
logstash indexer, 分別轉發數據到兩個不同的output
output { elasticsearch { hosts => ["10.1.1.1:8080", "10.1.1.2:8080"] } redis { host => "10.1.1.3" port => 6379 password => "7oEsjqUNoTdgE4" data_type => "list" key => "log_queue" db => 0 batch => true } }此時, 若是redis掛了, 則日志也不會刷到es中, 所以, 需要同時保證所有output的可用性
優化點: ELK增加agent_ip字段
需求: 在實際使用中, 有時候需要反向根據查詢結果, 獲知日志的來源機器
處理:
1.先獲取ip
GetLanIp () {## get associated LAN ip address ## usage: GetLanIp /sbin/ifconfig | awk ' /eth/{ getline; if (/inet addr:(172|10|192)\./) { gsub(".*addr:| *Bcast.*",""); print $0; exit; } }' return 0
}</pre>
2.放入環境變量
ETH1_IP=10.1.1.13.修改logstash配置
注意, 這里是logstash2.x的語法
environment { add_metadata_from_env => ["agent_ip", "ETH1_IP"] add_field => {"agent_ip" => "%{[@metadata][agent_ip]}" } }問題: elk的utc問題
elasticsearch內部使用的是utc, 存儲為long (milliseconds since the epoch) e.g. timestamp=1420070400000
可以看下 es 時間處理
logstash 接受了這種設定, 往es傳數據的時候, 根據UTC, 每天00:00新建一個index
kibana也接受這種設定, 在查詢和展示時根據用戶的時區進行處理
問題描述
這導致了, 對于東八區, 2015-11-6日, 8點之前, 只有 logstash-2015.11.05 這個index, 到8點的時候, 創建新的index logstash-2015.11.06 , 即, 對于我們這個時區的人來說, 一天的數據存在了兩個index里面
同類問題 Elasticsearch doesn't care about timezone and creates indexes with UTC
修正方案1: 修改logstash的數據時間
logstash團隊對于支持localtime的問題, 不予修復 討論 , 但是可以自行去修改logstash的代碼
當然, 可以修改每個logstash indexer的時間, 但是會帶來問題 問題 : 1. logstash都要修改 getLocalTime 2.相對時間搜索 3. kibana等相關插件/組件要修正
運維/升級和后續使用上會有很多地雷
修正方案2: 不修正
接受這種設定, 學習kibana, 類似自行確定要搜索的index 對于 00:00-08:00 的, 程序處理使用昨天的 indexer
所以, 更好的方式是, 不修正......原來不變的才是最好的
rolling restart
當存在配置變更時, 需要重啟es集群, 不可能全部重啟的, 這樣會導致服務不可用....
所以, 要一個個重啟
先執行
curl -XPUT 'http://localhost:9200/_cluster/settings' -d ' { "transient" : { "cluster.routing.allocation.enable" : "none" } }'然后, shutdown, 改配置, start
then : 一定要記得執行, 否則不會執行recovery.....會一直等著
curl -XPUT 'http://localhost:9200/_cluster/settings' -d ' { "transient" : { "cluster.routing.allocation.enable" : "all" } }'logstash文本解析配置grok語法
一個線上的工具, https://grokdebug.herokuapp.com/
挺好用的, 但是有時候變更頻繁相應有些緩慢
暫時沒有找到命令行工具
坑: GROK語法
上線后發現, 尼瑪, 部分應用日志沒有被采集
定位發現, 原來在 grok 的解析中使用了 WORD
而 WORD : 不支持連字符和下劃線
跪了, 需要自定義 LOGFILENAME [a-z\-A-Z0-9_\.]+ 放到pattern中
然后, 搜索的時候, 尼瑪, 也搜不到....語法要做處理, 使用 raw , es建索引的時候自動拆掉了導致搜索不到
{'term': {'app_name.raw': 'nms-t'}}一些相關用到的命令
- 查看plugin版本
https://www.elastic.co/guide/en/logstash/current/working-with-plugins.html
bin/plugin list --verbose
- create empty index
</ul>
curl -XPUT 'http://localhost:9100/logstash-2015.12.15/'
- 查看健康度
</ul>
curl 'http://localhost:9100/_cluster/health?pretty=true'
- 查看indices
</ul>
#!/bin/bashcurl 'http://localhost:9100/_cat/indices?v' | sort -k 3</pre>
刪除30天前crontab腳本
#!/bin/bashnow=
date +%Y%m%d
echo $now days_30_before=date -d "$now 31 days ago" +%Y.%m.%d
echo $days_30_before echo "尚未處理logstash2.1 muline codec, 配置多個數據來源, 存在串的情況, 生產中大數據量有, 小規模沒有復現....
好了, 先這些, 還有一些窩在某些目錄下, 后續整理好了發
wklken
2016-02-16
</div>