Skip to content

共享包

四个一方包 packages/dn42_* 是 Control Server 与 Node Agent 共用的地基:协议模型、渲染、文件产物、公共工具。本文讲它们的分层、依赖方向与各自职责。字段细节见 DesiredState 参考

依赖方向

dn42_common 是无上游依赖的叶子。dn42_schemas 只依赖 common。dn42_templates 依赖三者(产出 RenderedFile)。无循环依赖。控制面(apps/control-server)用 schemas(校验/合成);Node Agent 用全部四个(渲染 + 规划 + 执行)。

dn42_schemas —— 协议模型

所有跨组件传输的数据结构,基于 Pydantic v2。基类 StrictModelbase.py):extra="forbid"(拒未知字段)+ frozen=True(不可变)+ canonical_json() / canonical_sha256()(稳定序列化,用于内容寻址)。

文件内容
desired_state.pyDesiredState 顶层 + validate_references + 四个 _normalize_* 钩子(端口发布、bird socket、DNS runtime、DNS anycast)
network.pyNodeSpec(含 link_local 单源)、InterfaceSpecWireGuardPeerSpec
routing.pyBgpSessionSpecBfdSpecBird2ConfigSpecInternalTopologySpecBirdHostSpecDummyInterfaceSpecBgpLargeCommunitySpec
dns.pyDnsSpecDnsZoneSpecDnsRecordSpecDnsForwardSpec
runtime.pyRouterRuntimeSpecRuntimeServiceSpecUnderlayNetworkSpecPortPublishSpecWireGuardPortRangeSpecRpkiSpec 等容器编排模型
agent.pyAgent 协议:注册请求/响应、RuntimeSnapshotReconciliationReportApplyResult、各 Observed*
enums.pyInterfaceKindServiceRoleAddressFamilyApplyStatusBootstrapStatusNodeHealthObservationStatus
testing.py示例 builder(hkg1、本地多节点),供测试与渲染 golden 用

DesiredState 的字段、校验规则、normalize 钩子是单独的参考主题,见 DesiredState 参考

dn42_templates —— 渲染

DesiredState 渲染为节点上的配置文件与脚本。入口 render_desired_state(state) -> list[RenderedFile]desired_state.py)。

产出模板
bird/*.confconfig-bird2/(community_filters、custom_filters、rpki、anycast_services、bird.conf、dn42_peers、ibgp、ospf、ospf_interfaces)
wireguard/<iface>.confconfig-wireguard/interface.conf.j2
coredns/Corefile + coredns/zones/db.<zone>config-coredns/(DNS 启用时)
scripts/bird/*scripts/wg/*config-scripts/(apply / start 脚本)

bird2.pybuild_config_bird2_contextDesiredState 翻译成 BIRD 模板上下文(ownipownnets*_ipsetbird_hostswg_peerslarge_communitiesroute_collectorsrpki_ip 等)——这里就是"loopback / prefixes → OWNIP / ipset"等派生发生的地方(见 地址模型)。Jinja 环境用 StrictUndefined(缺变量即报错)+ shell_quote / yaml_quote 过滤器。

router 容器的 Dockerfile 不渲染成文件,由 agent 在内存里从 runtime.router_dockerfile 经 Docker Engine API 生成。

dn42_runtime —— 文件产物与 Dockerfile

文件内容
types.pyRenderedFile(不可变;路径强校验:禁 ..、NUL、绝对路径、Windows 盘符)
docker.pyrender_router_dockerfile()(多阶段 router 镜像模板)
paths.py模板目录发现

写盘计划的执行(原子写 + 删除)由此包提供,被 agent 的 writer 调用。

dn42_common —— 公共工具

无上游依赖的叶子,被其余三包与两个 app 共用。

模块内容
validators/IP / 网络 / link-local、DN42 地址空间(172.20.0.0/14fd00::/8、anycast 段)、ASN、WireGuard key / endpoint、域名、ISO8601、agent token
labels.py容器/网络 label 单源:dn42.manageddn42.node_iddn42.config_hashdn42.component
naming.pynode_project_nameservice_container_name<project>-<service>-1)、agent_id_for
communities.pyDN42 origin region community 编码、国家代码映射
serialization.pycanonical_json_dumps / canonical_sha256_hex(内容寻址哈希)
jinja.pycreate_environmentshell_quoteyaml_quote
io.pyatomic_write_text / atomic_write_json
crypto.pyWireGuard 密钥生成、恢复密钥 seal / unseal(escrow)

labels.pyserialization.py 一起支撑了内容寻址:容器 config_hash 来自容器定义 payload 的 canonical SHA-256,是最小扰动设计的基础(见 架构)。

锁步约束

修改 dn42_commondn42_schemas 的校验规则、哈希算法或模型字段,会同时影响控制面与全机群 agent——两侧对同一输入的接受集与摘要口径必须一致,否则会分叉。

StrictModelextra="forbid" 让这类分叉在解析期就报错而不是静默降级,代价是发布顺序有硬性要求:加字段先升控制面、删字段先升 agent。详见 锁步契约