在《没有平台和核心工程团队,"FDE"只是驻场外包》文中,我们说过:FDE 是"人肉反向传播",FDE 把现场的"误差"带回平台、核心工程团队更新"权重",但如果新权重送不回现场,这条回路依然是断的——单向的反馈只是客服,双向的循环才是学习系统。负责"送回去"的,就是今天的主角:Apollo,Palantir 的持续交付平台。FDE 那篇文章里我们给了它一段话的篇幅;这一次,把它整个拆开。
先看官方定义:Apollo 是"一个可扩展、可伸缩的软件管理与部署平台(an extensible, scalable platform for managing and deploying software)",它把 Palantir 二十年来在关键任务系统上积累的运维最佳实践编码成了产品,用于"升级、监控和管理 Palantir 产品的每一个实例"。
这句话听着平淡,难点在场景。普通 SaaS 的隐含假设是"厂商的云能够触达你的环境",而 Palantir 面对的客户环境是:私有云、物理内网、混合云,乃至彻底物理隔离的涉密网络——官方文档的原话是"无论环境位于何处、连接是否持续稳定",并明确支持断连(air-gapped)环境,合规框架覆盖 FedRAMP、IL5、IL6。再往外说,还有潜艇、卫星、前线装备这样的边缘节点。
在这些地方,传统 SaaS 的"我推你收"模式直接失效:厂商既进不去,也不被允许进去。 软件交付问题从"如何快"变成了"如何才能送达"。Apollo 的全部架构设计,都是从这个问题出发的。
架构:Hub-Spoke 星型拓扑
Apollo 的总体架构是一张经典的星型图(见下图,来自 Palantir 官方文档)。
图的上半部分在 Apollo 之外:你的 CI/CD(Gradle、GitLab 等)构建产物,发布到你的制品库(Artifactory、Docker 仓库等)。注意,Apollo 不取代你的构建体系,它接管的是"之后"的事——CI/CD 只需把元数据注册进来。
图的左半部分是中心 Hub 环境。Hub 控制面里有四个关键角色:产品目录(Product Catalog)登记所有产品与版本元数据;变更管理(Change Management)负责审批——任何环境变更都要经过相应批准,发布通道的贡献者也受权限约束;声明状态(Declared State)表达"这个环境应该是什么配置";编排引擎(Orchestration Engine)是整个系统的大脑,负责计算并下发执行计划(Plan)。
图的右半部分是若干受管 Spoke 环境。每个客户现场、每个独立部署都是一个 Spoke。每个 Spoke 内部署着 Spoke 控制面,其中最关键的就是 Apollo Agent:它一边与 Hub 的编排引擎双向通信,一边管理本环境内的"你的软件",并直接从制品库拉取镜像。
图的下半部分是双向可观测:Spoke 侧的 Agent 持续上报本环境状态(Reported State)、探针(Probes)、遥测与日志,汇入 Hub 的中央可观测层,并可以对接 Splunk、Prometheus、Datadog 等第三方体系。
一句话概括这张图的技术架构:意图在 Hub 集中声明,执行在 Spoke 分布式完成,状态从 Spoke 持续回流。 集中编排与分布执行,是 Apollo 同时做到"统一管控"和"环境自治"的结构基础。
原理一:拉取式(pull),而不是推送(push)
这张图里最容易被忽略、却最重要的一个细节是:连接 Hub 与 Spoke 的箭头,方向是 Spoke 主动的。官方文档写得很明确:运行在 Spoke 控制面里的 Agent,持续轮询(poll)编排引擎,获取新的 Plan;约束条件满足后,引擎把 Plan 发给对应的 Agent 执行;Agent 执行完再上报成败。
为什么必须是拉取式?因为在 Palantir 的世界里,Hub 根本没有"推门进去"的权限:涉密网络不允许任何入站连接,潜艇和卫星只有间歇性的脆弱链路,很多客户的防火墙规则是"只出不进"。推送式部署在这些场景里是物理上不可能的。而拉取式把主动权放在环境内部——只要环境能向外打一个电话,更新就能送进去:通的时候多拉一点,断的时候原地等待,恢复后自动续上。这也是官方"无论连接是否持续稳定"承诺的技术底座。
拉取式同时成就了 Apollo 最漂亮的一句承诺:"Write once, deploy anywhere(一次构建,随处部署)"——开发者合并一次代码,不需要关心它将如何到达所有环境;送达这件事,由星型网络里无数个主动伸手的 Agent 各自完成。
原理二:发布通道订阅制
版本到了 Hub,怎么决定哪个环境升哪个版本?Apollo 的答案不是"排期下发",而是发布通道(Release Channel)订阅制。
发布通道按稳定性与标签把版本分组,官方默认提供三级:DEV、RELEASE_CANDIDATE、RELEASE——Release 版本进全部通道,候选版本进 DEV 与 RC,其余只进 DEV。而每个环境的运维方,按自己对"新特性速度"与"稳定性"的取舍,把环境里的实体订阅到合适的通道上:激进的测试环境订 DEV,生产环境订 RELEASE。升级从此像订阅杂志——渠道按自己的口味订阅,新刊一到自动送达;而不是上门推销——厂商挨个敲门问你要不要升。
通道之间还有晋升管道(promotion pipeline):一个新版本先在 DEV 通道浸泡,编排引擎依据 Agent 持续上报的状态,评估它是否通过了健康晋升标准;通过了,自动进入下一级通道,订阅了该通道的环境在维护窗口内自动升级。评估失败怎么办?编排引擎会自动召回(recall)该版本,确保所有环境都撤下它;单个 Plan 执行失败且环境状态已被改变时,则自动下发回滚 Plan 恢复原状。管道还配了三种超时兜底:浸泡超时(约定时间内健康不达标即取消)、金丝雀超时(7 天到不了目标版本即取消)、整体晋升超时(30 个自然日强制截止)。
把这套机制连起来看:灰度、浸泡、晋升、召回、回滚、超时——不是运维手册上的人肉流程,而是全部编码在引擎里的自动行为。
原理三:约束驱动,而不是目标态
Apollo 文档里有一句初看反直觉的话:"Apollo 不为环境或实体设定特定的目标状态(Apollo does not have a specific target state for Environments or Entities)。"
一般配置管理系统的思路是"声明目标态,然后收敛到它"。Apollo 不这么干:一个实体由"产品 + 发布通道"定义,而不是钉死在某个版本号上;引擎做的是持续提出满足全部约束条件的 Plan。约束(Constraints)是 Plan 被执行前必须满足的前置条件,比如跨服务依赖关系、所支持的数据库 schema 版本等——这些都是开发者在发布时显式声明的。
这个设计的深意在于:环境的多样性是默认前提,而不是例外。 几百个环境版本不一、配置各异、维护窗口不同,根本不存在一个整齐划一的"目标态";存在的只有"在此时此刻、在此环境下,哪些约束必须成立"。约束驱动让同一个版本可以安全地流向千差万别的环境,也让升级在任何中断点都可以安全地停下、续跑——这正是数万次周更不出大乱子的理论根基。再叠加变更管理的审批流(与 SAML 身份提供方集成,合规敏感操作必须经授权人批准),自动化与合规这对老冤家被同时安顿了下来。
规模与启示:这条腿也是工程体系
机制讲得再多,不如看运行数字:Apollo 支撑着 Palantir 全部产品线的交付,每天跨数百个服务与资产编排数千次零停机升级,折算到每周是数万次发布——官方博客给出的量级是每周四万次以上。于是才有了那句我们引用过的话:每一个部署环境都是"活着的"(every deployment is a living environment)。为了让版本进入涉密网络更快,Palantir 甚至还有专门的前线基础设施工程团队,做二进制传输服务这样的"特快通道",把原本数周的更新压缩到以小时计。
回到本系列的主线。上一篇我们说,判断真假 FDE 看三件事:有没有自己的平台、反馈进了谁的 backlog、平台功能有多少是从现场长出来的。看完 Apollo,这个清单还得补上一条:你的新版本上一次自动到达所有客户现场,是什么时候? "反馈回灌"是机制,"特性发布"同样是机制——前者靠 FDE 与核心工程团队的协同,后者靠 Apollo 这样的交付工程体系。两条腿缺了任何一条,剩下的都只是一个摔倒的飞轮。
学 Palantir 的正确顺序也因此更完整了:先建平台,再建核心工程团队,然后既要打通反馈回灌的通道,也要建起持续交付的管道——让现场的知识流得回来,让平台的进步送得出去。 否则,学得再像,依然只是把驻场外包,翻译成了英文。
参考资料:Palantir 官方 Apollo 文档(palantir.com/docs/apollo/core/introduction/、how-apollo-works、overview、release-channels)
提醒:请朋友们将“智见AI视界”加“星标”,觉得写得好就点击右下角“拇指”和“收藏”哦,不然会慢慢收不到文章推送~
关联阅读

