使用 `journald` 驱动时如何查询指定容器的日志
解读
在国内生产环境中,systemd 与 journald 是 CentOS 7/8、Ubuntu 20.04 等主流镜像的默认初始化系统。面试官问此题,核心想验证两点:
- 你是否真的把 Docker 日志驱动从默认 json-file 切到 journald 并落地过;
- 面对大规模集群时,你能否快速、精准、低侵入地捞日志,而不是粗暴地
docker logs。
答不出journalctl关键字段或不会过滤,会被直接判定为“只背过书,没上过线”。
知识点
- 日志驱动配置:
/etc/docker/daemon.json中"log-driver": "journald",重启 Docker 生效。 - journald 索引字段:
- CONTAINER_TAG 镜像名:tag
- CONTAINER_ID_FULL 64 位完整容器 ID
- CONTAINER_NAME 启动时带
k8s_前缀的 Pod 容器名
- journalctl 过滤语法:
-u匹配 systemd unit、-o控制输出格式、-b限制本次启动、_SYSTEMD_UNIT=docker.service限定日志源。 - 时间与分页:
--since、--until支持2024-07-01 08:00:00格式,配合--no-pager可在脚本里直接 grep。 - 性能与权限:
journald日志存/run/log/journal或/var/log/journal,磁盘打爆是常见故障;普通用户需加入 systemd-journal 组才能读取。 - 与 JSON-File 差异:
docker logs仅适用于本地驱动,journald场景下docker logs会直接报错,必须转用journalctl。
答案
-
确认本机日志驱动
docker info | grep 'Logging Driver'
输出应为journald。 -
查询指定容器最近一次启动的日志
已知容器短 ID 为3b8f2e1b5e31,先拿完整 ID:
CID=$(docker inspect -f '{{.Id}}' 3b8f2e1b5e31)用 CONTAINER_ID_FULL 字段精准过滤:
journalctl -o short-iso _SYSTEMD_UNIT=docker.service CONTAINER_ID_FULL=$CID --since '1 hour ago'若只记得容器名 my-nginx,可用:
journalctl -o cat CONTAINER_NAME=my-nginx --since '30 minutes ago' | grep ERROR -
持续 tail 最新日志(等价于
docker logs -f)
journalctl -f -o short-iso CONTAINER_ID_FULL=$CID -
时间范围导出给研发排障
journalctl -o json --since '2024-07-02 14:00:00' --until '2024-07-02 14:30:00' CONTAINER_ID_FULL=$CID > container.json -
权限不足时
sudo usermod -aG systemd-journal ${USER}重新登录即可。
拓展思考
- 多节点场景:journald 日志仅存本机,大规模集群需结合 rsyslog→Kafka 或 fluent-bit+Elasticsearch 做集中化,避免 SSH 逐台
journalctl。 - 字段裁剪:生产镜像建议写 JSON 结构化日志到 stdout,再通过
journalctl -o json直接落盘 ES,减少二次解析 CPU 开销。 - 存储策略:默认 SystemMaxUse=1G 在容器密集节点 3 天就满,需调大
/etc/systemd/journald.conf并配合 logrotate 做压缩。 - 安全加固:敏感业务需开启 Seal=yes 防止日志被篡改,同时把 CONTAINER_ID_FULL 与 Kubernetes Pod UID 做映射,满足等保审计要求。