一、方案背景

在公司内部devops平台的微服务化改造过程中,我们遇到了典型的分布式系统观测难题:服务间调用链路复杂、性能瓶颈难以定位、故障排查效率低下。特别是在生产环境出现问题时,往往需要花费大量时间在各个服务的日志中寻找蛛丝马迹。

经过前期的技术调研和实际踩坑,我们最终确定了基于 OpenTelemetry Collector + Kubernetes Operator + 阿里云 SLS 的观测平台解决方案。这套方案的核心目标是:让开发团队能够快速定位问题,让运维团队能够主动发现问题,让业务团队能够洞察系统性能对用户体验的影响

二、技术选型深度对比

2.1 阿里云链路追踪实战踩坑记录

在实际接入阿里云链路追踪的过程中,我们遇到了几个关键问题:

数据闭环问题
  • 问题描述:阿里云链路追踪的数据完全封闭在云平台内部,外部系统无法获取原始数据

  • 影响范围:无法进行定制化数据分析、无法与现有监控体系集成、难以实现跨平台数据关联

  • 业务痛点:当我们需要基于链路数据做业务分析或告警定制时,完全受限于阿里云提供的功能

功能局限性问题
  • 接口筛选限制:无法按照 kind:server 进行接口列表筛选,导致客户端调用和服务端处理混在一起

  • 告警配置受限:告警规则无法基于 span 的 kind 属性进行精确配置

  • 环境隔离混乱:通过标签区分环境导致全局拓扑图极为混乱,影响问题排查效率

技术架构分析

阿里云链路追踪的本质

  • 底层基于 SkyWalking 实现

  • SkyWalking 本身是 OpenTracing 的增强版,包含 Trace 和 Metrics 数据

  • 但并非标准的 OpenTelemetry 协议,缺乏标准化支撑

核心问题根源

  • 云产品的数据闭环特性,基本断绝了定制化扩展的可能性

  • 非标准协议导致后期 Metrics 定制化扩展时无标准可循

  • 强耦合的产品设计限制了技术栈的灵活性

2.2 链路追踪方案对比

基于实际使用经验,我们对主流链路追踪方案进行了深入对比:

方案标准支持运维成本存储后端数据消费厂商绑定推荐度
SkyWalking自有协议高(需自建ES集群)Elasticsearch受限中等
JaegerOpenTracing/OTel高(需自建存储)Cassandra/ES开放⚠️
阿里云链路追踪基于SkyWalking托管封闭
阿里云SLS完整OTel支持托管开放

2.3 为什么不选择 SkyWalking?

运维成本过高

存储后端复杂性:

# SkyWalking 典型部署架构
SkyWalking OAP Server:- 需要 Elasticsearch 集群(至少3节点)- 需要配置索引模板和生命周期策略- 需要监控 ES 集群健康状态- 数据量大时查询性能下降明显Elasticsearch 集群:resources:requests:memory: "4Gi"     # 每节点最少4GB内存cpu: "2"limits:memory: "8Gi"     # 生产环境建议8GB+cpu: "4"

成本分析对比:

组件SkyWalking方案SLS方案
计算资源OAP Server: 2C4G × 2无需自建
存储资源ES集群: 4C8G × 3按量付费
运维人力需要ES人员运维无需专门运维
月成本估算¥3000-5000¥800-1500
技术标准化问题

协议兼容性:

// SkyWalking 使用自有协议
type SegmentObject struct {TraceSegmentId string `json:"traceSegmentId"`// 非标准 OpenTelemetry 格式
}// OpenTelemetry 标准格式
type Span struct {TraceId    []byte `json:"trace_id"`SpanId     []byte `json:"span_id"`// 遵循 OTLP 协议标准
}
  • 厂商锁定风险:SkyWalking 使用自有数据格式,迁移成本高

  • 生态兼容性:与 OpenTelemetry 生态集成需要额外适配

  • 标准化程度:不符合 CNCF 推荐的 OpenTelemetry 标准

2.4 为什么选择 OpenTelemetry + 阿里云 SLS?

基于前面踩坑经验的总结,我们最终选择了 OpenTelemetry + 阿里云 SLS 的技术方案:

OpenTelemetry 的标准化价值

在经历了阿里云链路追踪的数据闭环问题后,我们深刻认识到标准化的重要性:

# OpenTelemetry 配置(标准化)
receivers:otlp:protocols:grpc:endpoint: "0.0.0.0:55680"http:endpoint: "0.0.0.0:55681"exporters:# 可以轻松切换到任何支持 OTLP 的后端otlp/sls:endpoint: "https://sls-endpoint"# 或者切换到其他厂商otlp/jaeger:endpoint: "http://jaeger:14250"

实际项目中的迁移便利性:

  • 从阿里云链路追踪迁移时,应用代码完全不需要修改

  • 我们可以同时导出到多个后端,在迁移过程中进行数据对比验证

  • 基于 CNCF 标准,避免了再次踩坑的风险

成本效益分析

在实际项目预算评估中,我们发现成本差异非常明显:

真实成本对比(基于我们的实际使用量):

# 月处理约100GB Trace数据的成本对比
SkyWalking 自建方案:
- ECS费用: ¥2400 (OAP Server + ES集群)
- 存储费用: ¥800 (高性能SSD)
- 运维成本: ¥2000 (需要专门的ES运维)
- 监控告警: ¥200 (额外的监控组件)
总计: ¥5400/月阿里云 SLS 方案:
- 存储费用: ¥600 (100GB数据)
- 查询费用: ¥300 (日常查询)
- 运维成本: ¥0 (托管服务)
总计: ¥900/月实际节省: 83% (¥4500/月)

这个成本差异在项目立项时起到了决定性作用,特别是考虑到我们团队缺乏 Elasticsearch 专业运维经验的情况下。

数据开放性解决核心痛点

这是我们选择 SLS 而不是阿里云链路追踪的关键原因:

实时数据消费能力:

# SLS 支持实时数据消费,这是我们实际在用的代码
from aliyun.log import LogClient# 实时消费 Trace 数据进行业务分析
client = LogClient(endpoint, access_key_id, access_key_secret)
response = client.pull_logs(project, logstore, shard_id, cursor)# 我们基于这个能力实现了自定义的性能告警
for log in response.get_logs():# 检测慢查询if log.get('duration') > 2000 and 'mysql' in log.get('operation_name', ''):send_slow_query_alert(log)# 检测错误率异常if log.get('status_code') == 'ERROR':update_error_metrics(log)

解决的实际问题:

  • 自定义告警:我们可以基于业务逻辑设置精确的告警规则,而不是被限制在云产品的固定功能中

  • 数据关联分析:能够将链路数据与业务指标进行关联,实现更深层次的业务洞察

  • 多维度消费:同一份数据可以同时供给 Grafana、自建告警系统、数据分析平台使用

2.5 最终技术架构确认

基于以上分析,我们确定的技术架构为:

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   应用服务      │    │  OpenTelemetry   │    │   数据存储      │
│                 │    │    Collector     │    │                 │
│ ┌─────────────┐ │    │  (DaemonSet)     │    │ ┌─────────────┐ │
│ │   Metrics   │─┼────┼──────────────────┼────┼→│ Prometheus  │ │
│ └─────────────┘ │    │                  │    │ └─────────────┘ │
│ ┌─────────────┐ │    │                  │    │ ┌─────────────┐ │
│ │   Traces    │─┼────┼──────────────────┼────┼→│ 阿里云 SLS  │ │
│ └─────────────┘ │    │                  │    │ └─────────────┘ │
│ ┌─────────────┐ │    │                  │    │ ┌─────────────┐ │
│ │    Logs     │─┼────┼──────────────────┼────┼→│业务LogStore │ │
│ └─────────────┘ │    │                  │    │ └─────────────┘ │
└─────────────────┘    └──────────────────┘    └─────────────────┘↓┌──────────────────┐│     Grafana      ││   (统一展示)     ││                  ││ • Prometheus数据 ││ • SLS Trace数据  ││ • 日志关联查询   │└──────────────────┘

架构特点:

  1. Metrics:通过 Prometheus 直接采集和存储,利用其成熟的生态

  2. Traces:通过 OpenTelemetry Collector 上报到阿里云 SLS,享受托管服务优势

  3. Logs:保持现有业务 LogStore 不变,避免业务改造

  4. 展示:统一在 Grafana 中展示所有观测数据,实现一站式监控

核心优势:

  • 成本最优:相比自建 SkyWalking 节省 80%+ 成本

  • 标准开放:基于 OpenTelemetry 标准,避免厂商锁定

  • 运维简单:无需维护复杂的存储集群

  • 扩展性强:支持数据实时消费和自定义分析

  • 业务无感:日志系统保持不变,减少业务改造风险

三、核心概念解析

3.1 OpenTelemetry Collector DaemonSet 架构优势

为什么选择 DaemonSet 部署模式?

1. 网络开销最小化

传统的集中式 Collector 部署方式存在以下问题:

  • 跨节点网络传输:应用数据需要通过 K8s Service 或 Ingress 路由到远程 Collector,增加网络跳数

  • 网络延迟累积:数据传输路径:应用 → kube-proxy → Service → 远程节点 → Collector

  • 带宽竞争:所有节点的观测数据汇聚到少数几个 Collector 实例,容易形成网络瓶颈

DaemonSet 模式的网络优势:

传统模式:App Pod  → 远程 OAP SERVER Pod (跨节点网络,需要nat网关)DaemonSet:App Pod → DaemonSet:55680 (同集群同节点网络栈,不走nat网关)
  • 本地通信:应用直接通过 DaemonSet:55680 与同节点的 Collector 通信,避免跨节点网络传输

  • 零延迟:同节点网络延迟接近 0,大幅降低观测数据的传输延迟

  • 带宽节省:节点内通信不占用集群网络带宽,避免对业务流量的影响

  • 高可用性:每个节点独立的 Collector 实例,单点故障不影响其他节点

2. 资源利用优化

# DaemonSet 资源配置示例
resources:requests:memory: "128Mi"    # 每节点固定资源消耗cpu: "100m"limits:memory: "256Mi"    # 可预测的资源上限cpu: "200m"
  • 资源分散:Collector 资源消耗分散到各个节点,避免单节点资源热点

  • 线性扩展:随着节点数量增加,Collector 处理能力线性扩展

  • 故障隔离:单个节点的 Collector 故障不影响其他节点的数据收集

3. 配置管理简化

# 统一的 ConfigMap 配置
apiVersion: v1
kind: ConfigMap
metadata:name: otel-collector-config
data:config.yaml: |receivers:otlp:protocols:grpc:endpoint: "0.0.0.0:55680"  # 所有节点统一配置
  • 配置一致性:所有节点使用相同的 Collector 配置,简化运维管理

  • 热更新支持:通过 ConfigMap 更新可以同时影响所有节点的 Collector

  • 版本管理:DaemonSet 确保所有节点运行相同版本的 Collector

3.2 Kubernetes Operator 无侵入式改造原理

为什么选择 Operator 模式?

1. 声明式配置管理

传统的观测接入方式存在以下问题:

  • 手动配置:需要开发人员手动修改每个应用的 Deployment 配置

  • 配置分散:观测配置散布在各个应用的部署文件中,难以统一管理

  • 人为错误:手动配置容易出现拼写错误、配置不一致等问题

  • 维护成本高:配置变更需要逐个应用修改,工作量大

Operator 的声明式优势:

# 应用只需添加标签,无需修改容器配置
metadata:labels:odyssey-apm-enable: "true"        # 声明:我需要观测odyssey-apm-language: "java"      # 声明:我是 Java 应用odyssey-apm-sampling-rate: "0.3"  # 声明:30% 采样率
  • 标签驱动:通过标签声明观测需求,Operator 自动处理具体实现

  • 配置集中:所有观测逻辑集中在 Operator 中,便于统一管理和升级

  • 自动化执行:标签变更自动触发配置更新,无需人工干预

2. 无侵入式注入机制

Java 应用无侵入原理:

// Operator 自动注入的环境变量
javaToolOptions := fmt.Sprintf("-javaagent:/usr/local/agent/opentelemetry.jar " +"-Dotel.service.name=%s " +"-Dotel.exporter.otlp.traces.endpoint=http://DaemonSet:55680",serviceName)container.Env = append(container.Env, corev1.EnvVar{Name:  "JAVA_TOOL_OPTIONS",Value: javaToolOptions,
})
  • JavaAgent 机制:利用 JVM 的 -javaagent 参数在类加载时进行字节码增强

  • 零代码改动:应用代码完全不需要修改,只需在镜像中包含 OpenTelemetry JavaAgent

  • 自动埋点:JavaAgent 自动识别并埋点常见框架(Spring、MyBatis、Redis 等)

  • 运行时注入:通过环境变量在容器启动时注入配置,不影响镜像构建

Golang 应用最小侵入原理:

// Operator 注入的环境变量
envVars := map[string]string{"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "http://DaemonSet:55680","OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": "grpc","OTEL_SERVICE_NAME":                  serviceName,"OTEL_TRACES_SAMPLER":                "parentbased_traceidratio","OTEL_TRACES_SAMPLER_ARG":            samplingRate,
}
  • 环境变量配置:通过标准的 OpenTelemetry 环境变量进行配置

  • SDK 自动初始化:OpenTelemetry Go SDK 自动读取环境变量并初始化

  • 最小代码改动:只需在应用启动时调用 SDK 初始化函数

  • 标准化接入:遵循 OpenTelemetry 标准,便于后续迁移和升级

3. 动态配置管理

实时监听机制:

// Operator 的 Reconcile 循环
func (r *ObserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {// 1. 监听 Deployment 变化事件var deployment appsv1.Deploymentif err := r.Get(ctx, req.NamespacedName, &deployment); err != nil {return ctrl.Result{}, client.IgnoreNotFound(err)}// 2. 检查观测标签if apmEnable, exists := deployment.Labels["odyssey-apm-enable"]; exists && apmEnable == "true" {// 3. 自动注入观测配置r.injectObservabilityConfig(&deployment)} else {// 4. 自动清理观测配置r.removeObservabilityConfig(&deployment)}return ctrl.Result{}, nil
}
  • 事件驱动:基于 K8s API 的 Watch 机制,实时响应 Deployment 变化

  • 自动同步:标签添加/删除自动触发配置注入/清理,保持状态一致

  • 批量管理:支持批量操作,可以同时管理多个应用的观测配置

  • 版本控制:配置变更通过 K8s 的版本控制机制进行管理

4. 运维友好性

统一管理界面:

# 查看所有启用观测的应用
kubectl get deployments -l odyssey-apm-enable=true# 批量启用观测
kubectl label deployments -l app.type=microservice odyssey-apm-enable=true# 查看 Operator 运行状态
kubectl logs -f deployment/odyssey-obser-operator
  • 可视化管理:通过 kubectl 命令或 K8s Dashboard 可视化管理观测配置

  • 批量操作:支持基于标签选择器的批量配置操作

  • 审计日志:所有配置变更都有完整的审计日志

  • 故障自愈:Operator 持续监控并自动修复配置漂移

3.3 架构优势总结

方面传统方式Operator + DaemonSet 方式
网络开销跨节点传输,延迟高本地通信,零延迟
配置管理手动分散配置自动化集中管理
代码侵入需要修改应用代码Java 零侵入,Go 最小侵入
运维复杂度高,需要逐个配置低,标签驱动自动化
扩展性集中式瓶颈线性扩展
故障影响单点故障影响全局故障隔离,影响最小
资源利用资源热点资源分散,利用率高

核心特性

  • 无侵入接入:Java 应用通过 JavaAgent 零代码改动,Golang 应用通过环境变量配置

  • 自动化管理:通过 K8s Operator 自动监听 Deployment 变化,动态注入观测配置

  • 统一数据出口:所有观测数据统一上报至阿里云 SLS,支持多维度分析

  • 灵活采样控制:支持通过标签配置链路采样率,平衡性能与观测精度

  • 多平台支持:既支持奥德赛 CICD 平台一键开启,也支持独立 K8s 环境手动配置

四、架构设计

4.1 整体架构图

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   应用服务       │    │  OpenTelemetry   │    │   阿里云 SLS     │
│                │    │    Collector     │    │                │
│ ┌─────────────┐ │    │                 │    │ ┌─────────────┐ │
│ │ Java App    │─┼────┼─► gRPC:55680   ─┼────┼─► Trace Store │ │
│ │ (JavaAgent) │ │    │   HTTP:55681    │    │ │             │ │
│ └─────────────┘ │    │                 │    │ └─────────────┘ │
│                │    │                 │    │                │
│ ┌─────────────┐ │    │                 │    │ ┌─────────────┐ │
│ │ Golang App  │─┼────┼─► OTLP Protocol ─┼────┼─► Metrics    │ │
│ │ (SDK)       │ │    │                 │    │ │ Store       │ │
│ └─────────────┘ │    │                 │    │ └─────────────┘ │
└─────────────────┘    └──────────────────┘    └─────────────────┘▲                       ▲                       ││                       │                       ▼
┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ K8s Operator    │    │   DaemonSet      │    │   观测平台       │
│                │    │                 │    │                │
│ ┌─────────────┐ │    │ ┌─────────────┐ │    │ ┌─────────────┐ │
│ │ Deployment  │ │    │ │ OTel        │ │    │ │ SLS 控制台   │ │
│ │ Watcher     │ │    │ │ Collector   │ │    │ │             │ │
│ └─────────────┘ │    │ │ Pod         │ │    │ └─────────────┘ │
│                │    │ └─────────────┘ │    │                │
│ ┌─────────────┐ │    │                 │    │ ┌─────────────┐ │
│ │ Env Var     │ │    │                 │    │ │ Grafana +   │ │
│ │ Injector    │ │    │                 │    │ │ Jaeger UI   │ │
│ └─────────────┘ │    │                 │    │ └─────────────┘ │
└─────────────────┘    └──────────────────┘    └─────────────────┘

4.2 数据流向

应用 Pod → OpenTelemetry Collector (DaemonSet) → 阿里云 SLS↑                    ↑
Operator 注入配置    本地 localhost:55680
  1. 配置注入:Operator 监听 Deployment 变化,自动注入观测配置

  2. 数据生成:应用启动时自动初始化 OpenTelemetry SDK

  3. 本地收集:应用通过 localhost:55680 将数据发送到同节点 Collector

  4. 数据处理:Collector 对数据进行批处理、采样、格式转换

  5. 远程上报:Collector 将处理后的数据上报到阿里云 SLS

4.3 组件职责

组件职责部署方式
OpenTelemetry Collector接收应用上报的 OTLP 数据,转发至 SLSDaemonSet(每个节点一个实例)
K8s Operator监听 Deployment 变化,自动注入观测配置Deployment(集群级单实例)
应用服务通过 Agent 或 SDK 上报观测数据现有 Deployment
阿里云 SLS存储和分析观测数据云服务

五、核心组件实现

5.1 OpenTelemetry Collector

配置说明

基于 otelcol-contrib 构建,配置文件 /tools/obser/config.yaml

receivers:otlp:protocols:grpc:endpoint: "0.0.0.0:55680"  # 接收 gRPC 协议数据http:endpoint: "0.0.0.0:55681"  # 接收 HTTP 协议数据exporters:alibabacloud_logservice/sls-trace:endpoint: "sre-observability-monitor.cn-shanghai.log.aliyuncs.com"project: "sre-observability-monitor"logstore: "odyssey-stage-traces"access_key_id: "${SLS_ACCESS_KEY_ID}"access_key_secret: "${SLS_ACCESS_KEY_SECRET}"service:pipelines:traces:receivers: [otlp]exporters: [alibabacloud_logservice/sls-trace]
部署清单
apiVersion: apps/v1
kind: DaemonSet
metadata:name: odyssey-otel-collectornamespace: odyssey-observability
spec:selector:matchLabels:app: odyssey-otel-collectortemplate:metadata:labels:app: odyssey-otel-collectorspec:containers:- name: otel-collectorimage: {otel collector的docker镜像}ports:- containerPort: 55680name: grpc- containerPort: 55681name: httpenv:- name: SLS_ACCESS_KEY_IDvalueFrom:secretKeyRef:name: sls-credentialskey: access-key-id- name: SLS_ACCESS_KEY_SECRETvalueFrom:secretKeyRef:name: sls-credentialskey: access-key-secretresources:requests:memory: "128Mi"cpu: "100m"limits:memory: "256Mi"cpu: "200m"hostNetwork: true  # 使用主机网络,便于应用访问

5.2 Kubernetes Operator

功能特性

基于 /operator/obser/main.go 实现的 K8s Operator,具备以下能力:

  1. 自动发现:监听集群内所有 Deployment 的创建、更新、删除事件

  2. 标签驱动:根据 Deployment 标签自动判断是否需要注入观测配置

  3. 多语言支持:支持 Java(JavaAgent)和 Golang(SDK)两种接入方式

  4. 采样率控制:支持通过标签配置链路采样率

  5. 服务名映射:优先使用 Pod 的 app 标签作为服务名

标签配置规范
标签名说明
odyssey-apm-enable"true"启用观测功能
odyssey-apm-language"java""golang"应用语言类型,默认 java
odyssey-apm-sampling-rate"0.1" ~ "1.0"链路采样率,默认 1.0(全采样)
环境变量注入逻辑

Java 应用

JAVA_TOOL_OPTIONS="-javaagent:/usr/local/agent/opentelemetry.jar \-Dotel.service.name=${SERVICE_NAME} \-Dotel.exporter.otlp.traces.endpoint=http://localhost:55680 \-Dotel.exporter.otlp.traces.protocol=grpc \-Dotel.exporter.otlp.traces.insecure=true \-Dotel.metrics.exporter=none \-Dotel.logs.exporter=none \-Dotel.traces.sampler=parentbased_traceidratio \-Dotel.traces.sampler.arg=${SAMPLING_RATE}"

Golang 应用

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://localhost:55680"
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="grpc"
OTEL_SERVICE_NAME="${SERVICE_NAME}"
OTEL_TRACES_SAMPLER="parentbased_traceidratio"
OTEL_TRACES_SAMPLER_ARG="${SAMPLING_RATE}"

5.3 应用接入方式

Java 应用(无侵入)
  1. 镜像准备:在应用镜像中预置 OpenTelemetry JavaAgent``dockerfile# 在应用 Dockerfile 中添加ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar /usr/local/agent/opentelemetry.jar\

  2. 标签配置:在 Deployment 上添加观测标签``yamlmetadata:labels:odyssey-apm-enable: "true"odyssey-apm-language: "java"odyssey-apm-sampling-rate: “0.3” # 30% 采样率\

  3. 自动生效:Operator 自动注入 JAVA_TOOL_OPTIONS 环境变量,应用重启后生效

Golang 应用(otel动态插桩)
  1. 编译代理:使用otel go agent完成编译改造,只需要加上前缀 otel即可

  2. 标签配置:在 Deployment 上添加观测标签``yamlmetadata:labels:odyssey-apm-enable: "true"odyssey-apm-language: "golang"odyssey-apm-sampling-rate: “0.5” # 50% 采样率\

  3. 自动生效:Operator 自动注入 OTEL 相关环境变量,应用重启后生效

六、部署实施方案

6.1 环境准备

命名空间创建
kubectl create namespace odyssey-observability
SLS 凭证配置
kubectl create secret generic sls-credentials \--from-literal=access-key-id="LTAI5t7snKaMwG2RjVAdFv8H" \--from-literal=access-key-secret="4t1E90OJyWhrYfoRtbwsuLQxiJmueN" \-n odyssey-observability

6.2 组件部署顺序

  1. 部署 OpenTelemetry Collector DaemonSet``bashkubectl apply -f otel-collector-daemonset.yaml\

  2. 部署 K8s Operator``bashkubectl apply -f odyssey-obser-operator.yaml\

  3. 验证部署状态``bashkubectl get pods -n odyssey-observabilitykubectl logs -f deployment/odyssey-obser-operator -n odyssey-observability\

6.3 应用接入流程

devops 平台CICD 平台接入

image.png

  1. 平台配置:在devops CICD 平台的应用配置页面

  2. 一键开启:勾选"开启观测"选项

  3. 参数配置

    • 应用语言:Java / Golang

    • 采样率:0.1 - 1.0

  4. 自动部署:平台自动在 Deployment 上添加相应标签并重新部署

独立 K8s 环境接入

image.png

  1. 手动添加标签:``bashkubectl label deployment odyssey-apm-enable=truekubectl label deployment odyssey-apm-language=javakubectl label deployment odyssey-apm-sampling-rate=0.3\

  2. 触发更新:``bashkubectl rollout restart deployment \

  3. 验证接入:``bashkubectl describe deployment | grep -A 10 “Environment”\

七、观测数据消费

7.1 阿里云 SLS 控制台

链路查询

image.png

  • 入口:SLS 控制台 → sre-observability-monitor 项目 → odyssey-环境-traces 日志库

  • 查询语法:```sql

    • | SELECT \* FROM log WHERE service\_name = ‘user-service’ AND duration > 1000```
服务拓扑

image.png

image.png

  • 自动生成:基于 Trace 数据自动构建服务依赖关系图

  • image.png

  • 性能分析:展示服务间调用的延迟、错误率、吞吐量

7.2 自建 Grafana + Jaeger

https://apm.cds8.cn

sls自带监控大盘只是为了方便我们前期使用,最终还是会自己部署grafana去完成数据的在线观测,由于我们使用otel规范,所以可以很轻松的使用jaeger query插件完成trace的可视化展示,指标利用普罗米修斯去拉取指标数据即可。

Jaeger Query 部署
apiVersion: apps/v1
kind: Deployment
metadata:name: jaeger-query
spec:replicas: 1selector:matchLabels:app: jaeger-querytemplate:metadata:labels:app: jaeger-queryspec:containers:- name: jaeger-queryimage: jaegertracing/jaeger-query:latestenv:- name: SPAN_STORAGE_TYPEvalue: "elasticsearch"- name: ES_SERVER_URLSvalue: "http://elasticsearch:9200"ports:- containerPort: 16686
Grafana 数据源配置
  1. 添加 Jaeger 数据源:URL 指向 Jaeger Query 服务

  2. 添加 SLS 数据源:通过 SLS API 接入指标数据

  3. 创建综合大盘:整合链路、指标、日志的统一视图

八、监控告警策略

8.1 基础设施监控

指标阈值告警级别
OTel Collector CPU 使用率> 80%Warning
OTel Collector 内存使用率> 85%Warning
Operator Pod 状态NotReady > 5minCritical
SLS 上报失败率> 5%Warning

8.2 应用观测告警

指标阈值告警级别
服务响应时间 P99> 2sWarning
服务错误率> 1%Warning
服务错误率> 5%Critical
链路断点检测到Warning

九、性能优化与最佳实践

9.1 采样策略

分层采样
  • 生产环境:默认 10% 采样率,关键服务 30%

  • 测试环境:50% 采样率

  • 开发环境:100% 采样率

动态采样
# 高 QPS 服务降低采样率
metadata:labels:odyssey-apm-sampling-rate: "0.1"  # 10% 采样# 关键业务服务提高采样率
metadata:labels:odyssey-apm-sampling-rate: "0.5"  # 50% 采样

9.2 资源配置建议

OpenTelemetry Collector
  • CPU:每 1000 spans/s 需要约 100m CPU

  • 内存:每 1000 spans/s 需要约 128Mi 内存

  • 网络:确保与 SLS 的网络连通性稳定

K8s Operator
  • CPU:100m(轻量级,主要处理 K8s API 调用)

  • 内存:128Mi

  • 权限:需要 Deployment 的 get、list、watch、update 权限

9.3 故障排查指南

常见问题
  1. 应用无链路数据

    • 检查 Deployment 标签是否正确

    • 验证 OTel Collector 是否正常运行

    • 确认应用是否成功注入环境变量

  2. 链路数据不完整

    • 检查采样率配置

    • 验证服务间网络连通性

    • 确认 SDK 版本兼容性

  3. 性能影响

    • 调整采样率

    • 优化 Collector 资源配置

    • 检查 SLS 上报延迟

调试命令
# 查看 Operator 日志
kubectl logs -f deployment/odyssey-obser-operator -n odyssey-observability# 查看 Collector 状态
kubectl get pods -l app=odyssey-otel-collector -n odyssey-observability# 测试 OTLP 端点连通性
kubectl exec -it <app-pod> -- telnet localhost 55680# 查看应用环境变量
kubectl exec -it <app-pod> -- env | grep OTEL

本文章为本人在公司内部的技术分享,已隐去关键信息,欢迎大家讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/97896.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/97896.shtml
英文地址,请注明出处:http://en.pswp.cn/web/97896.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 进阶实战:从待办清单到完整应用(路由 / 状态管理 / 性能优化全攻略)

Vue 进阶实战&#xff1a;从待办清单到完整应用&#xff08;路由 / 状态管理 / 性能优化全攻略&#xff09; 在上一篇博客里&#xff0c;我们一起实现了能本地存储的待办清单&#xff0c;不少朋友留言说&#xff1a;“学会了基础&#xff0c;但遇到‘登录后才能访问页面’‘多…

uniApp开发XR-Frame微信小程序 | 动态加载与删除模型

在使用xr-frame开发3D小程序时&#xff0c;我们经常需要根据需求去动态加载模型或删除模型&#xff0c;在官方的说明中&#xff0c;提到了相关方法&#xff0c;但并不太明确&#xff0c;也没有确切的实例。 我们先来看一下官方给出的说明。 一. Shadow元素 我们需要用代码动…

把多个 PPT 合并在一起,三步告别复制粘贴

制作部门汇报分册、项目阶段文件等工作需要将多个零散的PPT合并为一份完整文档。手动复制粘贴不仅效率低下&#xff0c;还容易导致格式错乱、动画丢失。本文介绍一种高效方法&#xff0c;三步操作即可将多个PPT文件快速合并为单一文档。无论是整合汇报材料&#xff0c;还是准备…

安卓旋转屏幕后如何防止数据丢失-ViewModel入门

Android ViewModel 入门教程 在日常开发中&#xff0c;当 Activity 因为旋转屏幕或内存回收被销毁重建时&#xff0c;UI 中的数据也会丢失。 这时候&#xff0c;Android Jetpack 提供的 ViewModel 就能帮我们解决这个问题。 1. 什么是 ViewModel ViewModel 是一种架构组件。它专…

Linux 下的 Vim 使用与网络安全配置详解

目录 引言 一、Vim 编辑器的使用 1. Vim 的模式 2. 常用操作命令 3. 保存与退出 4. 多窗口与 Shell 切换 二、Linux 网络基础 1. 网络分类 2. IP 地址与分类 三、网络配置与工具 1. ifconfig 2. netstat 3. wget 4. 主机名与 IP 映射 四、Linux 防火墙与安全设置…

Docker 容器传输文件的常用方法

Docker 容器传输文件的常用方法 在 Docker 日常使用中&#xff0c;经常需要在主机与容器之间传输文件&#xff08;如配置文件、代码包、日志等&#xff09;。以下是四种最常用的实现方式&#xff0c;覆盖临时传输、持久共享、构建集成等不同场景。 1. 使用 docker cp 命令&…

视频转音频在线工具大比拼,哪家体验更胜一筹?

最近工作上遇到了个挺有意思的需求&#xff0c;需要从几个教学视频里提取出音频内容&#xff0c;方便做成播客形式&#xff0c;让学员能随时随地学习。一开始&#xff0c;我以为这活儿挺简单的&#xff0c;不就是把视频里的声音单独弄出来嘛&#xff0c;结果一上手才发现&#…

KafKa02:Kafka配置文件server.properties介绍

一、配置文件位置二、配置文件介绍默认下&#xff1a;9092 是处理消息队列核心业务&#xff08;客户端与 broker 交互&#xff09;的端口9093 是集群内部控制器通信的端口# 指定节点角色&#xff0c;这里同时作为 broker&#xff08;消息代理&#xff09;和 controller&#xf…

哈尔滨云前沿服务器租用托管

黑龙江前沿数据&#xff0c;始建于2005年&#xff0c;多年的历史&#xff0c;专业从事域名注册&#xff0c;虚拟主机&#xff0c;服务器租用&#xff0c;云主机&#xff0c;网站建设等互联网服务。电信/联通/双线/机房/众多机房供您选择&#xff0c;总有一个适合您的服务器&…

Qt开发经验 --- Qt 修改控件样式的方式(16)

文章目录[toc]1 概述2 Qt Style Sheets (QSS)3 使用 QStyle 和 QProxyStyle4 设置 Palette (调色板)5 使用预定义的 QStyle6 直接设置控件属性7 自定义控件绘制更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发经验 &#x1f448;1 概述 Qt 提供了多种修改…

Vue3》》Svg图标 封装和使用

SVG 安装插件 npm i vite-plugin-svg-icons // vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import { createSvgIconsPlugin } from vite-plugin-svg-icons import { resolve } from path export default defineConfig({//配置路径别…

【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡

【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡引言本次二开布局没有变&#xff0c;但是下一次整体布局会有变&#xff0c;不过本次开发发现朋友圈跳转功能的流程步骤也做了一定的变化。原生项目复杂就复杂于就算一个颜色…

龙蜥8.10中spark各种集群及单机模式的搭建spark3.5.6(基于hadoop3.3.6集群)

先说最终的访问端口&#xff0c;如我这里ip为172.20.94.37、172.20.94.38、172.20.94.39&#xff0c;主机名分别为&#xff1a;hadoop37、hadoop38、hadoop39. 最终访问&#xff08;默认端口&#xff09;&#xff1a; hadoop webui 172.20.94.37:9870 hdfs 端口 8020 yarn 172.…

关于我重新学习 react 的第一遍

今天是25年9月11号&#xff0c;很久很久没有学习前端知识了&#xff0c;坦诚来说还清楚记得在大学里因为前端技术第一次获奖的心情&#xff0c;也清晰记得写完第一篇博客后的心情&#xff0c;工作和运动给我最大程度的成就感。 打破自己 重新开始 完全地 版本一 25.9.11 文章目…

第2课:Agent系统架构与设计模式

第2课&#xff1a;Agent系统架构与设计模式 课程目标 理解Agent的基本概念和特性掌握多Agent系统的设计模式学习Agent通信协议和消息传递实践创建简单的Agent框架 课程内容 2.1 Agent基础概念 什么是Agent&#xff1f; Agent是一个具有自主性、反应性、社会性和主动性的计…

Day42 51单片机中断系统与8×8 LED点阵扫描显示

day42 51单片机中断系统与88 LED点阵扫描显示一、51单片机引脚位操作 —— sbit 关键字 作用 sbit 是专用于 51 单片机架构的 C 语言扩展关键字&#xff0c;用于定义特殊功能寄存器&#xff08;SFR&#xff09;中的某一位&#xff0c;从而实现对单个 I/O 引脚的直接位操作。 示…

差分: 模板+题目

题目&#xff1a;【模板】差分 应用场景&#xff1a;快速解决将某一个区间所有元素加上 “一个数” 的操作。 第一步&#xff0c;预处理差分数组。 f[i] 表示&#xff1a;当前元素与前一个元素的差值 a[i] - a[i-1]; 但在题目中&#xff0c;我们其实可以不用到a[]这个数组…

GD32 Timer+ADC多通道+DMA+PWM调试记录

本例记录使用GD32307C开发板&#xff0c;实现以内部Timer1 CH1为触发源&#xff0c;触发ADC0的两个通道&#xff0c;进行并行非连续采样&#xff0c;病通过DMA传输采样结果。同时输出PWM&#xff0c;用来检测Timer1 CH1的触发周期。下面介绍具体实现过程&#xff1a;1. gpio初始…

阻塞 IO为什么叫BIO,非阻塞IO为什么叫NIO,异步IO为什么叫AIO

IOIO的核心就是数据传输&#xff0c;也就是程序与外部设备之间进行传输&#xff0c;通过IO的核心可以分为&#xff0c;文件IO和网络IO文件IO交互的对象就是本地存储设备&#xff0c;比方说读写本地文件。网络IO交互的对象就是网络设备&#xff0c;核心的应用场景就是网络通信。…

10分钟了解什么是多模态大模型

10分钟了解什么是多模态大模型&#xff08;MM-LLMs&#xff09; 1. 什么是多模态 Multimodality 多模态&#xff08;Multimodality&#xff09;是指集成和处理两种或两种以上不同类型的信息或数据的方法和技术。在机器学习和人工智能领域&#xff0c;多模态涉及的数据类型通常…