线上服务挂了2小时没日志可查!K8s日志采集的坑,我一个不落全踩了

线上服务挂了2小时没日志可查!K8s日志采集的坑,我一个不落全踩了 凌晨1点47分钉钉告警群炸了。订单服务5xx飙到30%用户下单全部超时。我爬起来打开Kibana准备查日志——空的。切到Grafana看Fluent Bit指标——采集量断崖式归零。日志没了线上故障等于在黑暗里排雷。最后这个故障花了2小时才定位根因整个过程中日志系统的崩溃让排查效率暴降80%。事后复盘我发现日志链路上埋了至少4个定时炸弹而这些问题90%的K8s集群都存在只是还没爆而已。事故现场时间周三凌晨1:47告警order-service 5xx rate 20%持续5分钟用户体感下单接口超时页面转圈后报错业务影响核心交易链路中断预估损失约12万/小时打开Kibana查order-service最近10分钟ERROR日志索引里最后一条停在1:32——距离告警过去15分钟之后一片空白。kubectl logs直接看Pod$ kubectl logs order-service-7b8f9c6d4-xk2mn-nproduction--tail100能看到实时日志。应用还在打日志问题出在采集链路。排查踩坑——4步全错第一步Fluent Bit挂了$ kubectl get pods-nlogging-lappfluent-bit NAME READY STATUS RESTARTS AGE fluent-bit-4xk2n1/1 Running03d fluent-bit-7nm9p1/1 Running03d fluent-bit-bx5st1/1 Running03d全部Running没重启。第二步ES写不进去了$curl-selasticsearch.logging.svc:9200/_cluster/health|jq.{status:green,number_of_nodes:3,active_shards:847}集群健康green状态。第三步网络抖动$ kubectlexec-itfluent-bit-4xk2n-nlogging --curl-selasticsearch.logging.svc:9200通的返回正常。到这里已经懵了——Agent在跑、ES正常、网络通畅日志就是不进来。第四步看Fluent Bit自身日志$ kubectl logs fluent-bit-4xk2n-nlogging--tail50关键报错出现了[2025/07/10 01:33:15] [warn] [input:tail:tail.0] pausing tail, mem_buf_limit reached [2025/07/10 01:33:15] [warn] [input:tail:tail.0] pausing tail, mem_buf_limit reached内存缓冲区满了停止读取日志文件。但缓冲区为什么会满正常情况下日志从读取到写入ES只需几十毫秒不可能积压。继续往上翻[2025/07/10 01:30:42] [error] [output:es:es.0] HTTP status429, Retry in 15 seconds [2025/07/10 01:30:57] [error] [output:es:es.0] HTTP status429, Retry in 30 seconds [2025/07/10 01:31:27] [error] [output:es:es.0] HTTP status429, Retry in 60 secondsES返回429Too Many Requestsbulk写入被限流了。根因——4个炸弹同时引爆整个崩溃链路应用日志量突增 → ES bulk队列打满返回429 → Fluent Bit重试堆积 → 内存缓冲区撑满 → 停止采集 → 日志断流日志量为什么突增回头看监控1:30有个CronJob触发数据同步任务每秒打印上万行DEBUG日志日志量瞬间打到平时50倍。4个问题叠加问题本质CronJob没有日志级别控制生产环境跑DEBUGES写入队列太小bulk_queue_size默认200一打满就拒绝Fluent Bit mem_buf_limit只有5MB下游阻塞立刻停采没有对高日志量Pod做采集隔离一个Pod暴增拖垮整个节点任何一个单独存在都不会炸四个叠在一起就是连环爆。修复方案——配置直接拿走修复1缓冲区扩容 文件缓冲兜底内存缓冲从5MB调到50MB开启filesystem buffer满了先落盘不丢弃[SERVICE] Flush 1 Log_Level info HTTP_Server On HTTP_Listen 0.0.0.0 HTTP_Port 2020 storage.path /var/fluent-bit/storage/ storage.sync normal storage.checksum off storage.max_chunks_up 128 [INPUT] Name tail Path /var/log/containers/*.log Parser cri Tag kube.* Mem_Buf_Limit 50MB storage.type filesystem Skip_Long_Lines On Refresh_Interval 5 Rotate_Wait 30 DB /var/fluent-bit/tail-db/pos.db核心storage.type filesystem配合storage.path缓冲区满了日志写本地磁盘暂存下游恢复后再发。这是防丢日志的关键配置。修复2ES扩大写入队列# elasticsearch.ymlthread_pool:write:queue_size:1000# 默认200size:8# 写入线程数按CPU核数调indices:memory:index_buffer_size:20%# 默认10%Fluent Bit output端加重试控制[OUTPUT] Name es Match kube.* Host elasticsearch.logging.svc.cluster.local Port 9200 Logstash_Format On Logstash_Prefix k8s-logs Replace_Dots On Suppress_Type_Name On Buffer_Size 512KB Retry_Limit 5 workers 2workers 2多线程并发写入提高吞吐Retry_Limit 5避免无限重试耗尽资源。修复3高日志量Pod采集隔离 限流[FILTER] Name grep Match kube.* Exclude $kubernetes[labels][logging-exclude] true [FILTER] Name throttle Match kube.batch.* Rate 1000 Window 5 Interval 1s Print_Status trueCronJob Pod模板加标签metadata:labels:logging-exclude:true修复4Kyverno强制生产环境日志级别apiVersion:kyverno.io/v1kind:ClusterPolicymetadata:name:require-log-levelspec:validationFailureAction:Enforcerules:-name:check-log-levelmatch:resources:kinds:-Podnamespaces:-productionvalidate:message:生产环境Pod必须设置LOG_LEVEL且不能为DEBUGpattern:spec:containers:-env:-name:LOG_LEVELvalue:!DEBUG架构改造——加Kafka缓冲层改造前容器stdout → Fluent Bit → Elasticsearch直连改造后容器stdout → Fluent Bit → Kafka缓冲 → Logstash → Elasticsearch ↘ S3审计日志冷存储Kafka扛着ES挂了日志也不丢。Fluent Bit的Kafka output配置[OUTPUT] Name kafka Match kube.* Brokers kafka-0.kafka.svc:9092,kafka-1.kafka.svc:9092,kafka-2.kafka.svc:9092 Topics k8s-logs Timestamp_Key timestamp rdkafka.log.connection.close false rdkafka.request.required.acks 1 rdkafka.message.max.bytes 1048576日志系统自身的监控——不能裸奔# Prometheus告警规则groups:-name:logging-pipelinerules:-alert:FluentBitInputPausedexpr:fluentbit_input_paused 1for:2mlabels:severity:criticalannotations:summary:Fluent Bit采集暂停日志可能丢失-alert:FluentBitOutputRetryHighexpr:rate(fluentbit_output_retries_total[5m])10for:3mlabels:severity:warningannotations:summary:Fluent Bit写入重试频繁下游可能阻塞-alert:KafkaConsumerLagexpr:kafka_consumer_group_lag{grouplogstash-consumer}100000for:5mlabels:severity:warningannotations:summary:日志消费积压超10万条Fluent Bit开启metrics端点[SERVICE] HTTP_Server On HTTP_Listen 0.0.0.0 HTTP_Port 2020Prometheus通过:2020/api/v1/metrics/prometheus拉取。三条血泪教训1. 日志系统必须有自己的监控和告警。日志链路断了你根本不知道等排查线上故障才发现没日志——已经晚了。2. 永远不要让一个Pod的日志暴增拖垮整个节点的采集。做好隔离和限流CronJob/Job这类批处理任务是重灾区。3. 内存缓冲区 ≠ 不丢日志。Mem_Buf_Limit到了就停采必须配合文件缓冲或Kafka才能真正保障。如果你的K8s集群日志方案还是Fluent Bit直连ES、没有缓冲层、没有采集限流、没有日志系统自身的监控——趁没爆之前赶紧改别等凌晨2点被教做人。觉得有用就转发一下让更多人少踩这个坑