12月31, 2020

记一次Filebeat无法监控Docker日志文件的bug

因为直接使用Elastic默认配置,忽视了机器上Docker的非默认设置导致集群日志检索不可用的故障排查过程。运维人员修改了系统级软件的默认配置后,最好告诉一下会用这台机器的其他运维人员。

因为项目需要,需要在客户方提供的一台机器上部署Anylearn。其中系统组件完全部署完成后,所有系统功能正常,但是唯独日志无法获取。

故障排除过程

首先因为认为部署文件是从官方网站直接下载的所以排除了是由于配置项错误导致的问题。日志系统使用了Elastic官方提供的ECK1.3,包括Elasticsearch 7.9.2 + Kibana 7.9.2 + Filebeat 7.9.2。配置文件如下

apiVersion: beat.k8s.elastic.co/v1beta1
kind: Beat
metadata:
  name: filebeat
spec:
  type: filebeat
  version: 7.9.2
  elasticsearchRef:
    name: elasticsearch
  kibanaRef:
    name: kibana
  config:
    filebeat:
      autodiscover:
        providers:
        - type: kubernetes
          node: ${NODE_NAME}
          hints:
            enabled: true
            default_config:
              type: container
              paths:
              - /var/log/containers/*${data.kubernetes.container.id}.log
    processors:
    - add_cloud_metadata: {}
    - add_host_metadata: {}
  daemonSet:
    podTemplate:
      spec:
        serviceAccountName: filebeat
        automountServiceAccountToken: true
        terminationGracePeriodSeconds: 30
        dnsPolicy: ClusterFirstWithHostNet
        hostNetwork: true # Allows to provide richer host metadata
        containers:
        - name: filebeat
          securityContext:
            runAsUser: 0
            # If using Red Hat OpenShift uncomment this:
            #privileged: true
          volumeMounts:
          - name: varlogcontainers
            mountPath: /var/log/containers
          - name: varlogpods
            mountPath: /var/log/pods
          - name: varlibdockercontainers
            mountPath: /var/lib/docker/containers
          env:
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
        volumes:
        - name: varlogcontainers
          hostPath:
            path: /var/log/containers
        - name: varlogpods
          hostPath:
            path: /var/log/pods
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  verbs:
  - get
  - watch
  - list
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat
subjects:
- kind: ServiceAccount
  name: filebeat
  namespace: default
roleRef:
  kind: ClusterRole
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elasticsearch
spec:
  version: 7.9.2
  http:
    tls:
      selfSignedCertificate:
        disabled: true
  nodeSets:
  - name: default
    count: 1
    config:
      node.store.allow_mmap: false
---
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
  name: kibana
spec:
  version: 7.9.2
  count: 1
  elasticsearchRef:
    name: elasticsearch
...

检查ElasticSearch

日志上中没有任何的报错信息,首先查看Elasticsearch。使用API/_cat/indices列出所有的索引信息,发现没有filebeat-7.9.2等类似字眼的索引模式。 image.png

说明问题出在Filebeat这边,没有数据被推给elasticsearch

检查Filebeat

观察Filebeat的日志,发现没有任何ERROR级别的log信息,所有的东西看起来一切正常。仔细观察beat信息,发现其中Harvester的部分非常奇怪。 image.png

"filebeat":{"harvester":{"open_files":0, "running": 0}}

这就很奇怪了,从宿主机目录下观察,或者使用vim尝试编辑,都是能正常打开的。进入容器后,使用ls命令不加任何参数,在日志扫描目录/var/log/containers下也能ls出文件,这就很奇怪了。我还以为是filebeat版本的问题,推流不兼容等等,换了很多版本,来回部署。都不行。之后在别的机器上使用相同的配置也部署了,一切正常。区别在于,正常工作的机器上,filebeat的日志里harvester是正常工作的。 image.png

定位问题

最终,我决定调整日志等级,试试看是不是filebeat吞掉了什么报错信息。在配置文件的spec.config下面添加logging.level: debug,有意思的事情就发生了。 image.png

2020-12-31T16:11:51.236Z    DEBUG    [input]    log/input.go:315    stat(/var/log/containers/xlearn-backend-775cd69f64-b5l56_xlearn_xlearn-backend-fb2467621de33f0738db1b5b42866167d08f0c69fca302cc96fb9080c3a9d1e3.log) failed: stat /var/log/containers/xlearn-backend-775cd69f64-b5l56_xlearn_xlearn-backend-fb2467621de33f0738db1b5b42866167d08f0c69fca302cc96fb9080c3a9d1e3.log: no such file or directory

好家伙,这么重要的信息你都放在debug里吗???我当即进入容器,然后ls这些日志文件,发现在/var/log/containers目录下,这些日志文件确实是存在的,我尝试cat了其中一个,但是却发现真的打不开。我使用ls -l命令重新扫描了一下这个目录,然后发现了bug的源头: image.png

这些文件都是软链接,而软连接最终指向的文件不见了!我沿着链接路径从/var/log/containers/追踪到了/var/log/pods/目录下,发现这里的文件也都是软链接,他们指向的文件也不见了。 image.png

最终这些链接指向了/docker/containers目录,但是这个目录在容器里是没有的,而宿主机上有这个目录。

故障原因

宿主机上,运维人员修改了docker默认存放日志的位置,从/var/lib/docker/containers/改到了/docker/containers。默认配置下,filebeat的容器里会挂载宿主机的/var/log/containers/var/log/pods//var/lib/docker/containers三个目录,但是宿主机上/var/lib/docker/containers目录是不存在的,所以导致filebeat只拿到了两个装着日志软链接的目录和一个空目录,没有挂载真正的日志文件,导致harvester不能正确读取日志,最终无法向elasticsearch推流。

总结

  • 不要轻信默认配置
  • 运维人员修改了系统级软件的默认配置后,最好告诉一下会用这台机器的人
  • 找不到的bug建议打开debug级日志,你永远想象不到这里面藏了什么重要的信息

本文链接:https://blog.magichc7.com/post/inform-your-partner-bofore-you-change-any-system-config.html

-- EOF --

相关评论