filebeat采集容器日志時(shí)根據(jù)kubernetes元數(shù)據(jù)限定采集源的問(wèn)題

在使用filebeat采集部署在使用騰訊云TKE容器集群上的日志時(shí),會(huì)把default、kube-system等默認(rèn)的命名空間下的日志都采集上來(lái),但是這些命名空間下的日志一般都不是我們需要的,怎么過(guò)濾掉對(duì)這些命名空間下的容器運(yùn)行日志?比較直觀(guān)的想法是在filebeat的yml配置中定義好processors,使用drop_event processor對(duì)采集上來(lái)的不需要的日志進(jìn)行丟棄,這種方法雖然能夠?qū)崿F(xiàn)日志的過(guò)濾,但是filebeat還是會(huì)對(duì)不需要采集的容器日志進(jìn)行監(jiān)聽(tīng)和采集,一定程度上降低了filebeat的效率,所以有沒(méi)有好的方法能夠從源頭就不采集不需要的日志呢?

1. 使用filebeat 7.x版本采集容器日志

對(duì)于容器日志的采集,filebeat有專(zhuān)門(mén)的inupt類(lèi)型:docker和container兩種,早期的6.x版本的filebeat只有docker input類(lèi)型,對(duì)于使用docker作為運(yùn)行時(shí)組件的kubernetes集群,比較友好;在7.2版本的filebeat又重新開(kāi)發(fā)了container類(lèi)型的input類(lèi)型,無(wú)論是docker組件還是containerd組件,都可以比較好的支持。因此從7.2版本開(kāi)始,docker input就被廢棄了,官方推薦使用container input。

在使用filebeat 7.x版本采集容器日志時(shí),推薦采用container input,并且使用autodiscover實(shí)現(xiàn)容器的自動(dòng)發(fā)現(xiàn),也就是在有新的容器運(yùn)行時(shí),filebeat會(huì)自動(dòng)去采集新建的容器日志,而不需要再去修改filebeat.yml來(lái)實(shí)現(xiàn)對(duì)新部署的容器日志的采集。而正式使用autodiscover功能,使得限定采集源成為了可能,因?yàn)樵赼utodiscover模式下,filebeat在啟動(dòng)時(shí)就會(huì)去調(diào)用kubernetes API來(lái)獲取當(dāng)前集群下所有的namespace、pod、container等元數(shù)據(jù)的信息,然后根據(jù)這些元數(shù)據(jù)再去指定的目錄采集對(duì)應(yīng)的日志。

下面給出一個(gè)可用的限定采集源的filebeat.yml:

filebeat.autodiscover:
  providers:
    - type: kubernetes
      hints.enabled: true
      templates:
        - condition:
            and:
              - or:
                  - equals:
                      kubernetes.namespace: testa
                  - equals:
                      kubernetes.namespace: testb
              - equals:
                  kubernetes.container.name: nginx
                  kubernetes.labels:
                    k8s-app: nginx
          config:
             - type: container
               paths:
                - /var/log/containers/${data.kubernetes.pod.name}_${data.kubernetes.namespace}_${data.kubernetes.container.name}-*.log
output.elasticsearch:
  hosts: ['x.x.x.x:9200']
  username: "xxx"
  password: "xxx"

上述配置中,用于限定采集源的就是condition模塊下的部分,用于限定只采集testa 或者 testb命名空間下的nginx容器的日志??梢愿鶕?jù)kubernetes元數(shù)據(jù)來(lái)限定采集源,可用的元數(shù)據(jù)有以下這些:

host
port (if exposed)
kubernetes.labels
kubernetes.annotations

kubernetes.container.id
kubernetes.container.image
kubernetes.container.name
kubernetes.namespace
kubernetes.node.name
kubernetes.pod.name
kubernetes.pod.uid

kubernetes.node.name
kubernetes.node.uid

kubernetes.namespace
kubernetes.service.name
kubernetes.service.uid
kubernetes.annotations

上述配置中,condition可以根據(jù)需求定義更復(fù)雜的限定條件,可以參考Conditions進(jìn)行填寫(xiě)。

另外需要注意的是,上述配置中的config模塊下的paths路徑,需要也通過(guò)占位符對(duì)日志文件的名稱(chēng)進(jìn)行匹配,否則就會(huì)出現(xiàn)采集上來(lái)的日志內(nèi)容與kubernetes元數(shù)據(jù)不一致的問(wèn)題。比如/var/log/containers目錄下有各個(gè)pod的日志,日志文件名的命名規(guī)則為{pod_name}_{namespace}_{container_name}-{container_id}.log

nginx-6c5ff7b97b-6t5k4_default_nginx-eeecb30c81564668b1858c186099ab525431b435ed1b8fa3b25704cbbbca6a2d.log

那么 paths就需要通過(guò)$符進(jìn)行規(guī)則匹配:

${data.kubernetes.pod.name}_${data.kubernetes.namespace}_${data.kubernetes.container.name}-*.log

2. 使用filebeat 6.x版本采集容器日志

6.x版本的filebeat,只有docker input, 對(duì)于docker運(yùn)行時(shí)組件比較友好,而對(duì)于containerd運(yùn)行時(shí)組件,不太友好,沒(méi)有較好的方式限定采集源,只能全量采集所有容器的日志。

2.1 采集docker組件部署的kubernetes集群中的容器日志:

filebeat.autodiscover:
  providers:
    - type: kubernetes
      templates:
        - condition:
            and:
              - equals:
                  kubernetes.labels:
                    k8s-app: nginx
          config:
             - type: docker
               combine_partial: true
               containers:
                 ids:
                   - ${data.kubernetes.container.id}
output.elasticsearch:
  hosts: ['http://x.x.x.x:9200']
  username: "xxxx"
  password: "xxx"

其中的condition條件用于限定只采集標(biāo)簽為k8s-app: nginx的容器的日志。

2.2 采集containerd組件部署的kubernetes集群中的容器日志:

filebeat.autodiscover:
  providers:
    - type: kubernetes
      hints.enabled: true
      templates:
        - condition:
            and:
              - equals:
                  kubernetes.labels:
                    k8s-app: nginx
          config:
            - type: docker
              combine_partial: true
              symlinks: true
              containers:
                  path: "/var/log/containers"
                  ids:
                    - ""
output.elasticsearch:
  hosts: ['http://x.x.x.x:9200']
  username: "xxx"
  password: "xxxx"

上述配置與2.1中配置的區(qū)別是,需要顯式的指定container.path為/var/log/containers, 因?yàn)閏ontainerd組件下,容器日志在該目錄下,并且為軟鏈接,需要指定symlinks: true,否則就無(wú)法采集。另外,container.ids需要指定為空字符串,不必限定容器的id的匹配規(guī)則,該配置項(xiàng)對(duì)docker組件部署的容器有效,因?yàn)閐ocker組件下,容器日志默認(rèn)在/var/lib/docker/containers目錄下,且日志文件名采用容器id命名。

上述配置的問(wèn)題就是condition條件不會(huì)生效,會(huì)全量采集所有的命名空間下的容器日志,目前沒(méi)有找到較好的解決辦法來(lái)限定采集源,但是可以通過(guò)定義drop_event processor來(lái)丟棄掉不需要采集的日志。實(shí)際使用中,還是建議直接使用7.2及以上版本的filebeat來(lái)采集使用containerd組件部署的kubernetes集群中的容器日志。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容