k8s 應用日志收集


  • [ ] 在進行日志收集的過程中,我們首先想到的是使用Logstash,因為它是ELK stack中的重要成員,但是在測試過程中發現,Logstash是基於JDK的,在沒有產生日志的情況單純啟動Logstash就大概要消耗500M內存,在每個Pod中都啟動一個日志收集組件的情況下,使用logstash有點浪費系統資源,經人推薦我們選擇使用Filebeat替代,經測試單獨啟動Filebeat容器大約會消耗12M內存,比起logstash相當輕量級。

方案選擇
Kubernetes官方提供了EFK的日志收集解決方案,但是這種方案並不適合所有的業務場景,它本身就有一些局限性,例如:

所有日志都必須是out前台輸出,真實業務場景中無法保證所有日志都在前台輸出
只能有一個日志輸出文件,而真實業務場景中往往有多個日志輸出文件
Fluentd並不是常用的日志收集工具,我們更習慣用logstash,現使用filebeat替代
我們已經有自己的ELK集群且有專人維護,沒有必要再在kubernetes上做一個日志收集服務
基於以上幾個原因,我們決定使用自己的ELK集群。

Kubernetes集群中的日志收集解決方案

編號 方案 優點 缺點
1 每個app的鏡像中都集成日志收集組件 部署方便,kubernetes的yaml文件無須特別配置,可以為每個app自定義日志收集配置 強耦合,不方便應用和日志收集組件升級和維護且會導致鏡像過大
2 單獨創建一個日志收集組件跟app的容器一起運行在同一個pod中 低耦合,擴展性強,方便維護和升級 需要對kubernetes的yaml文件進行單獨配置,略顯繁瑣
3 將所有的Pod的日志都掛載到宿主機上,每台主機上單獨起一個日志收集Pod 完全解耦,性能最高,管理起來最方便 需要統一日志收集規則,目錄和輸出方式

綜合以上優缺點,我們選擇使用方案二。

該方案在擴展性、個性化、部署和后期維護方面都能做到均衡,因此選擇該方案。

filebeat日志收集架構圖
圖片 - filebeat日志收集架構圖
image

鏡像地址:https://github.com/flyhxg/docker-test/tree/master/filebeat-5.4.0

測試
我們部署一個應用filebeat來收集日志的功能測試。

創建應用yaml文件filebeat-test.yaml。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: filebeat-test
  namespace: default
spec:
  replicas: 3
  template:
    metadata:
      labels:
        k8s-app: filebeat-test
    spec:
      containers:
      - image: 192.168.20.210:5000/filebeat:5.4.0
        name: filebeat
        volumeMounts:
        - name: app-logs
          mountPath: /log
        - name: filebeat-config
          mountPath: /etc/filebeat/
      - image: harbor-001.jimmysong.io/library/analytics-docker-test:Build_8
        name : app
        ports:
        - containerPort: 80
        volumeMounts:
        - name: app-logs
          mountPath: /usr/local/TalkingData/logs
      volumes:
      - name: app-logs
        emptyDir: {}
      - name: filebeat-config
        configMap:
          name: filebeat-config
---
apiVersion: v1
kind: Service
metadata:
  name: filebeat-test
  labels:
    app: filebeat-test
spec:
  ports:
  - port: 80
    protocol: TCP
    name: http
  selector:
    run: filebeat-test
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
data:
  filebeat.yml: |
    filebeat.prospectors:
    - input_type: log
      paths:
        - "/log/*"
        - "/log/usermange/common/*"
    output.elasticsearch:
      hosts: ["172.23.5.255:9200"]
      username: "elastic"
      password: "changeme"
      index: "filebeat-docker-test"

說明

該文件中包含了配置文件filebeat的配置文件的ConfigMap,因此不需要再定義環境變量。

當然你也可以不同ConfigMap,通過傳統的傳遞環境變量的方式來配置filebeat。

例如對filebeat的容器進行如下配置:

  containers:
  - image: 192.168.20.210:5000/filebeat:5.4.0
    name: filebeat
    volumeMounts:
    - name: app-logs
      mountPath: /log
    env: 
    - name: PATHS
      value: "/log/*"
    - name: ES_SERVER
      value: 172.23.5.255:9200
    - name: INDEX
      value: logstash-docker
    - name: INPUT_TYPE
      value: log

這里如果有想不通路徑下的日志區分,可以加上document_type

apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
data:
  filebeat.yml: |
    filebeat.prospectors:
    - input_type: log
      paths:
        - "/log/*.log"
      document_type: app-logs
      multiline.pattern: '^[[:space:]]+|^Caused by:|^#{3}|^;|^org|^com'
      multiline.negate: false
      multiline.match: after
    - input_type: log
      paths:
        - "/logs/*.log"
      document_type: access-logs
      multiline.pattern: '^[[:space:]]+|^Caused by:|^#{3}|^;|^org|^com'
      multiline.negate: false
      multiline.match: after
    output.elasticsearch:
      hosts: ["192.168.30.21:9200"]
      index: "filebeat-test-%{+yyyy.MM.dd}"

目前使用這種方式會有個問題,及時PATHS只能傳遞單個目錄,如果想傳遞多個目錄需要修改filebeat鏡像的docker-entrypoint.sh腳本,對該環境變量進行解析增加filebeat.yml文件中的PATHS列表。

推薦使用ConfigMap,這樣filebeat的配置就能夠更靈活。

注意事項

將app的/usr/local/TalkingData/logs目錄掛載到filebeat的/log目錄下。
該文件可以在manifests/test/filebeat-test.yaml找到。
我使用了自己的私有鏡像倉庫,測試時請換成自己的應用鏡像。
Filebeat的環境變量的值配置請參考https://github.com/rootsongjc/docker-images
創建應用

部署Deployment

kubectl create -f filebeat-test.yaml

查看http://172.23.5.255:9200/_cat/indices將可以看到列表有這樣的indices:

green open filebeat-docker-test            7xPEwEbUQRirk8oDX36gAA 5 1   2151     0   1.6mb 841.8kb

訪問Kibana的web頁面,查看filebeat-2017.05.17的索引,可以看到filebeat收集到了app日志。

點開每個日志條目,可以看到以下詳細字段:

filebeat收集的日志詳細信息
圖片 - filebeat收集的日志詳細信息
_index值即我們在YAML文件的configMap中配置的index值
beat.hostname和beat.name即pod的名稱
source表示filebeat容器中的日志目錄
我們可以通過人為得使index = service name,這樣就可以方便的收集和查看每個service的日志。

在使用了6.2.4版本的ELK以后,使用如上配置,if [type]匹配不到在filebeat里面使用document_type定義的字符串。在多次調試和詢問后,發現在6.0版本以上已經取消了document_type的定義。如果要實現以上的配置只能使用如下配置
三、解決方案
?解決方案為在filebeat里面新增一個fields字段,service : GameStatis都是自己定義的,定義完成后使用Logstash的if 判斷,條件為if [fields][service] == "GameStatis".就可以了。
?filebeat配置:

  filebeat.yml: |
    filebeat.prospectors:
    - input_type: log
      paths:
        - "/log/*.log"
      fields:
        service: app_logs


免責聲明!

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



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