ELK:收集Docker容器日志


簡介



  • 之前寫過一篇博客 ELK:日志收集分析平台,介紹了在Centos7系統上部署配置使用ELK的方法,隨着容器化時代的到來,容器化部署成為一種很方便的部署方式,收集容器日志也成為剛需。本篇文檔從 容器化部署ELK系統,收集容器日志,自動建立項目索引,ElastAlert日志監控報警,定時刪除過期日志索引文件 這幾個方面來介紹ELK。
  • 大部分配置方法多是看官方文檔,理解很辛苦,查了很多文章,走了很多彎路,分享出來,希望讓有此需求的朋友少走彎路,如有錯誤或理解不當的地方,請批評指正。
  • 邏輯結構如下圖

img-w500

 
 

ELK之容器日志收集及索引建立



docker pull docker.elastic.co/elasticsearch/elasticsearch:6.6.2
docker pull docker.elastic.co/kibana/kibana:6.6.2
docker pull docker.elastic.co/beats/filebeat:6.6.2
docker pull docker.elastic.co/logstash/logstash:6.6.2

Elasticsearch 容器部署

Elasticsearch 啟動命令說明

  • 啟動兩個端口,9200為數據查詢和寫入端口,也即是業務端口,9300為集群端口,同步集群數據,此處我單節點部署
  • 指定日志輸出格式為json格式,默認情況下也為json格式,默認輸出路徑 /var/lib/docker/containers/*/*.log
  • 日志文件最多保留三個,每個最多10M
  • 容器開機自啟
  • 傳遞參數為單節點部署
  • 數據存儲映射至宿主機
  • 需要給 /data/elasticsearch 賦予權限,否則報權限不足的錯誤
docker run -d \
    --user root \
    -p 127.0.0.1:9200:9200 \
    -p 9300:9300 \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name elasticsearch \
    --restart=always \
    -e "discovery.type=single-node" \
    -v /data/elasticsearch:/usr/share/elasticsearch/data \
    docker.elastic.co/elasticsearch/elasticsearch:6.6.2
    
chmod 777 -R /data/elasticsearch

Logstash 容器部署

Logstash 配置文件說明

  • 配置文件映射至至宿主機
  • match => { "message" => "%{TIMESTAMP_ISO8601:log-timestamp} %{LOGLEVEL:log-level} %{JAVALOGMESSAGE:log-msg}" } 將日志做簡單拆分, 時間戳重命名為 log-timestamp,日志級別重命名為 log-msg,如果拆分成功輸出日志中就會產生這兩個字段
  • 通過 remove_field => ["beat"] 移除無用字段
  • 輸出到elasticsearch
  • 索引通過 容器名稱-時間 建立
mkdir -pv /data/conf
cat > /data/conf/logstash.conf << "EOF"
input {
  beats {
    host => "0.0.0.0"
    port => "5043"
  }
}
filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:log-timestamp} %{LOGLEVEL:log-level} %{JAVALOGMESSAGE:log-msg}" }
  }
  mutate {
#    remove_field => ["message"]
    remove_field => ["beat"]
   }
}
output {
  stdout { codec => rubydebug }
  elasticsearch {
        hosts => [ "elasticsearch:9200" ]
        index => "%{containername}-%{+YYYY.MM.dd}"
  }
}
EOF

Logstash 啟動命令說明

  • 通過 --link elasticsearch 連接 elasticsearch 容器,並生成環境變量在容器中使用
  • 配置文件映射如容器
docker run -p 5043:5043 -d \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name logstash \
    --link elasticsearch \
    --restart=always \
    -v /data/conf/logstash.conf:/usr/share/logstash/pipeline/logstash.conf \
    docker.elastic.co/logstash/logstash:6.6.2

Kibana容器部署

  • 啟動參數參考上述組件
docker run -p 5601:5601 -d \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name kibana \
    --link elasticsearch \
    --restart=always \
    -e ELASTICSEARCH_URL=http://elasticsearch:9200 \
    -v /data/conf/kibana.yml:/usr/share/kibana/config/kibana.yml \
    -v /data/elastalert-kibana-plugin:/usr/share/kibana/plugins/elastalert-kibana-plugin \
    docker.elastic.co/kibana/kibana:6.6.2
  • 通過服務器IP地址即可訪問Kibana web http://IP:5601

Filebeat 容器部署

Filebeat 配置文件說明

  • Filebeat是一個輕量級的日志收集工具,是Elastic的Beat組成員,默認情況下,docker輸出的日志格式為json格式,需要解碼才方便查看日志的路徑為 /var/lib/docker/containers/*/*.log
  • - type: log 選擇filebeat輸入類型選擇log,之后通過解碼json的配置將docker輸出的日志解碼,輸入類型也可選擇docker,但是我試過目前版本該數據類型有些功能受限,比如后面rename時,只能rename一個
  • json解碼: 必須至少指定設置其中之一來啟用JSON解析模式,建議三行都加上,不然,有些功能會有問題
  • json.overwrite_keys #如果啟用了keys_under_root和此設置,那么來自解碼的JSON對象的值將覆蓋Filebeat通常添加的字段(type, source, offset,等)以防沖突。
  • json.add_error_key #如果啟用此設置,則在出現JSON解組錯誤或配置中定義了message_key但無法使用的情況下,Filebeat將添加“error.message”和“error.type:json”鍵。
  • json.message_key #一個可選的配置設置,用於指定應用行篩選和多行設置的JSON密鑰。 如果指定,鍵必須位於JSON對象的頂層,且與鍵關聯的值必須是字符串,否則不會發生過濾或多行聚合。
  • 多行合並: 將多行日志合並成一條,比如java的報錯日志,規則為,如果不是以四個數字,即年份開頭的日志合並到上一條日志當中
  • 排除或刪除通配符行: 即排除含有相關關鍵字的行,或只收集含有相關關鍵字的行
  • 排除通配文件: 即不讀取該含該字符的文件的日志
  • 添加docker元數據: 將docker容器的相關數據收集起來,方便作為索引的字段, match_source_index: 4 為獲取docker數據的索引,其數據為json格式,索引太低可能無法獲取關鍵docker數據
  • 處理器重命名和刪除無用字段: - rename: 將上面收集的元數據重命名來提升其索引等級,以便交給logstash來處理,其中 docker.container.name 為docker容器的名字,重命名為 containername字段, - drop_fields: 清除掉無用索引數據,不輸出到 output
  • 日志輸出:日志輸出的幾種方式 output.file 輸出到文件,output.console 輸出到標准輸出,通過 docker logs containName 查看,該兩種輸出方便調試
cat > /data/conf/filebeat.yml << "EOF"
filebeat.inputs:
- type: log
  paths:
   - '/var/lib/docker/containers/*/*.log'
# json解碼
  json.add_error_key: true
  json.overwrite_keys: true
  json.message_key: log
# 多行合並
#  multiline:
#    pattern: ^\d{4}
#    negate: true
#    match: after
#
# 排除或刪除通配符行
#  exclude_lines: ['^DBG']
#  include_lines: ['ERROR', 'WARN', 'INFO']
# 排除通配文件
#  exclude_files: ['\.gz$']
#
# 添加docker元數據
  processors:
    - add_docker_metadata:
        match_source: true
# 選取添加docker元數據的層級
        match_source_index: 4
# 處理器重命名和刪除無用字段
processors:
- rename:
    fields:
     - from: "json.log"
       to: "message"
     - from: "docker.container.name"
       to: "containername"
     - from: "log.file.path"
       to: "filepath"
- drop_fields:
    fields: ["docker","metadata","beat","input","prospector","host","source","offset"]
# 日志輸出
output.logstash: # 輸出地址
  hosts: ["192.168.30.42:5043"]
#output.elasticsearch:
#  hosts: ["192.168.30.42:9200"]
#  protocol: "http"
#output.file:
#  path: "/tmp"
#  filename: filebeat.out
#output.console:
#  pretty: true
EOF

Filebeat 啟動命令

  • -v /var/lib/docker/containers/:/var/lib/docker/containers/ 映射日志目錄
  • -v /var/run/docker.sock:/var/run/docker.sock:ro 映射docker套接字文件,來收集docker信息,添加docker元數據
docker run -d \
    --name filebeat \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --restart=always \
    -v /data/conf/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro \
    -v /var/lib/docker/containers/:/var/lib/docker/containers/ \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    docker.elastic.co/beats/filebeat:6.6.2

  • Filebeat是日志收集客戶端,正常情況下其部署在需要收集日志的主機上

添加kibana索引

  • 通過服務器IP地址訪問Kibana web http://IP:5601 同時添加索引
    img-w500

  • 如此便可查看相關日志
    img-w500

 
 

ELK之ElastAlert日志告警



  1. any:只要有匹配就報警;
  2. blacklist:compare_key字段的內容匹配上 blacklist數組里任意內容;
  3. whitelist:compare_key字段的內容一個都沒能匹配上whitelist數組里內容;
  4. change:在相同query_key條件下,compare_key字段的內容,在 timeframe范圍內發送變化;
  5. frequency:在相同 query_key條件下,timeframe 范圍內有num_events個被過濾出來的異常;
  6. spike:在相同query_key條件下,前后兩個timeframe范圍內數據量相差比例超過spike_height。其中可以通過spike_type設置具體漲跌方向是up,down,both 。還可以通過threshold_ref設置要求上一個周期數據量的下限,threshold_cur設置要求當前周期數據量的下限,如果數據量不到下限,也不觸發;
  7. flatline:timeframe 范圍內,數據量小於threshold閾值;
  8. new_term:fields字段新出現之前terms_window_size(默認30天)范圍內最多的terms_size (默認50)個結果以外的數據;
  9. cardinality:在相同 query_key條件下,timeframe范圍內cardinality_field的值超過 max_cardinality 或者低於min_cardinality
  10. Percentage Match: 在buffer_time 中匹配所設置的字段的百分比高於或低於閾值時,此規則將匹配。默認情況下為全局的buffer_time

ElastAlert容器啟動

  • -p 3030:3030 指定映射端口,該端口需要kibana調用
  • -v config/elastalert.yaml:/opt/elastalert/config.yaml 映射ElastAlert的配置文件
  • -v rules:/opt/elastalert/rules 映射報警規則文件目錄
  • --link elasticsearch ElastAlert需要連接ElasticSearch 進行數據的查詢
  • rule_templates:/opt/elastalert/rule_templates 該目錄下為報警規則的模版,可使用其配置並放入 rules 使其生效,具體配置規則參考 https://elastalert.readthedocs.io/en/latest/ruletypes.html
git clone https://github.com/bitsensor/elastalert.git; cd elastalert
sed -i -e 's/localhost/elasticsearch/g' `pwd`/config/elastalert.yaml
docker run -d \
    -p 3030:3030 \
    -v `pwd`/config/elastalert.yaml:/opt/elastalert/config.yaml \
    -v `pwd`/config/config.json:/opt/elastalert-server/config/config.json \
    -v `pwd`/rules:/opt/elastalert/rules \
    -v `pwd`/rule_templates:/opt/elastalert/rule_templates \
    --link elasticsearch \
    --name elastalert \
    bitsensor/elastalert:latest
  • 可通過 elastalert-test-rule rules/rule1.yamlelastalert 容器內測試報警規則

Kibana 需要更改配置

  • 添加 elastalert 相關的配置,包括主機名和端口
cat > /data/conf/kibana.yml << "EOF"
# Default Kibana configuration from kibana-docker.

server.name: kibana
server.host: "0"
elasticsearch.hosts: http://elasticsearch:9200
xpack.monitoring.ui.container.elasticsearch.enabled: true
elastalert-kibana-plugin.serverHost: elastalert
elastalert-kibana-plugin.serverPort: 3030

Kibana 啟動參數更改

  • 配置 Kibana的插件 elastalert-kibana-plugin 需要注意的是,插件的下載地址 https://github.com/bitsensor/elastalert-kibana-plugin/releases 需要找到對應自己 kibana 版本,否則插件無法安裝成功
  • 從目前版本來看,插件的使用不是很方便,其相當於在 ElasticAlert 啟動時 -v rules:/opt/elastalert/rules 目錄下寫文件
  • -v /data/kibana/elastalert-kibana-plugin:/usr/share/kibana/plugins/elastalert-kibana-plugin 映射插件目錄
cd /data
wget https://github.com/bitsensor/elastalert-kibana-plugin/releases/download/1.0.2/elastalert-kibana-plugin-1.0.2-6.6.2.zip
unzip elastalert-kibana-plugin-1.0.2-6.6.2.zip
docker run -p 5601:5601 -d \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name kibana \
    --link elasticsearch \
    --link elastalert \
    --restart=always \
    -e ELASTICSEARCH_URL=http://elasticsearch:9200 \
    -v /data/conf/kibana.yml:/usr/share/kibana/config/kibana.yml \
    -v /data/kibana/elastalert-kibana-plugin:/usr/share/kibana/plugins/elastalert-kibana-plugin \
    docker.elastic.co/kibana/kibana:6.6.2

  • 啟動后,可查看 http://IP:5601,可通過此來創建報警規則

img-w500

報警規則配置

  • 這里給出一個報警規則的示例,更多請查看文檔 https://elastalert.readthedocs.io/en/latest/ruletypes.html
  • es_host: elasticsearch 該配置會使用docker容器中的變量
  • name: filebeat info frequency rule 報警規則的名稱,需要唯一
  • timeframe: 設定查詢的時間尺度,這里指定為5分鍾
  • filter 指定報警條件,示例為日志中message字段還有INFO信息就示作匹配
  • alert 指定報警方式,報警方式有很多,這里使用slack,可查看文檔配置
# Alert when the rate of events exceeds a threshold

# (Optional)
# Elasticsearch host
# es_host: elasticsearch.example.com
es_host: elasticsearch

# (Optional)
# Elasticsearch port
# es_port: 14900
es_port: 9200

# (OptionaL) Connect with SSL to Elasticsearch
#use_ssl: True

# (Optional) basic-auth username and password for Elasticsearch
#es_username: someusername
#es_password: somepassword

# (Required)
# Rule name, must be unique
name: filebeat info frequency rule

# (Required)
# Type of alert.
# the frequency rule type alerts when num_events events occur with timeframe time
type: frequency

# (Required)
# Index to search, wildcard supported
index: filebeat-*

# (Required, frequency specific)
# Alert when this many documents matching the query occur within a timeframe
num_events: 1

# (Required, frequency specific)
# num_events must occur within this amount of time to trigger an alert
timeframe:
#  hours: 1
  minutes: 5
# (Required)
# A list of Elasticsearch filters used for find events
# These filters are joined with AND and nested in a filtered query
# For more info: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html

filter:
- query:
    query_string:
      query: "message:INFO"
# (Required)
# The alert is use when a match is found

alert:
- "slack"

alert_subject: "{} @{}"
alert_subject_args:
  - containername
  - log-timestamp
alert_text_type: alert_text_only
alert_text: |
  > 【Name】: {}
  > 【Log-Msg】: {}
alert_text_args:
  - containername
  - message


slack_webhook_url: "https://hooks.slack.com/services/xxxx/xxxx/xxxxxx"
slack_title_link: "https://elk.glinux.top"
slack_title: "ELK URL"
slack_username_override: "ELK Alert"
slack_channel_override: "#filebeat-test"
  • 報警的效果如圖

img-w500

 
 

定時刪除過期日志索引文件



  • 該腳本用於刪除7天以前的索引文件(過月日志清除),腳本為參考他人作品,做了少許更改,可查看參考文檔
  • curl -s "http://127.0.0.1:9200/_cat/indices?v" 該命令可以查看es中的索引
  • curl -XDELETE -s "http://127.0.0.1:9200/filebeat-2019.04.27" 該命令用於刪除es中的 filebeat-2019.04.27 索引
cat > /data/delete_index.sh << "EOF"
#!/bin/bash

elastic_url=127.0.0.1
elastic_port=9200
user="username"
pass="password"
log="/data/log/delete_index.log"


# 當前日期時間戳減去索引名時間轉化時間戳是否大於1
dateDiff (){
    dte1=$1
    dte2=$2
    diffSec=$((dte1-dte2))
    if ((diffSec > 6)); then
	echo "1"
    else
        echo "0"
    fi
}


# 循環獲取索引文件,通過正則匹配過濾
for index in $(curl -s "${elastic_url}:${elastic_port}/_cat/indices?v" | awk -F' ' '{print $3}' | grep -E "[0-9]{4}.[0-9]{2}.[0-9]{2}$"); do
# 獲取索引文件日期,並轉化格式
  date=$(echo $index | awk -F'-' '{print $NF}' | sed -n 's/\.//p' | sed -n 's/\.//p')
# 獲取當前日期
  cond=$(date '+%Y%m%d')
# 根據不同服務器,計算不同數值
  diff=$(dateDiff "${cond}" "${date}")
# 打印索引名和結果數值
  #echo -n "${index} (${diff})"

# 判斷結果值是否大於等於1
  if [ $diff -eq 1 ]; then
    curl -XDELETE -s "${elastic_url}:${elastic_port}/${index}" && echo "${index} 刪除成功" >> $log || echo "${index} 刪除失敗" >> $log
fi
done
EOF

  • 該腳本可以做成定時任務,每天都執行一次,來刪除過期數據

 
 

參考文檔



ELK

  1. 使用Docker搭建ELK日志系統 https://zhuanlan.zhihu.com/p/32559371
  2. Beats詳解(四) http://www.51niux.com/?id=204
  3. Offical document: https://www.elastic.co/guide/index.html
  4. 將日志輸出到Docker容器外: https://www.jianshu.com/p/bf2eb121ac62
  5. elk日志大盤顯示和日志監控報警配置實踐: https://blog.csdn.net/yujiak/article/details/79897408

Elastalert

  1. elastalert github地址: https://github.com/bitsensor/elastalert
  2. elastalert-kibana-plugin github地址: https://github.com/bitsensor/elastalert-kibana-plugin/tree/1.0.2
  3. ElastAlert 官方操作文檔:https://elastalert.readthedocs.io/en/latest/ruletypes.html

索引定期清除

  1. 歷史索引刪除 http://www.cenhq.com/2017/11/07/elasticsearch-deletes-index-by-date/

其他

  1. Centos 7 Docker命令自動補全 https://medium.com/@ismailyenigul/enable-docker-command-line-auto-completion-in-bash-on-centos-ubuntu-5f1ac999a8a6
  2. Searchguard 插件支持OpenLdap:https://github.com/floragunncom/search-guard-kibana-plugin
  3. 設置登錄認證: https://birdben.github.io/2017/02/08/Kibana/Kibana學習(六)Kibana設置登錄認證
  4. SSL免費證書 https://certbot.eff.org/lets-encrypt/ubuntuxenial-nginx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM