拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenSandbox Node Agent:节点级沙箱数据采集的部署、存储布局与恢复运维实践

OpenSandbox Node Agent节点级沙箱数据采集的部署、存储布局与恢复运维实践【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandboxNode Agent 是 OpenSandbox 中一个可选的 Linux DaemonSet 组件负责将编译进镜像的一个或多个 Source如容器 stdout/stderr汇聚成统一的采集流水线并把沙箱记录持久化到单个配置的 Sink本地文件或阿里云 OSS中。本文基于仓库文档 docs/components/node-agent.md 完整展开覆盖 Helm 安装与 Secret 配置、cluster/namespace/sandbox_id/pod_uid对象布局与 finalized marker 语义、checkpoint 恢复与目标切换的运维规程、健康检查与遥测约束以及从 Kind 冒烟测试到真实 OSS 烟雾测试的完整验证链路帮助你在生产环境中正确部署、排障并安全地变更该组件。定位与适用边界Node Agent 每个 Kubernetes 节点运行一份将多个 Source 合并进公共流水线保持每条流内部顺序并将沙箱记录写入唯一配置的文件或 OSS Sink。当前发布的镜像包含container-logsSource读取同节点上非池化non-pooledOpenSandbox Pod 的 stdout 与 stderrfile与阿里云oss两类 Sink。组件 READMEcomponents/nodeagent/README.md还说明标准二进制内置了一个可选的syscallsSource基于 eBPF 采集 cgroup 维度的系统调用记录NDJSON 输出需要 Linux 5.11、cgroup v2、tracefs 以及BPF/PERFMON能力且仅当 Helm 显式启用时才会挂载相应宿主路径并附加能力。本文聚焦官方文档描述的container-logs发布路径。实验性声明恢复协议已经实现但生产资源默认值仍依赖 OSEP-0019见 oseps/0019-node-agent-sandbox-collection.md基准测试与 24 小时浸泡结果。在结果公布前应把 Chart 的资源值当作起始值而非容量承诺。默认的block丢弃策略对整个 Source 入口施加背压per-sandbox 队列上限只约束内存占用并不承诺沙箱之间的延迟隔离。安装与部署用 Helm 部署 file Sink 验证环境总 Chartumbrella chart默认关闭 Node Agent。以本地持久文件做验证安装helm install nodeagent ./kubernetes/charts/opensandbox-node-agent \ --namespace opensandbox-system \ --create-namespace \ --set config.clusterIDprod-a \ --set sink.typefile部署时需要注意三个宿主路径约束默认container-logsSource 会只读挂载/var/log/podscheckpoint 目录config.stateDir默认/var/lib/opensandbox/nodeagent与持久文件目标sink.file.path默认/var/lib/opensandbox/nodeagent-data是两个相互独立的可写宿主路径见 values.yaml 中hostPaths的定义state与fileData必须分别匹配config.stateDir和sink.file.path这两个可写路径的生命周期必须至少与 kubelet 日志等长否则采集断点与已落盘数据可能先于源日志消失。Source 选择的行为契约config.sources选择编译进镜像的 Source默认为[container-logs]。配置校验components/nodeagent/pkg/config/config.go要求列表非空、无重复、无空项。文档明确了三种关键行为未知 Source 名Agent 不会启动一个残缺流水线而是直接保持 unready未选择container-logsChart 不再挂载 Pod 日志目录也不渲染该 Source 的专属配置禁用或改名 Source 但其 checkpoint 命名空间或 stream-kind 绑定仍残留Agent 同样保持 unready。正确做法是先排空drain并删除该 Source 的状态再修改启用集合。这一行为在主入口 components/nodeagent/main.go 中可验证checkpoint.ValidateEnabledSources(cfg.Sources)失败会替换 readiness 为source-state-conflict并原地等待信号而不是退出或重置状态。关键配置参数Chart 的 values.yaml 与进程的环境变量解析config.go共同定义了完整参数面默认值如下表Chart 参数 / 环境变量默认值说明config.sources/NODEAGENT_SOURCEScontainer-logs启用的 Source 列表逗号分隔config.clusterID/NODEAGENT_CLUSTER_ID必填记录中上报的集群标识必须是 DNS labelconfig.stateDir/NODEAGENT_STATE_DIR/var/lib/opensandbox/nodeagent节点本地 checkpoint 状态目录绝对路径config.stateMaxBytes/NODEAGENT_STATE_MAX_BYTES1 GiBcheckpoint 状态上限config.memoryBudgetBytes/NODEAGENT_MEMORY_BUDGET_BYTES256 MiB节点侧记录缓冲内存预算config.perSandboxQueueBytes/NODEAGENT_PER_SANDBOX_QUEUE_BYTES16 MiB单沙箱排队上限超过即触发背压不得大于全局内存预算config.perSandboxRateLimit/NODEAGENT_PER_SANDBOX_RATE_LIMIT0不限速单沙箱字节/秒限速config.maxLineBytes/NODEAGENT_MAX_LINE_BYTES1 MiB单行日志上限须加记录开销后装进 per-sandbox 队列预算config.partialTimeout/NODEAGENT_PARTIAL_TIMEOUT5s半行partial line超时config.dropPolicy/NODEAGENT_DROP_POLICYblockSink 不可用时的策略仅允许block或dropconfig.sinkTimeout/NODEAGENT_SINK_TIMEOUT30s单次 Sink 写尝试超时config.retryMaxInterval/NODEAGENT_RETRY_MAX_INTERVAL30sSink 重试最大间隔config.endedStateRetention/NODEAGENT_ENDED_STATE_RETENTION24h已结束沙箱状态保留时长sink.file.path/NODEAGENT_FILE_PATH/var/lib/opensandbox/nodeagent-datafile Sink 数据目录须与状态目录、日志目录不重叠sink.file.maxBytes/NODEAGENT_FILE_MAX_BYTES1 GiB单个输出文件轮转阈值sink.file.maxFiles/NODEAGENT_FILE_MAX_FILES16保留的轮转文件数上限 1048576sink.file.maxTotalBytes/NODEAGENT_FILE_MAX_TOTAL_BYTES10 GiB轮转文件总字节上限不得小于maxBytessink.file.retention/NODEAGENT_FILE_RETENTION24h轮转文件保留窗口config.serverAddr/NODEAGENT_SERVER_ADDR:8080健康检查 HTTP 地址config.pprofAddr/NODEAGENT_PPROF_ADDR空禁用可选 pprof 地址必须绑定 loopback校验逻辑还强制路径安全NODEAGENT_STATE_DIR、NODEAGENT_LOG_ROOT默认/var/log/pods等必须是绝对路径且不允许..、glob 或路径穿越启用container-logs时状态目录不得与日志根目录重叠config.go。配置 OSS SinkOSS 凭据必须来自 Kubernetes SecretSecret 至少含access-key-id、access-key-secret可选session-token这三个键名与 Chart 中accessKeyIDKey、accessKeySecretKey、sessionTokenKey对应然后配置sink: type: oss oss: endpoint: https://oss-cn-example.aliyuncs.com bucket: sandbox-logs keyPrefix: logs existingSecret: nodeagent-oss权限与拒绝规则Agent 凭据需要对象的append / read / write权限以及读取bucket 的 versioning、WORM 与 lifecycle 配置的权限凭据不得包含对象删除DeleteObject清理走独立的离线命令Agent 启动时会主动检查 bucket若 versioning 或 WORM 已启用或存在与受管前缀managed cluster prefix重叠的 lifecycle 规则拒绝启动 Source。该检查在 oss.go 中实现GetBucketVersioning返回非空状态、GetBucketWorm返回有效 WormId/State、或 lifecycle 规则前缀与受管前缀前缀重叠时均返回api.Permanent错误endpoint 在配置加载阶段就会被规范化identity.CanonicalOSSEndpointkeyPrefix必须是安全的非空对象前缀不允许..、.、空段或反斜杠见 config.go。Secret 轮换后必须重启 Node Agent DaemonSet——Kubernetes 不会更新运行中容器内 Secret 派生的环境变量。存储布局与 marker 语义每种记录类型都有一个编译期存储格式定义其编码、Content-Type、元数据与对象族object family。当前container-log格式在 file 与 OSS 两类持久目标中布局相同cluster/namespace/sandbox_id/pod_uid/ sandbox.log sandbox.generation.log sandbox.finalized.revision.json这一布局由后端无关的objectlayout包统一生成layout.go 中Family.GenerationName(generation)对 generation 0 生成base.log其余生成base.generation.logMarkerName(revision)生成base.finalized.revision.json。所有路径段都经过safeLeaf校验防止调用方提供的段改变目录边界。marker 是累计不可变快照sandbox.finalized.revision.json是累计不可变快照。消费者选择最高连续数字 Revision并校验其中列出的每个对象的 size 与 CRC64。marker 的coverage_started_at字段固定了该流所有 Revision 共享的采纳边界adoption boundary。marker.go 定义了 marker 结构schema_version、target_id、finalize_id、revision、stream_ref、resource含 sandbox_id 与 namespace/pod/node/cluster 等 Kubernetes 资源属性、coverage_started_at、status、had_drops、had_source_gaps、loss_reasons、finalized_at以及objects每个对象的 key、generation、size、CRC64。状态取值由Status()函数确定有 source gap →incomplete否则有 drop →complete-with-drops否则 →complete。Status含义complete无主动丢弃、无已知 source gap。at-least-once 投递仍可能含重复。complete-with-drops至少一条记录被主动丢弃且受影响区间已被记账。incomplete至少一个已知 source 区间无法读取或其覆盖性无法被证明。重启对连续监控的影响Agent 在流仍打开时重启会中断连续监控已恢复的数据仍会投递但下一个 marker 为incomplete理由为monitor-interrupted——因为重启后找不到字节并不能证明故障期间没有发生过短暂的日志轮转消失。已经进入 finalize 的 Revision 则保留其冻结结果。恢复状态与目标变更checkpoint.db恢复身份而非数据NODEAGENT_STATE_DIR/checkpoint.db是一个 bbolt 数据库只存储恢复元数据不存日志负载state.go 的包注释明确这一点。它把节点绑定到一个目标身份target identityAgent 首次启动时创建数据库数据库损坏或与目标身份不匹配时readiness 保持 false永远不会被静默重置main.go 中state.Open失败即置state-unavailable并原地等待删除已有数据库会丢弃恢复身份可能让替换实例无法调和 Sink 中已存在的对象。因此状态目录里可见metaschema/writer/target id、source、pipeline、sink等桶state.go以及文件级检查点offset、device/inode、prefix hash与 gap/drop 记账记录。变更目标target的标准操作序列在改变目标身份之前必须停止该节点上的新沙箱调度 → 等待活跃/可重开流与 GC 积压归零 → 确认受跟踪日志目录已消失 → 停止 Node Agent → 归档并删除整个状态目录。不支持按流per-stream的状态重置。file Sink 的自动清理目前自动清理只覆盖container-log对象族且需同时满足固定 late-repair 截止时间已过、NODEAGENT_FILE_RETENTION默认 24h保留窗口到期、受跟踪 CRI 日志目录消失、finalize 成功。清理流程是两阶段的先写 bbolt tombstone再把完整对象族移入.gc暂存目录并同步父目录最后删除暂存族。它从不会为了腾空间而删除单个 generation。其他记录格式需要各自的清理支持。主流程通过检测 Sink 是否实现CollectExpired接口来周期性驱动该逻辑main.go。OSS 清理离线、显式、可恢复OSS 清理是离线操作运行nodeagent-oss-cleanup工具发布镜像中也包含在/usr/local/bin/nodeagent-oss-cleanup使用独立的删除凭据和持久--state-file。协议是首次运行不带--apply持久化并检视清理 manifest执行必须带--confirm-target-drainedtarget-id且该值必须与--target-id完全一致cmd/oss-cleanup/main.go 强制--apply与--extend-data-plan互斥两者都要求 drain 确认工具先删除全部 Revision marker 并验证其消失再删除数据对象中断的工作可从 manifest 恢复。健康检查与遥测/healthz只报告进程存活采集失败与阻塞进展由/readyz暴露。/readyz额外要求配置有效、Pod 身份已同步、状态目录可写、无活跃的 Source/Sink 重试循环、Sink 可恢复、无未解决的运行时故障。readiness 理由使用低基数代码如invalid-config、sink-unavailable、source-state-conflict、store-stale、operation-retrying、cleanup-error均可见于 main.go且绝不包含凭据、路径、bucket 名或原始后端错误。配置 OTLP metrics 导出后Node Agent 上报记录数与字节数、主动丢弃、重试、当前队列字节数与 Sink Consume 延迟这些指标不使用sandbox ID、Pod ID、路径、bucket 或 StreamRef 作为 label保证基数受控。验证路径Kind 冒烟测试file Sink 重启恢复components/nodeagent/test/kind-smoke.sh构建 Agent、把 Chart 部署到 Kind、验证普通 Pod 采集与 Pool Pod 排除、重启 DaemonSet并校验恢复后的流因监控中断被标记为incomplete。从仓库根目录运行前置条件是 Docker daemon或 Docker Desktop已在运行且docker、kind、helm、kubectl、jq在PATH中components/nodeagent/test/kind-smoke.sh脚本创建隔离的nodeagent-smoke集群并在退出时删除失败时设置KEEP_KIND_CLUSTER1可保留集群供排查。零退出码证明 file-sink 路径、Pool 排除、Agent 重启恢复与最终 marker 检查全部通过——它不覆盖 OSS。无凭据的 OSS 协议单测协议单测使用确定性 fake backend 覆盖未知的 AppendObject 结果与冲突位置无需任何凭据cd components/nodeagent go test ./pkg/sink/oss没有 OSS 凭据时集成测试仍可编译以检查构建兼容性这不是连通性或协议通过go test -tagsintegration -run ^$ ./pkg/sink/oss真实 OSS 烟雾测试使用一个专供测试的 base prefix每次运行创建唯一子前缀避免与保留的历史运行冲突。bucket 必须关闭 versioning 与 WORM且没有与受管前缀重叠的 lifecycle 规则凭据权限与 Agent 相同append、read、write 与 bucket 配置读取不需要DeleteObject。export NODEAGENT_TEST_OSS_ENDPOINThttps://oss-cn-example.aliyuncs.com export NODEAGENT_TEST_OSS_BUCKETsandbox-logs-test export NODEAGENT_TEST_OSS_PREFIXopensandbox/nodeagent-smoke export OSS_ACCESS_KEY_ID... export OSS_ACCESS_KEY_SECRET... # 临时凭据可选 export OSS_SESSION_TOKEN... cd components/nodeagent go test -tagsintegration -run ^TestRealOSSSmoke$ -v ./pkg/sink/oss测试追加一条规范日志记录、发布 Revision 1、读回两个对象并把 marker 中记录的 size 与 CRC64 同 OSS 元数据比对。由于测试凭据无删除权限对象被有意保留成功的输出会打印后续清理所需的target-id、family-prefix与container。清理保留对象在同一组OSS_ACCESS_KEY_*环境变量中换成具备删除权限的凭据先持久化并检视清理计划cd components/nodeagent make build ./bin/nodeagent-oss-cleanup \ --endpoint $NODEAGENT_TEST_OSS_ENDPOINT \ --bucket $NODEAGENT_TEST_OSS_BUCKET \ --family-prefix printed-family-prefix \ --container printed-container \ --target-id printed-target-id \ --state-file $PWD/nodeagent-cleanup.db排空目标并审查计划后追加--apply --confirm-target-drainedprinted-target-id重跑持久 state file 让中断的清理可续传。边界情况若一次中断未完成的清理报告了一个不在持久计划中的数据对象应先确认目标仍然完全排空然后带--extend-data-plan同样的 drain 确认、但不带--apply重跑——这只会持久化并打印扩展后的计划、不删除数据逐条审阅 key 后再单独执行--apply步骤。已完成的清理任务是终态不可重开。小结Node Agent 的设计重心是可恢复性与可审计性checkpoint 只存恢复元数据并与目标身份强绑定marker 以累计不可变快照暴露完整的覆盖语义complete/complete-with-drops/incompletefile Sink 清理两阶段执行、OSS 清理显式离线且 marker 先于数据删除。运维上需要牢记的硬约束是不要静默删除checkpoint.db、不要在活跃流存在时切换目标、Source 集合变更前先排空其状态、OSS Secret 轮换后重启 DaemonSet并在 OSEP-0019 基准与浸泡结果发布前把 Chart 资源值视为起始值而非生产容量承诺。【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门