Grafana Tempo 在 HashiCorp Nomad 上的单二进制(Monolithic)部署指南
【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo
本指南基于仓库 example/nomad/tempo-monolith 目录下的 Nomad 作业定义,系统讲解如何用一条nomad job run命令,在 HashiCorp Nomad 集群中以单二进制(monolithic)模式部署 Grafana Tempo 并使用 S3 兼容对象存储作为后端。读完本文,你将掌握tempo.hcl中每个变量与配置段的含义、端口与健康检查的编排方式,以及-target=all、-config.expand-env等启动参数在 Tempo 源码中的真实作用,可直接照搬到自己的 Nomad 环境。
一、部署模式与适用场景
Tempo 支持多种部署形态,本示例采用的是monolithic mode(单体模式),即把全部功能组件打包进一个进程运行。在 cmd/tempo/app/modules.go 中可以看到,Tempo 用SingleBinary常量标识该模式,其值就是字符串"all":
SingleBinary string = "all" func IsSingleBinary(target string) bool { return target == SingleBinary }从同一文件的模块依赖关系(cmd/tempo/app/modules.go)可以确认,"all"这个复合目标实际组合了以下全部组件:
SingleBinary: {BackendScheduler, BackendWorker, QueryFrontend, Querier, Distributor, MetricsGenerator, LiveStore}也就是说,分发器(Distributor)、查询前端(QueryFrontend)、查询器(Querier)、指标生成器(MetricsGenerator)等职责全部收敛在单一进程内。这种模式的优势是部署简单、依赖少、资源占用低,适合开发环境、演示环境以及中小规模写入量的场景;需要横向扩展时再切换到多进程的微服务模式。
⚠️重要提示(原文档原文):本示例基于 Tempo2.x架构创建,尚未针对 3.x 更新(因为维护者并未在 Nomad 上部署)。该示例目前处于deprecated(废弃)状态,如果社区不更新它,未来可能被移除。3.x 中新增了 LiveStore、PartitionRing 等组件,部署形态与 2.x 已有差异,请结合你实际使用的 Tempo 版本审慎参考。
二、前置条件与作业文件结构
2.1 前置条件
原文档明确要求的唯一硬性前提是:
- S3 兼容对象存储:本示例的 trace 后端使用 S3,因此需要一个可访问的 S3 兼容服务(如 AWS S3、MinIO、Ceph RGW 等),并准备好
endpoint、access key、secret key。
另外按仓库实际情况补充的环境前提:
- 一个可用的HashiCorp Nomad 集群(或单节点 dev 模式),且客户端节点安装了Docker 驱动——因为
tempo.hcl中的 task 使用driver = "docker"(见 example/nomad/tempo-monolith/tempo.hcl); - 节点能访问
grafana/tempo:${var.version}镜像仓库; - 如使用示例默认的 Prometheus Remote Write 地址(
http://prometheus.service.consul/api/v1/write),则环境中应有 Consul DNS 服务发现及可用的 Prometheus,否则请通过变量覆盖。
2.2 文件清单
example/nomad/tempo-monolith目录下只有两个文件:
| 文件 | 作用 |
|---|---|
tempo.hcl | Nomad 作业定义(HCL),内含 Tempo 配置模板 |
README.md | 原文档,说明用法与变量 |
其中 Tempo 自身的 YAML 配置并没有单独成文件,而是以Nomadtemplate内联模板的形式嵌在tempo.hcl中,渲染后写入local/config.yml。
三、tempo.hcl 逐段详解
3.1 变量定义(可参数化配置)
作业顶部定义了 4 个variable,与原文档中的变量表一一对应:
variable "version" { type = string description = "Tempo version" default = "2.7.1" } variable "prometheus_remote_write_url" { type = string description = "Prometheus Remote Write URL" default = "http://prometheus.service.consul/api/v1/write" } variable "s3_url" { type = string description = "S3 URL" default = "s3.dummy.url" } variable "s3_access_key_id" { type = string description = "S3 Access Key ID" default = "any" } variable "s3_secret_access_key" { type = string description = "S3 Secret Access Key" default = "any" }变量速查表:
| 变量名 | 默认值 | 说明 |
|---|---|---|
version | "2.7.1" | Tempo 镜像版本(grafana/tempo:${var.version}) |
s3_url | "s3.dummy.url" | S3 存储 endpoint 地址(注意:tempo.hcl中默认值为s3.dummy.url,README 中写的是s3.dummy.url.com,以 hcl 文件实际值为准) |
s3_access_key_id | "any" | S3 Access Key ID |
s3_secret_access_key | "any" | S3 Secret Access Key |
prometheus_remote_write_url | "http://prometheus.service.consul/api/v1/write" | 指标生成器(metrics_generator)Remote Write 目标 |
"any"等占位默认值表明:生产部署必须通过-var显式覆盖,仅当你的 S3 恰好不需要校验凭据(如本地 MinIO 关闭认证)时才可沿用默认。
3.2 作业骨架与网络端口
job "tempo" { datacenters = ["*"] group "tempo" { count = 1 network { port "http" { to = 3200 } port "grpc" {} port "otlp" { to = 4317 } }datacenters = ["*"]:允许调度到任意数据中心,可按需改成具体 DC 名;count = 1:单实例部署,符合单体模式语义;- 三个端口映射:
http:容器内3200端口——Tempo 的 HTTP API(查询、/ready健康检查等);grpc:不固定to,由容器默认监听——Tempo 内部 gRPC(查询前端与查询器之间通信);otlp:容器内4317端口——OpenTelemetry 协议 gRPC 接收端点。
3.3 服务发现与健康检查
service { name = "tempo-http" port = "http" tags = [] check { name = "tempo-http" port = "http" type = "http" path = "/ready" interval = "20s" timeout = "1s" } } service { name = "tempo-grpc" port = "grpc" tags = [] check { port = "grpc" type = "grpc" interval = "20s" timeout = "1s" grpc_use_tls = false tls_skip_verify = true } } service { name = "tempo-otlp" port = "otlp" tags = [] }tempo-http:注册到 Consul,并用HTTP 探活/ready每 20 秒检查一次,超时 1 秒;tempo-grpc:使用gRPC 健康检查协议,并显式关闭 TLS(grpc_use_tls = false),因为本示例是纯内网明文部署;tempo-otlp:仅注册服务(供采集器通过服务发现找到 OTLP 端点),不做健康检查。
/ready探针并非任意占位路径。在 cmd/tempo/app/app.go 中,Tempo 启动时会注册/ready处理器;其实现(同文件readyHandler,见 cmd/tempo/app/app.go)会逐个检查 Generator、Query Frontend、LiveStore 等模块的就绪状态,全部就绪才返回200 OK,否则返回503。因此这个探针能真实反映“服务可对外服务”而非仅仅是“进程存活”。
3.4 task 定义与启动参数
task "tempo" { driver = "docker" user = "nobody" kill_timeout = "90s" config { image = "grafana/tempo:${var.version}" ports = ["http", "grpc", "otlp"] args = [ "-target=all", "-config.file=/local/config.yml", "-config.expand-env=true", ] }要点:
user = "nobody":以非 root 用户运行容器,符合最小权限原则;kill_timeout = "90s":给 Tempo 留出优雅关闭(flush WAL、落盘 block)的时间;- 三个启动参数:
-target=all:显式指定以单二进制模式启动。实际上在 cmd/tempo/app/config.go 中该 flag 的默认值就是SingleBinary(即"all"),这里显式写出更清晰;-config.file=/local/config.yml:指定配置文件路径(由下方template渲染生成);-config.expand-env=true:允许在配置文件中展开环境变量。其实现位于 cmd/tempo/main.go:读取配置文件原文后调用envsubst.EvalEnv做环境变量替换,再以yaml.UnmarshalStrict严格解析。这意味着配置里可以放心使用$NOMAD_*这类 Nomad 注入的环境变量。
3.5 内联 Tempo 配置模板
template块把一段 YAML 渲染为容器内的local/config.yml(example/nomad/tempo-monolith/tempo.hcl),这是整个作业的核心:
server: log_level: info http_listen_port: {{ env "NOMAD_PORT_http" }} grpc_listen_port: {{ env "NOMAD_PORT_grpc" }} distributor: receivers: # this configuration will listen on all ports and protocols that tempo is capable of. otlp: protocols: http: grpc: endpoint: 0.0.0.0:{{ env "NOMAD_PORT_otlp" }} metrics_generator: processor: service_graphs: max_items: 10000 storage: path: {{ env "NOMAD_ALLOC_DIR" }}/tempo/wal remote_write: - url: ${var.prometheus_remote_write_url} send_exemplars: true storage: trace: backend: s3 wal: path: {{ env "NOMAD_ALLOC_DIR" }}/tempo/wal local: path: {{ env "NOMAD_ALLOC_DIR" }}/tempo/blocks s3: bucket: tempo # how to store data in s3 endpoint: ${var.s3_url} insecure: true access_key: ${var.s3_access_key_id} secret_key: ${var.s3_secret_access_key} overrides: defaults: metrics_generator: processors: - service-graphs - span-metrics逐段说明:
server:HTTP 与 gRPC 监听端口直接取自 Nomad 分配的动态端口环境变量NOMAD_PORT_http/NOMAD_PORT_grpc,保证与 3.2 节的端口映射一致;distributor.receivers:启用 OTLP 接收器,同时开放HTTP(4318 语义)与 gRPC协议,gRPC 端点绑定0.0.0.0:NOMAD_PORT_otlp(4317)。注释点明这会“监听 Tempo 所支持的所有端口与协议”;metrics_generator:开启service-graphs处理器(服务拓扑图,max_items: 10000限制内存中的服务图条目数),存储路径位于分配目录下的 WAL,并通过 Remote Write 把指标发给 Prometheus(send_exemplars: true会附带 exemplar);storage.trace:后端选s3;WAL 与本地缓存路径都放在NOMAD_ALLOC_DIR(Nomad 为每个分配提供的本地磁盘目录,重启后即被清理,适合缓存类数据);S3 配置中insecure: true表示走HTTP 而非 HTTPS(自建 S3 常用);bucket 固定为tempo,endpoint 与凭据来自变量;overrides:租户默认覆盖配置——为所有租户默认启用service-graphs与span-metrics两个指标生成处理器。
3.6 资源限制
resources { cpu = 300 memory = 1024 }CPU 300 MHz、内存 1024 MB。单体模式把全部组件塞进一个进程,内存主要消耗在:接收与批量写、WAL 缓冲、service-graphs 的max_items条目、以及查询时的 block 索引。生产环境建议根据实际写入量与查询量上调,并观察/ready与日志再行调整。
四、运行作业
4.1 基本运行
在包含tempo.hcl的目录下执行:
nomad job run tempo.hcl4.2 覆盖版本变量
作业默认拉取grafana/tempo:2.7.1(对应variable.version默认值)。要换版本,可以改 hcl 里的 default,或直接命令行覆盖:
nomad job run -var="version=2.7.1" tempo.hcl4.3 覆盖 S3 与 Prometheus 变量
同理,S3 与 Remote Write 参数务必显式指定,例如:
nomad job run \ -var="s3_url=minio.example.internal:9000" \ -var="s3_access_key_id=tempo" \ -var="s3_secret_access_key=<secret>" \ -var="prometheus_remote_write_url=http://prometheus.service.consul/api/v1/write" \ tempo.hcl运行后可在 Consul 中发现tempo-http、tempo-grpc、tempo-otlp三个服务;向 OTLP gRPC 端点(4317)写入 trace,即可通过 HTTP API(3200)查询。
五、验证与排障
- 健康检查:
curl http://<node-ip>:<http-port>/ready,返回200表示各模块就绪;503 响应体会指出是哪个模块未就绪(Generator / Query Frontend / LiveStore); - 指标生成链路:确认
metrics_generator的 Remote Write 目标可达,否则service-graphs/span-metrics生成的指标无法送达 Prometheus,服务拓扑图与 RED 指标会缺失; - 存储验证:写入若干 trace 后检查 S3 bucket
tempo下是否出现 block 数据(compact 任务会周期性把 WAL 落盘为 block 并上传); - 模板渲染:如果配置有误,可先在本机渲染模板检查产物:替换
{{ env "..." }}与${var.*}后执行tempo -config.file=config.yml -config.verify(Tempo 支持-config.verify只校验配置不启动,见 cmd/tempo/main.go)。
六、注意事项与局限(以仓库为准)
- 版本适配:示例面向 2.x 架构(默认
2.7.1)。当前仓库源码已演进到包含 LiveStore、PartitionRing、BlockBuilder 等 3.x 组件的版本(见 cmd/tempo/app/modules.go),若用新版本镜像,建议对照相应版本官方配置模板更新overrides与storage段; - S3 凭据安全:凭据通过
-var传入并最终进入作业定义,注意保护 Nomad 作业定义与 Consul KV 的访问权限;生产建议改用 Nomad 的template+ Vault 集成注入密钥,而非明文变量; - 单点形态:
count = 1无副本、无多可用区冗余,NOMAD_ALLOC_DIR中的数据随分配销毁而丢失(已上传 S3 的 block 不受影响,WAL/本地缓存可重建);生产高可用请参考仓库 example/nomad/tempo-distributed 或分布式部署文档; - 废弃状态:如原文档所述,此示例可能被移除,建议以官方 Helm 或 example/docker-compose 中的单二进制示例作为长期维护的部署参考。
七、参考资料
- 本示例作业文件:example/nomad/tempo-monolith/tempo.hcl
- 原文档(含变量表与用法):example/nomad/tempo-monolith/README.md
- 单二进制模式与
-target定义:cmd/tempo/app/modules.go、cmd/tempo/app/config.go - 配置加载与
-config.expand-env实现:cmd/tempo/main.go /ready就绪探针实现:cmd/tempo/app/app.go
【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考