基于 OpenTelemetry:Kubernetes 环境下 Python 应用无侵入接入落地实践

本文介绍如何通过观测云实现 Kubernetes 环境下 Python 应用的无侵入式可观测接入,还原跨服务调用关系,快速定位慢请求与异常,降低接入和运维成本。

最佳实践
banner.png

面向已经运行在 Kubernetes 中的 Python 应用,通过自动注入零代码采集链路数据并上报观测云,无需修改业务启动命令或手工创建 Span。

背景

微服务应用通常包含多个内部调用。只查看接口状态和容器日志,可以知道请求失败,却难以回答请求经过了哪些服务、耗时集中在哪里,以及异常由哪个下游引起。

OpenTelemetry(OTel)提供统一的可观测数据标准,但逐个修改 Python 应用、安装依赖和调整启动命令,会增加接入和维护成本。本实践从“Python 业务已经部署并正常运行”出发,使用 Kubernetes 自动注入完成接入。

实践目标包括:

  • 不修改业务代码和原有启动命令;
  • 通过标签控制需要接入的 Python 工作负载;
  • 自动采集 HTTP 服务端与客户端调用;
  • 将 Trace、Metrics 和 Logs 通过 OTLP 发送到观测云;
  • 在观测云中还原跨服务调用关系,定位慢请求和异常调用。

观测云介绍

观测云是一站式可观测平台,可统一接入和分析基础设施、容器、指标、日志、链路等数据。不同类型的观测数据使用统一的服务、环境和资源属性建立关联,使排查过程可以从服务异常继续下钻到一次请求、相关日志及其运行环境。

应用性能监测(APM)以分布式链路追踪为核心,将一次请求经过的服务和组件组织成完整调用链。接入链路数据后,可以在观测云中查看:

  • 服务性能:请求数、错误率、平均响应时间以及 P90、P99 等延迟指标;
  • 服务关系:通过服务拓扑了解上下游依赖和调用方向;
  • 链路详情:通过火焰图、瀑布图和 Span 列表分析各调用环节的耗时与状态;
  • 关联分析:根据 trace_id、service 等字段关联请求产生的日志、指标和基础设施信息。

观测云通过 DataKit 接收 OpenTelemetry、DDTrace、Jaeger、Zipkin 等协议产生的链路数据。本实践选择 OpenTelemetry:Python OTel 探针负责生成可观测数据,DataKit 在 Kubernetes 集群内接收 OTLP 数据并上报观测云,DataKit Operator 则负责在应用 Pod 创建时自动注入探针。下文将围绕这条接入链路展开配置。

实践

方案架构与接入流程

本方案由 DataKit Operator、Python OTel 探针和 DataKit 共同完成。整个接入过程分为探针注入和数据上报两个阶段。

1.png

探针注入流程:

  1. 为 Python 应用的 Pod 模板添加语言标签;
  2. Kubernetes 创建 Pod 时调用 DataKit Operator 注册的 Mutating Admission Webhook;
  3. Operator 根据注入规则修改 Pod 配置,加入 initContainer、共享卷和 OTel 环境变量;
  4. Pod 启动时自动加载 Python OTel 探针,无需修改业务代码和启动命令。

数据上报流程:

  1. OTel 探针自动采集应用产生的 Trace、Metrics 和 Logs;
  2. 探针通过 OTLP/HTTP 将数据发送到集群内的 DataKit;
  3. DataKit 对数据进行处理后上报观测云;
  4. 用户在观测云中查看服务调用链、运行指标和关联日志。

下面依次完成 DataKit、DataKit Operator 和业务应用的配置,并验证最终接入效果。

配置 DataKit

如果集群尚未安装 DataKit,先按照官方文档完成 Kubernetes 安装;已有 DataKit 时只需确认以下配置,不要覆盖原有采集器:

配置 要求
ENV_DEFAULT_ENABLED_INPUTS 包含 opentelemetry
ENV_HTTP_LISTEN 设置为 0.0.0.0:9529
datakit-service 暴露 9529 端口

应用配置后确认 DataKit 正常运行并已启用 OpenTelemetry input:

kubectl rollout status daemonset/datakit -n datakit --timeout=5m
kubectl get pod,service,endpointslice -n datakit -o wide
kubectl logs -n datakit daemonset/datakit --tail=100 | grep -i opentelemetry

业务探针通过以下地址访问 DataKit:

http://datakit-service.datakit.svc.cluster.local:9529

配置 DataKit Operator

安装 DataKit Operator 官方清单,并在 admission_inject_v2.otels 中添加 Python 规则。本文使用语言标签选择工作负载,不绑定具体服务名:

{
  "name": "otel-python",
  "language": "python",
  "namespace_selectors": ["*"],
  "label_selectors": ["admission.datakit/otel-language=python"],
  "check_annotation": false,
  "image": "ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:0.64b0",
  "image_pull_policy": "IfNotPresent",
  "envs": {
    "POD_NAME": "{fieldRef:metadata.name}",
    "POD_NAMESPACE": "{fieldRef:metadata.namespace}",
    "NODE_NAME": "{fieldRef:spec.nodeName}",
    "OTEL_SERVICE_NAME": "{fieldRef:metadata.labels['app']}",
    "OTEL_RESOURCE_ATTRIBUTES": "k8s.pod.name=$(POD_NAME),k8s.namespace.name=$(POD_NAMESPACE),k8s.node.name=$(NODE_NAME)",
    "OTEL_PROPAGATORS": "tracecontext,baggage",
    "OTEL_TRACES_SAMPLER": "parentbased_always_on",
    "OTEL_TRACES_EXPORTER": "otlp",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_PYTHON_LOG_AUTO_INSTRUMENTATION": "true",
    "OTEL_PYTHON_FLASK_EXCLUDED_URLS": "healthz",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
    "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "http://datakit-service.datakit.svc.cluster.local:9529/otel/v1/traces",
    "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "http://datakit-service.datakit.svc.cluster.local:9529/otel/v1/logs",
    "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://datakit-service.datakit.svc.cluster.local:9529/otel/v1/metrics"
  },
  "resources": {
    "requests": {"cpu": "100m", "memory": "64Mi"},
    "limits": {"cpu": "500m", "memory": "512Mi"}
  }
}

OTEL_SERVICE_NAME 复用业务已有的 app 标签生成服务名。如果集群使用其他标签规范,应同步调整这里的字段映射。OTEL_PYTHON_FLASK_EXCLUDED_URLS 用于排除高频健康检查路径。

完整 Operator 配置见 manifests/datakit-operator.yaml。修改 ConfigMap 后重启 Operator,使配置重新加载:

kubectl apply -f manifests/datakit-operator.yaml
kubectl rollout restart deployment/datakit-operator -n datakit
kubectl rollout status deployment/datakit-operator -n datakit --timeout=5m

应用接入

在业务 Deployment 的 spec.template.metadata.labels 中加入语言标签。app 用于生成 service.name,admission.datakit/otel-language 用于匹配 Python 注入规则:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: <业务命名空间>
spec:
  template:
    metadata:
      labels:
        app: order-service
        admission.datakit/otel-language: python

将标签合并到业务 Deployment,并通过现有发布流程应用

kubectl apply -f <业务 Deployment 清单>
kubectl rollout status deployment/<应用名> -n <业务命名空间> --timeout=5m

新增上述标签会改变 Pod 模板,Deployment 将自动滚动创建新 Pod,无需额外执行重启。如果标签在安装 Operator 前已经存在,或者只修改了 Operator 注入规则,现有 Pod 不会被重新处理,此时需要主动触发滚动更新:

kubectl rollout restart deployment/<应用名> -n <业务命名空间>
kubectl rollout status deployment/<应用名> -n <业务命名空间> --timeout=5m

应用验证

首先检查新 Pod 是否已经注入探针:

kubectl get pod -n <业务命名空间> -o wide
kubectl describe pod -n <业务命名空间> -l app=<应用名>

注入成功后,Pod 中应出现:

  • datakit-otel-lib-init initContainer;
  • /otel-auto-instrumentation-python 共享卷挂载;
  • OTEL_SERVICE_NAME 和 OTLP endpoint 等环境变量;
  • 状态为 Running,业务容器处于 Ready。

通过应用原有入口发送一次能够触发下游调用的请求,并使用唯一的 X-Request-ID 标记本次验证流量。先在观测云日志中按 Request ID 找到对应的 trace_id,再进入 应用性能监测 → 链路 查询。重点确认:

  1. 入口服务和下游服务均产生 Span;
  2. Span 之间具有正确的父子关系;
  3. 请求方法、路由、状态码和耗时符合实际请求;
  4. 慢请求和异常请求能够在链路中定位到具体服务。

如果 Pod 没有注入,优先检查语言标签位置、Operator 日志和探针镜像拉取状态;如果 Pod 已注入但没有数据,检查 DataKit 的 9529 端口、OpenTelemetry input 和业务容器中的 exporter 错误。

实践效果

完成自动注入后,向订单服务发起一次正常请求。观测云共采集到 9 个 Span,覆盖订单、商品和库存三个服务;入口 POST /orders 成为完整链路的根 Span,持续时间为 13.24 ms,本次请求没有错误 Span。

链路全貌与关联日志

火焰图展示了订单请求及其四次下游调用,可以直观看到每个调用在整条链路中的发生时间和耗时占比。链路详情同时按 trace_id 关联出三个服务产生的 5 条业务日志。

2.png

服务调用关系

服务调用关系还原出以 order-service 为入口的调用拓扑:订单服务分别调用 catalog-service 和 inventory-service,每个下游服务均被调用两次。该视图能够快速确认服务依赖、调用次数及各服务在本次请求中的耗时占比。

3.png

Span 时序与明细

瀑布图进一步展示了 Span 的父子关系和执行顺序,说明 Trace 上下文已经在服务间完成传播。

4.png

总结

通过 DataKit Operator 与 OpenTelemetry 自动注入,Python 应用无需改造业务代码即可获得完整的跨服务链路和关联日志。该方案将探针管理从应用侧收敛到 Kubernetes 平台侧,兼顾标准化、低侵入和规模化接入,为云原生 Python 应用接入观测云提供了一条清晰、可复制的路径。

参考资料

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台