1. 程式人生 > >EFK完成k8s應用日誌收集

EFK完成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