news 2026/9/25 6:51:31

Kata Containers Tracing 全解析:基于 OpenTelemetry 实现 Runtime 与 Guest Agent 的全链路追踪

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kata Containers Tracing 全解析:基于 OpenTelemetry 实现 Runtime 与 Guest Agent 的全链路追踪
  • 云原生
  • 容器运行时

【免费下载链接】kata-containers

Kata Containers is an open source project and community working to build a standard implementation of lightweight Virtual Machines (VMs) that feel and perform like containers, but provide the workload isolation and security advantages of VMs. https://katacontainers.io/

项目地址:https://gitcode.com/gh_mirrors/ka/kata-containers
点击查看免费下载

Kata Containers 的 runtime(宿主机侧)和 agent(虚拟机内侧)都能生成 OpenTelemetry trace span,帮助管理员观察各组件的行为以及每个操作所花费的时间。本篇技术文章将围绕仓库中的 tracing 文档 展开:先讲清 trace/span 的基础概念与 Kata 的 tracing 架构(尤其是 agent 如何跨越 VM 边界把 span 送抵宿主机收集器),再给出完整的启用配置、trace forwarder 的部署步骤与前提条件,并结合源码深入剖析 VSOCK 传输协议、span 的生成与合并机制、agent 关闭行为等实现细节,帮助读者掌握 Kata 全链路可观测性的配置与排障能力。

1. 什么是 Trace 与 Span:OpenTelemetry 基础

一个启用 OpenTelemetry 的应用会创建若干 trace "span"。每个 span 包含以下属性:

  • 一个名字(name);
  • 一对时间戳(记录某个操作开始与结束的时间);
  • 对父 span 的引用(parent span reference)。

所有 span 都必须被finish(或称complete),OpenTelemetry 框架才能生成最终的 trace 信息——其本质是闭合涵盖根 span(root span)及其全部子 span 的那笔"事务"。

在 Kata 中,根 span 代表的就是某个组件从启动到关闭所花费的总时间(即 "run time")。这一点在 agent 源码中有直接印证:

在 src/agent/src/main.rs 中,agent 启动时如果配置了config.tracing,就会先调用tracer::setup_tracing()初始化 OpenTelemetry 提供者,随后立即进入一个名为"root-span"的 span:

if config.tracing { tracer::setup_tracing(NAME, &logger)?; } let root_span = span!(tracing::Level::TRACE, "root-span"); // XXX: Start the root trace transaction. // // XXX: Note that *ALL* spans needs to start after this point!! let span_guard = root_span.enter();

注释明确说明"此后开始的所有 span 都挂在这个根事务之下"。而到 agent 关闭阶段(src/agent/src/main.rs),会先drop(span_guard)、drop(root_span)强制 flush 所有 span,再调用tracer::end_tracing()关闭全局 tracer 提供者。这解释了为什么"span 必须完成,trace 才完整"。

2. 整体架构:宿主机 runtime 与 VM 内 agent 的追踪难题

2.1 Runtime tracing 架构

运行在宿主机环境中的 runtime 被改造为可选地生成 trace span,并直接发送到宿主机的 trace 收集器(collector)。因为 runtime 与 collector 运行在同一上下文,所以没有跨边界问题。

从源码结构看,Go runtime 的 tracing 采用 OpenTracing 接口 + Jaeger collector 的方式:shim 在加载完 runtime 配置后创建 tracer 并打开 root span,见 src/runtime/pkg/containerd-shim-v2/create.go:

// create tracer // This is the earliest location we can create the tracer because we must wait // until the runtime config is loaded jaegerConfig := &katatrace.JaegerConfig{ JaegerEndpoint: s.config.JaegerEndpoint, JaegerUser: s.config.JaegerUser, JaegerPassword: s.config.JaegerPassword, } _, err = katatrace.CreateTracer("kata", jaegerConfig) ... // create root span rootSpan, newCtx := katatrace.Trace(s.ctx, shimLog, "rootSpan", shimTracingTags)

Rust runtime(runtime-rs)则在 src/runtime-rs/crates/runtimes/src/tracer.rs 中用 OpenTelemetry SDK +opentelemetry_jaeger实现:维护一个全局ROOTSPAN,在读取配置且config.runtime.enable_tracing打开时进入(trace_setup),收到 containerd 的 shutdown 请求时退出(trace_end),使整个 sandbox 生命周期内"不直接运行在某个 span 之下的线程"也能被追踪。其默认 endpoint 为http://localhost:14268/api/traces(Jaeger HTTP Thrift 收集器)。

2.2 Agent tracing 架构:trace forwarder 跨越 VM 边界

OpenTelemetry 系统依赖 collector 从应用中收集 span。应用要使用 collector,必须与 collector 运行在同一上下文。这对追踪 Kata agent 构成了难题:agent 运行在虚拟机内部,而 collector 通常在宿主机上。

为此,Kata 提供了 trace forwarder 组件(kata-trace-forwarder)。它运行在与 collector 相同的上下文中(通常在宿主系统上),通过VSOCK 通道监听 agent 生成的 trace,再使用 OpenTelemetry Protocol(OTLP)把它们转发给 trace 收集器。

注意:

该设计使得 agent 追踪无需修改 guest 镜像即可实现,因此使用 osbuilder 构建的自定义镜像同样能从 agent tracing 中获益。

原文档中的架构示意(宿主机、VM、forwarder 与 collector 的关系):

+--------------------------------------------+ | Host | | | | +---------------+ | | | OpenTelemetry | | | | Trace | | | | Collector | | | +---------------+ | | ^ +---------------+ | | | spans | Kata VM | | | +-----+-----+ | | | | | Kata | spans o +-------+ | | | | Trace |<-----------------| Kata | | | | | Forwarder | VSOCK o | Agent | | | | +-----------+ Channel | +-------+ | | | +---------------+ | +--------------------------------------------+
数据链路在源码中的对应实现

agent 侧的"出口"是一个专门的 VSOCK exporter,位于 src/agent/vsock-exporter/src/lib.rs,其文件头注释把协议讲得很清楚:

  • 默认向宿主机(VMADDR_CID_HOST)的10240 端口发起 VSOCK 连接(DEFAULT_PORT: u32 = 10240,与 forwarder 端的DEFAULT_KATA_VSOCK_TRACING_PORT常量严格对应,见 src/tools/trace-forwarder/src/main.rs);
  • 协议采用最简单的"头 + 负载"结构:先发送一个 8 字节(大端序)的负载长度头,再发送序列化后的 span 数据(JSON)。forwarder 依据头部知道要读多少字节才能完整消费一个 span;
  • exporter 是懒连接:首次export()时才建立 VSOCK 连接并缓存;若连接断开(NotConnected)则丢弃连接、下次自动重连,从而保证 forwarder 短暂重启时 agent 不崩溃。

forwarder 端的setup_tracing(agent 侧初始化,src/agent/src/tracer.rs)则把该 exporter 包装成 OpenTelemetry 的TracerProvider(batch exporter + Tokio 运行时),并通过tracing_opentelemetry层注册为全局 subscriber,同时设置TraceContextPropagator作为 W3C 传播器。

跨进程 span 关联的关键在于 ttrpc 调用链:trace_rpc_call!宏(src/agent/src/tracer.rs)在 agent 处理每个来自 shim 的 RPC 时,先从 ttrpc 请求元数据中提取上下文载体(extract_carrier_from_ttrpc),用全局 propagator 解析出父上下文,然后为本 RPC 创建 span 并set_parent(parent_context)。也就是说,runtime 发起 RPC 时注入的 trace context 会通过 ttrpc 元数据传入 guest,使 agent 的 span 挂载为 runtime 对应 span 的子 span——这正是原文档所述"collated"(合并)效果的实现机制。

3. Agent tracing 的前提条件

要启用 agent 追踪,需要满足:

  • 必须有一个运行中的 OTLP 兼容 trace 收集器。

    虽然收集器通常运行在宿主机上,也可以从 Docker 镜像中运行(只需把相应端口暴露给收集器即可)。

    常见的 OTLP 兼容收集器包括:

    • Jaeger(v1.35+)
    • OpenTelemetry Collector
    • Grafana Tempo

    运行 Jaeger "all-in-one" Docker 镜像(v1.35+)是测试时启动收集器最快速、最简单的方式。请确保它配置为在 **4317 端口(gRPC)**或 **4318 端口(HTTP)**接受 OTLP 数据。

  • 如果要追踪 agent,必须用正确的 OTLP endpoint 启动 trace forwarder。

注意:

  • 如果启用了 agent 追踪但 forwarder 没有运行,agent 会记录一条错误日志(表明它无法生成 trace span),但功能继续正常运行;
  • trace forwarder 启动前要求有一个 OTLP 兼容收集器在运行。若收集器没有运行,trace forwarder 会报错退出。

4. 启用 tracing:配置项与生效范围

默认情况下,所有组件的 tracing 都是关闭的。要启用任何形式的 tracing,必须至少为某个组件打开enable_tracing选项。

注意:

启用该选项后,只对此后启动的容器生效。

4.1 启用 runtime tracing

[runtime] enable_tracing = true

配置字段定义在 src/libs/kata-types/src/config/runtime.rs,除enable_tracing外,[runtime]段还有配套的 Jaeger 端点参数(Go runtime 使用):

参数类型默认值说明
enable_tracingboolfalse是否让 runtime 生成 tracing span
jaeger_endpointstring空(runtime-rs 侧默认为http://localhost:14268/api/traces)Jaeger HTTP Thrift collector 的完整 URL
jaeger_userstring空Jaeger 需要 basic auth 时的用户名
jaeger_passwordstring空Jaeger 需要 basic auth 时的密码

从 runtime-rs 的实现看(src/runtime-rs/crates/runtimes/src/manager.rs),只有config.runtime.enable_tracing为真时才会执行trace_setup,即创建 Jaeger 收集管线并进入 ROOTSPAN;若设置了密码但用户名为空,tracing 会拒绝启用并告警(verify_jaeger_config逻辑,见 src/runtime-rs/crates/runtimes/src/tracer.rs)。

此外,Kata 还支持通过 Kubernetes annotation 覆盖配置:io.katacontainers.config.agent.enable_tracing(常量定义见 src/libs/kata-types/src/annotations/mod.rs),可在不改动 TOML 配置文件的情况下按 Pod 级别开启 agent 追踪,这对在共享集群上临时排查问题非常方便。

4.2 启用 agent tracing

[agent.kata] enable_tracing = true

该字段的定义及官方注释在 src/libs/kata-types/src/config/agent.rs,注释中明确了两条行为约束,与原文档附录一致:

  • 如果 runtime 也启用了 tracing,agent 的 span 会关联到相应的 runtime 父 span;
  • 启用后,runtime 会等待容器关闭完成,因此容器关闭时间会略有增加。

4.3 两者同时启用:span 的合并(collation)

注意:

如果 agent tracing 和 runtime tracing 同时启用,产生的 trace span 会被"合并"(collated):在 trace 收集器的 Web UI 中展开某个 runtime span,可以看到由该 runtime 操作产生的 agent trace span。

其机制即第 2.2 节所述的 ttrpc 上下文传播:runtime 端在发起 CreateContainer/StartContainer 等 RPC 时把当前 span context 写入请求元数据,agent 端用TraceContextPropagator解出父 span,从而形成"runtime 根 span → runtime 操作 span → agent RPC span → agent 内部 span"的完整调用树。

5. trace forwarder 实战:按 Hypervisor 部署

trace forwarder 的 README 给出了比主文档更细的运行步骤,核心流程为:

  1. 启动 OTLP 兼容收集器(如 Jaeger v1.35+、OpenTelemetry Collector 或 Grafana Tempo);
  2. 以合适的 OTLP endpoint 启动 trace forwarder;
  3. 确认 Kata 配置文件中已启用 agent tracing;
  4. 照常创建 Kata 容器。

OTLP endpoint:forwarder 默认使用http://localhost:4317(gRPC)。要指向其他端点,使用--otlp-endpoint标志:

kata-trace-forwarder --otlp-endpoint http://my-collector:4317

forwarder 的完整命令行参数可在 src/tools/trace-forwarder/src/main.rs 中核对:--trace-name(默认kata-agent)、--otlp-endpoint、--socket-path(Cloud Hypervisor/Firecracker 用)、--vsock-cid(默认any)、--vsock-port(默认10240)、--log-level、--dump-only(禁用转发、把 span 写到 stdout,便于测试)。

5.1 QEMU:标准 VSOCK,非特权运行

QEMU 以标准方式支持 VSOCK socket,因此直接使用默认选项运行即可:

cargo run

无需特殊权限。判断当前配置的 hypervisor 可以用:

kata-runtime env --json|jq '.Hypervisor.Path'

5.2 Cloud Hypervisor / Firecracker:Hybrid VSOCK

Cloud Hypervisor 和 Firecracker 使用 "hybrid VSOCK"——通过本地 UNIX socket 而非宿主机内核与 guest 通信,因此需要指定 UNIX socket 路径。由于 forwarder 必须在 VM(sandbox)启动之前运行,而 socket 路径是 sandbox 特定的,需要先用env命令确定"模板路径"(其中{ID}代表真实的 sandbox ID 或名称):

Cloud Hypervisor 示例:

$ socket_path_template=$(sudo kata-runtime env --json | jq '.Hypervisor.SocketPath') $ echo "$socket_path_template" "/run/vc/vm/{ID}/clh.sock"

Firecracker 示例:

$ socket_path_template=$(sudo kata-runtime env --json | jq '.Hypervisor.SocketPath') $ echo "$socket_path_template" "/run/vc/firecracker/{ID}/root/kata.hvsock"

注意:不要依赖上面展示的路径——应自行执行命令获取,这些路径可能会变化。

确定模板路径后,构建并安装 forwarder(QEMU 场景无需此步)、创建 sandbox 目录、再运行 forwarder:

# Build make # Install cargo install --path . sudo install -o root -g root -m 0755 ~/.cargo/bin/kata-trace-forwarder /usr/local/bin
# 把 sandbox_id 改成你计划创建的容器(sandbox)名称 sandbox_id="foo" socket_path=$(echo "$socket_path_template" | sed "s/{ID}/${sandbox_id}/g" | tr -d '"') sudo mkdir -p $(dirname "$socket_path")
sudo kata-trace-forwarder --socket-path "$socket_path"

现在可以照常创建名为 "foo" 的 Kata 容器了。

注意:

因为 forwarder 需要在 sandbox 目录中创建 socket,而该目录属于root用户,所以 hybrid VSOCK 场景下 forwarder 必须先用root启动。这是 hybrid VSOCK 的独有限制:QEMU 下运行 forwarder 不需要特殊权限。为降低影响,forwarder 启动后会降权到nobody用户继续运行(对应 main.rs 帮助文本中的说明,降权目标用户为server::NON_PRIV_USER)。

6. 前提、限制与性能影响

6.1 Host 环境要求

  • 宿主机内核必须支持 VSOCK socket 类型。内核以CONFIG_VHOST_VSOCK选项编译时具备该能力。
  • 必须加载 VSOCK 内核模块:
sudo modprobe vhost_vsock

6.2 Guest 环境要求

  • guest 内核必须支持 VSOCK socket 类型:内核以CONFIG_VIRTIO_VSOCKETS选项编译时可用。

注意:Kata Containers 默认 guest 内核提供该特性。

6.3 Agent tracing 的完成时机

  • Agent 追踪只有在工作负载和 Kata agent 进程都退出之后才算"完成"。

    虽然在工作负载和 agent 退出之前可以查看 trace 信息,但它是不完整的。某些 trace 收集器的 Web UI 会将其显示为<trace-without-root-span>。如果工作负载仍在运行,横跨整个 Kata agent 生命周期的 trace 事务就不会完成。要查看完整的 trace 细节,请等工作负载结束,或停止容器。

    这与源码中"根 span 在 agent 关闭流程末尾才 drop 并 flush"的实现(src/agent/src/main.rs)一致:root span 不结束,整笔 trace 事务就未闭合。

6.4 性能影响

OpenTelemetry 面向高性能设计,它整合了前代项目(OpenTracing 与 OpenCensus)的优点,并采用非常高效的机制来捕获 trace span。此外,插入 agent 的 trace 点在编译时动态生成。这带来一个好处:新版本 agent 会自动受益于追踪基础设施的改进。总体上,启用 runtime 与 agent tracing 带来的影响应该极低。

6.5 Agent 关闭行为

正常操作下,Kata runtime 管理 VM 关闭并执行若干优化以加速该过程。但如果启用了 agent 追踪,由 agent 本身负责关闭 VM——这是为了确保所有 agent trace 事务都已完成。这意味着 agent 追踪开启时,容器关闭会有小的性能影响,因为 runtime 必须等待 VM 完全关闭。

7. 搭建 tracing 开发环境

如果你想调试、进一步开发或测试 tracing,强烈建议先启用完整调试(enable full debug)。若要在 guest 内调试 agent,还可以启用 debug 控制台(set up a debug console),以便进入 VM 环境。

8. 小结:一次完整的 span 生命周期

综合文档与源码,Kata 的 tracing 形成了一条清晰的跨边界链路:

  1. runtime 侧:shim 在配置加载后创建 tracer 并打开 root span(Go runtime 见 src/runtime/pkg/containerd-shim-v2/create.go,Rust runtime 见 src/runtime-rs/crates/runtimes/src/tracer.rs);
  2. 跨 VM 传播:RPC 元数据携带 W3C trace context 进入 guest,agent 端用trace_rpc_call!宏解析并挂接父 span(src/agent/src/tracer.rs);
  3. guest 侧导出:agent 的 span 经 vsock-exporter 以"8 字节长度头 + JSON span"的协议经 VSOCK 端口 10240 发往宿主机(src/agent/vsock-exporter/src/lib.rs);
  4. 宿主机转发:kata-trace-forwarder监听 VSOCK(标准 VSOCK 或 hybrid UNIX socket),按 OTLP 协议把 span 送到 Jaeger/OTel Collector/Tempo(src/tools/trace-forwarder);
  5. 收尾:agent 退出时 drop root span 并调用end_tracing()强制 flush,保证 trace 事务完整闭合(src/agent/src/main.rs)。

掌握以上链路后,无论是排查 sandbox 创建慢在哪一步(VM 冷启动、设备热插、guest 内挂载),还是对比 runtime 与 agent 各操作的时间占比,都可以直接在收集器 Web UI 中通过展开 span 树得到答案。

  • 云原生
  • 容器运行时

【免费下载链接】kata-containers

Kata Containers is an open source project and community working to build a standard implementation of lightweight Virtual Machines (VMs) that feel and perform like containers, but provide the workload isolation and security advantages of VMs. https://katacontainers.io/

项目地址:https://gitcode.com/gh_mirrors/ka/kata-containers
点击查看免费下载

相关推荐

上一篇:如何在vscode-dark-islands中启用图标发光效果?Seti Folder配置教程
下一篇:深入理解Ghostty-web的Buffer系统:终端数据处理的核心机制

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 6:50:50

CLI Agent 工具链实战:OpenRouter + MCP 协议 + 本地执行入口

1. 从 "treg" 这个标题说起&#xff1a;一个被低估的 CLI Agent 工具链入口第一次看到 "treg" 这个词&#xff0c;大概率会一脸懵——它不像codex、claude那样自带品牌辨识度&#xff0c;也不像mcp那样有明确的协议含义。但如果你最近在折腾 AI Agent 的 C…

作者头像 李华
网站建设 2026/9/25 6:50:26

ChatGPT Web 对话框消息实现:子路由切换、消息透传与对话面板设计——《ChatGPT 微服务应用体系构建》chatgpt-web 第5节实战

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总&#xff0c;旨在为大家提供一个清晰详细的学习教程&#xff0c;侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助&#xff0c;请给予支持(关注、…

作者头像 李华
网站建设 2026/9/25 6:49:50

Atlas 300V 24G推理卡部署YOLO实战:从ONNX到OM的完整指南

最近后台和评论区被同一个问题刷屏了&#xff1a;“atlas 300v 24g 是运算加速卡吗&#xff1f;”“atlas 能不能跑 yolo&#xff1f;”“部署起来是不是特别折腾&#xff1f;”问的人一多&#xff0c;我发现大家对这个系列产品存在不少误解——有人以为 Atlas 是显卡&#xff…

作者头像 李华