使用filebeat采集TKE容器日志

使用filebeat采集TKE容器日志

背景

当业务使用腾讯云容器服务TKE进行部署时,可以通过filebeat来采集TKE中各个pod的日志,写入到下游的Elasticsearch集群中,然后在kibana上进行日志的查询与分析。本文介绍如何使用filebeat daemonset的方式采集容器中的日志。

实战过程

下面以采用运行containerd的TKE容器集群,以采集nginx日志为例,介绍使用filebeat采集nginx pod上的日志并写入到es。

部署nginx daemonset

首先使用了一个Docker Hub中的nginx镜像,部署了一个名为nginx的daemonset:


image

部署filebeat daemonset

1.创建ConfigMap

filebeat以filebeat.yml文件为主配置文件,首先创建一个filebeat.yml配置的ConfigMap,


image

新建的ConfigMap中的变量名为filebeat.yml, 内容为具体的配置信息,以下是一个最简单的filebeat.yml配置

filebeat.inputs:
- type: log 
  symlinks: true
  paths:
    - /var/log/containers/*.log

output.elasticsearch:
  hosts: ['x.x.x.x:9200']
  username: "elastic"
  password: "x.x.x.x"

2.使用公有镜像库中的filebeat镜像,部署filebeat daemonset:


image

3.配置数据卷

image

4.配置运行参数


image

5.配置挂载点

image

数据卷和挂载点说明:

(1)使用ConfigMap数据卷,使得filebeat pod可以读取到自定义的filebeat.yml配置

(2) 使用主机路径/var/log/containers, 使得filebeat pod可以读取到其它pod的日志,因为其它pod的日志都会打印在宿主机的/var/log/containers路径下

(3)因为主机路径/var/log/containers下的pod日志,都是使用软链接,链接到/var/log/pods目录下的各个pod的日志文件,因为也需要把主机路径/var/log/containers挂载到filebeat pod上,这也是为什么在filebeat.yml中要定义symlinks: true的原因,因为默认情况下,filebeat不对读取链接文件

6.在kibana中查看日志

进入到filebeat.yml中定义的es集群对应的kibana中,查看对应索引是否生成,是否可以正常查看nginx日志:


image

通过以上步骤,可以看到,nginx的日志可以正常被采集到。但是上述配置采集的是宿主机上所有pod的日志,有时需要只采集固定的某几个pod的日志,该怎么实现呢?

通过YML配置部署一个可以获取到Pod元信息的filebeat demonset

在实际的业务场景中,通常需要通过filebeat采集部署在相同host上的多个pod的日志,往往也需要获取到采集到的pod的元信息,比如命令空间、pod名称、标签等信息,以方便进行过滤或者检索。获取到pod的元信息需要调用k8s的API, filebeat内部也实现了这个功能,因此可以直接使用filebeat的container input以及add_kubernetes_metadata processors来实现。

在TKE控制台上,点击”YML创建资源“按钮,直接使用如下yml配置创建filebeat demonset:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: default
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |-
    filebeat.inputs:
    - type: container
      paths:
        - /var/log/containers/*.log
      processors:
        - add_kubernetes_metadata:
            host: ${NODE_NAME}
            matchers:
            - logs_path:
                logs_path: "/var/log/containers/"
   
    processors:
      - add_cloud_metadata:
      - add_host_metadata:
    output.elasticsearch:
      hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
      username: ${ELASTICSEARCH_USERNAME}
      password: ${ELASTICSEARCH_PASSWORD}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: default
  labels:
    k8s-app: filebeat
spec:
  selector:
    matchLabels:
      k8s-app: filebeat
  template:
    metadata:
      labels:
        k8s-app: filebeat
    spec:
      serviceAccountName: filebeat
      terminationGracePeriodSeconds: 30
      containers:
      - name: filebeat
        image: ccr.ccs.tencentyun.com/tke-market/filebeat:7.10.1
        args: [
          "-c", "/etc/filebeat.yml",
          "-e",
        ]
        env:
        - name: ELASTICSEARCH_HOST
          value: x.x.x.x
        - name: ELASTICSEARCH_PORT
          value: "9200"
        - name: ELASTICSEARCH_USERNAME
          value: elastic
        - name: ELASTICSEARCH_PASSWORD
          value: Elastic123
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        securityContext:
          runAsUser: 0
          # If using Red Hat OpenShift uncomment this:
          #privileged: true
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: config
          mountPath: /etc/filebeat.yml
          readOnly: true
          subPath: filebeat.yml
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: varlog
          mountPath: /var/log
          readOnly: true
        - name: varpods
          mountPath: /var/log/pods
          readOnly: true
      volumes:
      - name: config
        configMap:
          defaultMode: 0640
          name: filebeat-config
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: varlog
        hostPath:
          path: /var/log
      - name: varpods
        hostPath:
          path: /var/log/pods
---
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: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: filebeat
  namespace: default
subjects:
  - kind: ServiceAccount
    name: filebeat
    namespace: default
roleRef:
  kind: Role
  name: filebeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: filebeat-kubeadm-config
  namespace: default
subjects:
  - kind: ServiceAccount
    name: filebeat
    namespace: default
roleRef:
  kind: Role
  name: filebeat-kubeadm-config
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat
  labels:
    k8s-app: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  - nodes
  verbs:
  - get
  - watch
  - list
- apiGroups: ["apps"]
  resources:
    - replicasets
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: filebeat
  # should be the namespace where filebeat is running
  namespace: default
  labels:
    k8s-app: filebeat
rules:
  - apiGroups:
      - coordination.k8s.io
    resources:
      - leases
    verbs: ["get", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: filebeat-kubeadm-config
  namespace: default
  labels:
    k8s-app: filebeat
rules:
  - apiGroups: [""]
    resources:
      - configmaps
    resourceNames:
      - kubeadm-config
    verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: default
  labels:
    k8s-app: filebeat
---

配置说明:

  1. 命令空间为default,根据需要也可以直接替换
  2. 创建了名为filebeat的服务账号,并且授予获取pods列表、获取pod详情等接口的权限,filebeat会使用该账号获取到pods的元信息
  3. 通过container input采集/var/log/containers/目录下的日志, container input可采集容器的stdout和stderr。

在kibana中查看日志, 可以看到每条日志中都包含有kubernetes字段:


image

上述配置通过container input直接采集到了filebeat pod所在的node上的所有pod的日志,当然,也包括了filebeat自身的日志,在真实的业务场景中,往往只需要采集业务关心的pod的日志即可,此时一种方式是通过在filebeat.yml中定义processor, 对采集到的所有日志event进行过滤,过滤掉不关心的日志event即可(比如通过drop event processor过滤掉某些不关心的namespace和pod的日志);另外一种解决办法是通过Autodiscover定义新的filebeat.yml配置文件,通过定义模板只采集固定pod的日志,下面是一个简单的Autodiscover配置,该配置只采集容器名称为nginx的pod的日志:

filebeat.autodiscover:
      providers:
        - type: kubernetes
          templates:
            - condition:
                equals:
                  kubernetes.container.name: nginx
              config:
                 - type: container
                   paths:
                    - /var/log/containers/${data.kubernetes.pod.name}_*.log
                     
processors:
      - add_cloud_metadata:
      - add_host_metadata:
output.elasticsearch:
      hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
      username: ${ELASTICSEARCH_USERNAME}
      password: ${ELASTICSEARCH_PASSWORD}


通过修改名为filebeat-config的ConfigMap, 并重新部署pod,使得新配置生效,在kibana中查看日志,可以看到只有nginx pod的日志被采集到了:


image

你可能感兴趣的:(使用filebeat采集TKE容器日志)