3. SPIRE 架构:SPIRE Server、SPIRE Agent、节点与工作负载注册
SPIRE(SPIFFE Runtime Environment)是 SPIFFE 规范的生产级参考实现。在服务网格的版本回滚场景中,SPIRE 负责为每个工作负载实例颁发唯一的 SPIFFE ID,并确保该身份在节点迁移、Pod 重启或版本切换时仍然可信。理解 SPIRE 的架构组件及其注册流程,是构建版本差异校验护栏的基础。
3.1 核心组件与职责
SPIRE 采用两层架构:SPIRE Server 作为全局身份控制面,SPIRE Agent 作为节点级身份代理。两者通过 gRPC 通信,共同完成节点和工作负载的身份注册与证书签发。
| 组件 | 部署位置 | 核心职责 | 关键数据 |
|---|---|---|---|
| SPIRE Server | 集群控制面(K8s 或物理机) | 管理 SPIFFE 信任域、签发 X.509-SVID 和 JWT-SVID、维护节点和工作负载注册条目 | 信任域 CA 私钥、注册条目数据库、吊销列表 |
| SPIRE Agent | 每个节点(K8s Node 或 VM) | 验证节点身份、代理工作负载的 CSR 请求、缓存 SVID、提供 Workload API | 节点证书、Agent 私钥、工作负载 SVID 缓存 |
| Workload API | Agent 上的 UDS(Unix Domain Socket) | 供工作负载进程获取 SVID 和信任包 | — |
版本回滚关键点: SPIRE Server 是身份策略的单一权威源。当服务网格执行回滚时,Server 必须能够区分旧版本和新版本工作负载的注册条目,避免回滚后的工作负载拿到错误的 SVID。
3.2 SPIRE 架构交互流程
下图展示了 SPIRE Server、SPIRE Agent 与工作负载之间的身份注册与 SVID 签发流程:
3.3 节点注册流程
节点注册是工作负载注册的前提。SPIRE Agent 启动后,必须首先向 SPIRE Server 证明自己的节点身份。Kubernetes 环境下,节点注册通常基于 PSAT(Projected Service Account ) 或 JWT-SVID 方式。
- Agent 启动:读取配置文件中的 join_ 或节点凭证。
- 节点挑战:Agent 向 Server 发起节点认证请求,附带节点凭证(如 K8s Node 的 SA )。
- Server 验证:Server 调用节点验证器(Node Attestor)验证凭证有效性,确认节点身份。
- 节点注册:验证通过后,Server 在注册条目数据库中创建或更新节点条目,并下发节点 SVID。
- Agent 就绪:Agent 持有节点 SVID,开始监听 Workload API 的 UDS 套接字。
版本回滚场景提示: 节点注册条目通常包含节点名称、节点所属集群、节点标签等属性。在回滚时,如果节点标签发生变化(例如从 v2 回滚到 v1),SPIRE Server 需要根据最新的注册条目重新评估节点身份,确保 Agent 拿到正确的节点 SVID。
3.4 工作负载注册流程
工作负载注册是 SPIRE 的核心能力。每个工作负载(如 Envoy sidecar、业务容器)通过一组 选择器(Selector) 来定义身份。选择器是 SPIRE 区分不同版本工作负载的关键机制。
| 选择器类型 | K8s 示例 | 版本差异校验用途 |
|---|---|---|
| k8s:ns | k8s:ns:default | 区分命名空间 |
| k8s:sa | k8s:sa:reviews-sa | 区分服务账户 |
| k8s:container-image | k8s:container-image:reviews:v1.2.3 | 直接区分版本镜像 |
| k8s:label | k8s:label:version:v1 | 通过标签区分版本 |
| unix:uid | unix:uid:1000 | 非 K8s 环境 |
工作负载注册的典型步骤:
- 定义注册条目:管理员通过
spire-server entry create命令或 API 创建注册条目,指定 SPIFFE ID、父节点 ID、选择器集合。 - Agent 匹配:SPIRE Agent 定期扫描节点上的进程/容器,根据选择器匹配工作负载。
- CSR 请求:匹配成功后,Agent 代表工作负载向 Server 发起证书签名请求(CSR)。
- Server 签发:Server 验证 CSR 来源(通过节点 SVID 签名),签发 SVID 并返回给 Agent。
- 工作负载获取:工作负载通过 Workload API 获取 SVID,用于 mTLS 通信。
# 创建注册条目示例:为 reviews 服务 v1 版本注册 SPIFFE ID
spire-server entry create \
--parentID spiffe://example.local/spire/agent/k8s_psat/node-worker-1 \
--spiffeID spiffe://example.local/ns/default/sa/reviews-sa/v1 \
--selector k8s:ns:default \
--selector k8s:sa:reviews-sa \
--selector k8s:label:version:v1
3.5 版本差异校验中的注册条目管理
在服务网格回滚护栏场景中,SPIRE 的注册条目管理需要支持 多版本共存 和 版本切换。以下是关键设计原则:
- 版本化 SPIFFE ID:在 SPIFFE ID 路径中嵌入版本信息,例如
spiffe://example.local/ns/default/sa/reviews/v1和.../v2,使身份与版本绑定。 - 选择器版本标签:使用 K8s 标签选择器(如
version: v1)区分不同版本的工作负载,避免依赖容器镜像名。 - 注册条目优先级:当同一工作负载匹配多个注册条目时,SPIRE 根据条目创建时间或显式优先级决定使用哪个条目。
- 回滚时的条目更新:回滚操作应触发注册条目的更新或切换,确保回滚后的工作负载获得正确的 SPIFFE ID。
常见陷阱: 如果注册条目中的选择器只匹配容器镜像名,而回滚时镜像 tag 从 v2 变回 v1,但镜像 digest 未变,SPIRE 可能无法正确区分版本。建议始终使用显式的版本标签选择器,而非仅依赖镜像名。
3.6 SPIRE 架构在回滚护栏中的角色总结
下表总结了 SPIRE 各组件在版本差异校验中的具体职责:
| 组件 | 回滚前 | 回滚中 | 回滚后 |
|---|---|---|---|
| SPIRE Server | 维护 v1 和 v2 的注册条目 | 接收回滚指令,更新注册条目优先级 | 确保 v1 工作负载获得正确 SVID |
| SPIRE Agent | 缓存 v1 和 v2 的 SVID | 检测工作负载版本变化,重新匹配选择器 | 为回滚后的工作负载重新签发 SVID |
| Workload API | 提供当前版本的 SVID | 在回滚期间保持 SVID 有效 | 提供回滚后版本的 SVID |
通过 SPIRE 的注册条目机制,服务网格可以在回滚时精确控制每个工作负载实例的身份,从而在版本差异校验中提供可信的身份基础。