有奖捉虫:行业应用 & 管理与支持文档专题 HOT

背景

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

实战过程

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

部署 nginx daemonset

首先使用了一个 Docker Hub 中的 nginx 镜像,部署了一个名为 nginx 的 DaemonSet。详情请参考 创建简单的 Nginx 服务

部署 filebeat daemonset

1. 创建 ConfigMap
1.1 filebeat 以 filebeat.yml 文件为主配置文件,首先创建一个 filebeat.yml 配置的 ConfigMap。
1.2 进入配置管理 > ConfigMap 页面,单击新建。


1.3 新建的 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 daemonSet

在实际的业务场景中,通常需要通过 filebeat 采集部署在相同 host 上的多个 pod 的日志,通常也需要获取到采集到的 pod 的元信息,例如命令空间、pod 名称、标签等信息,以方便进行过滤或者检索。获取到 pod 的元信息需要调用 k8s 的 API, filebeat 内部也实现了这个功能,因此可以直接使用 filebeat 的container input 以及 add_kubernetes_metadata processors 来实现。
1. 在 TKE 控制台上,单击 YML 创建资源按钮,直接使用如下 yml 配置创建 filebeat daemonSet。
---
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。
2. 在 kibana 中查看日志,可以看到每条日志中都包含有 kubernetes 字段。


3. 上述配置通过 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}

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