⚠️ 本仓库已废弃并归档(read-only),不再维护或部署。 单体sbw-controller已拆分为两个独立二进制并全面验证、退役:
- sbw-server —— 全局脑:owns YugabyteDB/etcd/Redpanda、placement/装箱、failover 决策、BSS/admin API、DB schema;经 gRPC
ServerCoverer契约(Watch/Report/Register)服务 coverer。不持有 tap。- sbw-coverer —— 分片传感/执行:GoBGP RIB-tap + 存活判断 + member→edge locality + agent-facing AgentService(L/R agent 在此 Register/Subscribe/Report);拨号 server,不持有任何 store。
拆分(server/coverer split,见
sbw-contract/docs/DESIGN-server-coverer-split.md)已实现、CI 全绿,并在 k3s lab 端到端验证(基本流 + onSubscribe 修复 + K=2 coverer 分配/homing + coverer failover + 恢复再平衡)。下文内容仅作历史参考。DEPRECATED & ARCHIVED. The monolith was split into sbw-server (global brain: stores, placement, failover decision, admin API) + sbw-coverer (sharded RIB-tap + liveness + the agent-facing AgentService). The split is implemented, CI-green, and validated end-to-end in the k3s lab. This repo is kept for historical reference only.
sbw-controller 是共享带宽池系统的控制面。它维护全局一致性,负责 pool 装箱、member 到 home edge 的映射、failover、agent 期望状态分发、admin API 和 RIB tap 存活判断。它不直接操作 VPP/BIRD 数据面,所有数据面物化都由 edge-agent 完成。
- 接收 BSS/admin 请求,创建、更新、删除、迁移 pool。
- 选择 primary/backup home edge,维护 IP/member 到 home 的唯一映射。
- 渲染每个 edge 的
EdgeDesiredState或增量EdgeDesiredDelta,通过 gRPC 推送给sbw-limiter的 edge-agent。 - 接收
EdgeReport,用于心跳、健康状态、applied version、capacity/account drift 和 pool hash drift。 - 通过嵌入式 GoBGP RIB tap 观察 edge BIRD 的 anchor/canary 路由,用于硬死、软死和 anchor 漂移判断。
- 在 sharding 模式下把 edge 覆盖关系和 failover 投票写入 etcd,多副本共享同一协调状态。
cmd/controller/:controller 进程入口。internal/controller/:control plane 组合层、配置、admin API、liveness/report/drift 处理。internal/orchestrator/:pool create/update/destroy/failover/migrate/reconcile 的核心状态机。internal/render/:把 contract 中的 pool/member 模型渲染成 per-edge desired state。internal/grpcsrv/:controller 侧 agent gRPC service。internal/ribtap/、internal/ribevent/:GoBGP tap 和归一化 RIB 事件。internal/guard/:RIB 存活守卫,避免 stale/missing host route 导致黑洞。internal/ledger/、internal/poolstore/、internal/srcmap/、internal/ybstore/:状态存储和容量/唯一性相关组件。deploy/systemd/、docker/、configs/:部署示例。
- Go 1.25。
sbw-contract,本地开发通过../sbw-contractreplace。- etcd,用于协调状态、registry、liveness、edge version 等。
- YugabyteDB 强制依赖,用于 pool/member/src->home 权威存储(internal/ybstore,pgxpool)。没有 all-etcd 回退路径:空 DSN 会在启动时打印
yugabyte is mandatory并os.Exit(1)。 - GoBGP fork,本仓
go.mod通过replace github.com/osrg/gobgp/v4 => ../gobgp使用本地多跳 BFD 补丁。
配置加载顺序为默认值、JSON 文件、BWPOOL_* 环境变量。常用字段:
grpc_listen_addr/BWPOOL_GRPC_LISTEN_ADDR:agent gRPC 服务监听地址。admin_listen_addr/BWPOOL_ADMIN_LISTEN_ADDR:admin HTTP API 监听地址,生产必须放在访问控制后。metrics_listen_addr/BWPOOL_METRICS_LISTEN_ADDR:Prometheus/metrics。etcd.endpoints/BWPOOL_ETCD_ENDPOINTS:etcd endpoint 列表。yugabyte.dsn/BWPOOL_YB_DSN:Yugabyte YSQL DSN,必填;为空时启动即os.Exit(1),无法禁用。bgp.router_id/BWPOOL_BGP_ROUTER_ID:设置后启用 RIB tap。edge_addrs、edge_addrs6:每个 edge 的 v4/v6 redirect next-hop。sharding.*:多 controller coverer、re-home 和 failover quorum 配置。
示例配置在 configs/controller.example.json 和 docker/controller.example.json。注意当前示例文件尚未对齐配置 schema(缺少必填的 yugabyte.dsn / etcd.endpoints),仅用它启动会因空 DSN 而 os.Exit(1);使用前请补全 yugabyte.dsn 与 etcd.endpoints 等字段并确认监听地址适合当前环境。
最小启动需要 etcd 和 YugabyteDB(Yugabyte 强制,DSN 为空会直接 os.Exit(1)):
BWPOOL_YB_DSN='postgres://bwpool@localhost:5433/bwpool?sslmode=disable' \
go run ./cmd/controller -config configs/controller.example.jsonDocker smoke 位于 docker/:
cd docker
docker compose up --build主要接口:
POST /v1/pools:创建 pool。PUT /v1/pools/{id}:更新 pool。GET /v1/pools、GET /v1/pools/{id}:查询 pool。DELETE /v1/pools/{id}:删除 pool。POST /v1/pools/{id}/migrate:计划迁移到 backup。GET /v1/agents:查看注册 agent。POST /v1/agents/{id}/decommission:排空并下线 edge。
Admin API 目前是裸 HTTP handler,本仓不内置鉴权。生产部署必须用网络 ACL、mTLS proxy、API gateway 或等价机制保护。
go test ./...
go vet ./...
make ci集成测试需要真实 GoBGP/网络环境:
go test -tags integration ./...- controller 和 agent 的 gRPC 当前默认明文传输,部署时应限制管理网络访问范围或在前面加 mTLS/认证层。
- Yugabyte 混合路径使用缓存容量做放置判断;在靠近容量上限或高并发创建前,应确认生产容量门禁策略已经落地。
- RIB tap 只在
bgp.router_id非空时启动;未启用 tap 时,failover 主要依赖 agent report 心跳。 - 多副本 sharding 需要正确配置
sharding.grpc_endpoint,不能把只适合本地监听的:1791广播给 agent。