Kubernetes生产环境使用filebeat Sidecar收集日志

在生产环境中,ES 通常是不会在 k8s 集群中存在的,一般 MySQL 和 Elasticsearch 都是独立在 k8s 之外。

那么无论哪种 pod,要甩日志到 ES,最轻量的方案肯定是用 filebeat 甩过去了。

当然,如果是阿里的 ACK,logtail 和 logstore 配搭已经非常不错了,根本用不到 filebeat 和 ES。

可但是,我们不想为阿里 sls、logstore 出钱买单,就只能用 filebeat + ES 了

说一下 filebeat 的 sidecar 边车(僚机)用法:

image-20211110192939845

如上图所示,简单说就是起一个 filebeat 的 logging-agent 边车(僚机),边车和主应用之间共享某个文件夹(mountPath),达到收集主应用日志并发送到 ES,而不用动 app-container 分毫。

我们以部署一个 Tomcat 应用为例来说明:

一、打造 filebeat 边车镜像

首先准备 Dockerfile

 1FROM alpine:3.12  
 2
 3ARG VERSION=7.15.1  
 4
 5COPY docker-entrypoint.sh /  
 6
 7RUN set -x \  
 8    && cd /tmp \  
 9    && wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${VERSION}-linux-x86_64.tar.gz \  
10    && tar xzvf filebeat-${VERSION}-linux-x86_64.tar.gz \  
11    && mv filebeat-${VERSION}-linux-x86_64 /opt \  
12    && rm /tmp/* \  
13    && chmod +x /docker-entrypoint.sh  
14
15
16ENV PATH $PATH:/opt/filebeat-${VERSION}-linux-x86_64  
17
18WORKDIR /opt/filebeat-${VERSION}-linux-x86_64  
19
20ENTRYPOINT ["/docker-entrypoint.sh"]  

我们以 alphine:3.12 为底版,然后下载 filebeat 7.15.1的二进制包并释放到 /opt 下,最后指定入口文件 /docker-entrypoint.sh

奥妙全在这个 docker-entrypoint.sh 中了

 1#!/bin/bash 
 2  
 3cat > /etc/filebeat.yaml << EOF 
 4filebeat.config.modules:
 5  path: /opt/filebeat-7.15.1-linux-x86_64/modules.d/*.yml
 6  reload.enabled: true
 7
 8# 加入自定义的字段
 9fields_under_root: true
10fields:
11  project: kuaijian-tomcat
12  pod_ip: ${POD_IP}
13  pod_name: ${POD_NAME}
14  node_name: ${NODE_NAME}
15  pod_namespace: ${POD_NAMESPACE}
16  
17# 收集云厂商的数据和docker的变量
18processors:
19  - add_cloud_metadata: ~
20  - add_docker_metadata: ~
21
22filebeat.modules:
23  - module: apache
24    access:
25      enabled: true
26      var.paths:
27      - "/usr/local/tomcat/logs/localhost_access_log.*.txt"
28    error:
29      enabled: true
30      var.paths:
31      - "/usr/local/tomcat/logs/application.log*"
32      - "/usr/local/tomcat/logs/catalina.*.log"
33      - "/usr/local/tomcat/logs/host-manager.*.log"
34      - "/usr/local/tomcat/logs/localhost.*.log"
35      - "/usr/local/tomcat/logs/manager.*.log"
36      
37setup.template.name: "tomcat-logs"
38setup.template.pattern: "tomcat-logs-*"
39output.elasticsearch:
40  hosts: ["172.19.20.xxx:9200","172.19.20.xxx:9200"]
41  index: "tomcat-logs-%{+yyyy.MM}"
42EOF 
43 
44set -xe 
45
46# If user don't provide any command 
47# Run filebeat 
48if [[ "$1" == "" ]]; then 
49     exec /opt/filebeat-7.15.1-linux-x86_64/filebeat -c /etc/filebeat.yaml  
50else 
51    # Else allow the user to run arbitrarily commands like bash 
52    exec "$@" 
53fi 

我们为什么不在 k8s 里用 configmap 来配置 filebeat.yml 呢?

理由是收集日志文件多且路径、类型各不相同,这么一堆的配置都放在 configmap 里会让人癫狂的。所以干脆放到镜像里,便于调试也便于修改。

上面我们也充分利用了 filebeat 的 module,有 module 可用就必须用 module,而不是手动指定 filebeat.inputs ,可用的 mudole 实在太多了,一定要善用!!!另外 tomcat 和 apache 的日志格式是一样的。

我们在最后执行的时候,也加了 exec $@ 便于调试,如果没有指定 CMD,就启动 filebeat,如果指定了比如 /bin/bash,就进入调试状态。

我们打好镜像就 push 到 harbor 里待用

附录:https://www.elastic.co/guide/en/beats/filebeat/current/configuration-general-options.html filebeat的配置列表

二、sidecar部署

我们写一个 k8s 的 tomcat deployment文件:

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: tomcat
 5  labels:
 6    app: tomcat
 7spec:
 8  replicas: 1
 9  selector:
10    matchLabels:
11      app: tomcat
12  template:
13    metadata:
14      labels:
15        app: tomcat
16    spec:
17      containers:
18      - name: filebeat-sidecar
19        image: xxxx.xxxx.xxx/filebeat:xxx
20        env:
21        - name: POD_NAMESPACE
22          valueFrom:
23            fieldRef:
24              apiVersion: v1
25              fieldPath: metadata.namespace
26        - name: NODE_NAME
27          valueFrom:
28            fieldRef:
29              apiVersion: v1
30              fieldPath: spec.nodeName
31        - name: POD_IP
32          valueFrom:
33            fieldRef:
34              apiVersion: v1
35              fieldPath: status.podIP
36        - name: POD_NAME
37          valueFrom:
38            fieldRef:
39              apiVersion: v1
40              fieldPath: metadata.name            
41        volumeMounts:
42        - name: logs-volume
43          mountPath: /usr/local/tomcat/logs
44      - name: tomcat
45        image: tomcat
46        ports:
47        - containerPort: 8080
48        volumeMounts:
49        - name: logs-volume
50          mountPath: /usr/local/tomcat/logs
51      volumes:
52      - name: logs-volume
53        emptyDir: {}

可以看到我们在这个 deployment 里定义了 pod 是单副本,里面跑了两个 container,一个是 filebeat,一个是 tocmat,两者通过同一个 volume 连接在一起,这样就可以做到不修改 tomcat container 而拿到里面的日志了。

这样就把 tomcat 应用的日志收到 ES 去了。


Haproxy一个端口跑多个服务
生产环境kubernetes使用持久化卷GlusterFS
comments powered by Disqus