90DaysOfDevOps 实战:在 Elastic Stack 中集成 APM Server 实现分布式追踪

原创2026-09-30 15:08:051,178 阅读
文章标签:文档/教程

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:加入基栈创建的 elk bridge 网络,使 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 步流程:

  1. 在 Kibana 首页的 Observability 面板中点击 Add APM。
  2. 点击 Check APM Server status,确认 APM Server 已启动且可被 Kibana 访问——这一步验证的是服务端与 Kibana 的连通性,若失败请优先排查扩展容器是否正常运行、elk 网络是否连通。
  3. 点击 Check agent status,验证你的 Agent 是否已成功注册上报——此时应已启动并运行了接入 SDK 的应用(如上面的 Flask 应用),若显示未注册,请检查应用容器能否访问 http://apm-server:8200。
  4. 点击 Load Kibana objects,为 APM 数据创建索引模式(index pattern),这是 Kibana 检索 APM 文档(apm-* 索引)的前提。
  5. 点击 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 可观测性扩展机制的通用范本。

登录后查看全文
90DaysOfDevOps