OneUptime Cloud Environments 完全指南:用 OpenTelemetry 自动发现并监控托管云计算环境
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
导读
本文基于 OneUptime 官方文档(德语版,另有内容更完整的 英语版)讲解Cloud Environments(云环境)功能:OneUptime 如何把 AWS ECS / Fargate、Google Cloud Run、Azure Container Apps 等托管云计算资源自动聚合为单一环境实体,并展示其实例级 CPU、内存、请求、日志与链路追踪。读完本文你将掌握环境识别规则、环境键(Resource Identifier)的构成、支持的平台清单、Collector / SDK 两种接入形态,以及环境、实例、服务三者之间的关系。
什么是 Cloud Environments
OneUptime 将托管云计算资源聚合为Cloud Environments(云环境)。一个环境既不是服务(Service)也不是机器(Host),而是你的容器真正运行的地方——例如某个 ECS 集群所在的账户与区域、某个 Cloud Run 项目与区域、某个 Container Apps 环境——它负责把运行在其中的所有工作负载聚合到一处。
环境的关键特征:
- 同一工作负载的按服务拆解视图仍然保留在Services(服务)下,环境是"汇总层"(roll-up),服务的拆分是明细层;
- 环境之下通过Instances(实例)标签页展示正在运行的任务、实例与副本(replicas),并在平台支持的前提下提供实时 CPU 与内存;
- 云环境视图是专门为托管 / PaaS 计算资源设计的。
需要特别强调的是:纯虚拟机(EC2、Compute Engine、Azure VM)仍然是 Hosts(主机),Kubernetes 集群仍然归入Kubernetes。云环境只针对托管 / PaaS 计算。
前置条件
接入前需要准备两样东西:
- OneUptime Telemetry Ingestion Token(遥测摄取令牌)——在项目设置 → Telemetry & APM → 摄取密钥(Ingestion Keys)中创建。德语文档建议创建后复制
x-oneuptime-token的值;该值是机密,请存放在对应云平台自己的密钥存储中。 - 一个 OpenTelemetry Collector 或 SDK——运行在工作负载内部或旁边,向 OneUptime 导出 OTLP 数据。
OneUptime 如何识别一个环境
环境键:cloud.platform | cloud.account.id | cloud.region
每一个唯一组合的cloud.platform+cloud.account.id+cloud.region即构成一个环境。例如"AWS ECS · us-east-1 · 123456789012"是一个单一实体,聚合运行其上的每个工作负载。
| 属性 | 是否必需 | 作用 |
|---|---|---|
cloud.platform | 是 | 必须是受管计算平台(例如aws_ecs、gcp_cloud_run、azure_container_apps) |
cloud.account.id | 否 | 环境键的一部分(AWS 账户 ID、GCP 项目 ID 或 Azure 订阅 ID) |
cloud.region | 否 | 环境键的一部分(us-east-1、us-central1、eastus…) |
service.instance.id | 否 | 用于Instances(实例)标签页中每个任务 / 实例(附带实时 CPU / 内存) |
三个值用|拼接成环境键,即该环境的Resource Identifier(资源标识符):
aws_ecs|123456789012|us-east-1 gcp_cloud_run|my-project|us-central1 azure_container_apps|00000000-0000-0000-0000-000000000000|eastus德语文档明确提醒:缺失的部分不会丢弃,而是保留为空段——例如aws_ecs||us-east-1。因此,一个省略了cloud.account.id的工作负载,会落在与设置了该属性的工作负载不同的环境里。这是你明明预期只有一个环境、却看到两个环境的常见原因。显示名称由同样的值生成:AWS ECS · us-east-1 · 123456789012。
这些属性通常由 OpenTelemetry 的Resource Detectors(资源探测器)自动填充。摄取(ingest)端会自动铸造环境键与显示名,无需手工注册;如果你手工创建环境,摄取只按环境键匹配,因此手工环境的 Resource Identifier 必须严格等于platform|account|region。
源码层面的佐证:环境键只在一处构造
从源码看,环境键与显示名由 Common/Types/Cloud/CloudPlatform.ts 统一构造(buildCloudEnvironmentKey与buildCloudEnvironmentName,见 L320-L372)。该文件注释明确它是以下四处的"单一事实来源"(single source of truth):
- 遥测摄取入口
OtelIngestBaseService.autoDiscoverCloudResource的环境发现门槛; - 摄取铸造的环境键 / 显示名;
- 仪表盘 Cloud Resources 的创建表单;
- 文档页面及将文档与产品锁定的测试。
buildCloudEnvironmentKey的实现正是把三部分trim()后用|连接,缺失段保留空串;buildCloudEnvironmentName则用·拼接"平台标签 + 区域 + 账户 ID"。平台标签存放在MANAGED_CLOUD_PLATFORMS描述符中,代码注释提醒:更改标签会重命名之后发现的每一个环境,请保持其稳定。
摄取入口的实现位于 App/FeatureSet/Telemetry/Services/OtelIngestBaseService.ts(autoDiscoverCloudResource):它先对cloud.platform做normalizeCloudPlatform规范化,若不在受管平台集合内则直接返回null(即不归入云环境);随后用cloud.provider或由平台推断出 provider,读取 region 与 account id,构造环境键后调用CloudResourceService.findOrCreateByResourceIdentifier按键查重/创建,并通过缓存 + 数据库唯一索引((projectId, resourceIdentifier))保证并发批次不会产生重复行。
实例身份:谁是一条"实例"记录
在一个环境内,每个运行中的任务 / 实例 / 副本对应一行实例记录,取自以下第一个出现的资源属性:
aws.ecs.task.idaws.ecs.task.arn(缩写为 task id)faas.instanceazure.container_app.instance.idservice.instance.idcontainer.idhost.idhost.name
平台自身的任务 / 实例身份有意排在前面:sidecar Collector 与应用 SDK 都能看到它,且它能在进程重启后存续;而 SDK 铸造的service.instance.id通常是每个进程一个随机 ID(Node SDK 默认的serviceinstance探测器正是如此),若以它为准,awsecscontainermetricsreceiver 按 task id 上报时,同一个 ECS 任务会被拆成两行。只有当平台没有自身身份时,才使用service.instance.id。
该回退链在源码中的常量定义见 Common/Utils/Telemetry/CloudInstanceIdentity.ts(CLOUD_INSTANCE_IDENTITY_ATTRIBUTES),解析函数resolveCloudInstanceName会按序取第一个非空属性,并在命中aws.ecs.task.arn时通过shortenEcsTaskArn把完整 ARN 缩写为任务 ID(arn:aws:ecs:us-east-1:123456789012:task/my-cluster/1a2b3c4d5e6f→1a2b3c4d5e6f)。文件注释还指出:在这条链出现之前,只有service.instance.id被读取,导致 ECS 环境的 Instances 标签页为空、CPU / 内存瓦片永不填充——因为 ECS 探测器从不设置该属性。摄取路径(按原样键)与指标快照折叠路径(resource.前缀键)共用同一常量,保证两边对"什么是实例"的判定永远不会不一致。实例行由CloudResourceInstanceService.recordInstance写入 CloudResourceInstance 表(该表对(projectId, cloudResourceId, instanceName)建立唯一索引,不可用户编辑)。
支持的平台与属性来源
| 平台 | cloud.platform | cloud.*由谁填充 | 实例身份 |
|---|---|---|---|
| AWS ECS / Fargate | aws_ecs | 资源探测器(resource detector) | aws.ecs.task.arn |
| AWS Elastic Beanstalk | aws_elastic_beanstalk | 资源探测器 | host.id |
| AWS App Runner | aws_app_runner | 手工设置 | host.name |
| Google Cloud Run | gcp_cloud_run | 资源探测器 | faas.instance |
| Google App Engine | gcp_app_engine | 资源探测器 | faas.instance |
| Azure Container Apps | azure_container_apps | 资源探测器 | azure.container_app.instance.id |
| Azure Container Instances | azure_container_instances | 手工设置 | host.name |
| Azure App Service | azure_app_service | 资源探测器 | host.id |
- "资源探测器":SDK 内的探测器或 Collector 的
resourcedetectionprocessor 读取平台元数据,自动填充cloud.*属性。 - "手工设置":上游没有对应探测器,需要你在
OTEL_RESOURCE_ATTRIBUTES中自行写入(各平台页面给出了精确写法)。
这条受管平台清单在源码中对应 Common/Types/Cloud/CloudPlatform.ts 的MANAGED_CLOUD_PLATFORMS描述符数组,每一项都携带detection: "detector" | "manual"与instanceAttribute。此外该文件还有两个值得注意的实现细节:
- Azure 平台名的点号改写:Node / .NET 的 Azure SDK 探测器把平台拼成点号形式(
azure.container_apps、azure.app_service),而语义约定与 Collector 探测器使用下划线。CLOUD_PLATFORM_ALIASES表(L217-L224)让摄取在入口处把这些值改写为下划线形式——否则同一订阅里,Node 应用与 Collector sidecar 会落入两个不同环境。改写是在normalizeCloudPlatform(L231-L253)中完成的,它还会先trim()并使用hasOwnProperty查找,避免"constructor"之类的原型链注入。 - FaaS 与托管平台互不抢占:
FaasCloudPlatform(aws_lambda、gcp_cloud_functions、azure_functions等)单独枚举,确保 Serverless 产品与云环境产品不会意外认领同一资源。
什么不属于云环境
| 你运行在 | 会出现在 | 原因 |
|---|---|---|
EC2、Compute Engine、Azure VM(aws_ec2、gcp_compute_engine、azure_vm) | Hosts | 虚拟机就是主机 |
| EKS、GKE、AKS、自管理 Kubernetes | Kubernetes | 由k8s.*属性路由 |
Lambda、Cloud Functions、Azure Functions(aws_lambda、gcp_cloud_functions、azure_functions) | Serverless Functions | 由faas.name路由 |
Cloud Run 与 App Engine 是**有意"跨界"**的:它们的探测器同时设置受管的cloud.platform和faas.name,因此每个服务既独立出现在Serverless Functions下,又由Cloud Environment把该项目与区域内的所有服务聚合起来。
接入配置:两步走
Step 1 — 激活云资源探测器
Collector 形态:在 OpenTelemetry Collector 中增加resourcedetectionprocessor:
processors: resourcedetection: detectors: [env, ecs] # Cloud Run 上用 [gcp],Azure 上用 [azure] timeout: 5sSDK 形态:设置OTEL_RESOURCE_DETECTORS:
OTEL_RESOURCE_DETECTORS=env,ecs英语版文档对两种形态做了更细的展开,值得参考:
- 形态 A —— SDK 直连 OneUptime:启用平台的资源探测器(Node
OTEL_NODE_RESOURCE_DETECTORS=env,host,os,aws/gcp/azure;PythonOTEL_EXPERIMENTAL_RESOURCE_DETECTORS=aws_ecs或gcp_resource_detector;Java-Dotel.resource.providers.aws.enabled=true/gcp;Go 的 contrib 探测器;.NET 的OpenTelemetry.Resources.*包),并把 OTLP exporter 指向 OneUptime。无需额外容器,也没有容器级 CPU / 内存。 - 形态 B —— sidecar OpenTelemetry Collector:在任务 / 实例 / 副本中再跑一个容器。应用向
localhost:4318导出;Collector 的resourcedetectionprocessor 给所有数据打上cloud.*戳记、持有令牌,并且在 ECS 上还能顺带上报每个任务的 CPU / 内存。
Step 2 — 向 OneUptime 导出 OTLP
exporters: otlphttp/oneuptime: endpoint: https://oneuptime.com/otlp headers: x-oneuptime-token: YOUR_TELEMETRY_INGESTION_TOKEN service: pipelines: traces: receivers: [otlp] processors: [resourcedetection] exporters: [otlphttp/oneuptime] metrics: receivers: [otlp] processors: [resourcedetection] exporters: [otlphttp/oneuptime] logs: receivers: [otlp] processors: [resourcedetection] exporters: [otlphttp/oneuptime]如果你自托管 OneUptime,把 endpoint 换成https://YOUR-ONEUPTIME-HOST/otlp。三条 pipeline(traces / metrics / logs)都必须保留resourcedetectionprocessor——指标如果没有cloud.platform会被归档到其他地方,环境里的 CPU / 内存瓦片就不会填充。
SDK 形态则直接在应用进程上设置:
OTEL_EXPORTER_OTLP_ENDPOINT="https://oneuptime.com/otlp" OTEL_EXPORTER_OTLP_HEADERS="x-oneuptime-token=YOUR_TELEMETRY_INGESTION_TOKEN"接入后的验证
第一条 span / 日志 / 指标到达后一分钟内,环境就会出现在Cloud → All Environments中。若想先确认令牌有效,可用:
curl -i https://oneuptime.com/otlp/v1/validate \ -H "x-oneuptime-token: YOUR_TELEMETRY_INGESTION_TOKEN"200且返回"valid": true:令牌解析到某个项目,继续;401:令牌缺失、格式错误、未知或已撤销,请重新创建。
环境概览视图:你能得到什么
环境概览(德语文档 "Was Sie erhalten")展示:
- CPU 与内存:每个运行中任务 / 实例的实时 CPU 与内存(来自
container.cpu.utilization/container.memory.usage),外加一个Top instances by CPU(CPU 最高的实例)列表; - Instances(实例):任务的实时数量;
- Anfragen(请求)与趋势图:从你的 traces 推导而来;
- 完整的Protokolle(日志)、Traces(链路追踪)、Metriken(指标)、Instanzen(实例)标签页。
同一批工作负载的按服务拆解视图在Services下查看。
英语版补充了三点重要细节:
- CPU / 内存瓦片只由指标填充,不来自 traces,并且要求指标数据携带与 traces相同的实例身份;在 ECS 上由 sidecar Collector 中的
awsecscontainermetricsreceiver 以ecs.task.cpu.utilized/ecs.task.memory.utilized提供。Cloud Run、Container Apps 等其他 PaaS 不向 sidecar 暴露容器统计,除非你自己上报这两个指标名,否则那里的 CPU / 内存瓦片保持为空——此时应以Requests瓦片为准。 - 形态 A(SDK 直连)永远不会发送容器指标,所以 CPU / 内存为空是预期行为。
- 环境在连续 15 分钟收不到遥测后会显示Disconnected,下一条 span / 日志 / 指标到达即恢复。实例另有"Stale(过期)"标签与清扫器:实例行若在
CLOUD_INSTANCE_STALE_MINUTES(默认 15,最小 10)内未出现会被硬删除,该时钟以环境自身的最后遥测时间为基准,因此 Collector 宕机只会"冻结"时钟而不会清空已知任务列表。
常见问题与排查要点
德语文档本身指向平台各自的接线文档与 Cloud Troubleshooting(云环境故障排查),后者按"失败实际发生的顺序"列出排查层级,核心要点可提前掌握:
- 环境没出现:先查
cloud.platform是否缺失或非受管值(常见原因:SDK 未启用探测器、Collector pipeline 跳过了resourcedetection、无探测器平台上OTEL_RESOURCE_ATTRIBUTES拼写错误);其次查令牌(401时 Collector 日志表现为Permanent error: ... 401);最后查出口网络(ECS 私有子网需要 NAT 网关或assignPublicIp=ENABLED,安全组放行 TCP 443;Cloud Run 需要 Cloud NAT)。 - 出现在 Hosts 下:资源带的是虚拟机平台(
aws_ec2等),通常是探测器顺序问题——detectors: [ec2, elastic_beanstalk]时第一个设置cloud.platform的探测器胜出,把elastic_beanstalk放到最前面。 - 只出现在 Serverless Functions 下:有
faas.name但没有受管的cloud.platform(注意 Cloud Run / App Engine 本应同时出现在两处)。 - 实例为空:遥测没带任何实例身份属性;CPU / 内存为空:指标缺失或指标与 traces 的实例身份不一致。
- 出现了两个环境:环境键逐字符精确匹配,
aws_ecs|123456789012|us-east-1与aws_ecs||us-east-1是不同环境,检查每个环境的 Resource Identifier 找出差异段。 - 手工创建的环境从不匹配:摄取只按 Resource Identifier匹配,必须与遥测携带的
platform|account|region完全一致(同一拼写、无多余空格);创建表单会从 Cloud Platform / Cloud Account ID / Cloud Region 三个字段推导出该键,因此这三者必须与遥测逐字符一致。
数据模型一览
- CloudResource(表名
CloudResource):一个环境一行,resourceIdentifier即环境键(aws_ecs|123456789012|us-east-1),name为显示名("AWS ECS · us-east-1 · 123456789012"),另有cloudPlatform/cloudProvider/cloudRegion/cloudAccountId等"最近一次看到"的取值、otelCollectorStatus、lastSeenAt、可覆盖的遥测保留天数(retainTelemetryDataForDays)与标签。代码注释明确(projectId, resourceIdentifier)唯一索引用于让并发首见摄取批次折叠为单行;cloud.*字段创建后可写、之后不可更新(摄取心跳updateLastSeen负责回填与刷新,手工编辑只会与 Collector 实际上报值漂移)。 - CloudResourceInstance(表名
CloudResourceInstance):一个运行实例一行,由摄取管线 upsert,不可用户编辑,(projectId, cloudResourceId, instanceName)唯一。
小结
Cloud Environments 是 OneUptime 遥测体系中对托管 / PaaS 计算的聚合视图:摄取端依据cloud.platform、cloud.account.id、cloud.region三元组自动发现并命名环境,实例身份则通过一条精心排序的属性回退链统一判定。接入只需在 Collector 或 SDK 中启用资源探测器、把 OTLP 指向/otlp端点并在指标 pipeline 中保留resourcedetection。排查时从令牌验证开始,按cloud.platform值、出口网络、实例身份、指标来源逐层排除,即可快速定位绝大多数问题。
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考