5

kubernetes生产环境使用filebeat sidecar收集日志

 2 years ago
source link: https://zhangrr.github.io/posts/20211110-k8s_sidecar/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在生产环境中,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

FROM alpine:3.12  

ARG VERSION=7.15.1  

COPY docker-entrypoint.sh /  

RUN set -x \  
    && cd /tmp \  
    && wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${VERSION}-linux-x86_64.tar.gz \  
    && tar xzvf filebeat-${VERSION}-linux-x86_64.tar.gz \  
    && mv filebeat-${VERSION}-linux-x86_64 /opt \  
    && rm /tmp/* \  
    && chmod +x /docker-entrypoint.sh  


ENV PATH $PATH:/opt/filebeat-${VERSION}-linux-x86_64  

WORKDIR /opt/filebeat-${VERSION}-linux-x86_64  

ENTRYPOINT ["/docker-entrypoint.sh"]  

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

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

#!/bin/bash 
  
cat > /etc/filebeat.yaml << EOF 
filebeat.config.modules:
  path: /opt/filebeat-7.15.1-linux-x86_64/modules.d/*.yml
  reload.enabled: true

# 加入自定义的字段
fields_under_root: true
fields:
  project: kuaijian-tomcat
  pod_ip: ${POD_IP}
  pod_name: ${POD_NAME}
  node_name: ${NODE_NAME}
  pod_namespace: ${POD_NAMESPACE}
  
# 收集云厂商的数据和docker的变量
processors:
  - add_cloud_metadata: ~
  - add_docker_metadata: ~

filebeat.modules:
  - module: apache
    access:
      enabled: true
      var.paths:
      - "/usr/local/tomcat/logs/localhost_access_log.*.txt"
    error:
      enabled: true
      var.paths:
      - "/usr/local/tomcat/logs/application.log*"
      - "/usr/local/tomcat/logs/catalina.*.log"
      - "/usr/local/tomcat/logs/host-manager.*.log"
      - "/usr/local/tomcat/logs/localhost.*.log"
      - "/usr/local/tomcat/logs/manager.*.log"
      
setup.template.name: "tomcat-logs"
setup.template.pattern: "tomcat-logs-*"
output.elasticsearch:
  hosts: ["172.19.20.xxx:9200","172.19.20.xxx:9200"]
  index: "tomcat-logs-%{+yyyy.MM}"
EOF 
 
set -xe 

# If user don't provide any command 
# Run filebeat 
if [[ "$1" == "" ]]; then 
     exec /opt/filebeat-7.15.1-linux-x86_64/filebeat -c /etc/filebeat.yaml  
else 
    # Else allow the user to run arbitrarily commands like bash 
    exec "$@" 
fi 

我们为什么不在 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文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat
  labels:
    app: tomcat
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: filebeat-sidecar
        image: xxxx.xxxx.xxx/filebeat:xxx
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: spec.nodeName
        - name: POD_IP
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: status.podIP
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name            
        volumeMounts:
        - name: logs-volume
          mountPath: /usr/local/tomcat/logs
      - name: tomcat
        image: tomcat
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: logs-volume
          mountPath: /usr/local/tomcat/logs
      volumes:
      - name: logs-volume
        emptyDir: {}

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK