Docker 容器内运行 rsyslog 报 "rsyslogd is not running... failed" 怎么办?
Docker 容器中 rsyslog 起不来的常见原因:没有 init 系统、缺少 /dev/log 套接字、前台运行配置错误。本文给出 Dockerfile 示例及排错步骤,并说明更推荐的容器日志方案。
容器里跑 rsyslog 的典型坑:容器默认没有 systemd/init,service rsyslog start 不可靠;缺少 /dev/log 套接字导致输入模块报错。让 rsyslog 直接以前台模式作为容器主进程运行最可靠:rsyslogd -n。
可用的 Dockerfile 示例
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y rsyslog && rm -rf /var/lib/apt/lists/*
COPY rsyslog.conf /etc/rsyslog.conf
# 前台模式运行(容器主进程)
CMD ["rsyslogd", "-n"]
关键点:-n 让 rsyslog 前台运行,容器的主进程就是它,挂了容器就退出(可被编排系统重启)。
常见报错排查
"rsyslogd is not running... failed":
用 service rsyslog start 启动失败时,直接手动前台运行看真实报错:
rsyslogd -n -d # debug 模式,输出具体错误
imklog 模块错误(imklog: cannot open kernel log):
容器内读不了内核日志。在 /etc/rsyslog.conf 中注释掉 module(load="imklog")。
/dev/log 不存在:
容器里没有 syslog 套接字。需要其他容器把日志发过来时,改用网络输入:
module(load="imudp")
input(type="imudp" port="514")
module(load="imtcp")
input(type="imtcp" port="514")
更重要的思考:容器里该不该跑 rsyslog?
容器最佳实践是一个容器一个进程,应用日志直接写 stdout/stderr,由容器运行时收集。在容器里跑 rsyslog 通常只在两种场景合理:
- 把容器做成日志收集器(接收其他系统的 syslog);
- 遗留应用只能写 syslog,短期过渡。
观测云对照
收集 syslog 的推荐做法是直接在宿主机或 K8s 中部署观测云 DataKit:开启 syslog 接收器,其他设备/容器把 syslog 发到 DataKit 的 514 端口,日志统一进入观测云平台检索分析。
常见问题(FAQ)
Q:多进程容器怎么管理 rsyslog 和应用?
A:用 supervisord 或 s6 作为 PID 1 管理多个进程;但优先重新评估架构,单容器单进程更清晰。
Q:rsyslog 在容器里收不到宿主机的日志?
A:rsyslog 容器化后只监听自己的网络命名空间。需要端口映射 -p 514:514/udp -p 514:514 才能接收外部 syslog。
Q:K8s 里怎么收 syslog?
A:DataKit DaemonSet 监听宿主机端口,或部署为带 hostNetwork 的采集层;网络设备 syslog 直接发到 DataKit 服务的地址。