- 文档/教程
【免费下载链接】90DaysOfDevOps
This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.
导读
在 90DaysOfDevOps 课程的 Elastic Stack(ELK)监控实战中,除了通过 Filebeat/Beats 主动采集日志,还有一条更轻量的路径:使用 Logspout 扩展,让部署在 Docker 里的每个容器无需任何改造,即可借助 Docker logs API 自动把 stdout/stderr 日志转发给 Logstash。本文以仓库中2022/ja/Days/Monitoring/Elastic Stack/extensions/logspout/目录下的扩展定义为核心,讲解 Logspout 的工作原理、Compose 覆盖文件中的关键配置、Logstash 侧的 UDP 输入接入方式,并结合 Dockerfile 与 Go 模块源码说明其底层实现,帮助你快速把"任意容器日志"汇入 Elastic Stack。
Logspout 扩展在 Elastic Stack 中的定位
Elastic Stack 的 Docker 化编排(见 docker-compose.yaml)本身包含 elasticsearch、logstash、kibana、setup 四个核心服务。而extensions/目录专门用于存放"第三方扩展",用于打通更多外部集成(extensions/README.md),其中包括 filebeat、metricbeat、apm-server、curator、enterprise-search 以及本文的主角 logspout。
Logspout 的定位与 Filebeat 不同:它运行在 Docker 宿主机层面,通过挂载/var/run/docker.sock调用 Docker logs API,统一抓取宿主机上所有容器的日志,再转发给 Logstash——容器侧完全不需要任何额外配置(无需打日志、无需装 Agent、无需改 Dockerfile)。这正是 logspout/README.md 开头所强调的:Logspout collects all Docker logs using the Docker logs API, and forwards them to Logstash without any additional configuration。
工作原理:一条从 Docker Socket 到 Logstash 的日志管道
Logspout 是 gliderlabs 出品的一款 Docker 日志路由工具,其核心链路为:
Docker 容器 stdout/stderr │ ▼ Docker logs API(通过挂载 /var/run/docker.sock 访问) │ ▼ Logspout 主进程(gliderlabs/logspout) │ logspout-logstash 适配器 ▼ UDP/TCP 发送到 logstash:5000 │ ▼ Logstash(udp input + json codec) │ ▼ Elasticsearch(logstash_internal 用户写入)其中关键的一环是"适配器"。Logspout 通过 Go 的匿名导入机制把 logstash-logstash 适配器编译进镜像,见 modules.go:
package main // installs the Logstash adapter for Logspout, and required dependencies import ( _ "github.com/gliderlabs/logspout/healthcheck" _ "github.com/gliderlabs/logspout/transports/tcp" _ "github.com/gliderlabs/logspout/transports/udp" _ "github.com/looplab/logspout-logstash" )从源码结构可以推断:logspout-logstash适配器负责将 Logspout 采集到的日志事件序列化成 Logstash 可识别的 JSON 并送出;同时显式导入了udp、tcp两个 transport,为后续路由(ROUTE_URIS)提供可用的发送通道;healthcheck则为容器提供健康检查能力。
对应的 Dockerfile 采用 Logspout 官方文档推荐的 custom 构建方式:
FROM gliderlabs/logspout:master ENV SYSLOG_FORMAT rfc3164基础镜像gliderlabs/logspout:master带有 ONBUILD 指令,会自动把构建上下文中的modules.go编译进 Logspout 主程序,因此镜像内才内置了 Logstash 适配器;SYSLOG_FORMAT则指定了 syslog 格式相关的环境默认值。
启用扩展:Compose 覆盖文件逐项拆解
启用方式无需改动任何现有编排文件,只需要在启动时追加一个 Compose 覆盖文件(原文档给出的命令):
docker-compose -f docker-compose.yml -f extensions/logspout/logspout-compose.yml up注意:原文档写的是docker-compose.yml,而当前仓库中基础编排文件的实际文件名是docker-compose.yaml(位于 Elastic Stack 目录),二者等价,按你本地实际文件名选择即可。Docker Compose 会按顺序合并两个文件,最终把logspout服务加入elk网络。
覆盖文件的核心内容位于 logspout-compose.yml,逐项解读如下:
version: '3.7' services: logspout: build: context: extensions/logspout # 使用上面的 Dockerfile + modules.go 构建自定义镜像 volumes: - type: bind source: /var/run/docker.sock # 挂载 Docker 守护进程 socket target: /var/run/docker.sock read_only: true # 只读挂载,降低权限风险 environment: ROUTE_URIS: logstash://logstash:5000 # 路由目标:Logstash 的 5000 端口 LOGSTASH_TAGS: docker-elk # 为事件附加的标签,便于在 Elasticsearch 中区分来源 networks: - elk depends_on: - logstash restart: on-failure配置要点与对应影响:
/var/run/docker.sock只读挂载:这是 Logspout 读取 Docker logs API 的通道。read_only: true表示 Logspout 只能读 Docker 事件与日志,不能对 Docker 进行写操作,是安全实践。ROUTE_URIS: logstash://logstash:5000:这是 Logspout 的路由声明,语法为<adapter>://<host>:<port>。logstash://会触发前面编译进去的logspout-logstash适配器,把日志发送到elk网络内 Logstash 服务名logstash的 5000 端口。LOGSTASH_TAGS: docker-elk:适配器会给每个日志事件打上该标签,Kibana 中可用tags: docker-elk过滤出这批 Docker 容器日志。networks: - elk:必须与 Logstash 处于同一 Docker 网络,才能通过服务名解析到logstash。depends_on: logstash:保证 Logstash 先启动,避免 Logspout 启动时路由目标不可达。restart: on-failure:Logspout 异常退出时自动重启,提升日志采集的可用性。
Logstash 侧接入:启用 udp input 并设置 json codec
Logspout 通过 UDP 把日志送到 Logstash 的 5000 端口,因此 Logstash 的管道配置必须增加udp输入,且codec必须是json(因为 logspout-logstash 适配器发送的是 JSON 格式事件)。原文档给出的配置片段:
input { udp { port => 5000 codec => json } }对照仓库中现有的 logstash.conf,可以看到当前管道已包含beats(5044)与tcp(5000)两个输入,但尚未包含 udp 输入:
input { beats { port => 5044 } tcp { port => 5000 } }也就是说,接入 Logspout 时你需要在管道中新增上述udp输入块(保留原有 beats/tcp 输入即可),完成后的输入段大致为:
input { beats { port => 5044 } tcp { port => 5000 } udp { port => 5000 codec => json } }这得益于基础编排文件 docker-compose.yaml 中 Logstash 服务的端口映射已经同时暴露了 TCP 与 UDP 两种协议("5000:5000/tcp"与"5000:5000/udp"),因此 UDP 流量可以直接进入容器。事件进入管道后,会按现有 output 配置写入 Elasticsearch:
output { elasticsearch { hosts => "elasticsearch:9200" user => "logstash_internal" password => "${LOGSTASH_INTERNAL_PASSWORD}" } }其中logstash_internal用户及密码由 setup 服务 在栈初始化时通过.env中的LOGSTASH_INTERNAL_PASSWORD创建。
验证接入是否生效
启动后可以按以下步骤验证整条链路:
- 确认服务状态:
docker-compose ps,应能看到logspout与logstash均为运行状态。 - 查看 Logspout 日志:
docker-compose logs logspout,正常时应显示路由建立成功(例如出现指向logstash:5000的路由日志)。 - 制造一条日志:任意在宿主机上运行(或已在运行)的容器只要输出到 stdout/stderr,Logspout 都会自动抓取,无需该容器做任何配置。
- 在 Kibana 验证:进入 Kibana(默认 5601 端口),在 Discover 中按
tags: docker-elk过滤,即可看到来自各个 Docker 容器的日志事件已进入 Elasticsearch。
使用边界与注意事项
- 面向宿主机所有容器:Logspout 抓取的是整个 Docker 守护进程可见的日志,适合"全量采集、统一收口"的场景;如果你只想采集特定容器的日志,更合适的选择是仓库中同样位于 extensions 下的 filebeat 扩展。
- 依赖 Docker socket:Logspout 必须能访问
/var/run/docker.sock,在 Docker Desktop、远程 Docker 主机或受限的容器运行环境中需确保该路径可用。 - 单宿主机语义:每个 Docker 主机需要一个 Logspout 实例;多主机集群场景需要按主机分别部署,或改用其他集中式采集方案。
- 日志格式:Logspout 默认采集容器 stdout/stderr 原始内容,结构化日志(JSON)需要容器自身输出 JSON,Logstash 侧才可能做字段解析;非 JSON 日志也可保留为 message 字段全文检索。
小结
在 90DaysOfDevOps 的 Elastic Stack 实战中,Logspout 扩展提供了一条"零侵入、零配置"的 Docker 日志接入路径:通过只读挂载 Docker socket 调用 logs API,配合 Go 模块编译进镜像的 logspout-logstash 适配器,把全量容器日志经 UDP 5000 送入 Logstash,最终落地 Elasticsearch 供 Kibana 检索分析。本文对应的全部编排与源码文件均可在仓库2022/ja/Days/Monitoring/Elastic Stack/extensions/logspout/下直接查看,英文原版对照位于 2022/Days/Monitoring/Elastic Stack,配合课程正文 day80.md 可形成完整的 Elastic Stack 学习闭环。
- 文档/教程
【免费下载链接】90DaysOfDevOps
This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.
相关推荐
90DaysOfDevOps 实战:使用 Logspout 扩展将 Docker 容器日志零配置接入 ELK 的 Logstash
90DaysOfDevOps 实战:使用 Logspout 扩展将 Docker 容器日志零配置接入 ELK 的 Logstash 在 ELK(Elastics
文档/教程90DaysOfDevOps 的 ELK 日志栈扩展:用 Logspout 将 Docker 容器日志零配置转发至 Logstash
90DaysOfDevOps 的 ELK 日志栈扩展:用 Logspout 将 Docker 容器日志零配置转发至 Logstash 在 90DaysOfDev
文档/教程90DaysOfDevOps 实战:为 Elastic Stack 启用 APM Server 扩展并接入 Agent
90DaysOfDevOps 实战:为 Elastic Stack 启用 APM Server 扩展并接入 Agent 导读 本篇文章围绕 90DaysOfDe
文档/教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考