ELK:收集k8s容器日志最佳實踐


簡介


  • 關於日志收集這個主題,這已經是第三篇了,為什么一再研究這個課題,因為這個課題實在太重要,而當今優秀的開源解決方案還不是很明朗;

  • 就docker微服務化而言,研發有需求標准輸出,也有需求文件輸出,每次登錄到服務器上去查看日志又多有不妥;現有的解決方案ELK,每次收集新應用日志都要更改配置文件重新適配日志路徑足以讓我們崩潰;

  • 對於k8s,沒有日志系統推行工作就無法進行,總不能讓開發小伙伴登錄到k8s上去找日志吧,鬼知道在哪個pod里;當然,k8s官方提供了解決方案efk,efk最大的問題就是無法對日志有效分組,所有日志都在一個索引里,影響查詢速度不說,對於研發小伙伴查找屬於自己應用的日志也很困難,不得不說,這個解決方案很雞肋;

  • 綜上三條,能夠統籌普通應用、docker微服務、k8s的日志收集方案迫在眉睫,今天就將能解決這些問題的日志收集方案的最佳實踐分享給大家;

  • 該實踐采用的是阿里雲的開源工具 log-pilot 采集日志,采集的過程中就將各種日志打標分類,類似最近比較火的垃圾分類,邏輯結構圖如下:
    img-w500

  • 三種節點類型:

    • k8s使用daemonset類型的副本集,使每個節點運行一個 log-pilot 來收集日志,該日志會含有 k8s_container_name、k8s_pod、k8s_node_name、 k8s_pod_namespace 等打標數據,輸出到相應的 logstash 來做索引
    • 運行docker微服務的主機上運行一個 log-pilot 來收集日志,該日志會含有 docker_container、topic、index 等打標數據,輸出到相應的 logstash 來做索引
    • 普通非容器程序的日志可以采用 filebeat 收集,日志中可以自定義標簽和字段,輸出到對應的 logstash 來做索引

log-pilot 說明和配置


  • 容器日志采集模式現在流行的方式有 SideCar模式和 Node模式,SideCar模式會占用大量資源,而Node模式需要智能的 logging agent 配合,而 log-pilot 就是那個智能的agent
  • log-pilot 可同時支持stdout和容器內文件日志采集,支持聲明式日志配置,同時擁有自動感知(發現)機制、自動checkpoint及具柄保持機制和自動日志數據打標
  • log-pilot 除擁有上述功能,還支持多插件多后端,低消耗,高性能,具體情況請看 K8S 日志實踐

log-pilot 插件支持

img-w500

log-pilot 工作模式

img-w500

log-pilot 配置方法

  • Kubernetes 下,Log-Pilot 可以依據環境變量 aliyun_logs_$name = $path 動態地生成日志采集配置文件,其中包含兩個變量:
    • $name 是我們自定義的一個字符串,它在不同的場景下指代不同的含義,在本場景中,將日志采集到 ElasticSearch 的時候,這個 $name 表示的是 Index
    • 另一個是 $path,支持兩種輸入形式,stdout 和容器內部日志文件的路徑,對應日志標准輸出和容器內的日志文件。
    • 第一種約定關鍵字 stdout 表示的是采集容器的標准輸出日志,如本例中我們要采集 tomcat 容器日志,那么我們通過配置標簽 aliyun.logs.catalina=stdout 來采集 tomcat 標准輸出日志。
    • 第二種是容器內部日志文件的路徑,也支持通配符的方式,通過配置環境變量 aliyun_logs_access=/usr/local/tomcat/logs/*.log 來采集 tomcat 容器內部的日志。當然如果你不想使用 aliyun 這個關鍵字,Log-Pilot 也提供了環境變量 PILOT_LOG_PREFIX 可以指定自己的聲明式日志配置前綴,比如 PILOT_LOG_PREFIX: "aliyun,custom"
  • 此外,Log-Pilot 還支持多種日志解析格式,通過 aliyun_logs_$name_format=<format> 標簽就可以告訴 Log-Pilot 在采集日志的時候,同時以什么樣的格式來解析日志記錄,支持的格式包括:none、json、csv、nginx、apache2regxp
  • Log-Pilot 同時支持自定義 tag,我們可以在環境變量里配置 aliyun_logs_$name_tags="K1=V1,K2=V2",那么在采集日志的時候也會將 K1=V1K2=V2 采集到容器的日志輸出中。自定義 tag 可幫助您給日志產生的環境打上 tag,方便進行日志統計、日志路由和日志過濾。

log-pilot 在k8s上的配置

cat > ops-log-pilot-filebeat-ds.yaml << EOF
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: ops-log-pilot-filebeat-ds
  namespace: ops
spec:
  selector:
    matchLabels:
      app: log-pilot-filebeat
      release: stable
  template:
    metadata:
      labels:
        app: log-pilot-filebeat
        release: stable
    spec:
      containers:
      - name: log-pilot-filebeat
        image: registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.6-filebeat
        env:
        - name: "NODE_NAME"
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: "PILOT_LOG_PREFIX"
          value: "glinux"
        - name: "LOGGING_OUTPUT"
          value: "logstash"
        # 請確保集群到ES網絡可達
        - name: "LOGSTASH_HOST"
          value: "logstash.glinux.top"
        - name: "LOGSTASH_PORT"
          value: "5053"
        volumeMounts:
        - name: sock
          mountPath: /var/run/docker.sock
        - name: root
          mountPath: /host
          readOnly: true
        - name: varlib
          mountPath: /var/lib/filebeat
        - name: varlog
          mountPath: /var/log/filebeat
        - name: localtime
          mountPath: /etc/localtime
          readOnly: true
        livenessProbe:
          failureThreshold: 3
          exec:
            command:
            - /pilot/healthz
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 2
        securityContext:
          capabilities:
            add:
            - SYS_ADMIN
      volumes:
      - name: sock
        hostPath:
          path: /var/run/docker.sock
      - name: root
        hostPath:
          path: /
      - name: varlib
        hostPath:
          path: /var/lib/filebeat
          type: DirectoryOrCreate
      - name: varlog
        hostPath:
          path: /var/log/filebeat
          type: DirectoryOrCreate
      - name: localtime
        hostPath:
          path: /etc/localtime
EOF
# 調用方法
kubectl apply -f ops-log-pilot-filebeat-ds.yaml

log-pilot 在docker主機上配置

docker run -d \
   --name log-pilot-filebeat \
   -v /var/run/docker.sock:/var/run/docker.sock \
   -v /etc/localtime:/etc/localtime \
   -v /:/host:ro \
   --cap-add SYS_ADMIN \
   -e PILOT_LOG_PREFIX=glinux \
   -e LOGGING_OUTPUT=logstash \
   -e LOGSTASH_HOST=logstash..glinux.top \
   -e LOGSTASH_PORT=5063 \
   --restart=always \
   registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.5-filebeat

logstash 配置方法


  • logstash的三個實例,我是運行在同一台機器上,同時kibana也是運行在這台機器上
  • 當然也可以通過一個logstash實例,配置中采用判斷條件建立不同索引,但會影響性能,所以這里我起了三個實例
  • logstash的主要功能是將收集到的日志進行拆分,采用某些字段建成索引,傳遞給 elasticsearch 集群
  • 這里強烈建議使用阿里雲的 elasticsearch 集群,可以先使用免費版 1核2G內存20G SSD 三組,原因是阿里雲和elastic有合作,es有授權,很多功能可以使用,比如用戶管理,監控等,后面會說到

logstash 處理k8s日志

  • logstash 監控配置文件,監控信息會體現在kibana中
cat > /data/logslogstash.yml << EOF
xpack.monitoring.elasticsearch.url: http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200
xpack.monitoring.elasticsearch.username: "user"
xpack.monitoring.elasticsearch.password: "pass"
EOF

配置文件

cat > /data/conf/logstash-k8s.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 => ["http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200"]
        user => ["user"]
        password => ["pass"]
        index => "%{k8s_container_name}-%{+YYYY.MM.dd}"
  }
}
EOF

啟動命令

docker run -p 5053:5043 -d \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name logstash-k8s \
    --restart=always \
    -v /data/conf/logstash-k8s.conf:/usr/share/logstash/pipeline/logstash.conf \
    -v /data/conf/logstash.yml:/usr/share/logstash/config/logstash.yml \
    logstash:6.6.2

logstash 處理docker日志

配置文件

cat > /data/conf/logstash-docker.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 => ["xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200"]
        user => ["uesr"]
        password => ["pass"]
        index => "%{docker_container}-%{+YYYY.MM.dd}"
  }
}
EOF

啟動命令

docker run -p 5063:5043 -d \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name logstash-docker \
    --restart=always \
    -v /data/conf/logstash-docker.conf:/usr/share/logstash/pipeline/logstash.conf \
    -v /data/conf/logstash.yml:/usr/share/logstash/config/logstash.yml \
    logstash:6.6.2

elasticsearch 說明


  • 如上所述,elasticsearch 使用阿里雲的產品 阿里雲 · Elasticsearch
  • 可以先使用免費版 1核2G內存20G SSD 三組
  • 開通后會有 地址、用戶名、密碼等信息,這些是要填寫在logstash的輸出配置文件中
  • 阿里雲和elastic有合作,es有授權,用戶管理、用戶登錄、索引監控、節點監控、logstash監控等功能均可正常使用
  • 除以上外,定期清理es的索引也很有必要,可以參考我之前的博客 ELK:收集Docker容器日志 中 定時刪除過期日志索引文件 章節
  • 使用阿里雲的es后,kibana上會有授權體現,這里貼兩張圖展示一下功能

kibana 的監控

img-w500

kibana 的管理

img-w500

kibana 說明和配置


  • 下面步驟操作完畢啟動后,此處訪問 http://IP:5603,用戶名和密碼同 elasticserach 的,輸入即可登錄kibana,如此建立索引,就可以正常的玩耍了

kibana 配置文件

  • 如下的配置文件會屏蔽掉許多沒用的插件功能模塊,如上圖顯示的清爽界面
cat > /data/conf/kibana-es-aliyun.yml << EOF
# Default Kibana configuration from kibana-docker.
server.name: kibana
server.host: "0"
elasticsearch.hosts: http://xxxxxx.es.aliyuncs.com:9200
elasticsearch.username: user
elasticsearch.password: pass
xpack.monitoring.ui.container.elasticsearch.enabled: true
timelion.enabled: false
console.enabled: false
xpack.grokdebugger.enabled: false
xpack.searchprofiler.enabled: false
xpack.canvas.enabled: false
xpack.ml.enabled: false
xpack.infra.enabled: false
xpack.apm.enabled: false
xpack.graph.enabled: false
EOF

kibana 啟動命令

docker run -p 5603:5601 -d \
    --user root \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    --name kibana-es-aliyun \
    --restart=always \
    -e ELASTICSEARCH_URL=http://xxxxxx.es.aliyuncs.com:9200 \
    kibana:6.6.2
  • 下面來看下優秀的登錄界面
    img-w500

日志收集效果驗證


docker日志收集案例 tomcat

  • 注意 label 的配置
   docker run -it -d --name tomcat -p 10080:8080 \
    -v /var/logs/:/usr/local/tomcat/logs \
    --label glinux.logs.catalina=stdout \
    --label glinux.logs.access=/usr/local/tomcat/logs/localhost_access_log.*.txt \
    tomcat
  • 日志收集效果如下圖:
    img-w500

k8s日志收集案例 tomcat

  • 注意env的配置
cat > tomcat-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: tomcat
spec:
  containers:
  - name: tomcat
    image: "tomcat:7.0"
    env:
# 1、stdout為約定關鍵字,表示采集標准輸出日志
# 2、配置標准輸出日志采集到ES的catalina索引下
    - name: glinux_logs_catalina
      value: "stdout"
# 1、配置采集容器內文件日志,支持通配符
# 2、配置該日志采集到ES的access索引下
    - name: glinux_logs_access
      value: "/usr/local/tomcat/logs/catalina.*.log"
# 容器內文件日志路徑需要配置emptyDir
    volumeMounts:
    - name: tomcat-log
      mountPath: /usr/local/tomcat/logs
  volumes:
  - name: tomcat-log
    emptyDir: {}
EOF
# 調用
kubectl apply -f tomcat-pod.yaml -n ops
  • 日志收集效果如下圖:
    img-w500

參考文檔



免責聲明!

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



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