Docker容器日志收集与ELK Stack日志分析平台搭建实战

Docker容器日志管理的痛点与解决思路

Docker容器日志是运维排障的一手数据源,但默认配置下日志散落在每个节点的/var/lib/docker/containers/目录,没有集中查询能力,磁盘空间也容易被日志撑满。一个中等规模Kubernetes集群(50个节点、500个Pod),日均日志量可达50-100GB,靠SSH到节点翻日志根本不现实。

容器日志收集的主流方案是Filebeat+ELK Stack(Elasticsearch+Logstash+Kibana)和Fluentd+EFK Stack。本文选择Filebeat方案,原因是Filebeat作为轻量级Shipper对宿主机资源消耗极低,同时与Elasticsearch生态无缝集成,配置和维护成本低于Logstash方案。

Filebeat容器日志采集配置详解

Filebeat的Autodiscover功能可以自动发现新创建的容器并开始采集日志,无需手动为每个容器配置日志路径。这是在Kubernetes环境中使用Filebeat的核心能力。

Filebeat以DaemonSet方式部署到每个节点:

# filebeat-kubernetes.yaml 核心配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: kube-system
data:
  filebeat.yml: |-
    filebeat.autodiscover:
      providers:
        - type: kubernetes
          hints.enabled: true
          templates:
            - condition:
                contains:
                  kubernetes.labels.app: "nginx"
              config:
                - type: container
                  paths:
                    - /var/log/containers/*-${data.kubernetes.container.id}.log
                  processors:
                    - add_kubernetes_metadata:
                        host: ${NODE_NAME}
                        matchers:
                          - logs_path:
                              logs_path: "/var/log/containers/"

    processors:
      - add_cloud_metadata: {}
      - add_host_metadata: {}

    output.elasticsearch:
      hosts: ["elasticsearch:9200"]
      index: "logstash-%{+yyyy.MM.dd}"

关键点:hints.enabled: true开启基于Pod注解的自动发现。给Pod加注解co.elastic.logs/enabled: "true"即可让Filebeat自动采集,不需要改Filebeat配置。

DaemonSet部署部分:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: filebeat
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      serviceAccountName: filebeat
      containers:
        - name: filebeat
          image: docker.elastic.co/beats/filebeat:8.14.0
          args: ["-c", "/etc/filebeat.yml", "-e"]
          volumeMounts:
            - name: config
              mountPath: /etc/filebeat.yml
              subPath: filebeat.yml
            - name: varlog
              mountPath: /var/log
            - name: varlibdockercontainers
              mountPath: /var/lib/docker/containers
              readOnly: true
      volumes:
        - name: config
          configMap:
            name: filebeat-config
        - name: varlog
          hostPath:
            path: /var/log
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers

Elasticsearch索引策略与存储优化

日志量一大,Elasticsearch的存储压力就上来。不加治理的ELK集群3个月就能吃掉几TB磁盘。核心优化策略是索引生命周期管理(ILM):

# 创建ILM策略:热-温-冷三层
PUT _ilm/policy/logstash-policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_size": "30gb",
            "max_age": "1d"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "3d",
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "shrink": {
            "number_of_shards": 1
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "14d",
        "actions": {
          "freeze": {},
          "set_priority": {
            "priority": 0
          }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

热阶段每天rollover一次或单索引超过30GB自动拆分;温阶段3天后force merge为单段并shrink到1分片,大幅减少段文件数和内存占用;冷阶段14天后freeze冻结索引,查询时才加载元数据;30天后自动删除。这套策略让一个日均100GB日志的集群,存储总量控制在3TB以内。

Kibana日志查询与告警看板搭建

Elasticsearch里有了数据,Kibana是前端查询界面。但光有查询还不够,需要配置告警规则主动发现问题。

在Kibana中创建告警规则(以Error日志告警为例):

# 通过Kibana API创建告警规则
POST /api/alerting/rule
{
  "rule_type_id": ".es-query",
  "name": "Pod Error日志告警",
  "params": {
    "aggType": "count",
    "esQuery": "{\"query\":{\"bool\":{\"filter\":[{\"match_phrase\":{\"message\":\"ERROR\"}},{\"range\":{\"@timestamp\":{\"gte\":\"now-5m\"}}}]}}}",
    "size": 100,
    "timeWindowSize": 5,
    "timeWindowUnit": "m",
    "threshold": [
      {
        "comparator": ">",
        "value": 50
      }
    ]
  },
  "actions": [
    {
      "id": "webhook-action-id",
      "params": {
        "body": "5分钟内ERROR日志超过50条,请检查集群状态"
      }
    }
  ]
}

告警规则每5分钟查询一次Elasticsearch,如果5分钟窗口内ERROR日志超过50条就触发告警。Webhook可以对接钉钉、企业微信、飞书的机器人接口。

日志查询看板的常用过滤技巧:

# Kibana KQL查询语法
# 按Pod名查询
kubernetes.pod.name: "order-service-*"

# 按命名空间+错误级别
kubernetes.namespace: "production" and log.level: "ERROR"

# 排除健康检查日志
kubernetes.pod.name: "api-gateway-*" and not message: "health check"

# 按时间范围+关键字段
@timestamp >= "2026-07-28T00:00:00" and @timestamp <= "2026-07-28T08:00:00" and http.status_code: "5*"

容器日志收集的常见故障排查

Filebeat采集延迟:当日志产生速度超过Filebeat发送速度,Filebeat内部队列会积压。检查方法:

# 查看Filebeat监控指标
curl -s localhost:5066/stats | jq '.lib.queue'
# 如果队列长度持续增长,需要增加output.elasticsearch.workers
# 或增大queue.mem.events(默认2048)

# filebeat.yml 调优
queue.mem:
  events: 4096
  flush.min_events: 256
  flush.timeout: 1s

output.elasticsearch:
  workers: 4
  bulk_max_size: 2048

日志文件被Docker轮转丢失:Docker默认json-file驱动有max-sizemax-file参数,当达到限制会轮转旧日志。如果Filebeat还没来得及读就被轮转删除,日志就丢了。解决方法:

# /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "5"
  }
}

把max-size设大一点,给Filebeat足够的采集窗口。同时确保Filebeat的close_renamedclose_removed配置合理,避免文件被轮转后Filebeat仍在读旧文件句柄。

Elasticsearch写入拒绝:当日志量突增(比如故障导致大量ERROR日志),Elasticsearch可能因为segment merge跟不上而返回429。Filebeat会自动重试,但如果持续拒绝,在Elasticsearch端临时调大写入队列:

PUT _cluster/settings
{
  "persistent": {
    "thread_pool.write.queue_size": 1000
  }
}

同时确认集群没有进入red状态(部分分片不可用导致写入失败),用GET _cluster/health检查。

Docker容器日志收集的搭建不复杂,难点在持续运营:索引膨胀、查询性能退化、采集延迟。ILM策略和监控告警是长期稳定运行的关键保障。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/docker-rong-qi-ri-zhi-shou-ji-yu-elkstack-ri-zhi-fen-xi/

(0)
小编小编
上一篇 1小时前
下一篇 1小时前

相关推荐