使用filebeat采集TKE容器日志
背景
当业务使用腾讯云容器服务TKE进行部署时,可以通过filebeat来采集TKE中各个pod的日志,写入到下游的Elasticsearch集群中,然后在kibana上进行日志的查询与分析。本文介绍如何使用filebeat daemonset的方式采集容器中的日志。
实战过程
下面以采用运行containerd的TKE容器集群,以采集nginx日志为例,介绍使用filebeat采集nginx pod上的日志并写入到es。
部署nginx daemonset
首先使用了一个Docker Hub中的nginx镜像,部署了一个名为nginx的daemonset:
部署filebeat daemonset
1.创建ConfigMap
filebeat以filebeat.yml文件为主配置文件,首先创建一个filebeat.yml配置的ConfigMap,
新建的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:
3.配置数据卷
4.配置运行参数
5.配置挂载点
数据卷和挂载点说明:
(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日志:
通过以上步骤,可以看到,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
---
配置说明:
- 命令空间为default,根据需要也可以直接替换
- 创建了名为filebeat的服务账号,并且授予获取pods列表、获取pod详情等接口的权限,filebeat会使用该账号获取到pods的元信息
- 通过container input采集/var/log/containers/目录下的日志, container input可采集容器的stdout和stderr。
在kibana中查看日志, 可以看到每条日志中都包含有kubernetes字段:
上述配置通过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的日志被采集到了: