ELK系列之四---如何通过Filebeat和Logstash优化K8S集群的日志收集和展示

前 言

上一篇文章《日志不再乱: 如何使用Logstash进行高效日志收集与存储》介绍了使用ELK收集通用应用的日志,在目前大多应用都已运行在K8S集群上的环境,需要考虑怎么收集K8S上的日志,本篇就介绍一下如何使用现有的ELK平台收集K8S集群上POD的日志。

K8S日志文件说明

一般情况下,容器中的日志在输出到标准输出(stdout)时,会以.log的命名方式保存在/var/log/pods/containerd_ID/目录中,例如:
在这里插入图片描述

K8S默认会在/var/log/containers/目录下创建软链接链接到/var/log/pods/containerd_id/目录下的具体日志文件,并规范化了软连接到文件名称,软链接的命名规范为

[podName]_[nameSpace]_[depoymentName]-[containerId].log

在这里插入图片描述

上面这个是deployment的命名方式,其他的会有些不同,例如:DaemonSet,StatefulSet等,不过所有的都有一个共同点,就是
每个软链接名称都是

*_[nameSpace]_*.log

所以根据这个日志特征我们可以很容易想到可以根据namespace来分别收集不同名称空间的日志。

一、日志收集架构

在ELK Stack组件中,有logstash和filebeat都可以实现日志收集,因为filebeat更轻量化,在K8S集群中通常使用filebeat来收集pod的日志,通过daemonSet控制器在每个K8S每个节点上运行一个filebeat来收集每个节点上的pod日志,filebeat官网图如下,filebeat输出支持对接Elasticsearch、Logstash、Kafka、Redis,本文选择对接Kafka,先缓存filebeat收集的日志,这样可以减少对ES的性能要求。
在这里插入图片描述

filebeat将收集的pod日志保存在K8S集群外的kafka集群,然后通过logstash再从kafka读取、过滤、整理之后再保存到elasticsearch集群中,然后通过kibana可视化管理日志,架构图如下
在这里插入图片描述

此架构中包含了K8S集群、Kafka集群、ElasticSearch集群,具体机器信息如下表

集群主机名IP地址应用
k8s-clusterk8s-master01172.16.1.65k8s-control
k8s-clusterk8s-node01172.16.1.66k8s-work
k8s-clusterk8s-node02172.16.1.67k8s-work
k8s-clusterk8s-node03172.16.1.68k8s-work
kafka-clusterkafka1172.16.1.11zookeeper/kafka/kibana
kafka-clusterkafka2172.16.1.12zookeeper/kafka
kafka-clusterkafka3172.16.1.13zookeeper/kafka
ES-clusteres1172.16.1.101elasticsearch
ES-clusteres2172.16.1.102elasticsearch
ES-clusteres3172.16.1.103elasticsearch
Logstashdeploy172.16.1.70Lostash

二、部署kafka集群

文章《在K8S上部署Cilium组件,看这一篇干货就够了》介绍了k8s-cluster集群的搭建过程,文章《可视化日志分析新境界:手把手教你搭建高效的ElasticSearch集群》介绍了ES-cluster集群的搭建过程

2.1、下载kafka

现在需要搭建kafka-cluster集群,在kafka-cluster集群的三个节点上下载最新版本kafka,下载二进制的压缩包
在这里插入图片描述

在每个节点上创建/opt目录,将kafka压缩包放到/opt目录下,解压并创建软连接
在这里插入图片描述

2.2、搭建zookeeper集群

最新版本kafka的taz包里已经包含了zookeeper的文件,所以在配置kafka之间先配置zookeeper,
三个几点上修改zookeeper配置文件如下
在这里插入图片描述

dataDir       #指定zookeeper的数据目录 
clientPort     #指定zookeeper的监听端口
maxClientCnxns   #限制最大client连接数

修改完成后,3个节点上同时开启zookeeper服务

~# /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties

在这里插入图片描述

查看三个几点都已监听2181端口即表示zookeeper集群搭建成功

2.3、搭建kafka集群

3个节点修改kafka的配置文件,如下图
在这里插入图片描述

broker.id                    #指定kafka的节点IP,每个节点都不相同
listeners                    #指定kafka的监听IP和端口,三个节点分别监听自己的IP
log.dirs                     #指定kafka的数据目录
zookeeper.connect            #指定zookeeper的连接地址,三个地址都写上

其他选项默认即可
3个节点同时启动kafka

~# /opt/kafka/kafka-server-start.sh -daemon /opt/kafka/config/server.properties

在这里插入图片描述

3个几点同时监听2181和9092两个端口即搭建成功

2.4、测试验证kafka

kafka有一个客户端工具OffsetExplorer,可链接kafka
在这里插入图片描述

创建连接时填入任意一个kafka节点的IP即可连接,连接显示绿色表示集群状态正常
可以通过kafka的命令行客户端测试数据的写入的读取

#创建一个topic
~# /opt/kafka/bin/kafka-topic.sh --crate --topic quick-events --bootstrap-server 172.16.1.12:9092 
#写入数据
~# /opt/kafka/bin/kafka-console-producer.sh --topic quick-events --bootstrap-server 172.16.1.12:9092
#读取数据
~# /opt/kafka/bin/kafka-console-consumer.sh --topic quick-events --bootstrap-server 172.16.1.12:9092

在这里插入图片描述

在OffsetExplorer上也可以看到刚才创建的topic和写入的数据
在这里插入图片描述

三、部署filebeat

在K8S集群上使用DaemonSet控制器部署filebeat,可以通过ELK Stack官网下载filebeat的部署文件filebeat-kubernetes.yaml

curl -L -O https://raw.githubusercontent.com/elastic/beats/8.15/deploy/kubernetes/filebeat-kubernetes.yaml

下载完成后修改yaml文件,添加创建elfk名称空间的指令,并修改下面所有资源的namespace为elfk

apiVersion: v1
kind: Namespace
metadata:
  name: elfk
  labels:
    name: elfk

修改ConfigMap部分,指定了按namespace收集

apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: elfk
  labels:
    k8s-app: filebeat
data:
  filebeat.yml: |-
    filebeat.inputs:
    - type: container
      enabled: true
      paths:
        - /var/log/containers/*_kube-system_*log
      fields:
        log_topic: kube-system
        env: dev
      multiline.pattern: '(^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\])|(^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3})|(^[0-9]{2}:[0-9]{2}:[0-9]{2})'
      multiline.negate: true
      multiline.match: after
      multiline.max_lines: 100

    - type: container
      enabled: true
      paths:
        - /var/log/containers/*_elfk_*log
      fields:
        log_topic: elfk
        env: dev
      multiline.pattern: '(^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\])|(^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3})|(^[0-9]{2}:[0-9]{2}:[0-9]{2})'
      multiline.negate: true
      multiline.match: after
      multiline.max_lines: 100
  
    - type: container
      enabled: true
      paths:
        - /var/log/containers/*_defaulte_*log
      fields:
        log_topic: defaulte
        env: dev
      multiline.pattern: '(^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\])|(^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3})|(^[0-9]{2}:[0-9]{2}:[0-9]{2})'
      multiline.negate: true
      multiline.match: after
      multiline.max_lines: 100
 
    - type: container
      enabled: true
      paths:
        - /var/log/containers/*_metallb-system_*log
      fields:
        log_topic: metallb-system
        env: dev
      multiline.pattern: '(^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\])|(^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3})|(^[0-9]{2}:[0-9]{2}:[0-9]{2})'
      multiline.negate: true
      multiline.match: after
      multiline.max_lines: 100
  
    - type: container
      enabled: true
      paths:
        - /var/log/containers/*_redis_*log
      fields:
        log_topic: redis
        env: dev
      multiline.pattern: '(^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\])|(^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3})|(^[0-9]{2}:[0-9]{2}:[0-9]{2})'
      multiline.negate: true
      multiline.match: after
      multiline.max_lines: 100
    filebeat.config.modules:
      path: ${path.config}/modules.d/*.yml
      reload.enabled: false

    processors:
    #添加k8s元数据信息
    - add_kubernetes_metadata:
        host: ${NODE_NAME}
        matchers:
        - logs_path:
            logs_path: "/var/log/containers/"
  
     #移除多余的字段
    - drop_fields:
        fields:
          - host
          - ecs
          - log
          - agent
          - input
          - stream
          - container
          - kubernetes.pod.uid
          - kubernetes.namespace_uid
          - kubernetes.namespace_labels
          - kubernetes.node.uid
          - kubernetes.node.labels
          - kubernetes.replicaset
          - kubernetes.labels
          - kubernetes.node.name
        ignore_missing: true
  
    - script:
        lang: javascript
        id: format_time
        tag: enable
        source: |
          function process(event) {
            var str = event.Get("message");

            // 用括号提取时间戳
            var regex = /^\[(.*?)\]/;
            var match = str.match(regex);
            if (match && match.length > 1) {
              var time = match[1]; //提取的不带括号的时间戳
              event.Put("time", time);
            }

			// 提取不带括号的时间戳
            var regex2 = /^\d{2}:\d{2}:\d{2}/;
            var match2 = str.match(regex2);
            if (match2) {
              time = match2[0]; // Extracted timestamp
              event.Put("time", time);
            }
          }
  
     #优化层级结构
    - script:
        lang: javascript
        id: format_k8s
        tag: enable
        source: |
          function process(event) {
            var k8s = event.Get("kubernetes");
            var newK8s = {
              podName: k8s.pod.name,
              nameSpace: k8s.namespace,
              imageAddr: k8s.container.name,
              hostName: k8s.node.hostname
            };
            event.Put("k8s", newK8s);
          }
    #添加时间,可以在logstash处理
    - timestamp:
        field: time
        timezone: Asia/Shanghai
        layouts:
          - '2006-01-02 15:04:05'
          - '2006-01-02 15:04:05.999'
        test:
          - '2019-06-22 16:33:51'

修改daemonset部分,添加k8s-control-plan容忍,允许在master节点上运行filebeat

    spec:
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule

部署filebeat

~# kubectl apply -f filebeat-kubernetes.yaml

在这里插入图片描述

检查资源运行情况

~# kubectl get all -n elfk -o wide

在这里插入图片描述

4个节点上都运行filebeat的pod即表示部署成功

四、部署Logstash

4.1、检查kafka上topic

先通过OffsetExlporer查看kafka上是否成功收到了数据,产生了topic
在这里插入图片描述

上图可以看到以namespace为名称产生了topic,说明数据已经成功对接到了kafka集群
在kafka集群上不可很好的查看和检索日志数据,现在需要将kafka上的日志传输到ES集群上,这里需要使用Logstash对日志进行转发和过滤

4.2、部署Logstash

这里复用上一篇里部署的Logstash,新写一份对接kafka的配置文件即可,如下图
在这里插入图片描述

input                   #写入kafka集群的一个节点地址
topics                  #写入kafka集群上已经产生的topic
codec                  #使用json插件解码,生成多个日志字段
output                 #写入ES集群的连接地址
index                   #写入index名称

可以先测试一下配置文件是否正确

~# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/kafka-to-es.conf -t

重启logstash

~# systemctl restart logstash

在这里插入图片描述

4.3、检查ES上数据

可以通过elasticsearch head插件或者cerebro插件查看ES-cluster集群上数据是否成功产生
在这里插入图片描述

可以看到ES-cluster上产生jnlikai-k8s-container-log开头的index表示k8s的日志数据已经被转发到了ES集群

五、在Kibana上检索日志

在Kibana上创建数据视图
在这里插入图片描述

创建成功后可以看到此视图下有很多k8s的日志字段,检索日志时可以根据这些字段进行任意筛选检索
在这里插入图片描述

查看视图时也可以看到K8S上的节点、名称空间都是单独字段
在这里插入图片描述

在这里插入图片描述

                                         欢迎关注作者的公众号,公众号每天分享运维干货文章 

在这里插入图片描述

<think>首先,用户的问题是:“请问Filebeat 是否支持同时收集主机 Kubernetes 集群日志”。我需要基于提供的引用系统指令来回答。 回顾系统指令: - 所有行内数学表达式必须使用 $...$ 格式。 - 独立公式必须使用 $$...$$ 格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 用户的问题是关于Filebeat是否支持同时收集主机Kubernetes集群日志。提供的引用中有相关信息: - 引用[2]:提到DaemonSet用于确保在集群中的每个节点上运行一个PodFilebeat部署为DaemonSet可以从所有节点上的所有容器收集日志- 引用[1]:Filebeat以DaemonSet运行在Kubernetes集群中的每台宿主机上去收集日志- 引用[3]:通过hostpath方式将日志文件持久化存储到服务器本地,然后通过ELK收集- 引用[5]:Logstash配置示例,Filebeat日志发送到Logstash。 关键点: - Filebeat可以部署为Kubernetes DaemonSet,在每个节点上运行,收集该节点上的容器日志- 同时,Filebeat也可以收集主机日志,因为DaemonSet在每个节点上运行,可以访问主机文件系统。 在Kubernetes环境中,Filebeat作为DaemonSet部署时,它运行在每个节点上,并可以配置为收集: 1. Kubernetes容器日志:通过读取/var/log/containers目录下的日志文件。 2. 主机系统日志:通过读取主机上的日志文件,如/var/log/messages, /var/log/syslog等。 所以,答案是肯定的:Filebeat支持同时收集主机Kubernetes集群日志。 回答结构: 1. 直接回答问题:是。 2. 解释如何实现:通过DaemonSet部署,在每个节点上运行,收集节点上的容器日志主机日志。 3. 引用相关部分:自然地添加引用标识。 4. 生成相关问题。 确保使用中文。 生成相关问题: - 基于主题,如如何配置Filebeat来同时收集主机容器日志FilebeatKubernetes中的最佳实践?等。 最终回答结构: - 开头直接回答。 - 详细解释步骤或原因。 - 引用支持信息。 - 结尾生成相关问题。</think>### Filebeat 是否支持同时收集主机 Kubernetes 集群日志? 是的,Filebeat 完全支持同时收集主机(宿主机)系统 Kubernetesk8s集群日志。这主要通过将 Filebeat 部署为 Kubernetes DaemonSet 来实现。DaemonSet 确保在集群中的每个节点上运行一个 Filebeat Pod,从而使 Filebeat 能够访问并收集该节点上的所有日志数据,包括主机系统日志 Kubernetes 容器日志。以下我将逐步解释实现原理、配置方法关键优势。 #### 1. **实现原理** - **DaemonSet 部署模式**:Filebeat 作为 DaemonSet 运行时,会在每个 Kubernetes 节点上自动启动一个 Pod。这个 Pod 可以挂载主机文件系统(如 `/var/log` 目录),从而直接读取主机日志文件(如系统日志、安全日志等)。同时,它也能访问 Kubernetes 容器日志路径(如 `/var/log/containers`),收集容器化应用的日志[^2]。 - **日志来源区分**:Filebeat 的配置允许同时定义多个输入源(inputs)。例如: - 主机日志:通过读取主机文件路径(如 `/var/log/messages` 或 `/var/log/syslog`)。 - Kubernetes 日志:通过读取容器日志文件(如 `/var/log/containers/*.log`),并自动解析 Kubernetes 元数据(如 Pod 名称、命名空间)。 - **数据转发**:收集日志可以统一发送到下游系统,如 Logstash 或 Elasticsearch,进行进一步处理存储[^1][^5]。 #### 2. **配置方法** 以下是简化配置步骤,确保 Filebeat 同时处理主机 Kubernetes 日志- **步骤 1: 创建 Filebeat DaemonSet 配置文件** 在 Kubernetes 中部署 Filebeat DaemonSet,通过 `hostPath` 挂载主机日志目录。示例 YAML 片段: ```yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: filebeat spec: template: spec: containers: - name: filebeat image: docker.elastic.co/beats/filebeat:8.7.0 volumeMounts: - name: host-logs mountPath: /host/var/log - name: container-logs mountPath: /var/log/containers volumes: - name: host-logs hostPath: path: /var/log - name: container-logs hostPath: path: /var/log/containers ``` 此配置将主机 `/var/log` 容器 `/var/log/containers` 目录挂载到 Filebeat Pod 中[^2][^3]。 - **步骤 2: 配置 Filebeat 输入源** 在 Filebeat 的配置文件(如 `filebeat.yml`)中,定义多个输入源: ```yaml filebeat.inputs: - type: filestream id: host-logs paths: - /host/var/log/messages - /host/var/log/syslog fields: log_type: host - type: container id: k8s-logs paths: - /var/log/containers/*.log fields: log_type: kubernetes ``` - `host-logs` 部分收集主机系统日志- `k8s-logs` 部分收集 Kubernetes 容器日志,并自动添加 Kubernetes 元数据(如 Pod ID)[^1][^5]。 - **步骤 3: 输出到下游系统** 配置 Filebeat日志发送到 Logstash 或 Elasticsearch: ```yaml output.logstash: hosts: ["logstash:5044"] ``` 或直接到 Elasticsearch: ```yaml output.elasticsearch: hosts: ["elasticsearch:9200"] indices: - index: "host-logs-%{+yyyy.MM.dd}" when.equals: fields.log_type: "host" - index: "k8s-logs-%{+yyyy.MM.dd}" when.equals: fields.log_type: "kubernetes" ``` 这样可以根据日志类型分离存储,便于查询[^1][^5]。 #### 3. **关键优势** - **高效统一**:DaemonSet 模式避免了在每个容器中单独部署日志代理,减少了资源开销。Filebeat 轻量级(资源占用小),适合高密度环境[^2]。 - **灵活性**:支持自定义过滤字段添加,例如通过 Logstash日志进行预处理(如提取特定错误码)[^5]。 - **可扩展性**:适用于混合环境,例如在 Kubernetes 节点上同时运行主机服务(如数据库)容器化应用[^3]。 - **可靠性**:Filebeat 内置重试机制,确保网络中断时日志不丢失。 #### 4. **注意事项** - **权限问题**:确保 Filebeat Pod 有足够权限读取主机文件(通常通过 Kubernetes SecurityContext 设置 `privileged: true` 或适当 SELinux 策略)。 - **性能影响**:在高日志量场景下,监控 Filebeat 的资源使用(CPU/内存),避免影响节点性能。建议设置日志轮转压缩[^1]。 - **Kubernetes 元数据**:启用 `add_kubernetes_metadata` 处理器,自动丰富日志上下文,便于 Kibana 可视化[^2]。 总之,Filebeat 通过 DaemonSet 部署是同时收集主机 Kubernetes 日志的推荐方法,已在生产环境中广泛验证。如果您有具体环境细节,我可以提供更针对性的配置建议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值