Skip to content

本文为 SPIRE 官方文档 scaling_spire.md 的中文译本,以英文原文为准。 🔗 穿越源码分析:高可用与大集群部署

扩展 SPIRE

可扩展性

SPIRE 部署可以调整规模或伸缩,以适应不断增长的工作负载(Workload)数量。一套 SPIRE 部署由一个或多个共享同一份复制数据存储(datastore)的 SPIRE Server 组成(换言之,是同一信任域(trust domain)内的一组 SPIRE Server),以及至少一个、但通常不止一个的 SPIRE Agent 组成。

部署规模各不相同。单个 SPIRE Server 就可以承载一定数量的 Agent 与工作负载注册条目(Workload Registration entry)。在做规模评估时需要考虑:由于管理和签发这些条目所对应身份涉及大量操作,SPIRE Server 实例的内存与 CPU 消耗往往会随部署中工作负载注册条目数量的增加而成比例增长。此外,单个 SPIRE Server 实例本身也构成单点故障(single point of failure)。

为了在给定部署中支撑更大规模的 Agent 与工作负载(数以万计乃至数十万个节点),可以对 SPIRE Server 数量进行横向扩展(horizontally scaling)。有了多台 Server,SPIRE Server 所承担的计算工作量会分摊到所有 SPIRE Server 实例上。除了增加容量,使用一个以上的 SPIRE Server 实例还消除了单点故障,从而实现高可用(High Availability)。

高可用模式下的 SPIRE Server

高可用示意图

要横向扩展 SPIRE Server(无论是出于高可用还是负载分担的目的),都需将同一信任域内的所有 Server 配置为读写同一份共享数据存储。

数据存储是 SPIRE Server 持久化动态配置信息(如注册条目和身份映射策略)的地方。SPIRE Server 内置了 SQLite,它也是默认的数据存储。SPIRE 支持多种兼容的 SQL 数据库,还提供了一个使用 Kubernetes CRD 的 Kubernetes 插件。横向扩展 SPIRE Server 时,请选择符合你需求的数据存储,并将所有 SPIRE Server 都配置为使用所选的数据存储。详情请参阅 datastore 插件配置参考

在高可用模式下,每台 Server 维护自己的证书颁发机构(Certificate Authority,CA),它既可以是自签名证书,也可以是基于共享根权威(即配置了 UpstreamAuthority 时)签发的中间证书。

选择 SPIRE 部署拓扑

SPIRE 有三种主要的部署拓扑(topology):

  • 单一信任域(Single trust domain)
  • 嵌套式 SPIRE(Nested SPIRE)
  • 联邦式 SPIRE(Federated SPIRE)

诸如管理域边界、工作负载数量、可用性要求、云厂商数量以及认证要求等因素,决定了适合你环境的拓扑,下文将逐一说明。

单一信任域

单一信任域示意图

单一信任域最适合单个环境,或同一管理域内具有相似特征的环境。采用单一总体信任域的主要动机,是从单个证书颁发机构签发身份,因为这可以减少分散部署中需要管理的 SPIRE Server 数量。

然而,当把单个 SPIRE 信任域部署到跨地域、跨平台、跨云厂商环境时,在地理上分散的位置之间或跨云厂商边界管理一份共享数据存储会带来一定的复杂度。在这种情况下,当部署扩展到跨多个环境时,针对"在单一信任域上使用共享数据存储"这一问题的解决方案,是把 SPIRE Server 配置成嵌套式拓扑。

嵌套式 SPIRE

嵌套式 SPIRE 示意图

嵌套式 SPIRE 允许多台 SPIRE Server "串接(chained)"在一起,并让所有 Server 仍然在同一信任域内签发身份,这意味着在同一信任域内被标识的所有工作负载,都会拿到可以针对该信任域根密钥进行校验的身份文档。

嵌套式拓扑的工作方式是:为每一台下游(downstream)"串接"的 SPIRE Server 就近部署一个 SPIRE Agent。下游 SPIRE Server 通过工作负载 API 获取凭据,用它直接向上游(upstream)SPIRE Server 认证,从而获取一个中间 CA。

有助于理解嵌套式拓扑运作方式的一个思维模型是:把顶层 SPIRE Server 看作全局 Server(为高可用可以是一组 Server),把下游 SPIRE Server 看作区域级或集群级 Server。

在这种配置中,顶层 SPIRE Server 持有根证书 / 根密钥,下游 Server 则请求一个中间签名证书,作为该下游 Server 的 X.509 签名权威。它带来了弹性:即便顶层宕机,中间层 Server 仍可继续运行。

嵌套式拓扑非常适合多云部署。得益于可以自由搭配节点认证器(node attestor),下游 Server 可以驻留在不同云厂商环境中,并为其中的工作负载和 Agent 提供身份。

作为对横向扩展 SPIRE Server(用于高可用与负载均衡)的补充,嵌套式拓扑还可以作为一种隔离策略,用来切分故障域(failure domain)。

联邦式 SPIRE

联邦式 SPIRE 示意图

有些部署可能需要多个信任根:也许是因为一个组织有多个由不同管理员负责的部门,或者因为它们有相互隔离、但偶尔需要通信的预发布(staging)与生产(production)环境。

另一个用例是组织之间的 SPIFFE 互操作,例如云厂商与其客户之间。

这两种"多信任域"与"互操作"用例,都需要一种定义良好、可互操作的方法,让一个信任域中的工作负载去认证另一个信任域中的工作负载。不同信任域之间的信任建立方式是:先认证对方的证书包端点(bundle endpoint),然后通过这个已认证的端点获取对方信任域的证书包(bundle)。

关于这一机制如何实现的更多细节,请参阅描述该机制的 SPIFFE 规范:https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Federation.md#4-spiffe-bundle-endpoint

关于配置联邦式 SPIRE 的教程,请参阅:https://github.com/spiffe/spire-tutorials/tree/main/docker-compose/federation

与外部系统的交互

与"SPIFFE 兼容"系统的联邦

与 SPIFFE 兼容系统联邦示意图

SPIFFE 身份签发方可以与其他暴露了 SPIFFE Federation API 实现的 SPIFFE 身份签发方建立联邦,从而让联邦各域中的工作负载能够安全地相互认证和通信。与 SPIRE 部署之间的联邦类似,SPIFFE 联邦被用来在多个 SPIFFE 兼容系统之间建立联邦,例如在一套 SPIRE 部署与一个 Istio 服务网格之间,或在某个数据中心某集群中运行的 Istio 服务网格与另一处运行的 Istio 服务网格之间。

例如,在当前的 Istio 中,服务网格上的所有应用都处于同一信任域,因而共享同一个信任根。但可能存在多个服务网格,或者服务网格中的应用需要与外部服务通信、且需对这些外部服务进行认证。使用联邦可以让多个 Istio 服务网格这类 SPIFFE 兼容系统安全地建立信任,以实现安全的跨网格与网格外通信。

与 OIDC 提供方系统的联邦

与 SPIFFE 兼容系统联邦示意图

SPIRE 提供了一项能力:可以代表已标识的工作负载,以编程方式向远端系统(如公有云厂商服务和与 OIDC 联邦兼容的机密存储)进行认证。例如,在 Amazon Web Services 的场景下,一个由 SPIRE 标识的工作负载可以与 AWS S3 Bucket、AWS RDS 实例或 AWS CodePipeline 进行认证和通信。

SPIRE OIDC Discovery Provider 使用 ACME 协议获取一张 WebPKI 证书,用它来保护一个端点,该端点对外提供一个兼容 OIDC 的 JWKS 证书包和一份标准的 OIDC discovery 文档。随后需要把远端 OIDC 认证服务配置为定位该端点并核验其 WebPKI 服务。配置就绪后,就可以把远端系统的 IAM 策略与角色设置为映射到特定的 SPIFFE ID。工作负载则通过发送一个 JWT-SVID 与该 OIDC 认证系统通信。目标系统随后从由 OIDC Discovery Provider 提供服务的预定义 URI 获取 JWKS。目标系统用该 JWKS 文件校验 JWT-SVID,如果 JWT-SVID 中包含的 SPIFFE ID 被授权访问所请求的资源,便会响应该请求。这样,工作负载无需持有该远端服务下发的任何凭据,就能访问这个外部远端服务。

关于 OIDC Discovery Provider 的配置参考,请见: https://github.com/spiffe/spire/tree/main/support/oidc-discovery-provider

关于配置面向 Amazon Web Services 的 OIDC 联邦的详细教程,请参阅:https://spiffe.io/spire/try/oidc-federation-aws/

部署规模评估的考量因素

为获得最佳性能而对 SPIRE 部署做规模评估时,需要考虑的因素包括但不限于以下几点:

  • SVID 与根证书的 TTL
  • 每个节点上工作负载的数量与分布
  • 大量使用 JWT-SVID(因为 JWT 必须按需签名,而不能像 X.509 那样预先缓存)
  • 注册变更的频率
  • SPIRE Server 节点上运行的其他进程
  • 底层基础设施环境的"形态"与"规模"

需要特别重视数据存储的设计与规划。注意上面的列表中并未提及数据存储性能,而它有可能成为 SPIRE 性能的瓶颈。总体来看,数据存储往往是最大的性能瓶颈,因为每次 Agent 同步(每个 Agent 每 5 秒一次)所进行的授权检查相对昂贵。在嵌套式拓扑中,这一开销可以降低,因为嵌套拓扑中的每个 SPIRE Server 集群都有自己的数据存储。

下表旨在为 SPIRE 部署中的 SPIRE Server 规模评估提供一个参考。这些参考数字基于一个测试环境,仅作为数量级层面的指导,并不代表对任何特定用户环境的性能保证。表中未包含网络带宽和数据库查询相关信息。此外,表中所示的工作负载与 Agent 数量,也并不代表理论上可能达到的 SPIRE 部署规模上限。

工作负载数量10 个 Agent100 个 Agent1000 个 Agent5000 个 Agent
10 个工作负载2 个 Server 单元,每个 1 CPU 核、1GB RAM2 个 Server 单元,每个 2 CPU 核、2GB RAM2 个 Server 单元,每个 4 CPU 核、4GB RAM2 个 Server 单元,每个 8 CPU 核、8GB RAM
100 个工作负载2 个 Server 单元,每个 2 CPU 核、2GB RAM2 个 Server 单元,每个 2 CPU 核、2GB RAM2 个 Server 单元,每个 8 CPU 核、8GB RAM2 个 Server 单元,每个 16 CPU 核、16GB RAM
1,000 个工作负载2 个 Server 单元,每个 16 CPU 核、8GB RAM2 个 Server 单元,每个 16 CPU 核、8GB RAM2 个 Server 单元,每个 16 CPU 核、8GB RAM4 个 Server 单元,每个 16 CPU 核、8GB RAM
10,000 个工作负载4 个 Server 单元,每个 16 CPU 核、16GB RAM4 个 Server 单元,每个 16 CPU 核、16GB RAM4 个 Server 单元,每个 16 CPU 核、16GB RAM8 个 Server 单元,每个 16 CPU 核、16GB RAM