ELK 維護的一些點

hepeace 8年前發布 | 24K 次閱讀 Logstash

來自: 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/bash

BASEDIR=$(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.1

3.修改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
 本文由用戶 hepeace 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!