Docker日志解析异常及关联问题求助:无效字符、高CPU等
Docker日志解析错误与Promtail读取失败、高CPU问题解决
问题背景
- 环境:Docker 24.0.2,未部署Kubernetes,使用
json-file日志驱动 - 执行
docker logs时部分容器报错,常见错误:Error grabbing logs: invalid character '\\x00' looking for beginning of value Error grabbing logs: invalid character 'l' after object key:value pair err="Could not parse timestamp from 'Error': parsing time \"Error\" as \"2006-01-02T15:04:05.999999999Z07:00\": cannot parse \"Error\" as \"2006\"" - 日志读取无规律:部分容器正常、部分异常;
--tail和--since参数表现不一致 - 当前
/etc/docker/daemon.json配置:{ "data-root": "/storage/docker", "insecure-registries": [###, ###], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "5" } } - 衍生问题:Promtail无法读取异常容器日志,主机CPU占用极高
已尝试无效操作
- 用
sed -i 's/\x00//g' ./*.log*移除日志空字符,导致日志完全无法读取 - 无法删除损坏日志或
~/.docker目录,需保留日志内容
解决方案
1. 修复损坏的JSON日志(保留内容)
json-file驱动要求每一行都是标准JSON,损坏原因多为容器输出非JSON内容、日志切割异常、空字符混入。按以下步骤修复:
单容器日志修复:
- 备份日志:
cp /storage/docker/containers/<容器ID>/<容器ID>-json.log /tmp/backup.log - 安全移除空字符(用
tr比sed更可靠):tr -d '\000' < /tmp/backup.log > /tmp/step1.log - 修复非JSON行:将不符合格式的行包装成合法JSON结构(用当前时间补全timestamp):
awk '/^{"log":.*,"time":".*"}$/ {print $0} !/^{"log":.*,"time":".*"}$/ {print "{\"log\":\"" $0 "\",\"time\":\"" strftime("%Y-%m-%dT%H:%M:%S.000000000Z") "\"}"}' /tmp/step1.log > /tmp/fixed.log - 替换原日志:先停止容器避免写入冲突,再
cp /tmp/fixed.log /storage/docker/containers/<容器ID>/<容器ID>-json.log,最后启动容器
- 备份日志:
批量修复脚本:
遍历所有容器日志自动修复(执行前务必停止所有容器):for log_file in /storage/docker/containers/*/*-json.log; do backup="${log_file}.bak" cp "$log_file" "$backup" tr -d '\000' < "$backup" > "$log_file.tmp" awk '/^{"log":.*,"time":".*"}$/ {print $0} !/^{"log":.*,"time":".*"}$/ {print "{\"log\":\"" $0 "\",\"time\":\"" strftime("%Y-%m-%dT%H:%M:%S.000000000Z") "\"}"}' "$log_file.tmp" > "$log_file" rm "$log_file.tmp" done
2. 解决高CPU占用问题
高CPU多因Docker daemon反复解析损坏日志、Promtail重试读取失败导致:
- 先暂停Promtail服务,待日志修复完成后重启
- 调整Docker日志缓存参数(修改
daemon.json):
重启Docker生效:"log-opts": { "max-size": "100m", "max-file": "5", "cache-disabled": "false", "cache-max-size": "5m", "cache-max-file": "2" }systemctl restart docker,减少daemon解析日志的CPU消耗
3. 预防后续日志损坏
- 自定义Python容器:用
logging模块输出JSON格式日志,避免直接打印非结构化文本:import logging from pythonjsonlogger import jsonlogger logger = logging.getLogger() logger.setLevel(logging.INFO) handler = logging.StreamHandler() formatter = jsonlogger.JsonFormatter('%(asctime)s %(levelname)s %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) - 所有容器日志统一通过stdout/stderr输出,由Docker日志驱动接管,禁止进程直接写日志文件
- 定期备份容器日志,可搭配
logrotate补充Docker的日志切割机制
4. 临时绕过损坏日志让Promtail正常工作
如果暂时无法全量修复,可在Promtail配置中过滤异常容器:
scrape_configs: - job_name: docker docker_sd_configs: - host: unix:///var/run/docker.sock refresh_interval: 15s relabel_configs: - source_labels: [__meta_docker_container_name] regex: ^/异常容器名1$|^/异常容器名2$ action: drop
替换异常容器名为实际名称,先让Promtail正常采集其他日志,降低CPU占用
内容的提问来源于stack exchange,提问作者Niv Cohen
相关产品推荐
相关产品推荐

