ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Cilium StateDB 深度指南:用统一状态表驱动控制面开发、Reconciler 与可观测性

Cilium StateDB 深度指南:用统一状态表驱动控制面开发、Reconciler 与可观测性 Cilium StateDB 深度指南用统一状态表驱动控制面开发、Reconciler 与可观测性【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/ciliumStateDB 是 Cilium 项目自研的内存数据库用于统一管理控制面状态。本文基于 Cilium 官方开发文档 statedb.rst完整覆盖 StateDB 的设计动机、意图表 → 控制器 → 期望状态表 → Reconciler 的四层架构、表定义规范、cilium-dbg shell检查命令、Kubernetes 对象反射、Reconciler 接入模式含 BPF map 场景以及全部 StateDB/Reconciler 指标并结合仓库中的示例代码contrib/examples/statedb与真实实现如 pkg/maps/bwmap/cell.go给出源码级讲解帮助你在 Cilium 中开发新的基于表的状态管理功能。注意StateDB 与 reconciler 仍在活跃开发中文档中涉及的 API 与指标名不保证稳定以当前仓库源码为准。一、为什么 Cilium 需要 StateDBStateDB 诞生于 Cilium 开发者和生产环境长期踩坑的经验总结目标是系统性地提升 Cilium agent 的韧性resilience、可测试性testability与可检查性inspectability。它对开发者的核心价值在于统一的状态访问 API所有共享状态都通过Table[Obj]访问取代过去各组件各自维护状态副本、互相回调RWMutex hashmap callback的模式。后者的问题在于某个观察状态的控制器如果出 bug可能导致关键功能停摆或吞吐量骤降而 StateDB 的不可变数据结构支持无锁读取读者互不阻塞。去重与内存优化历史上许多组件通过回调订阅各自保存一份状态对内存占用和 GC 开销影响很大。把状态统一到数据库式抽象后状态可以被去重、被多个消费者共享索引查询。可复用工具统一的存储抽象使得检查状态cilium-dbg shell -- db、对账状态StateDB reconciler、观测状态操作StateDB metrics这些工具可以跨组件复用。规模化之后架构的 API 面更小、状态可检查、数据易访问更易于理解、运维和扩展。更好的集成测试把状态与操作状态的逻辑分离摆脱大杂烩 Manager模式后只要一个组件的输入输出大多是表就可以把多个组件组合成纯由测试输入和期望输出定义的集成测试从而用简单得多的集成测试替代昂贵缓慢的端到端测试。这个目标用 Fred Brooks 在《人月神话》中的话概括最好Show me your flowchart and conceal your tables, and I shall continue to be mystified. Show me your tables, and I wont usually need your flowchart; itll be obvious.二、架构愿景四类构件划分控制面StateDB 的架构图见 statedb-arch.svg源文件为 statedb-arch.d2。按这种风格Cilium agent 可以粗略划分为四类构件用户意图表User intent tables来自外部数据源的告诉 agent 该做什么的对象。例如 Kubernetes 核心对象Pod 等、Cilium 专有 CRD如 CiliumNetworkPolicy或从 kvstore 等其它源摄取的数据。控制器Controllers观察用户意图表、并计算出期望状态表内容的控制循环。期望状态表Desired state tables控制器产出的内部状态简明描述应该做什么。例如描述某个 BPF map 的内容应当是什么、应该安装哪些路由。Reconcilers对账器观察期望状态表并将其与目标BPF map、Linux 路由表等对齐的控制循环。它通常是 StateDB reconciler 的一个实例其语义建立在带有 status 字段的对象表之上操作为Update、Delete和Prune。这样划分带来的关注点分离用户意图独立成表把解析/校验与后续计算解耦纯粹表示外部意图便于复用而不绑定具体功能实现细节控制器本质上就是输入表 → 输出表的函数易于理解和测试对账逻辑与期望状态计算分离低层错误处理与重试的复杂逻辑与纯业务逻辑计算分开通用 reconciler 带来久经考验、带遥测的重试实现agent 控制面本质上就是reconciler 之外的一切因此可以无需大量脚手架地对控制面做集成测试、模拟和基准测试。三、定义表Cilium 侧的规范与检查清单表与索引的基础 API 在 StateDB 项目中已有说明本节聚焦 Cilium 特有的实践规范来自原文档的 guidelines默认公开Table[Obj]方便新功能在其之上构建、也方便测试使用。同时导出表的索引或查询函数惯例写法var ByName nameIndex.Query。不要导出RWTable[Obj]除非外部模块确实需要直接写入如确有跨模块写入建议定义带校验的writer 函数保证写入良构。表若与某个具体功能紧密相关就随功能实现一起定义若被多个模块共享考虑放在pkg/k8s/tables或pkg/datapath/tables中以便发现。对象必须可 JSON 序列化可被检查需要存储不可序列化的数据如函数时将其设为私有字段或加json:-标签。对象若包含频繁变更的 map/set考虑使用cilium/statedb中的不可变part.Map/part.Set——不可变意味着修改时无需深拷贝也不会意外原地篡改。设计表时考虑它在模块外测试中的用法导出表构造器New*Table使其可以独立用于依赖该模块的集成测试。由于对象不可变设计上要廉价浅克隆例如把创建后不变的字段拆到独立 struct 中由对象按引用共享。为你的表写 benchmark了解索引与存储的成本。若对象较小100 字节优先按值存储Table[MyObject]而非Table[*MyObject]减少内存碎片、避免字段被意外修改但注意每个索引都会保存对象的一份拷贝必要时先测量。3.1 完整示例一张表 一个填充它的控制器仓库中的 contrib/examples/statedb/example.go 是一个可直接运行的最小示例完整展示了对象、索引、表构造与 Hive Cell 注册// Example is our object that we want to index and store in a table. type Example struct { ID uint64 CreatedAt time.Time } // TableHeader defines how cilium-dbg displays the header func (e Example) TableHeader() []string { return []string{ID, CreatedAt} } // TableRow defines how cilium-dbg displays a row func (e Example) TableRow() []string { return []string{ strconv.FormatUint(e.ID, 10), e.CreatedAt.String(), } } // TableName is a constant for the table name. This is used in cilium-dbg // to refer to this table. const TableName examples var ( // idIndex defines the primary index for the Example object. idIndex statedb.Index[Example, uint64]{ Name: id, FromObject: func(e Example) index.KeySet { return index.NewKeySet(index.Uint64(e.ID)) }, FromKey: index.Uint64, FromString: index.Uint64String, Unique: true, } // ByID exports the query function for the id index. Its a convention // for providing a short readable short-hand for creating queries. ByID idIndex.Query ) // NewExampleTable creates the table and registers it. func NewExampleTable(db *statedb.DB) (statedb.RWTable[Example], error) { return statedb.NewTable( db, TableName, idIndex, ) } // Cell provides the Table[Example] and registers a controller to populate // the table. var Cell cell.Module( example, Examples, // Provide RWTable[Example] privately cell.ProvidePrivate(NewExampleTable), // Provide Table[Example] publicly cell.Provide(statedb.RWTable[Example].ToTable), // Register a controller that manages the contents of the table. cell.Invoke(registerExampleController), ) type exampleController struct { db *statedb.DB examples statedb.RWTable[Example] } // loop 每秒插入一个 ID 递增的示例对象达到 5 个后清空重来。 func (e *exampleController) loop(ctx context.Context, health cell.Health) error { id : uint64(0) tick : time.NewTicker(time.Second) defer tick.Stop() health.OK(Starting) for { var tickTime time.Time select { case tickTime -tick.C: case -ctx.Done(): return nil } wtxn : e.db.WriteTxn(e.examples) id if id 5 { e.examples.Insert(wtxn, Example{ID: id, CreatedAt: tickTime}) } else { e.examples.DeleteAll(wtxn) id 0 } wtxn.Commit() health.OK(fmt.Sprintf(%d examples inserted, id)) } } func registerExampleController(jg job.Group, db *statedb.DB, examples statedb.RWTable[Example]) { ctrl : exampleController{db, examples} jg.Add(job.OneShot(loop, ctrl.loop)) }从源码结构看这个示例体现了三组关键模式cell.ProvidePrivate(NewExampleTable)让写表句柄RWTable[Example]只在本模块内可见再通过statedb.RWTable[Example].ToTable对外提供只读的Table[Example]——正是不要导出 RWTable规范的落地TableHeader/TableRow方法让cilium-dbg的db/show命令能直接渲染该表见第五节控制器是一个简单的控制循环开WriteTxn、插入/删除、Commit并通过cell.Health汇报健康状态可用cilium-dbg status --all-health或db/show health检查。3.2 消费表用 Changes() 追踪变更contrib/examples/statedb/main.go 展示了如何在一个迷你应用中消费该表——通过table.Changes(wtxn)注册变更追踪它会指示数据库把已删除对象保留到一边供观察然后在循环里迭代变更func followExamples(jg job.Group, db *statedb.DB, table statedb.Table[Example]) { jg.Add(job.OneShot( follow, func(ctx context.Context, _ cell.Health) error { // Start tracking changes to the table. This instructs the database // to keep deleted objects off to the side for us to observe. wtxn : db.WriteTxn(table) changeIterator, err : table.Changes(wtxn) wtxn.Commit() if err ! nil { return err } for { changes, watch : changeIterator.Next(db.ReadTxn()) for change, rev : range changes { e : change.Object fmt.Printf(ID: %d, CreatedAt: %s (revision: %d, deleted: %v)\n, e.ID, e.CreatedAt.Format(time.Stamp), rev, change.Deleted) } // Wait until theres new changes to consume. select { case -ctx.Done(): return nil case -watch: } } }, )) } func main() { hive.New( cell.Module(app, Example app, Cell, cell.Invoke(followExamples), ), ).Run(logging.DefaultSlogLogger) }这个Changes()watch通道模式就是 Reconciler 底层的观察机制第六节。可以在本地直接运行验证$ cd contrib/examples/statedb go run .四、常见陷阱与静态检查原文档列出了三类常见错误开发时务必留意对象入库后被修改StateDB 查询不返回副本所有读者都会看到修改结果查询返回的对象按引用存储如*T被修改后重新插入StateDB 会检测并 panic。按引用存储的对象在修改前必须浅克隆在 ReadTxn 中查询、结果被用于 WriteTxn两次事务之间结果可能已变化若需要乐观并发控制应在写事务中使用CompareAndSwap。仓库自带 tools/statedblint 静态检查器实现见 tools/statedblint/lint.go来捕获部分问题它作为 CI 的一部分运行本地可用make statedb-lint执行。五、用 cilium-dbg 检查 StateDBStateDB 自带一组 script 命令通过cilium-dbg shell调用。db列出所有已注册的表含对象数、索引、初始化器、Go 类型、最近一次写事务信息rootkind-worker:/home/cilium# cilium-dbg shell -- db Name Object count Deleted objects Indexes Initializers Go type Last WriteTxn health 61 0 identifier, level [] types.Status health (107.3us ago, locked for 43.7us) sysctl 20 0 name, status [] *tables.Sysctl sysctl (9.4m ago, locked for 12.8us) mtu 2 0 cidr [] mtu.RouteMTU mtu (19.4m ago, locked for 5.4us) ...db/show利用对象的TableHeader/TableRow方法打印表内容第三节示例中的TableHeader/TableRow就是为此服务rootkind-worker:/home/cilium# cilium-dbg shell -- db/show mtu Prefix DeviceMTU RouteMTU RoutePostEncryptMTU ::/0 1500 1450 1450 0.0.0.0/0 1500 1450 1450db/get、db/prefix、db/list、db/lowerbound支持按索引查询前提是索引定义了Index.FromStringrootkind-worker:/home/cilium# cilium-dbg shell -- db prefix --indexname devices cilium Name Index Selected Type MTU HWAddr Flags Addresses cilium_host 3 false veth 1500 c2:f6:99:50:af:71 up|broadcast|multicast 10.244.1.105, fe80::c0f6:99ff:fe50:af71 cilium_net 2 false veth 1500 5e:70:20:4d:8a:bc up|broadcast|multicast fe80::5c70:20ff:fe4d:8abc cilium_vxlan 4 false vxlan 1500 b2:c6:10:14:48:47 up|broadcast|multicast fe80::b0c6:10ff:fe14:4847shell 也可以交互运行支持help db查帮助、db/show --formatjson --out...导出 JSON# cilium-dbg shell cilium help db db Describe StateDB configuration ... cilium db/show mtu Prefix DeviceMTU RouteMTU RoutePostEncryptMTU ::/0 1500 1450 1450 0.0.0.0/0 1500 1450 1450 cilium db/show --out/tmp/devices.json --formatjson devices ...5.1 Script 命令全集可用于测试断言除只读检查外shell 的db/*命令组支持插入、比较、删除与断言是 txtar 集成测试的核心工具# Show the registered tables db # Insert an object db/insert my-table example.yaml # Compare the contents of my-table with a file. Retries until matches. db/cmp my-table expected.table # Show the contents of the table db/show # Write the object to a file db/get my-table Foo --formatyaml --outfoo.yaml # Delete the object and assert that table is empty. db/delete my-table example.yaml db/empty my-table -- expected.table -- Name Color Foo Red -- example.yaml -- name: Foo color: Red完整参考可用help db在cilium-dbg shell中或测试的break提示符下查看原文档还指出现有测试本身就是好参考可用git grep db/insert快速找到。六、Kubernetes 反射把 API Server 对象装进表要把 Kubernetes 对象反射进表可以用pkg/k8s中的 reflector 工具自动化。仓库中的 contrib/examples/statedb_k8s/pods.go 定义了 pod 表并注册了 reflectorconst PodTableName pods var ( // podNameIndex is the primary index for pods which indexes them by namespacename. podNameIndex statedb.Index[*v1.Pod, string]{ Name: name, FromObject: func(obj *v1.Pod) index.KeySet { return index.NewKeySet(index.String(obj.Namespace / obj.Name)) }, FromKey: index.String, FromString: index.FromString, Unique: true, } PodByName podNameIndex.Query ) // NewPodTable creates the pod table and registers it. func NewPodTable(db *statedb.DB) (statedb.RWTable[*v1.Pod], error) { return statedb.NewTableAny( db, PodTableName, podTableHeader, podTableRow, podNameIndex, ) } func podTableHeader() []string { return []string{Namespace, Name} } func podTableRow(pod *v1.Pod) []string { return []string{pod.Namespace, pod.Name} } // PodListerWatcher is the lister watcher for pod objects. This is separately // defined so integration tests can provide their own if needed. type PodListerWatcher cache.ListerWatcher func newPodListerWatcher(log *slog.Logger, cs client.Clientset) PodListerWatcher { if !cs.IsEnabled() { log.Error(client not configured, please set --k8s-kubeconfig-path) return nil } return PodListerWatcher(utils.ListerWatcherFromTyped(cs.Slim().CoreV1().Pods())) } // registerReflector creates and registers a reflector for pods. func registerReflector( jg job.Group, lw PodListerWatcher, db *statedb.DB, pods statedb.RWTable[*v1.Pod], ) error { if lw nil { return nil } cfg : k8s.ReflectorConfig[*v1.Pod]{ Name: pods, Table: pods, ListerWatcher: lw, // More options available to e.g. transform the objects. } return k8s.RegisterReflector(jg, db, cfg) } // PodsCell provides Table[*v1.Pod] and registers a reflector to populate // the table from the api-server. var PodsCell cell.Module( pods, Pods table, cell.ProvidePrivate(NewPodTable, newPodListerWatcher), cell.Provide(statedb.RWTable[*v1.Pod].ToTable), cell.Invoke(registerReflector), )注意几个可测试性设计PodListerWatcher单独抽象出来让集成测试可以注入自己的 ListerWatcherReflectorConfig预留了转换对象等更多选项。contrib/examples/statedb_k8s/main.go 组装了client.Cell提供client.Clientset与PodsCell再挂一个followPods任务用Changes()打印 pod 变更运行效果$ cd contrib/examples/statedb_k8s go run . --k8s-kubeconfig-path ~/.kube/config levelinfo msgStarting time2024-09-05T11:22:1502:00 levelinfo msgEstablishing connection to apiserver hosthttps://127.0.0.1:44261 subsysk8s-client time2024-09-05T11:22:1502:00 levelinfo msgConnected to apiserver subsysk8s-client levelinfo msgStarted duration9.675917ms Pod(default/nginx): Running (revision: 1, deleted: false) Pod(kube-system/cilium-envoy-8xwp7): Running (revision: 2, deleted: false) ...七、Reconciler把期望状态对账到目标系统StateDB reconciler 用于把表中的变更对账到目标系统BPF map、路由表等。接入需要四步。7.1 对象携带 Status 字段type MyObject struct { ID uint64 // ... Status reconciler.Status }7.2 实现对账操作reconciler.Operationstype myObjectOps struct{ ... } var _ reconciler.Operations[*MyObject] myObjectOps{} // Update reconciles the changed [obj] with the target. func (ops *myObjectOps) Update(ctx context.Context, txn statedb.ReadTxn, obj *MyObject) error { // Synchronize the target state with [obj]. [obj] is a clone and can be updated from here. // [txn] can be used to access other tables, but note that Update() is only called when [obj] is // marked pending. ... // Return nil or an error. If not nil, the operation will be repeated with exponential backoff. // If object changes the retrying will reset and Update() is called with latest object. return err } // Delete removes the [obj] from the target. func (ops *myObjectOps) Delete(ctx context.Context, txn statedb.ReadTxn, obj *MyObject) error { ... // If error is not nil the delete is retried until it succeeds or an object is recreated // with the same primary key. return err } // Prune removes any stale/unexpected state in the target. func (ops *myObjectOps) Prune(ctx context.Context, txn statedb.ReadTxn, objs iter.Seq2[*MyObject, statedb.Revision]) error { // Compute the difference between [objs] and the target and remove anything unexpected in the target. ... // If the returned error is not nil error is logged and metrics incremented. Failed pruning is currently not retried, // but called periodically according to config. return err }三个操作的语义要点Update收到的是对象克隆可安全修改返回错误时按指数退避重试若对象本身变化则重试重置并基于最新对象重新UpdateDelete失败会一直重试直到成功或对象以相同主键被重建Prune失败当前不重试但会按配置周期性再次调用并记录错误、打点指标。7.3 注册 reconciler 并接入 Hive Cellfunc registerReconciler( params reconciler.Params, ops reconciler.Operations[*MyObject], tbl statedb.RWTable[*MyObject], ) error { // Reconciler[..] is an API the reconciler provides. Often not needed. // Currently only contains the Prune() method to trigger immediate pruning. var r reconciler.Reconciler[*MyObject] r, err : RegisterReconciler( params, tbl, (*MyObject).Clone, (*MyObject).SetStatus, (*MyObject).GetStatus, ops, nil, /* optional batch operations */ ) return err } var Cell cell.Module( example, Example module, ..., cell.Invoke(registerReconciler), )注册时传入的三个函数分别负责对象克隆、写入状态、读取状态最后一个参数可传入批处理操作可选。7.4 以 Pending 状态插入对象触发对账var myObjects statedb.RWTable[*MyObject] wtxn : db.WriteTxn(myObjects) myObjects.Insert(wtxn, MyObject{ID: 123, Status: reconciler.StatusPending()}) wtxn.Commit()Reconciler 通过Changes()观察表对每个变为Pending的变更对象调用Update对删除对象调用Delete出错对象按可配置退避不断重试直至成功。完整的可运行示例见 StateDB 仓库的reconciler/example目录。Reconciler 还会运行一个后台任务上报自身健康状态只要有任何对象对账失败并进入重试队列状态即降级degraded。可用cilium-dbg status --all-health或cilium-dbg statedb health检查。7.5 对账 BPF map 的特化路径对 BPF map 场景可以直接用bpf.NewMapOps返回的操作实现省去手写 Update/Delete/Prune。目标对象只需实现BinaryKey和BinaryValue方法来构造二进制 key/value——可以即时构造也可以引用定义好二进制布局的 struct。Cilium 中后一种风格更主流// MyKey defines the raw BPF key type MyKey struct{ ... } // MyValue defines the raw BPF value type MyValue struct{ ... } type MyObject struct { Key MyKey Value MyValue Status reconciler.Status } func (m *MyObject) BinaryKey() encoding.BinaryMarshaler { return bpf.StructBinaryMarshaler{m.Key} } func (m *MyObject) BinaryValue() encoding.BinaryMarshaler { return bpf.StructBinaryMarshaler{m.Value} } func registerReconciler(params reconciler.Params, objs statedb.RWTable[*MyObject], m *bpf.Map) error { ops : bpf.NewMapOps*MyObject _, err : reconciler.Register( params, objs, func(obj *MyObject) *MyObject { return obj }, func(obj *MyObject, s reconciler.Status) *MyObject { obj.Status s return obj }, func(obj *MyObject) reconciler.Status { return obj.Status }, ops, nil, ) return err }真实的生产级示例可参考带宽地图模块 pkg/maps/bwmap/cell.go。八、StateDB 与 Reconciler 指标StateDB 和 reconciler 都有配套指标但由于粒度较细默认关闭。指标定义在 pkg/hive/statedb_metrics.go 和 pkg/hive/reconciler_metrics.go该部分文档为手工维护可能有滞后以源码为准。启用方式是将其加入 Helm 的prometheus.metrics选项语法为cilium_name。打开全部指标的配置prometheus: enabled: true metrics: - cilium_statedb_write_txn_duration_seconds - cilium_statedb_write_txn_acquisition_seconds - cilium_statedb_table_contention_seconds - cilium_statedb_table_objects - cilium_statedb_table_revision - cilium_statedb_table_delete_trackers - cilium_statedb_table_graveyard_objects - cilium_statedb_table_graveyard_low_watermark - cilium_statedb_table_graveyard_cleaning_duration_seconds - cilium_reconciler_count - cilium_reconciler_duration_seconds - cilium_reconciler_errors_total - cilium_reconciler_errors_current - cilium_reconciler_prune_count - cilium_reconciler_prune_errors_total - cilium_reconciler_prune_duration_seconds8.1 StateDB 指标清单名称标签说明statedb_write_txn_duration_secondstables,handle写事务的持续时长statedb_write_txn_acquisition_secondstables,handle锁定目标表花了多久statedb_table_contention_secondstable为写操作锁定某张表花了多久statedb_table_objectstable表内对象数量statedb_table_revisiontable当前版本号revisionstatedb_table_delete_trackerstable删除追踪器数量如Changes()订阅者statedb_table_graveyard_objectstable墓地里已删除对象的数量statedb_table_graveyard_low_watermarktable删除对象的低水位版本statedb_table_graveyard_cleaning_duration_secondstableGC 墓地耗时标签说明handle是数据库句柄名由(*DB).NewHandle创建默认句柄名为DBtable/tables格式如tableAtableB是指标相关的 StateDB 表。8.2 Reconciler 指标清单名称标签说明reconciler_countmodule_id已完成对账轮次数reconciler_duration_secondsmodule_id,op操作时长的直方图reconciler_errors_totalmodule_id错误总数update/deletereconciler_errors_currentmodule_id当前错误数reconciler_prune_countmodule_idprune 轮次数reconciler_prune_errors_totalmodule_idprune 期间错误总数reconciler_prune_duration_secondsmodule_id操作时长的直方图module_id是注册 reconciler 的 Hive 模块标识op是执行的操作取值为update或delete。8.3 指标禁用时也能看2 小时采样与绘图即使指标未启用也可以用 shell 的metrics与metrics/plot命令检查——因为 Cilium 会保留过去 2 小时所有指标的采样。这些指标也以 HTML 形式包含在 sysdump 中找cilium-dbg-shell----metrics-html.html文件。# kubectl exec -it -n kube-system ds/cilium -- cilium-dbg shell # Dump the sampled StateDB metrics from the last 2 hours cilium metrics --sampled statedb Metric Labels 5min 30min 60min 120min cilium_statedb_table_contention_seconds handledevices-controller tabledevices 0s / 0s / 0s 0s / 0s / 0s 0s / 0s / 0s 0s / 0s / 0s ... # Plot the rate of change in the health table # (indicative of number of object writes per second) cilium metrics/plot --rate statedb_table_revision.*health cilium_statedb_table_revision (rate per second) [ tablehealth ] ╭────────────────────────────────────────────────────────────────────╮ 2.4 ┤ .... ... ... . │ 1.2 ┤ . │ 0.0 ┤. │ ╰───┬───────────────────────────────┬──────────────────────────────┬─╯ -120min -60min now # Plot the write transaction duration for the devices table # (indicative of how long the table is locked during writes) cilium metrics/plot statedb_write_txn_duration.*devices cilium_statedb_write_txn_duration_seconds (p99) [ handledevices-controller ] 47.2ms ┤ . │ 23.9ms ┤ . . │ 0.5ms ┤................................. ..............................│ ╰───┬───────────────────────────────┬──────────────────────────────┬─╯ -120min -60min now # Plot the reconciliation errors for sysctl cilium metrics/plot reconciler_errors_current.*sysctl cilium_reconciler_errors_current [ module_idagent.datapath.sysctl ] 0.0 ┤....................................................................│ ╰───┬───────────────────────────────┬──────────────────────────────┬─╯ -120min -60min now九、小结与实践路线写新表先按第三节的清单设计对象与索引公开Table[Obj]与ByXxx查询函数、私有RWTable、保证 JSON 可序列化、考虑不可变与浅克隆成本、按值存储小对象、写 benchmark再用 contrib/examples/statedb 作为骨架跑通go run .接入外部数据用 contrib/examples/statedb_k8s 演示的k8s.RegisterReflector把 API Server 对象反射进表并用抽象 ListerWatcher 保证可测试性对账到目标系统对象加reconciler.Status实现Update/Delete/Prune用RegisterReconciler挂进 Hive Cell以StatusPending()插入触发对账BPF map 场景直接用bpf.NewMapOps参考 pkg/maps/bwmap/cell.go日常运维检查cilium-dbg shell的db、db/show、db/prefix、db/get检查表状态metrics --sampled/metrics/plot查看 2 小时内的争用、写事务时长与对账错误cilium-dbg statedb health/cilium-dbg status --all-health查看 reconciler 健康质量把关提交前运行make statedb-linttools/statedblint避免对象入库后被改、引用对象未克隆再插入、读/写事务间数据不一致这三类典型错误。StateDB 与 reconciler 仍在快速演进当前仓库 go.mod 依赖github.com/cilium/statedb v0.9.1API 与指标名可能随版本调整在动手前建议对照仓库中最新的源码与示例确认签名。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表