90DaysOfDevOps 实战:在 Elastic Stack 中集成 APM Server 实现分布式追踪
90DaysOfDevOps 实战:在 Elastic Stack 中集成 APM Server 实现分布式追踪
导读
本文以 90DaysOfDevOps 仓库中 Elastic Stack 监控实践项目(2022/es/Days/Monitoring/Elastic Stack)内嵌的 APM Server 扩展模块为核心,完整讲解如何通过 Docker Compose 叠加文件把 APM Server 接入 ELK(Elasticsearch + Logstash + Kibana)栈,如何配置 APM 采集端(以 Python Flask 为例)上报分布式追踪数据,以及在 Kibana 中完成连通性检查、导入默认仪表盘并开始观察应用性能的全流程。读完本文,你将掌握 APM Server 的容器化部署方式、核心配置项含义,以及把 APM Agent 接入服务端的最小可用方案。
APM Server 在 Elastic Stack 中的定位
APM(Application Performance Monitoring,应用性能监控)是 Elastic Stack 对应用可观测性能力的补充:当 Elasticsearch 负责存储与检索、Logstash 负责日志收集与加工、Kibana 负责可视化时,APM Server 负责接收来自各类语言 APM Agent(如 Python、Java、Node.js、Go 等)上报的追踪数据(traces、metrics、errors),并将其转换成可被 Elasticsearch 索引、进而在 Kibana 中以 APM 应用呈现的文档。
仓库内 extensions/README.md 将该目录定义为 "Third-party extensions that enable extra integrations with the Elastic stack",即官方 ELK Docker 编排之外的可选扩展。APM Server 正是其中负责应用性能监控集成的扩展,与同目录下的 filebeat、metricbeat、enterprise-search 等扩展并列,供需要应用级追踪能力的场景按需启用。
用 Docker Compose 叠加文件启用 APM Server
组合命令:基栈 + 扩展栈
仓库的 ELK 主编排文件是 docker-compose.yaml,其中定义了 setup、elasticsearch、logstash、kibana 四个服务,并声明了名为 elk 的 bridge 网络以及 setup、elasticsearch 两个命名卷。APM Server 扩展并不修改基栈文件,而是通过 额外的 Compose 叠加文件 与主文件合并启动:
$ docker-compose -f docker-compose.yaml -f extensions/apm-server/apm-server-compose.yml up
运行该命令前,需先在仓库根目录准备好 .env 文件,提供 ELASTIC_VERSION(例如 7.16.2)与 ELASTIC_PASSWORD 等变量——它们同时被基栈与扩展栈引用,保证 APM Server 与 Elasticsearch 使用同一套版本与认证凭据。
叠加文件逐项拆解
扩展的编排定义位于 extensions/apm-server/apm-server-compose.yml,其内容如下:
version: '3.7'
services:
apm-server:
build:
context: extensions/apm-server/
args:
ELASTIC_VERSION: ${ELASTIC_VERSION}
command:
# Disable strict permission checking on 'apm-server.yml' configuration file
# https://www.elastic.co/guide/en/beats/libbeat/current/config-file-permissions.html
- --strict.perms=false
volumes:
- ./extensions/apm-server/config/apm-server.yml:/usr/share/apm-server/apm-server.yml:ro,Z
ports:
- '8200:8200'
environment:
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
networks:
- elk
depends_on:
- elasticsearch
各关键点的实战含义:
build.context: extensions/apm-server/:以扩展目录为构建上下文,配合 Dockerfile 使用。该 Dockerfile 只有两行——接收ELASTIC_VERSION构建参数,并直接以官方镜像docker.elastic.co/apm/apm-server:${ELASTIC_VERSION}为基础。因此本地并不需要维护任何 APM Server 二进制,镜像版本完全跟随.env中的ELASTIC_VERSION。command: --strict.perms=false:官方 APM Server 镜像默认要求配置文件权限为 root 所有且仅可被 root 写。由于宿主机挂载进容器的apm-server.yml通常不具备这一权限组合,叠加文件显式关闭严格权限检查,避免容器启动即失败。这是该扩展能"开箱即用"的关键。volumes:把仓库内的 config/apm-server.yml 以只读方式挂载到容器内/usr/share/apm-server/apm-server.yml。:ro保证配置只读,:Z则用于解决 SELinux 环境下容器对挂载文件的访问控制问题(在启用 SELinux 的主机上可避免权限被拒绝)。ports: '8200:8200':将容器的 8200 端口映射到宿主机,这是 APM Agent 上报数据的默认端口,也是后续 Agent 配置中SERVER_URL的目标地址。environment.ELASTIC_PASSWORD:把宿主机.env中的密码传入容器,供配置文件中output.elasticsearch.password引用。networks: elk:加入基栈创建的elkbridge 网络,使 APM Server 能与elasticsearch、kibana服务通过服务名互访(这正是配置里能写http://elasticsearch:9200的原因)。depends_on: elasticsearch:确保 Elasticsearch 先启动,APM Server 再启动,避免启动初期因后端未就绪而持续报错。
理解 APM Server 的服务端配置
仓库内 extensions/apm-server/config/apm-server.yml 是挂载进容器的完整配置,全文如下:
apm-server:
host: 0.0.0.0:8200
output:
elasticsearch:
hosts: ['http://elasticsearch:9200']
username: elastic
password: ${ELASTIC_PASSWORD}
apm-server.host: 0.0.0.0:8200:监听地址绑定到容器内所有网卡接口,端口为 8200。0.0.0.0而非127.0.0.1是容器化部署的必要选择——否则宿主机以及同一网络内的其他容器(包括运行着 APM Agent 的应用容器)都无法访问该服务。若你的应用容器运行在另一个自定义网络而无法直连,还可以考虑把 APM Server 的host调整为可路由的地址或确保两个网络已打通。output.elasticsearch.hosts:输出目标指向http://elasticsearch:9200。这里的elasticsearch是 Compose 网络内的服务名,由 DNS 解析到 Elasticsearch 容器,无需硬编码 IP。该服务在基栈中通过9200:9200暴露到宿主机。username: elastic:使用 Elasticsearch 内置的超级用户elastic进行写入认证。基栈中setup服务在首次启动时负责初始化内部用户密码,elastic用户密码即来自.env的ELASTIC_PASSWORD。password: ${ELASTIC_PASSWORD}:从容器环境变量读取密码,密码不会以明文写在仓库文件里,避免凭据泄露。
从源码结构看,该配置遵循 Beats 家族(APM Server 基于 libbeat 构建)的统一配置模型:output.elasticsearch 块支持扩展为多主机列表、TLS 设置等更多字段,但当前仓库为了教学与演示用途刻意保持最小化——这正好呼应了原文档"最基础配置"的定位。
将 APM Agent 接入 APM Server:以 Python Flask 为例
最小连接配置
原文档给出的 Python Flask 示例是接入 APM Server 的最小可运行方案。它通过 elasticapm 官方 SDK 的 Flask 集成,在应用配置中仅声明两个必填项——SERVICE_NAME 与 SERVER_URL:
import elasticapm
from elasticapm.contrib.flask import ElasticAPM
from flask import Flask
app = Flask(__name__)
app.config['ELASTIC_APM'] = {
# Set required service name. Allowed characters:
# a-z, A-Z, 0-9, -, _, and space
'SERVICE_NAME': 'PYTHON_FLASK_TEST_APP',
# Set custom APM Server URL (default: http://localhost:8200)
'SERVER_URL': 'http://apm-server:8200',
'DEBUG': True,
}
两点实战细节:
SERVICE_NAME是必填项,用于在 Kibana APM 应用中区分不同服务,字符集限制为a-z, A-Z, 0-9, -, _和空格。示例中的PYTHON_FLASK_TEST_APP符合该约束,可直接沿用或按需替换。SERVER_URL的默认值是http://localhost:8200,适用于 Agent 与 APM Server 同机运行的情况。示例中改为http://apm-server:8200,是因为 Flask 应用通常运行在另一个容器中,需要通过 Compose 服务名访问 APM Server 容器;如果你的应用跑在宿主机上,保持默认值(配合宿主机映射端口 8200)即可。
示例中的 DEBUG: True 用于开发阶段输出 SDK 日志,生产环境建议移除或改为更严格的日志级别。
其他语言的配置入口
APM Agent 的语言生态很广(Java、Node.js、Ruby、Go、.NET、PHP、JavaScript 前端等),每种语言的配置方式与字段名略有差异。原文档明确指向 Elastic APM 官方文档的 [APM Agents][apm-agents] 章节——该章节按语言分列了完整配置项与接入教程。接入时按同样思路处理即可:始终设置服务名与服务端地址,再按语言文档补充采样率、环境标签、过滤规则等高级选项。需要注意的是,各语言 Agent 均通过 HTTP 向 apm-server 的 8200 端口上报数据,因此只要服务端端口可达、认证/网络配置一致,接入方式对不同语言是统一的。
在 Kibana 中验证连通并导入默认仪表盘
APM Server 启动后,还需要在 Kibana 侧完成一次性的初始化引导,原文档给出了完整的 5 步流程:
- 在 Kibana 首页的 Observability 面板中点击
Add APM。 - 点击
Check APM Server status,确认 APM Server 已启动且可被 Kibana 访问——这一步验证的是服务端与 Kibana 的连通性,若失败请优先排查扩展容器是否正常运行、elk网络是否连通。 - 点击
Check agent status,验证你的 Agent 是否已成功注册上报——此时应已启动并运行了接入 SDK 的应用(如上面的 Flask 应用),若显示未注册,请检查应用容器能否访问http://apm-server:8200。 - 点击
Load Kibana objects,为 APM 数据创建索引模式(index pattern),这是 Kibana 检索 APM 文档(apm-*索引)的前提。 - 点击
Launch APM,进入 APM 仪表盘,开始查看服务的吞吐量、延迟、错误率以及事务(transaction)与 Span 级别的追踪明细。
完成这五步后,应用上报的追踪数据就会以服务地图(Service Map)、事务瀑布图(Trace Waterfall)等形式呈现在 APM 应用中,配合 Elasticsearch 已索引的日志与指标,即可对应用性能进行端到端观测。
排障提示与后续拓展
- APM Server 无法启动:最常见原因是配置文件权限被镜像的严格校验拒绝,叠加文件中已通过
--strict.perms=false规避;若自行修改后仍失败,请确认挂载路径与容器内路径一致。 - Agent 显示离线:按"检查清单"逐层排查:APM Server 容器是否运行(
docker-compose ps)、8200 端口是否监听(curl http://localhost:8200)、应用容器与 APM Server 是否在同一网络、SERVER_URL中的主机名是否能被应用容器解析。 - 数据写不进去:确认
apm-server.yml中 Elasticsearch 地址、用户名、密码与基栈.env配置一致,并查看 APM Server 容器日志中的输出报错。 - 扩展生态:仓库 extensions 目录下还提供了 filebeat、metricbeat、enterprise-search、curator、logspout 等扩展,接入方式与 APM Server 完全一致——复用
-f docker-compose.yaml -f extensions/<name>/<name>-compose.yml的叠加启动模式,即可按需组合 Elastic Stack 的多种能力。
小结
通过本仓库的 APM Server 扩展,你将一条完整的 APM 数据链路落地为可运行的容器化方案:APM Agent(如 Python Flask SDK)→ APM Server(监听 8200)→ Elasticsearch(9200 写入)→ Kibana APM 应用(可视化)。核心要点可归结为三点:用叠加 Compose 文件实现"基栈不动、扩展即插即用";用服务名与共享网络打通容器间通信;用环境变量注入密码避免明文凭据。这套模式同样适用于仓库内其他扩展,是理解 Elastic Stack 可观测性扩展机制的通用范本。