跳转至

第07章 日志管理

日志管理图

📚 章节概述

本章将深入讲解日志管理系统,包括ELK Stack(Elasticsearch、Logstash、Kibana)的配置和使用。通过本章学习,你将能够搭建完整的日志收集、存储和分析平台。

🎯 学习目标

完成本章后,你将能够:

  1. 理解日志管理的核心概念和架构
  2. 掌握ELK Stack的配置和使用
  3. 了解Fluentd日志收集
  4. 掌握日志聚合和过滤
  5. 能够搭建生产级的日志管理系统

7.1 日志管理概述

7.1.1 什么是日志管理

日志管理是对系统、应用、网络等产生的日志进行收集、存储、分析和可视化的过程。

日志的类型

  1. 应用日志
  2. 应用程序输出的日志
  3. 业务日志、错误日志
  4. 示例:Python logging、Java Log4j

  5. 系统日志

  6. 操作系统日志
  7. 内核日志、系统服务日志
  8. 示例:/var/log/messages、/var/log/syslog

  9. 访问日志

  10. Web服务器访问日志
  11. API请求日志
  12. 示例:Nginx access.log、Apache access.log

  13. 安全日志

  14. 安全事件日志
  15. 登录日志、审计日志
  16. 示例:/var/log/secure、/var/log/auth.log

7.1.2 日志管理架构

Text Only
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  应用服务    │    │  系统服务    │    │  网络设备    │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                   │                   │
       └───────────────────┼───────────────────┘
                   ┌───────▼────────┐
                   │  日志收集器     │
                   │  (Filebeat/   │
                   │   Fluentd)    │
                   └───────┬────────┘
                   ┌───────▼────────┐
                   │  日志处理      │
                   │  (Logstash/   │
                   │   Fluentd)    │
                   └───────┬────────┘
                   ┌───────▼────────┐
                   │  日志存储      │
                   │  (Elasticsearch)│
                   └───────┬────────┘
                   ┌───────▼────────┐
                   │  日志分析      │
                   │  (Kibana)     │
                   └───────────────┘

7.2 ELK Stack

7.2.1 ELK Stack概述

ELK Stack由Elasticsearch、Logstash、Kibana三个开源工具组成,用于日志管理。

核心组件

  1. Elasticsearch
  2. 分布式搜索引擎
  3. 存储和索引日志
  4. 支持全文搜索

  5. Logstash

  6. 日志收集和处理
  7. 数据转换和过滤
  8. 支持多种输入输出

  9. Kibana

  10. 日志可视化
  11. 仪表板和图表
  12. 数据分析

7.2.2 安装ELK Stack

Docker Compose安装

YAML
services:  # services定义各个服务容器
  # Elasticsearch - 分布式搜索和存储引擎
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node          # 单节点模式,适合开发测试环境
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"   # JVM堆内存,生产环境需调大
      - xpack.security.enabled=false         # 关闭安全认证(仅限开发环境)
    ports:
      - "9200:9200"   # REST API端口
      - "9300:9300"   # 节点间通信端口
    volumes:
      - es-data:/usr/share/elasticsearch/data  # 持久化索引数据
    networks:
      - elk

  # Logstash - 日志处理管道
  logstash:
    image: docker.elastic.co/logstash/logstash:8.12.0
    container_name: logstash
    ports:
      - "5044:5044"   # Beats日志接收端口
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline  # 挂载管道配置文件
    depends_on:
      - elasticsearch
    networks:
      - elk

  # Kibana - 日志可视化和分析界面
  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    container_name: kibana
    ports:
      - "5601:5601"   # Web UI端口
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200  # 指定ES连接地址
    depends_on:
      - elasticsearch
    networks:
      - elk

  # Filebeat - 轻量级日志收集器
  filebeat:
    image: docker.elastic.co/beats/filebeat:8.12.0
    container_name: filebeat
    user: root  # 需要root权限读取宿主机日志文件
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro  # 配置文件(只读)
      - /var/log:/var/log:ro                                          # 宿主机系统日志
      - /var/lib/docker/containers:/var/lib/docker/containers:ro      # Docker容器日志
      - /var/run/docker.sock:/var/run/docker.sock:ro                  # Docker API,获取容器元数据
    depends_on:
      - logstash
    networks:
      - elk

networks:
  elk:
    driver: bridge  # 桥接网络,各服务通过容器名互相访问

volumes:
  es-data:  # ES数据持久化卷

Logstash配置

Text Only
# logstash/pipeline/logstash.conf
input {
  # 接收Filebeat发送的日志数据
  beats {
    port => 5044
  }
}

filter {
  # 解析JSON日志(正则匹配以{开头}结尾的消息)
  if [message] =~ /^\{.*\}$/ {
    json {
      source => "message"
    }
  }

  # 解析Nginx访问日志
  if [type] == "nginx-access" {
    grok {
      match => { "message" => "%{COMBINEDAPACHELOG}" }  # 预定义的Apache/Nginx组合日志格式
    }
  }

  # 添加时间戳
  date {
    match => [ "timestamp", "ISO8601" ]
  }

  # 添加地理位置
  if [clientip] {
    geoip {
      source => "clientip"
      target => "geoip"
    }
  }

  # 删除不需要的字段,节省存储空间
  mutate {
    remove_field => [ "message", "host" ]
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "logstash-%{+YYYY.MM.dd}"  # 按日期创建索引,便于生命周期管理
  }

  # 调试输出(生产环境建议移除)
  stdout { codec => rubydebug }
}

Filebeat配置

YAML
# filebeat/filebeat.yml
filebeat.inputs:
# 系统日志采集
- type: log          # 文件日志采集模式
  enabled: true
  paths:
    - /var/log/*.log
    - /var/log/**/*.log
  fields:
    type: system     # 自定义字段,标识日志来源类型
  fields_under_root: true  # 将自定义字段提升到根级别,便于Logstash过滤

# Nginx访问日志采集
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  fields:
    type: nginx-access  # 标记为Nginx日志,Logstash中使用grok解析
  fields_under_root: true

# Docker容器日志采集
- type: container    # 容器日志采集模式,自动解析容器日志格式
  enabled: true
  paths:
    - /var/lib/docker/containers/*/*.log
  processors:
  - add_kubernetes_metadata:     # 自动关联K8s Pod名称、命名空间等元数据
      host: ${NODE_NAME}
      matchers:
      - logs_path:
          logs_path: "/var/log/containers/"

# 输出到Logstash进行进一步处理
output.logstash:
  hosts: ["logstash:5044"]

# Kibana地址,用于加载预置仪表板和索引模式
setup.kibana:
  host: "kibana:5601"

# Filebeat自身的日志配置
logging.level: info
logging.to_files: true
logging.files:
  path: /var/log/filebeat
  name: filebeat
  keepfiles: 7        # 保留最近7个日志文件
  permissions: 0644

7.3 Fluentd

7.3.1 Fluentd概述

Fluentd是一个开源的数据收集器,用于统一日志层。

核心特性

  1. 轻量级
  2. 资源占用少
  3. 高性能
  4. 易于部署

  5. 插件丰富

  6. 500+插件
  7. 支持多种输入输出
  8. 高度可扩展

  9. 灵活配置

  10. 简单的配置语言
  11. 支持路由和过滤
  12. 支持缓冲和重试

7.3.2 安装Fluentd

Kubernetes安装

YAML
apiVersion: v1  # apiVersion指定K8s API版本
kind: ConfigMap  # kind指定资源类型
metadata:
  name: fluentd-config
  namespace: logging
data:
  fluent.conf: |
    # 数据源:持续读取容器日志文件
    <source>
      @type tail                                    # 类似tail -f,持续跟踪文件变化
      path /var/log/containers/*.log                # 采集所有容器日志
      pos_file /var/log/fluentd-containers.log.pos  # 记录读取位置,重启后断点续读
      tag kubernetes.*                              # 为日志打标签,用于后续路由匹配
      read_from_head true                           # 首次启动从文件头开始读取
      <parse>
        @type json
        time_format %Y-%m-%dT%H:%M:%S.%NZ          # K8s容器日志的时间戳格式
      </parse>
    </source>

    # 自动添加Pod名称、命名空间、标签等K8s元数据
    <filter kubernetes.**>
      @type kubernetes_metadata
    </filter>

    # 向日志记录中添加自定义字段
    <filter kubernetes.**>
      @type record_transformer
      <record>
        hostname "#{Socket.gethostname}"            # 记录采集节点的主机名
      </record>
    </filter>

    # 输出到Elasticsearch
    <match kubernetes.**>
      @type elasticsearch
      host elasticsearch
      port 9200
      logstash_format true             # 使用Logstash兼容的索引命名格式
      logstash_prefix fluentd          # 索引前缀:fluentd-YYYY.MM.dd
      logstash_date_format %Y.%m.%d
      include_tag_key true             # 在日志中包含标签字段
      tag_key @log_name
      flush_interval 1s               # 缓冲刷新间隔,每秒写入一次ES
    </match>
---  # YAML文档分隔符
# DaemonSet确保每个节点运行一个Fluentd Pod
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: logging
  labels:
    app: fluentd
spec:  # spec定义资源的期望状态
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule      # 允许调度到Master节点,确保全集群日志采集
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
        - name: FLUENT_ELASTICSEARCH_HOST
          value: "elasticsearch.logging.svc.cluster.local"  # ES服务的集群内DNS地址
        - name: FLUENT_ELASTICSEARCH_PORT
          value: "9200"
        - name: FLUENT_ELASTICSEARCH_SCHEME
          value: "http"
        resources:              # 资源限制,防止Fluentd占用过多节点资源
          limits:
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:           # 挂载宿主机目录以采集日志
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: fluentd-config
          mountPath: /fluentd/etc/
      terminationGracePeriodSeconds: 30   # 优雅终止等待30秒
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: fluentd-config
        configMap:
          name: fluentd-config  # 引用上面定义的ConfigMap
---
# Fluentd的ServiceAccount,提供Pod运行身份
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: logging
---
# ClusterRole授权Fluentd读取Pod和Namespace信息(用于元数据关联)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: fluentd
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - namespaces
  verbs:
  - get
  - list
  - watch
---
# 将ClusterRole绑定到Fluentd的ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: fluentd
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: fluentd
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: logging

7.4 练习题

基础题

  1. 选择题
  2. ELK Stack中的E代表什么?

    • A. Elasticsearch
    • B. Elastic
    • C. Enterprise
    • D. Engine
  3. 简答题

  4. 解释ELK Stack的三个组件。
  5. 说明Fluentd的核心特性。

进阶题

  1. 实践题
  2. 搭建一个完整的ELK Stack。
  3. 配置Fluentd收集Kubernetes日志。
  4. 配置日志过滤和转换。

  5. 设计题

  6. 设计一个生产级的日志管理架构。
  7. 设计一个多环境日志方案。

答案

1. 选择题答案

  1. A(ELK Stack中的E代表Elasticsearch)

2. 简答题答案

ELK Stack的三个组件: - Elasticsearch:分布式搜索引擎,存储和索引日志 - Logstash:日志收集和处理,数据转换和过滤 - Kibana:日志可视化,仪表板和数据分析

Fluentd的核心特性: - 轻量级,资源占用少 - 插件丰富,支持多种输入输出 - 灵活配置,支持路由和过滤

3. 实践题答案

参见7.2-7.3节的示例。

4. 设计题答案

参见7.1-7.3节的架构设计。

7.5 面试准备

大厂面试题

字节跳动

  1. 解释日志管理的架构。
  2. ELK Stack的优缺点是什么?
  3. 如何优化日志查询性能?
  4. 如何处理日志丢失?

腾讯

  1. Fluentd和Logstash的区别是什么?
  2. 如何实现日志的实时分析?
  3. 如何设计日志保留策略?
  4. 如何处理日志格式不一致?

阿里云

  1. Elasticsearch的索引设计原则是什么?
  2. 如何实现日志的告警?
  3. 如何监控日志系统本身?
  4. 如何设计日志权限管理?

📚 参考资料

🎯 本章小结

本章深入讲解了日志管理系统,包括:

  1. 日志管理的核心概念和架构
  2. ELK Stack的配置和使用
  3. Fluentd日志收集
  4. 日志聚合和过滤
  5. 完整的实战案例

通过本章学习,你掌握了日志管理的核心技术,能够搭建生产级的日志管理系统。下一章将深入学习配置管理。