Skip to content

SPIRE 多活 / 双机 / 高可用(HA)/ 容灾 分析

分析对象:SPIRE v1.15.2 所有 路径:行号,已用一手代码/文档核对。 配套文档:整体架构 · SVID 颁发流程


0. 核心结论(TL;DR)

SPIRE 的高可用不是"主备切换 + leader 选举",而是真·多活(active-active)。全库无 leader 选举 / Raft / 分布式锁(grep -rniE "leader.?elect|raft|paxos|distributed.lock" pkg/server/ 零命中)。它由四层正交机制叠加而成:

机制出处
① 共享状态同一 trust domain 的多个 spire-server 读写同一个共享 SQL datastoredoc/scaling_spire.md:15
② 各自签发,统一信任每个 server 维护自己独立的 CA 密钥,把自己的 CA 证书 append 到共享 bundle;所有 server 签的 SVID 都能用同一 bundle 验证ca/manager/manager.go:1035;doc/scaling_spire.md:19
③ 上游/嵌套统一信任根经 UpstreamAuthority 让多 server 挂到同一外部 CA(Vault/AWS PCA/…)或上游 SPIRE(Nested),中间 CA 上溯同一 root见 §3、§4
④ Agent 侧容错Agent 只从本地内存缓存给 workload 发 SVID,并提前轮换,server 短时全挂也不影响存量 workload见 §6

一句话:多台 server 无主地共享一个数据库 + 各签各的 CA 汇入共享 bundle,所以既不需要 leader,也不需要共享签名密钥。


1. 共享状态存储(HA 的基石)

1.1 DataStore:多 server 共享的"单一事实源"

DataStore 接口(pkg/server/datastore/datastore.go:14)存储所有需要跨 server 共享的动态状态:

类别内容行号
Bundles信任 bundle(X509 CA + JWT 授权公钥)datastore.go:16-24
Registration Entries注册条目datastore.go:33-41
Entry / Node Events变更事件流(用于多 server 缓存同步,见 1.4)datastore.go:44-67
Attested Nodes已认证节点/agentdatastore.go:51-60
Join Tokens一次性入网令牌datastore.go:75-78
Federation Relationships联邦关系datastore.go:81-85
CA Journals每 server 的 CA 轮换账本(见 2.2)datastore.go:88-91

除了 CA 私钥本身(在各自 KeyManager),其余全部状态都在这个共享库里。任一 server 宕机,其他 server 从同一库读到完全相同的注册条目/节点/bundle。

1.2 支持的数据库,以及为何生产多活必须用共享 Postgres/MySQL 而非 sqlite

内置 SQL 插件(pkg/server/datastore/sqlstore/)支持的方言:mysql / postgres / sqlite3,外加带 IAM 认证的 aws_mysql / aws_postgres

sqlite 不能用于生产多活的根本原因——它是本地单文件、单写者数据库:

go
// pkg/server/datastore/sqlstore/sqlstore.go:1022
// sqlite3 can only have one writer at a time. since we're in WAL mode, ...

这个写锁是进程内(db.opMu.Lock()),跨不了机器/进程;连接串就是本地文件路径,两台 server 无法安全共享。因此官方要求横向扩展时"configure all servers in same trust domain to read and write to the same shared datastore"(doc/scaling_spire.md:15),即 Postgres 或 MySQL(网络多写数据库)。

多 server 对同一行的并发"读-改-写"由 withReadModifyWriteTx 保证:MySQL/Postgres 走 SELECT ... FOR UPDATE 行锁(sqlstore.go:980-999),注释还特意声明兼容 Percona XtraDB Cluster 与 PostgreSQL hot-standby。

1.3 读写分离(read-only replica):ro_connection_string + TolerateStale

明确支持,这是 SPIRE 为大规模多活设计的读副本卸载能力:

  • 配置项 ro_connection_string(sqlcommon config;conf/server/server_full.conf:288-291;doc/plugin_server_datastore_sql.md:239,注明不适用 sqlite)。非空时插件额外打开第二条只读连接 ds.roDb
  • 读一致性开关 DataConsistency 枚举(datastore.go:95):RequireCurrent(默认,读主库)vs TolerateStale(允许读副本、可能略陈旧)。只有调用方传 TolerateStale ro_db 已配置才走副本。
  • 一个精妙的安全默认:首次全量加载缓存强制走主库,只有增量事件扫描才允许走副本——authorized_entryfetcher_registration_entries.go:144 注释 // preliminary loading should not be done via read-replicas(RequireCurrent)vs 增量扫描 TolerateStale

1.4 事件驱动的多 server 缓存一致性(HA 的关键隐藏机制)

每台 server 在内存里维护一份"授权注册条目缓存"(authorizedentries.Cache)以避免每次签发都全表扫库。多台 server 如何保持这份缓存近实时一致?靠共享库里的 events 表 + 轮询:

server A 改注册条目 → 写共享库并产生一条 event
                    → server B 下个轮询周期看到 event(ListRegistrationEntryEvents, GreaterThanEventID)
                    → server B 刷新自己的内存缓存
  • 增量扫描 scanForNewEvents(authorized_entryfetcher_registration_entries.go:108-136,TolerateStale 可下沉只读副本);
  • 初始全量 loadCache(:139-168,RequireCurrent);
  • 跳号/乱序事件用 eventTracker(endpoints/eventTracker.go)补偿。

这就是多活下各 server 缓存最终一致的机制,且读事件可下沉到只读副本,减轻主库压力。

1.5 托管数据库(AWS RDS / Aurora,IAM 认证)

database_type = "aws_postgres" | "aws_mysql" 接入托管库,驱动 pkg/server/datastore/sqldriver/awsrds/buildAuthToken 生成短期 IAM 令牌连库。生产上通常把共享 datastore 交给 RDS Multi-AZ / Aurora 这类自带 HA/failover/只读副本的托管服务——数据库层的 HA 由数据库自己保证,SPIRE 只管连


2. 多 Server 实例的协调:CA 签名密钥如何共处

2.1 关键设计:各 server 独立 CA,证书汇入共享 bundle(无共享密钥、无 leader)

doc/scaling_spire.md:19 一句话点破 HA 下的 CA 模型:

In High Availability mode, each server maintains its own Certificate Authority, which may be either self-signed certificates or an intermediate certificate off of a shared root authority (i.e. when configured with an UpstreamAuthority).

即多个 server 不共享签名密钥、也不选主。每台 server:

  1. 在自己的 KeyManager 里生成自己的 CA 私钥(manager.go:280);
  2. selfSignX509CA(root 模式)或 upstreamSignX509CA(nested/upstream 模式);
  3. 把这张 CA 证书 append 到共享 bundle:
go
// pkg/server/ca/manager/manager.go:1035
res, err := ds.AppendBundle(ctx, &common.Bundle{
    TrustDomainId:  m.c.TrustDomain.IDString(),
    RootCas:        rootCAs,          // 本 server 自己的 CA 证书
    JwtSigningKeys: jwtSigningKeys,
})

于是共享 bundle 里累积了全部 server 各自的 CA 证书。任何 agent 从任一 server 取到的都是这个合并 bundle,所以 server A 签发的 SVID 能被"验证 server B 所签 SVID"的一方接受——统一信任、零协调。这就是不需要 leader、不需要共享私钥的根本原因。

2.2 CA journal:每 server 一份,靠 KeyManager 公钥自我定位

ca/manager/journal.go 把本 server 轮换出的 CA 密钥账本持久化到共享库(SetCAJournal)。多台 server 共用一张 ca_journals 表,如何区分哪条属于哪台 server? 靠 KeyManager 里的公钥反查(findCAJournal,journal.go:250-285):

遍历本 server KeyManager 的所有公钥 → 算 authorityID → FetchCAJournal(authorityID)
  → 匹配上 = 这条 journal 属于我

含义:server 的身份 = 它 KeyManager 里的密钥。只要密钥还在,重启后就能找回自己的 CA 账本、继续用原 CA;找不到匹配则当作全新 server、重新准备 CA。→ 这直接决定了 §2.4 KeyManager 的选型。

2.3 Prepare / Activate / Rotate:每 server 自主轮换,无需协调

每台 server 各跑一个 Rotator,每 10s 检查一次自己的 CA slot(ca/rotator/rotator.go),完全自主:

  • 准备提前量 = 生命周期的 1/2(上限 30 天);
  • 激活/切换提前量 = 生命周期最后 1/6(上限 7 天)。

即"过半准备下一张,进入最后 1/6 才切换",中间有 current 与 next 两张 CA 都在 bundle 里的重叠期,保证轮换平滑。因为准备/激活都是往共享 bundle 追加新 CA,多台 server 各自轮换天然无冲突。PruneCAJournals(safety 14 天)清理已下线 server 的陈旧账本。

2.4 KeyManager 在多活下的选型(memory vs disk vs KMS)——重要

CA 私钥不在共享库里,而在各 server 的 KeyManager 插件中。多活下选型直接影响"server 重启/重调度后能否找回自己的 CA"(见 2.2):

KeyManager私钥位置多活/重启行为
memory仅进程内存重启即丢钥 → 匹配不到 journal → 每次重启生成全新 CA、bundle 膨胀。能用但不推荐
disk本机磁盘 keys_path只有重挂到同一持久卷才找得回;容器漂移到别的节点且非持久卷时等同 memory
KMS 类(AWS KMS / GCP KMS / Azure Key Vault / HashiCorp Vault)外部 KMS,私钥永不出 KMS密钥与计算实例解耦,pod 可自由重调度仍能取回自己的钥;安全性也最好

对"共享 KMS 才能真多活"这一常见说法的精确修正:KMS 的价值不是让多台 server 共享同一把密钥,而是把每台 server 各自的密钥材料从具体主机上解耦,使弹性/容器环境下 server 可随意扩缩容、重调度而不丢 CA 身份。 AWS KMS 文档(doc/plugin_server_keymanager_aws_kms.md:56-63)印证:每台 server 有独立实例标识(key_identifier_file),各自管理自己的一组 KMS 密钥(用 tag spire-server-id 区分);某台永久下线后其密钥两周无刷新会被其他 server 回收。 准确表述应是:多活下推荐用 KMS/Vault 类 KeyManager,让每个 server 的持久 CA 密钥不绑死在某台主机上


3. UpstreamAuthority 与信任链(多 server 挂同一上游 CA)

3.1 作用

当配置了 UpstreamAuthority,每台 server 的 CA 走 upstreamSignX509CA:把自己的公钥做成 CSR → upstreamClient.MintX509CA(...) → 上游签回一张中间 CA。因 X.509 链式语义,不同 server 铸出的中间 CA 都上溯到同一个上游 root,彼此签的 SVID 互相可验。上游 root 经流式订阅写进共享 bundle(upstream_client.goSyncX509Rootsds.AppendBundle),因共享 datastore 而对全体 server 一致。

3.2 各上游插件(共享外部 CA)

插件目标共享 CA文档
vaultHashiCorp Vault PKIdoc/plugin_server_upstreamauthority_vault.md
aws_pcaAWS ACM Private CA..._aws_pca.md
gcp_casGCP Certificate Authority Service..._gcp_cas.md
cert-managerK8s cert-manager..._cert_manager.md
ejbcaEJBCA..._ejbca.md
awssecretAWS Secrets Manager 里的 root CA 私钥..._awssecret.md
disk本地磁盘 PEM CA..._disk.md
spire同域上游 SPIRE server(Nested 专用)..._spire.md

两个实践注意点:

  • JWT 发布差异:只有 spire 上游插件真正实现 PublishJWTKeyAndSubscribe,其余返回 Unimplemented。故用了 JWT-SVID 的 Nested 拓扑不适合用 Vault 上游(doc/plugin_server_upstreamauthority_vault.md 明确)。
  • disk 上游从本机 PEM 文件加载 root 私钥:要让多台 server 用它链到同一 root,必须把相同的 cert/key 文件分发到每台 server——这是把 root 私钥直接放盘的固有运维/安全代价,也是生产上更推荐 KMS/Vault/PCA 而非 disk 的原因。

4. Nested SPIRE(嵌套/分层)多活拓扑

命名更正:旧文档常提的 SignX509CASVID 在 v1.15.2 不存在。真实名称:服务端 RPC SVID/NewDownstreamX509CA,内部方法 ca.SignDownstreamX509CA(见 SVID 颁发流程 §4.1 的 ServerCA 接口)。

4.1 root 侧:给 downstream server 签中间 CA

root server 的 handler(pkg/server/api/svid/v1/service.go:603)带授权门:只有 caller 命中一条 Downstream==true 的注册条目才放行:

go
// pkg/server/api/svid/v1/service.go:603
func (s *Service) NewDownstreamX509CA(ctx, req) (...) {
    ...
    downstreamEntries, isDownstream := rpccontext.CallerDownstreamEntries(ctx)
    if !isDownstream {                                       // :614  授权门
        return ... "caller is not a downstream workload"
    }
    x509CASvid, err := s.ca.SignDownstreamX509CA(ctx, ca.DownstreamX509CAParams{  // :637  root 私钥签中间 CA
        PublicKey: csr.PublicKey, TTL: ...,
    })
    // 返回 中间 CA 链 + root bundle
}

门控链路完整:注册条目 Downstream bool 列(CLI spire-server entry create -downstream)→ OPA 策略 allow_downstream(policy_data.json)→ 中间件 isDownstreamViaEntries 校验 caller 的 entries。中间 CA 模板设 IsCA=true+KeyCertSign,Subject OU 打 DOWNSTREAM-<链深度>(证实可多级嵌套)。

4.2 downstream 侧:spire 上游插件 + 并置 Agent

downstream server 用 upstreamauthority "spire" 插件去 root 领中间 CA。认证方式很关键:downstream server 通过与它并置(co-located)的 SPIRE Agent 的 Workload API 取得自己的 SVID,再用它 mTLS 认证到 root——正是 doc/scaling_spire.md:45 说的"obtains credentials over the Workload API to directly authenticate with the upstream SPIRE Server"。

4.3 拓扑与故障隔离

        [Root SPIRE Server(s)]        ← 持 root key;本层可用"共享 DB 多实例"再做 HA
         签中间 CA(NewDownstreamX509CA)
                │  mTLS(经各下游并置 Agent 的 Workload API)
        ┌───────┼─────────┐
   [Downstream A]   [Downstream B]   [Downstream C]   ← 区域/集群级 server
   独立 datastore    独立 datastore    独立 datastore     各持一张中间 CA
        │                │                │
   本区 Agents/WL    本区 Agents/WL    本区 Agents/WL

要点(均有出处):

  1. 同一 trust domain、单一信任根,全域 SVID 互验(doc/scaling_spire.md:43)。
  2. root 宕机不影响下游:下游只在首次/轮换时找 root 领中间 CA,拿到后用本地中间 CA 独立签本区 workload——:49 "the top tier can go down, and intermediate servers will continue to operate"。
  3. 下游互相隔离:每个下游有独立 datastore(:103),单个下游或其库故障只影响本区——:53 "containment strategy to segment failure domains"。
  4. 两级各自可再 HA,正交叠加;多云友好(下游可用不同 node attestor);并降低 root 侧库压力(昂贵的 per-agent 授权下沉到各下游库)。

5. 联邦(Federation):跨 trust domain 交换信任 bundle

联邦本质是"各 trust domain 互换信任 bundle"。配置入口 FederationConfig(pkg/server/config.go:168):BundleEndpoint(出向发布)+ FederatesWith(入向拉取)。

5.1 出向:bundle endpoint 发布本域 bundle

pkg/server/endpoints/bundle/server.go 起独立 HTTPS 服务(TLS ≥1.2,只接 GET /),从共享库取本域 bundle,序列化为 SPIFFE 标准 JWKS(X.509 标 use:"x509-svid"、JWT 标 use:"jwt-svid")。两种认证 profile:

profile认证特点
https_spiffe(默认)直接用本 server 自己的 SVID 作 TLS 证书bootstrap:先有对方 bundle 才能拉对方 bundle,首建联邦要离线交换一次初始 bundle
https_web(ACME / 磁盘证书)Web PKI 证书无 bootstrap 依赖,更适合跨组织/跨云松耦合

5.2 入向:周期刷新外域 bundle

bundle/client/Manager 每 10s 对账联邦关系,每个外域一个 goroutine 按 refresh hint(默认 5 分钟)轮询 updater.UpdateBundle:从对端取 JWKS → 与本地不同才 ds.SetBundle 落库;拉取失败保留本地旧副本——对端宕机不丢既有信任。配置源:静态 federates_with(配置文件)+ 动态 Trust Domain API,静态覆盖动态

5.3 与多活/多区域的关系

  • 正交两层:单 trust domain 内 HA(多 server 共享库/信任根)与跨 trust domain 联邦是两个正交维度。
  • 多区域典型形态:每 region 一套独立 trust domain + 独立 CA + 独立库,region 间通过 bundle endpoint 互换 CA;跨区域信任只靠交换公开 bundle,不共享私钥/不共享数据库,耦合最低、爆炸半径最小。
  • workload 侧落地:注册条目带 FederatesWith,agent 下发 SVID 时把对应外域 bundle 塞进 WorkloadUpdate.FederatedBundles,workload 即可验证外域对端。

6. Agent 侧的高可用

6.1 连一个 server_address(DNS/L4 LB + 客户端 round-robin)

Agent 配单个 server_address(可为 DNS 名或 IP)。它被包成 gRPC dns:/// scheme 并启用客户端 round-robin,所以一个 DNS 名解析出的多台 server IP 会被 gRPC 自动轮询——这就是连接层 HA:

go
// pkg/agent/client/dial.go:23
roundRobinServiceConfig = `{ "loadBalancingConfig": [ { "round_robin": {} } ] }`

生产上把 server_address 指向 DNS 名 / L4 LB(如 K8s Service server_address="spire-server")即可后挂多台 server。

6.2 server 不可达时,用缓存 SVID 继续服务 workload

Workload API 只读本地内存缓存,从不直连 server(handler → Manager → 纯内存 LRU cache)。因此 server 全挂期间,存量 workload 的 X509-SVID 照常发放。JWT-SVID 还有显式兜底:server 不可达则返回缓存副本(manager.go:341-343 "Unable to renew JWT; returning cached copy")。

6.3 轮换提前量(对抗 server 宕机的缓冲)

默认半寿命轮换:SVID 剩余寿命降到生命周期一半(±10% 抖动打散峰值)就提前轮换,留出约半个寿命的缓冲容忍 server 短时不可用(common/rotationutil/rotationutil.go)。可选 availability_target(仅 X509,须 ≥24h)把缓冲拉得更长,以覆盖更久的 server 停机窗口。

6.4 同步失败保留旧缓存

两个同步循环(条目 5s、SVID 500ms,失败指数退避)在拉取出错时提前 return、根本不动缓存;只有拉取成功才 UpdateEntries/UpdateSVIDs。agent 自身 SVID 轮换失败且未过期时只记日志、继续用现有 SVID。→ server 宕机期间缓存原样保留,持续发证


7. 实践拓扑总结

综合 doc/scaling_spire.md:23-27(三种拓扑)与上述代码:

7.1 三种拓扑对比图

一句话区分:A 是同一信任域内加机器(共享库、共享信任根);B 是同一信任域内分层(root 签中间 CA 给独立库的下游,切故障域);C 是跨信任域(各自独立,只交换公开 bundle 建立互信)。

7.2 对比表

维度A · 单域多 ServerB · NestedC · 联邦
信任域数11多(每域一个)
信任根 / CA各 server 自签 CA 汇入共享 bundle(或共用上游)root 持 root key,downstream 用中间 CA各域独立 root
数据库1 个共享库(所有 server)root 1 个 + 每 downstream 各 1 个独立库每域各自独立库
SVID 互验全域直接互验全域直接互验(同一信任根)需先交换 bundle 才能互验
故障隔离弱(共享库是关键点)强(下游互隔,root 挂下游继续)最强(完全独立)
跨区/跨云共享库跨区延迟高、不推荐适合(下游可用不同 attestor)适合(松耦合)
有无 leader/主从无(server 对等多活;主备下沉到 DB 层)无(两级各自对等)无(各域独立)
典型场景同区域 HA 与横向扩展大规模 / 多集群 / 故障隔离多组织 / 多管理域 / staging-prod 隔离

7.3 三种形态的落地要点

形态结构适用场景权衡
A. 单 trust domain + 多 server + 共享 DBN 台 server 共享 Postgres/MySQL(可加只读副本);各 server 独立 CA 汇入共享 bundle;推荐配 UpstreamAuthority 统一 root + KMS/Vault KeyManager单一管理域、同区域/同集群的 HA 与横向扩展最简单;但共享 DB 跨地域/跨云延迟高、运维复杂;DB 是关键单点,须用 RDS/Aurora 类托管 HA + 备份做容灾
B. Nested(root + 多 downstream)顶层 root(自身可 HA)持 root key 签中间 CA;各区域一个 downstream,各有独立 DB,经 spire 上游领中间 CA跨区域/跨云/大规模;需故障域隔离root 挂了下游继续跑;下游互相隔离、单点半径小;降低顶层库压力;代价是拓扑复杂、每个下游需并置 agent
C. 多 trust domain + 联邦每区域/组织一个独立 trust domain(独立 root/CA/DB),经 bundle endpoint 互换 bundle多管理域、跨组织互通、staging/prod 隔离耦合最低、爆炸半径最小、不共享私钥/DB;但跨域信任是"最终一致"(按 refresh hint 刷新),https_spiffe 首建需 bootstrap

实战常叠加:例如每个 region 内用形态 A(多 server + 共享库 + KMS)做 HA,region 之间用形态 C 联邦;或形态 B 的 root 层用形态 A 做 HA

doc/ 下相关文档索引

  • doc/scaling_spire.md核心:HA 模式、三拓扑、sizing 表(:107-112 均从 2 Server Units 起,即默认双实例 HA)
  • doc/plugin_server_datastore_sql.md — 共享 datastore、支持的 DB、ro_connection_string 只读副本、Cloud SQL/AWS IAM
  • doc/plugin_server_keymanager_aws_kms.mdKMS KeyManager 的 HA 章节(:56-63);同类 _gcp_kms.md / _azure_key_vault.md / _hashicorp_vault.md
  • doc/plugin_server_upstreamauthority_spire.md — Nested 专用 spire 上游插件
  • doc/spire_server.md(federation 配置/bundle endpoint)、doc/spire_agent.md(server_addressavailability_target、LB 示例)
  • doc/multiple_instances.md — 单机用 systemd 模板跑多实例(注:是运维便利,非 HA 机制本身)

8. 辨析:没有"active-active 双活"时,是 1主1备n从吗?还是靠联邦?

这是一个常见疑问。结论先行:

SPIRE server 层不存在 master / standby / follower / leader 的概念。全库搜 master|standby|primary|leader|failover(grep -rniE ... pkg/server/)只命中一处,还是 sqlstore.go:996 关于 PostgreSQL "hot standby" 的注释——那说的是数据库,不是 SPIRE。

8.1 为什么 SPIRE server 没有主从

SPIRE server 是近乎无状态的对等节点(peers):所有需要共享的动态状态(注册条目、attested nodes、bundle、events、join tokens、CA journal)都在外部共享 SQL 库里(见 §1.1),server 进程本身几乎不持久化关键状态(唯一的例外是各自 KeyManager 里的 CA 私钥,见 §2.4)。既然状态不在 server 内,就没有"谁是权威副本"的问题,也就不需要选主、不需要主从复制——要么跑 1 台(单点),要么跑多台且全部 active。SPIRE 里没有"平时待命、主挂了才顶上的 standby server"。

8.2 "1主1备n从" 属于数据库层,不是 SPIRE 层

你想要的主从/主备语义,SPIRE 把它下沉给了数据库:

你的诉求SPIRE 的落地方式
主库 + 只读从库(读扩展)用 Postgres/MySQL 的 primary + read replica;SPIRE 配 ro_connection_string + TolerateStale 把读打到从库(§1.3)
主库故障自动切换(failover)由数据库 / 托管服务负责(RDS Multi-AZ、Aurora、Patroni 等);SPIRE server 无感,它只连一个(可故障转移的)连接串
server 冗余多台 server 一律 active-active,连同一个(高可用的)库

也就是说:"1 master + 1 standby + n follower" 是你给数据库选的拓扑,SPIRE server 永远是对等多实例。一个常见的生产组合就是:3 台 spire-server(active-active) + 1 主 + 1 备 + N 只读副本的 Postgres

8.3 联邦不是用来做同域高可用的

  • 联邦解决的是"跨信任域互信"(不同 root/CA 的两个 trust domain,如何让 X 域的 workload 认证 Y 域的 workload),手段是互换公开 trust bundle(§5)。
  • 同一信任域内的冗余,永远是"多 server 共享库"(§1、§2),而不是联邦。把联邦拿来做同域 HA 是概念错配:联邦两端是两套独立的信任根与数据库,并不共享注册表,彼此签发的身份要显式交换 bundle 才互认。

8.4 三句话总结

  1. 想要 server 冗余 → 多台 active-active + 共享库(无主从,§1)。
  2. 想要"主/备"语义 → 那是数据库的事(primary/standby + failover),SPIRE server 仍是多活对等。
  3. 想跨信任域认证 → 用联邦(交换 bundle),这与"高可用"是正交的两件事。

附:一句话回答"SPIRE 怎么做多活"

同一 trust domain 内,多台 server 无主地共享一个 SQL 数据库存放全部注册/节点/bundle/事件状态(sqlite 因单文件单写者不可用,须 Postgres/MySQL,可加只读副本卸载读);每台 server 各签各的 CA 并把证书汇入共享 bundle(靠 KeyManager 公钥认领各自的 CA journal,推荐 KMS/Vault 让密钥不绑主机),故无需 leader、无需共享签名密钥;跨区域/跨故障域再用 Nested(root 签中间 CA 给独立库的下游,root 挂下游继续跑)或联邦(独立 trust domain 互换 bundle)扩展;Agent 侧经 DNS/LB round-robin 连多 server,并从本地缓存 + 提前半寿命轮换持续给 workload 发证,扛得住 server 短时全挂。

内容基于 SPIFFE/SPIRE 官方开源资料整理与翻译,仅供学习交流;商标与版权归各自所有者。SPIFFE 与 SPIRE 是 CNCF 项目。