使用现有 Prometheus
Docker Compose 快速入门会部署一个内置 Prometheus。如果你已经在运行 Prometheus,可以让 API7 网关使用现有实例,并移除内置实例。本页介绍涉及的两条指标路径,并提供安全的迁移流程,确保控制台的 Monitoring 页面持续正常工作。
网关指标如何到达 Prometheus
API7 网关指标可以通过两条独立路径到达 Prometheus 实例。理解这两条路径是顺利迁移的关键,因为同一组指标可能通过任一路径到达 Prometheus。
| 路径 | 数据流 | 用途 |
|---|---|---|
| 远程写入 | 数据面 → DP Manager → Prometheus(/api/v1/write) | 控制台的 Monitoring 页面。控制面通过查询此 Prometheus 填充页面数据。 |
| 抓取 | Prometheus → 数据面 :9091(参见监控指标) | 你自己的 Grafana 仪表板或告警系统。 |
内置 Prometheus 是控制台使用的远程写入接收端。两条路径中的指标名称和标 签完全相同,只有抓取得到的序列会额外携带 Prometheus 添加的 job 和 instance 标签。由于控制台查询使用 sum(...) by (...) 聚合,并且不按 job 筛选,因此无论数据来自远程写入还是抓取,控制面都能以相同方式工作。
如果同一个 Prometheus 既抓取数据面,又接收远程写入,每项指标都会出现两条序列。控制台随后会将它们重复计数,导致请求数和带宽显示为实际值的两倍。每个 Prometheus 实例只保留一条路径。
前提条件
- 一个控制面容器可以访问的外部 Prometheus 实例。
- 包含
docker-compose.yaml、dashboard_conf/conf.yaml和dp_manager_conf/conf.yaml的控制面部署目录。在某些版本中,服务名称可能是api7-ee-dashboard和api7-ee-dp-manager。
选择迁移路径
根据外部 Prometheus 当前获取网关指标的方式选择路径。
| 路径 A — 保留抓取 | 路径 B — 远程写入 | |
|---|---|---|
| 适用场景 | 外部 Prometheus 已经抓取数据面的 :9091 端口 | 外部 Prometheus 尚未抓取数据面 |
| 外部 Prometheus 变更 | 无,抓取配置保持不变 | 添加 --web.enable-remote-write-receiver,由控制面向其写入指标 |
| 所需权限 | 只读 | 读取(控制台查询)+ 写入(DP Manager 远程写入) |
| 现有 Grafana / 告警 | 不受影响 | 序列不再包含 job 和 instance 标签;必须更新按这些标签筛选的查询 |
如果 Prometheus 已经抓取数据面,路径 A 的改动较少。下文以路径 A 为主线,随后提供路径 B 的完整操作步骤。验证和回滚适用于两条路径。
路径 A:保留抓取并移除内置 Prometheus
第 1 步:备份当前配置
cd <control-plane-directory>
BAK="/var/tmp/api7-prom-backup-$(date +%F)"
mkdir -p "$BAK"
cp -a docker-compose.yaml dashboard_conf dp_manager_conf "$BAK"/
第 2 步:确认外部 Prometheus 中已有网关指标
这是只读检查,不会进行任何更改。
curl -sG --data-urlencode 'query=count(apisix_http_status)' \
"http://<external-prometheus>:9090/api/v1/query"
先通过路由发送几个请求,再运行此检查,结果应大于 0。结果为空不一定表示抓取异常:在流量尚未到达网关,或未将 prometheus 插件启用为全局规则时,结果也会为空。如果产生流量后计数仍为 0,请先修复抓取任务或启用插件。如果外部 Prometheus 启用了身份验证,请为此 curl 添加凭据(例如 -u <user>:<password>),并使用 https:// URL;否则会返回 401 或 403,这并非指标问题。
第 3 步:让控制台使用外部 Prometheus 并停止远程写入
编辑 dashboard_conf/conf.yaml。将 addr 改为外部 Prometheus,并禁用遥测,使控制面停止写入会与抓取结果重复的指标。
prometheus:
addr: "http://<external-prometheus>:9090" # 必须能从控制台容器内访问
query_path_prefix: ""
whitelist:
- "/api/v1/query_range"
- "/api/v1/query"
# 保持其余配置不变
telemetry:
enable: false
如果 telemetry.enable 仍为 true,控制面会继续远程写入与抓取序列冲突的指标,控制台会将它们重复计数。
此 telemetry 配置块是控制面 dashboard_conf/conf.yaml 中的顶层键。它不是优化遥测数据传输中介绍的数据面 api7ee.telemetry 退出选项。在此处禁用它会让 DP Manager 停止向 Prometheus 远程写入。重新创建控制面容器后更改即会生效,数据面会继续运行并处理流量,无需重启数据面。
路径 A 无需修改 dp_manager_conf/conf.yaml。禁用遥测后,DP Manager 会停止连接 Prometheus,因此不再使用其中的 addr 值。
第 4 步:从 Docker Compose 中移除内置 Prometheus
从 docker-compose.yaml 中删除两项内容:prometheus 服务配置块,以及引用它的 depends_on 条目。3.9.x 参考 Compose 文件没有为 Prometheus 声明持久化数据卷。如果你的部署自行添加了命名卷或绑定挂载,请先记录其挂载关系并按需导出历史数据;在确定不需要回滚前,不要删除实际存储。
services:
# 删除整个 prometheus 服务配置块
# prometheus:
# image: api7/prometheus:...
dashboard:
depends_on:
postgresql: {condition: service_healthy}
# 删除下一行
# prometheus: {condition: service_healthy}
如果保留 depends_on 条目,堆栈会因 service "dashboard" depends on undefined service "prometheus": invalid compose project 而无法启动。重启前运行 docker compose config >/dev/null 即可发现此问题。
第 5 步:重启控制面
本指南中的 docker compose 命令(包括本步骤以及验证和回滚部分)使用服务名称 dashboard 和 dp-manager。如果 Compose 文件中的名称是 api7-ee-dashboard 和 api7-ee-dp-manager,请在所有命令中替换为对应名称。
docker compose config >/dev/null && echo "compose OK"
# 重新创建控制面组件
docker compose up -d --force-recreate dashboard dp-manager
# 按名称移除现已成为孤立容器的内置 Prometheus。
# 第 4 步已从文件中删除其服务,因此运行 `docker compose rm prometheus`
# 会报告 "no such service"。 请改为直接删除容器:
docker rm -f <compose-project>-prometheus-1
docker compose logs --tail=100 dp-manager | grep -i prometheus
DP Manager 日志中不应出现 failed to write prometheus metrics。数据面无需重启,流量也不会中断。
--remove-orphansdocker compose up -d --remove-orphans 也能达到目的,但它会删除 Compose 项目中所有不再在文件中定义的容器,而不只是 Prometheus。如果数据面或任何其他容器运行在同一项目中,却没有相应的服务条目,此选项也会将其删除。按名称删除容器更安全。
路径 B:切换到远程写入
如果外部 Prometheus 尚未抓取数据面,请使用路径 B。先备份配置(第 1 步),再按顺序完成以下步骤。
第 B-1 步:在外部 Prometheus 上启用远程写入接收端
这是 Prometheus 进程的启动参数,而不是 prometheus.yml 设置。请将其添加到 Prometheus 的启动方式中,然后重启 Prometheus 使其生效:
- systemd:将
--web.enable-remote-write-receiver添加到ExecStart,再运行systemctl daemon-reload && systemctl restart prometheus。 - Docker / Docker Compose:将
--web.enable-remote-write-receiver添加到容器的command,再重新创建容器。 - Kubernetes:将该参数添加到 Prometheus 容器的
args,再滚动更新 Pod。
重启后确认接收端已启用:
curl -s -o /dev/null -w '%{http_code}\n' -X POST "http://<external-prometheus>:9090/api/v1/write"
# 400 = 已启用(无效请求体,符合预期) 404 = 仍未启用
如果端点需要身份验证,请添加匹配的认证方式(例如为 Basic 身份验证添加 -u <user>:<password>),并使用 https:// URL。没有凭据时,请求会在到达接收端前返回 401 或 403,这与接收端未启用并不是同一问题。
第 B-2 步:让控制台和 DP Manager 使用外部 Prometheus
在两个配置文件中修改 addr。与路径 A 不同,此处应保持 telemetry.enable: true,使 DP Manager 继续上报指标,但改为远程写入外部 Prometheus。
prometheus:
addr: "http://<external-prometheus>:9090" # 必须能从控制台容器内访问
query_path_prefix: ""
whitelist:
- "/api/v1/query_range"
- "/api/v1/query"
# 保持其余配置不变
telemetry:
enable: true # 路径 B 中保持启用
prometheus:
addr: "http://<external-prometheus>:9090"
remote_write_path: "/api/v1/write"
第 B-3 步:移除内置 Prometheus 并重启控制面
按照第 4 步中的说明,从 docker-compose.yaml 中移除内置 Prometheus,再严格按照第 5 步中的说明重启控制面。重新创建 dashboard 和 dp-manager 容器后,第 B-2 步中的两项更改都会生效。数据面会继续运行并处理流量,无需重启。
第 B-4 步:移除现有抓取任务
仅当此 Prometheus 已经抓取数据面时,才移除对应的抓取任务,避免指标重复到达,然后重新加载 Prometheus(向进程发送 SIGHUP,或在 Prometheus 使用 --web.enable-lifecycle 运行时请求 POST /-/reload)。更新所有按 job 或 instance 筛选的 Grafana 面板或告警规则,因为远程写入的序列不包含这些标签。
身份认证
如果外部 Prometheus 要求 Basic 身份验证,请添加 basic_auth 配置块。该配置块必 须正确嵌套,直接在 prometheus 下设置 username 和 password 不会生效。仅通过 HTTPS 或可信网络发送 Basic 凭据;通过纯 http:// 发送时,凭据会以明文传输。请将 addr 指向 https:// 端点,或通过同机反向代理终止 TLS。
prometheus:
addr: "https://<external-prometheus>:9090" # 使用 https,避免凭据以明文发送
basic_auth:
username: "api7-readonly"
password: "<password>"
在路径 B 中,请在 dp_manager_conf/conf.yaml 中使用相同的 basic_auth 配置块。由于 DP Manager 会写入 /api/v1/write,其凭据必须拥有写入权限。
对于双向 TLS,控制面原生支持通过 tls 配置块配置客户端证书,无需代理。将 addr 指向 https:// 端点,并引用客户端密钥对和 CA:
prometheus:
addr: "https://<external-prometheus>:9090"
tls:
enable_client_cert: true
cert_file: /path/to/client.crt
key_file: /path/to/client.key
ca_file: /path/to/ca.crt
在路径 B 中,请在 dp_manager_conf/conf.yaml 中使用相同的 tls 配置块,并将证书文件挂载到控制面容器中。
对于 Bearer Token 或控制面不原生支持的其他认证方式,请在 Prometheus 前部署反向代理来注入凭据。将 addr 指向该代理;如果代理在某个路径前缀下提供 API,请设置 query_path_prefix。路径 B 的写入请求也使用同一前缀。请将 dp_manager_conf/conf.yaml 中的 remote_write_path 设为包含此前缀的路径(例如 /prom-proxy/api/v1/write),或让代理保留 /api/v1/write。
控制台和 DP Manager 从不同文件读取凭据,因此可以为它们提供不同账户,但这只分离了凭据,并没有分离权限。Prometheus 原生授权是全有或全无:任何有效账户都可以读取和写入,因此仅使用不同账户并不能让控制台凭据变为只读。若只需实现凭据隔离,使用不同账户即可,无需特殊角色。要强制实施最小权限(例如防止泄露的查询凭据向 Prometheus 写入数据),请在前面部署反向代理,并限制每个账户只能访问相应端点。只允许控制台账户访问 /api/v1/query 和 /api/v1/query_range;在路径 B 中,只允许 DP Manager 账户访问 /api/v1/write。不要在路径 B 中阻止 DP Manager 访问写入端点,否则远程写入会失败。
验证
发送一些流量,然后等待五分钟再检查。最后一个样本到达后,Prometheus 最多还会返回对应序列五分钟,因此在此之前,已禁用路径产生的陈旧序列仍可能出现。
下面的“没有重复序列”和“值与数据面一致”检查以该外部 Prometheus 只接收一个数据面的指标为前提。如果它汇聚多个数据面,请勿使用未限定范围的查询:多个合法实例可能使计数大于 1,外部总和也无法与单个数据面端点直接比较。请先使用部署中能唯一标识同一数据面的标签缩小两侧查询范围;如果没有这样的共同标签,请分别核对 Prometheus 抓取目标和 DP Manager 写入日志,不要将下面的未限定查询用作重复判据。
-
没有重复序列:
apisix_http_status{code="200"}按路由、服务和实例各返回一条序列,这符合预期。重复指的是同一组标签通过两条路径到达,只能通过抓取添加的job和instance标签区分。检查时忽略这两个标签进行分组;如果任意分组包含多条序列,说明两条路径仍同时启用。产生返回200的测试流量后,如果迁移正确,以下查询不会返回结果:curl -sG --data-urlencode \'query=count without (job, instance) (apisix_http_status{code="200"}) > 1' \"http://<external-prometheus>:9090/api/v1/query" -
值与数据面一致:将外部 Prometheus 中的
sum(apisix_http_status{code="200"})与数据面端点中相同指标的总和进行比较(curl "http://127.0.0.1:9091/apisix/prometheus/metrics"),两者应一致。 -
控制台的 Monitoring 页面在 30 分钟时间范围内的所有面板中都显示数据。
-
DP Manager 日志中没有写入错误:
docker compose logs --tail=200 dp-manager | grep -c 'failed to write prometheus'返回0。
回滚
恢复备份,并重新启动内置 Prometheus。数据面无需重启;对于路径 A,外部 Prometheus 也无需更改。
cd <control-plane-directory>
cp -a /var/tmp/api7-prom-backup-<date>/* .
docker compose up -d prometheus
docker compose up -d --force-recreate dashboard dp-manager
3.9.x 参考 Compose 文件没有为内置 Prometheus 定义持久化数据卷,因此上述回滚会启动一个没有旧历史数据的新 Prometheus。若部署使用了自定义命名卷或绑定挂载,请在启动前恢复并重新挂载同一存储。
内置 Prometheus 不会补收切换期间的指标。对于路径 B,还 需还原外部 Prometheus:重新添加已移除的抓取任务;当不再有任何发送端需要远程写入接收端时,移除 --web.enable-remote-write-receiver 参数。该参数属于启动命令,因此请使用启用它时采用的方式应用移除操作,详见第 B-1 步。使用 Docker Compose 时应重新创建容器,普通的 restart 会复用旧命令。使用 systemd 时,应编辑 ExecStart 并重启服务。启用的接收端会接受未经身份验证的写入,此参数本身不会添加身份验证。如果保留接收端,请通过身份验证和网络控制保护 /api/v1/write。
注意事项
- 历史数据不会迁移。 3.9.x 参考 Compose 文件不会把内置 Prometheus 数据保存在命名卷中;移除或重新创建容器前,如需保留历史数据,请先将其导出(
promtool tsdb dump)。如果部署自行配置了持久化存储,请保留并记录其挂载关系,以便回滚时重新挂载。 - 新增数据面需要抓取目标(路径 A)。 每个新增数据面都必须添加到 Prometheus
scrape_configs中;Prometheus 无法访问的数据面不会产生指标。路径 B 没有此问题,因为指标通过现有的数据面到 DP Manager 通道传输。 adc sync可能清空指标。 网关指标依赖默认的prometheus全局规则。如果 ADC 配置文件省略global_rules.prometheus,同步会删除该规则,并导致所有网关指标停止上报。有关启用此插件的说明,请参阅监控指标。- 控制面自身指标是可选的。 内置 Prometheus 还会抓取控制面自身的指标(
api7_dashboard_*、etcd_*)。控制台不使用这些指标;仅当需要使用它们排查问题时,才为控制面的7081端口添加抓取目标。