K8S 使用 SideCar 模式部署 Filebeat 收集容器日志

2023-11-18

对于 K8S 内的容器日志收集,一般有两种常用的方式:

1、使用 DaemonSet 在每台 Node 上部署一个日志收集容器,用于收集当前 Node 上所有容器挂载到宿主机目录下的日志
2、使用 SideCar 模式将日志收集容器与业务容器部署在同一个 Pod 中,只收集对应容器的日志

这两种方式各有优缺点。使用 DaemonSet 方式部署日志收集服务,管理起来简单,但是如果一个 Node 中运行了过多的 Pod,那么日志收集会存在性能瓶颈。使用 SideCar 模式可以更有针对性的收集容器的日志,但是缺点是在运行了很多的业务时,SideCar 占用的资源也会增加。同时这种方式也会出现跟业务耦合的问题。

在我们实践 K8S 的过程中,结合当前业务的特点,最终选定了 SideCar 的方式,虽然占用的资源会增加,但是基于后期大规模日志收集稳定性的考虑,这些资源消耗是在承受范围之内的。

而日志收集的组件,经过长时间比对各种开源服务,选择了 Filebeat。一个是因为在业务未上容器之前,就是使用的 Filebeat 来收集的日志,在维护方面有很多的经验。还有就是 Filebeat 可以处理一些日志收集中出现的复杂情况,例如对于多行日志的处理(堆栈日志)。

下面对于整个实施步骤进行说明。
 

一、创建命名空间

首先创建一个命名空间,yaml 文件内容如下:

---
apiVersion: v1
kind: Namespace
metadata:
  name: ns-smc-gateway
  labels:
    name: ns-smc-gateway

二、创建 Filebeat 配置文件

由于是使用容器的方式运行 FIlebeat,所以需要使用 Configmap 创建一个 Filebeat 的配置文件,然后通过卷挂载的方式挂载到 Filebeat 容器的指定目录下。

创建 Configmap 的 yaml 文件内容如下(注意命名空间的配置,否则后面 Filebeat 无法挂载 Configmap

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: ns-smc-gateway
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |-
    filebeat.idle_timeout: 2s
    filebeat.inputs:
    - type: log
      paths:
       - /opt/logs/app.log
      fields:
        type: app-log
      enabled: true
      backoff: 1s
      backoff_factor: 2
      close_inactive: 1h
      encoding: plain
      harvester_buffer_size: 262144
      max_backoff: 10s
      max_bytes: 10485760
      scan_frequency: 10s
      tail_lines: true
    - type: log
      paths:
       - /opt/logs/app.err
      fields:
        type: app-err-log
      enabled: true
      backoff: 1s
      backoff_factor: 2
      close_inactive: 1h
      encoding: plain
      harvester_buffer_size: 262144
      max_backoff: 10s
      max_bytes: 10485760
      scan_frequency: 10s
      tail_lines: true

    filebeat.name: filebeat-shiper
    filebeat.spool_zie: 50000
    output.elasticsearch:
      bulk_max_size: 8192
      hosts:
      - 10.16.12.206:30187
      - 10.16.12.207:30187
      - 10.16.12.208:30187
      - 10.16.13.214:30187
      - 10.16.13.215:30187
      index: smc-gateway-%{[fields.type]}-*
      indices:
        - index: smc-gateway-app-log-%{+yyyy.MM.dd}
          when.equals:
            fields.type: app-log
        - index: smc-gateway-app-err-log-%{+yyyy.MM.dd}
          when.equals:
            fields.type: app-err-log
      workers: 4
    processors:
    - drop_fields:
        fields:
        - agent.ephemeral_id
        - agent.hostname
        - agent.id
        - agent.type
        - agent.version
        - ecs.version
        - input.type
        - log.offset
        - version
    - decode_json_fields:
        fields:
        - message
        max_depth: 1
        overwrite_keys: true
    setup.ilm.enabled: false
    setup.template.name: smc-gateway-log
    setup.template.pattern: smc-gateway-*
    setup.template.overwrite: true
    setup.template.enabled: true

三、创建 Deployment

接下来使用 Deployment 控制器来部署 Pod,这个 Pod 中包含了业务容器和 Filebeat 服务容器。yaml 文件内容如下:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: smc-gateway
  namespace: ns-smc-gateway
  labels:
    app: smc-gateway
spec:
  replicas: 1
  selector:
    matchLabels:
      app: smc-gateway
  template:
    metadata:
      name: smc-gateway
      labels:
        app: smc-gateway
    spec:
      imagePullSecrets:
      - name: harbor-secret
      containers:
      - name: smc-gateway-for-test                         # 业务容器的名称
        image: 10.16.12.204/smc-gateway/smc-gateway:1.1    # 业务容器镜像的私服下载地址
        imagePullPolicy: Always
        env:                                               # 需要传入到业务容器中的环境变量,在服务启动的时候调用
          - name: data_center
            value: bx
          - name: server_mode
            value: test
        volumeMounts:                                      # 指定业务日志在容器中输出的目录
        - name: logdata
          mountPath: /opt/logs

      - name: filebeat-for-smc-gateway                     # 指定 Filebeat 容器的名称
        image: docker.elastic.co/beats/filebeat:7.3.0      # filebeat 镜像下载地址,这里使用的官方镜像仓库
        args: [                                            # 指定服务启动时的参数
          "-c", "/opt/filebeat/filebeat.yml",              # 注意这里,文件的路径和名称要和 Configmap 传入的路径和名称一致
          "-e",
        ]
        env:
        - name: POD_IP                    # 这里是将 pod 的 IP 地址赋值给这个变量传入容器中,便于后面 Filebeat 在日志中添加自定义的字段信息
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: status.podIP
        - name: pod_name                  # 这里是将 pod 的名称赋值给这个变量,便于后面 Filebeat 在日志中添加自定义的字段信息
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        securityContext:                  # 这里用于设置 Pod 的安全上下文
          runAsUser: 0                    # 指定容器内的服务以 ID 为 0 的用户运行(也就是root)
        volumeMounts:
        - name: config                    # 指定 filebeat 配置文件要挂载的路径
          mountPath: /opt/filebeat/
        - name: logdata               # 指定卷的名称,这个名称要和前面业务容器指定的日志路径的卷名称一致,这样后面才会挂载同一个 emptyDir      
          mountPath: /opt/logs/       # 指定要将业务的日志挂载在 filebeat 容器中的路径,这个路径要和 Configmap 中指定的日志路径一致
      volumes:
      - name: logdata                 # 为前面声明名称为 logdata 的卷挂载一个 emptyDir 卷(filebeat 和业务容器都会挂载这个卷)
        emptyDir: {}
      - name: config                  # 为前面声明名称为 config 的卷(filebeat 配置文件)挂载一个 configmap,并指定configmap 的名称
        configMap:
          name: filebeat-config
          items:
          - key: filebeat.yml
            path: filebeat.yml

需要注意的是,使用 SideCar 模式收集容器日志实现的本质,就是将业务容器内的日志路径存储到本地宿主机的一个目录下,然后这个目录也会同时挂载到日志收集服务容器中,这样日志收集服务才可以读取到业务的日志。

所以上面的 yaml 文件中,首先业务容器的日志目录声明为一个卷,并命名为 logdata。而下面的 Filebeat 容器中也声明了一个 logdata 的卷。由于这两个卷名称一样,所以这两个卷挂载是同一个 emptyDir。也就实现了在 Filebeat 容器中读取业务日志的目的。当然使用 emptyDir 将容器中的日志存储到宿主机本地并不是持久化存储,emptyDir 会随着容器的删除而销毁。

四、创建 Service

将业务容器的 8080 端口暴露出去,yaml 文件内容如下:

---
apiVersion: v1
kind: Service
metadata:
  name: smc-service
  labels:
    app: smc-service
  namespace: ns-smc-gateway
spec:
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30378
  selector:
    app: smc-gateway
  type: NodePort

五、验证

将以上 yaml 文件执行后,会在 ns-smc-gateway 命名空间下创建一个 Pod,这个 Pod 中包含两个容器。

[@k8s-master2 ~]# kubectl get pods -n ns-smc-gateway
NAME                          READY   STATUS    RESTARTS   AGE
smc-gateway-fcf598c4b-wphhr   2/2     Running   0          150m

[@k8s-master2 ~]# kubectl describe pod smc-gateway-fcf598c4b-wphhr -n ns-smc-gateway | grep -B1 "Container ID"
  smc-gateway-for-test:
    Container ID:   docker://3711e3a5bc8fafc94ea174578c0a79774f5b25c7eae6c7aa47759e513645f221
--
  filebeat-for-smc-gateway:
    Container ID:  docker://1b87242cdf8632edc1bea2fe23910f68c2d5da0254163b123bfc414829f7bea7

此时到 Kibana 中的索引管理中,会看到已经新增了两个业务索引,配置对应的索引模式后,就可以在 Kibana 中看到对应的日志。

Filebeat 根据不同的日志设置不同的索引

平时在物理机上使用 Filebeat 收集日志时,会编写多个 filebeat 配置文件然后启动多个 filebeat 进程来收集不同路径下的日志并设置相对应的索引。那么如果将所有的日志路径都写到一个 filebeat 配置文件中,就需要根据不同的日志来设置索引了。

其实 logstash 也可以实现这个功能。但是此处只演示在 Filebeat 上实现。步骤和讲解如下:
例如现在有如下三个日志文件,需要输出到不同的索引

access.log     ---->  索引:web-nginx-access-log
error.log      ---->  索引:web-nginx-error-log
blacklist.log  ---->  索引:web-nginx-blacklist-log

所需要的 filebeat 配置文件如下:

filebeat.idle_timeout: 2s
filebeat.name: filebeat-shiper
filebeat.spool_zie: 50000

filebeat.inputs:                             # 从这里开始定义每个日志的路径、类型、收集方式等信息
- type: log                                  # 指定收集的类型为 log
  paths:
   - /usr/local/nginx/logs/access.log        # 设置 access.log 的路径
  fields:                                    # 设置一个 fields,用于标记这个日志
    type: access-log                         # 为 fields 设置一个关键字 type,值为 access-log
  enabled: true
  backoff: 1s
  backoff_factor: 2
  close_inactive: 1h
  encoding: plain
  harvester_buffer_size: 262144
  max_backoff: 10s
  max_bytes: 10485760
  scan_frequency: 10s
  tail_lines: true
- type: log
  paths:
   - /usr/local/nginx/logs/error.log         # 设置 error.log 的路径
  fields:                                    # 设置一个 fields,用于标记这个日志
    type: error-log                          # 为 fields 设置一个关键字 type,值为 error-log
  enabled: true
  backoff: 1s
  backoff_factor: 2
  close_inactive: 1h
  encoding: plain
  harvester_buffer_size: 262144
  max_backoff: 10s
  max_bytes: 10485760
  scan_frequency: 10s
  tail_lines: true
- type: log
  paths:
   - /usr/local/nginx/logs/blacklist.log     # 设置 blacklist.log 的路径
  fields:                                    # 设置一个 fields,用于标记这个日志
    type: blacklist-log                      # 为 fields 设置一个关键字 type,值为 blacklist-log
  enabled: true
  backoff: 1s
  backoff_factor: 2
  close_inactive: 1h
  encoding: plain
  harvester_buffer_size: 262144
  max_backoff: 10s
  max_bytes: 10485760
  scan_frequency: 10s
  tail_lines: true

output.elasticsearch:
  workers: 4
  bulk_max_size: 8192
  hosts:                                     # 设置 elastic 的地址  
  - 10.16.12.206:30187
  - 10.16.12.207:30187
  - 10.16.12.208:30187
  - 10.16.13.214:30187
  - 10.16.13.215:30187
  index: web-nginx-%{[fields.type]}-%{+yyyy.MM.dd}     # 设置索引名称,后面引用的 fields.type 变量。此处的配置应该可以省略(不符合下面创建索引条件的日志,会使用该索引,后续会测试是否是这样)
  indices:                                             # 使用 indices 代表要创建多个索引
    - index: web-nginx-access-log-%{+yyyy.MM.dd}       # 设置 access.log 日志的索引,注意索引前面的 web-nginx 要与setup.template.pattern 的配置相匹配
      when.equals:                                     # 设置创建索引的条件:当 fields.type 的值等于 access-log 时才生效
        fields.type: access-log
    - index: web-nginx-error-log-%{+yyyy.MM.dd}
      when.equals:
        fields.type: error-log
    - index: web-nginx-blacklist-log-%{+yyyy.MM.dd}
      when.equals:
        fields.type: blacklist-log
  
processors:
- drop_fields:
    fields:
    - agent.ephemeral_id
    - agent.hostname
    - agent.id
    - agent.type
    - agent.version
    - ecs.version
    - input.type
    - log.offset
    - version
- decode_json_fields:
    fields:
    - message
    max_depth: 1
    overwrite_keys: true

setup.ilm.enabled: false                    # 如果要创建多个索引,需要将此项设置为 false
setup.template.name: web-nginx-log          # 设置模板的名称
setup.template.pattern: web-nginx-*         # 设置模板的匹配方式,上面索引的前缀要和这里保持一致
setup.template.overwrite: true
setup.template.enabled: true

编辑完成后,启动 filebeat 进程。到 Kibana 中查看索引列表,可以发现已经有三个新创建的索引:

名称                                   运行状况    状态     主分片    副本分片    文档计数    存储大小
web-nginx-access-log-2020.10.28        green     open      1         1         110      73.9kb
web-nginx-error-log-2020.10.28         green     open      1         1         354      155kb
web-nginx-blacklist-log-2020.10.28     green     open      1         1         460      219.5kb

 针对这三个索引创建索引模式后,就可以在 Kibana 中对日志进行展示了。

【Kubernetes】Filebeat以sidecar模式实现容器日志收集

说明

Filebeat可以以sidecar模式来进行容器日志的收集,也就是filebeat和具体的服务容器部署在同一个pod内,指定收集日志的路径或文件,即可将日志发送到指定位置或Elasticsearch这类的搜索引擎。
每个pod内部署filebeat的模式,好处是和具体的应用服务低耦合,可扩展性强,不过需要在yaml进行额外配置。

yaml示例

# app服务
---
apiVersion: v1
kind: Service
metadata:
  name: test-app
  labels:
    app: test-app
spec:
  selector:
    app: test-app
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
    name: test-port
#定义日志收集相关配置的一个configmap
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-filebeat-config
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |-
    filebeat.prospectors:
    - type: log
      paths:
        - /logdata/*.log
      tail_files: true
      fields:
        pod_name: '${pod_name}'
        POD_IP: '${POD_IP}'
    setup.template.name: "app-logs"
    setup.template.pattern: "app-logs-*"
    output.elasticsearch: # 日志输出到ES
      hosts: ["192.168.1.xx:9200","192.168.1.xxx:9200"]
      index: "app-logs-%{+yyyy.MM}"
# deployment, 也可通过daemonset方式
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
spec:
  replicas: 1
  minReadySeconds: 15     #滚动升级15s后标志pod准备就绪
  strategy:
    rollingUpdate:        #replicas为2, 升级过程中pod个数在1-3个之间
      maxSurge: 1         #滚动升级时会先启动1个pod
      maxUnavailable: 1   #滚动升级时允许pod处于Unavailable的最大个数
  selector:
    matchLabels:
      app: test-app
  template:
    metadata:
      labels:
        app: test-app
    spec:
      terminationGracePeriodSeconds: 30 #30秒内优雅关闭程序
      containers:
      - image: hub.exmaple.com/publib/filebeat:6.1.3     #提前下载下来到私有镜像库的镜像(官方的可能会被墙)
        name: filebeat
        args: [
          "-c", "/opt/filebeat/filebeat.yml",
          "-e",
        ]
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: status.podIP
        - name: pod_name
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        securityContext:
          runAsUser: 0
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 200m
            memory: 200Mi
        volumeMounts:
        - name: config               #将configmap的内容放到容器本地目录
          mountPath: /opt/filebeat/
        - name: data
          mountPath: /usr/share/filebeat/data
        - name: logdata       #同一个pod内的两个应用共享目录logdata, 一个写一个读
          mountPath: /logdata
      - name: test-app
        image: hub.example.com/service/test-service:latest  #提供具体服务的app镜像
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: logdata       #指定挂在目录到logdata
          mountPath: /usr/local/tomcat/logs
      volumes:
      - name: data
        emptyDir: {}
      - name: logdata         #定义logdata为EmptyDir类型挂载目录
        emptyDir: {}
      - name: config
        configMap:
          name: test-filebeat-config  #使用前面定义的configmap
          items:
          - key: filebeat.yml
            path: filebeat.yml

查看filebeat和app的运行日志

kubectl logs -f <pod名> filebeat
kubectl logs -f <pod名> test-app

这时可看到详细的运行日志情况,同时elasticsearch上也会新建一个app-logs-xxxx.xx索引

Filebeat 将多个日志输出到不同的 Kafka Topic

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

K8S 使用 SideCar 模式部署 Filebeat 收集容器日志 的相关文章

随机推荐

  • VMware下centos7开机登陆页面死循环问题详细解决

    一 问题描述 昨天安装东西 不了解捉瞎的时候在 etc profile下添加了几行export导入环境变量 结果重启虚拟机到用户登录页面 输入了正确的密码后还是出来的登陆页面 一直进不去 二 问题解决 查看博客发现大概率是更改 etc pr
  • linux中利用rsync实现文件增量同步

    inotify tools的安装和使用方法 使用inotify监控文件或目录变化 inotify是一种强大的 细粒度的 异步的文件系统事件监控机制 linux内核从 2 6 13 起 加入了inotify支持 通过inotify可以监控文件
  • Linux shell脚本中shift的用法说明

    Linux shell脚本中shift的用法说明 shift命令用于对参数的移动 左移 通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理 常见于Linux中各种程序的启动脚本 示例1 依次读取输入的参数并打印参数个数 r
  • Unity基础知识及一些基本API的使用

    Unity基础知识及一些基本API的使用 1 Unity界面介绍 Unity的默认Editor窗口主要呈现为以上布局 它们分别为 1 工具栏 工具栏提供最基本的工作功能 左侧的按钮用于访问 Unity Collaborate Unity 云
  • OC5228 100V多功能LED恒流驱动器-高辉调光 65536:1 调光比

    同脚位拼对拼替代智芯HI7001 磁吸灯 舞台灯电源方案新贵 概述 OC5228 是一款外围电路简单的多功能平均电流型LED 恒流驱动器 适用于5 100V 电压范围的降压BUCK 大功率调光恒流LED 领域 芯片PWM 端口支持超小占空比
  • React学习(懒加载)

    学习目标 提示 10分钟学会组件懒加载 1 路由懒加载 SPA应用中 为了优化首页加载和渲染性能 让路由页面组件按需访问加载 解决方案 路由懒加载 代码操作 编辑App jsx import App css 引入页面组件 import Lo
  • 太不可思议了,我的文章居然有人转载

    今天无意间逛Google 发现有人转载我的垃圾文章 简直不可思议 http www newbooks com cn info 50429 html 本来是写起耍的 算是整理加一点实际经验写成的 让我又高兴又惭愧 惭愧文章写的差 高兴我的文章
  • js遍历数组中的对象并拿到值

    拿到一组数组 数组中是对象 想拿到这个对象里面的某个值 可以参考以下例子 这样就拿到所有n1的值 想拿到这个对象里面所有对应的值如下 也可以这样取值 往数组里面push多个值 js中 用法 双叹号可以理解为将其强制类型转换为布尔值 例如 a
  • WebSocket协议深入理解

    1 WebSocket和HTTP的关系 WebSocket只有在建立握手连接的时候借用了HTTP协议的头 连接成功后的通信部分都是基于TCP的连接 总体来说 WebSocket协议是HTTP协议的升级版 2 研究WebSocket的思路 服
  • cortex-M3 异常-- SVC、PendSV介绍

    出处 http blog csdn net guozhongwei1 article details 49544671 问 ucos 任务切换时机 如何满足实时性 找上SVC PendSV啦 先了解下 以下出自 cortex M3权威指南
  • C语言中3种不同出错处理方式的优缺点

    这个是我在 数据结构习题集 上看到的一个习题 攒下来自己收藏 非原创 在程序设计中 常用下列三种不同的出错处理方式 1 用EXIT语句终止执行并报告错误 2 以函数的返回值区别正确返回或错误返回 3 设置一个函数变量的函数参数以区别正确返回
  • 移动开发!如何快速的开发一个完整的直播app,架构师必备技能

    金九银十过后各大网络平台都是各种面经分享 包括已收offer 或面试失败的都有 相信大部分人都拿到了自己心仪的大厂offer 不过也有没有少数没能进到自己内心向往的大厂而懊恼的 那么到底如何才能进大厂 该准备些什么才能进大厂 此时字节总监有
  • 有些so文件没有导入到lib目录问题解决

    在使用第三方sdk或者第三方库时 经常在libs目录下 会有一些so文件 比如高德地图的3Ddemo 就包含两个含有so文件的目录 而有的第三方不止两个目录的so文件 正常是这样子的 有多个文件目录的 但是 如果有的sdk只有两个关于so文
  • 给定一个数字范围,求一个数出现的次数

    题目 输入 29 33 3 输出 5 3出现5次 import sys def find lis start lis 0 end lis 1 m lis 2 n 0 for i in range start end 1 j i while
  • 前端单元测试03之Sion

    前端单元测试03之Sion 前端测试存在的问题 在讲Sinon之前 我们得先讲一下在学习了Mocha chai以及enzyme之后 我们的前端测试还存在的一些问题 比如前台测试需要与后台交互 获取后台数据后再根据相应数据进行测试 又比如一个
  • 关于微信小程序使用JavaScript实现检索算法

    检索算法 拟解决生活中最常见的问题之一 检索问题 查找问题 wxml wxss js 拟解决生活中最常见的问题之一 检索问题 查找问题 该问题要求在一个列表中查找某个具体元素是否出现 若出现 返回具体元素在数组中的位置 否则返回 1 根据列
  • 论文翻译(11) — livox_camera_calib标定论文

    目录 1 引言 2 原理 A 概述 B 边缘提取和匹配 C 外部标定 D 对标定结果上边缘分布的分析 E 初始化和粗略标定 论文链接 https arxiv org pdf 2103 01627v2 pdf 源码链接 https githu
  • 如何判断Linux服务器是否被入侵?

    1 如何判断自己的服务器是否被入侵 背景 随着开源产品的越来越盛行 作为一个Linux运维工程师 能够清晰地鉴别异常机器是否已经被入侵了显得至关重要 个人结合自己的工作经历 整理了几种常见的机器被黑情况仅供参考 以下情况是在CentOS 6
  • 光模块SFP+与SFP、XFP、QSFP、QSFP+的区别

    光收发模块 一 光收发一体模块定义 光收发一体模块由光电子器件 功能电路和光接口等组成 光电子器件包括发射和接收两部分 发射部分是 输入一定码率的电信号经内部的驱动芯片处理后驱动半导体激光器 LD 或发光二极管 LED 发射出相应速率的调制
  • K8S 使用 SideCar 模式部署 Filebeat 收集容器日志

    对于 K8S 内的容器日志收集 一般有两种常用的方式 1 使用 DaemonSet 在每台 Node 上部署一个日志收集容器 用于收集当前 Node 上所有容器挂载到宿主机目录下的日志 2 使用 SideCar 模式将日志收集容器与业务容器