1. 课程导入与身份挑战

在传统数据中心里,安全边界通常由防火墙和网段划分来定义:只要请求来自“内网”,就被默认为可信。但微服务、容器和 Kubernetes 把应用拆成了成百上千个短生命周期的进程,它们可能运行在任意节点、任意云上,IP 地址随时变化,网络位置不再等于可信身份。零信任(Zero Trust)正是对这一现实的回应,其核心主张可以概括为一句话:永不默认信任,始终显式验证。而“验证谁”这件事,落到服务与进程层面,就是工作负载身份(Workload Identity)问题。

零信任架构中缺失的一环

零信任架构通常被描述为几个支柱:身份、设备、网络、应用与数据,加上持续验证与最小权限。多数组织在“用户身份”上已经做得不错——员工用 SSO 登录,配合 MFA。但当服务 A 要调用服务 B 时,身份往往退化成了静态密钥:一个写死在配置文件里的 API Key、一段长期有效的数据库密码、一张共享的 TLS 证书。这些凭据一旦泄露,攻击者就能冒充服务,横向移动,而系统很难察觉。

问题的根源在于:工作负载没有稳定、可验证、可轮换的身份。它不像人有用户名和密码,也不像服务器有固定的资产编号。一个 Pod 今天叫 orders-7d9f,明天重建后叫 orders-3c2a;它的 IP 从 10.244.1.37 变成 10.244.2.91。如果身份绑定在 IP 或主机名上,任何调度、扩缩容都会让身份失效或错配。

零信任的验证对象必须从“网络位置”转向“可加密验证的身份”。工作负载身份要回答三个问题:我是谁(身份标识)、我如何证明我是谁(凭据与证明)、我能做什么(授权策略)。

SPIFFE 与 SPIRE 的定位

SPIFFE(Secure Production Identity Framework For Everyone)是一套开放标准,它定义了工作负载身份应该长什么样、如何签发、如何验证。其中最核心的概念是 SPIFFE ID,它是一个 URI 形式的全局唯一标识,例如:

spiffe://example.org/ns/default/sa/orders

这个 ID 的结构是 spiffe://信任域/路径。信任域(trust domain)通常对应一个组织或集群边界,路径部分可以编码命名空间、服务账号、服务名等语义信息。SPIFFE ID 本身只是名字,真正让它可信的是配套的 SVID(SPIFFE Verifiable Identity Document)——一张短生命周期的 X.509 证书或 JWT,其中 URI SAN 字段携带 SPIFFE ID,并由信任域内的签发机构签名。

SPIRE(SPIFFE Runtime Environment)则是 SPIFFE 标准的生产级实现。它由两部分组成:SPIRE Server 负责签发身份、管理注册条目和信任域;SPIRE Agent 运行在每个节点上,负责对本地工作负载进行证明(attestation),并把 SVID 通过 Workload API 交付给进程。工作负载不需要持有任何长期密钥,它只需连接本地的 Unix Domain Socket,就能拿到自己的身份和信任包(trust bundle)。

SPIRE 身份签发与交付链路 工作负载通过本地 Workload API 获取短生命周期 SVID,无需持有长期密钥 SPIRE Server 信任域:example.org 签发 SVID / 管理注册条目 维护信任包(Trust Bundle) 上游 CA / 密钥管理 SPIRE Agent 节点证明(Node Attestation) 工作负载证明(Workload Attestation) 暴露 Workload API Socket 缓存并轮换 SVID 工作负载 orders 服务 / 进程 连接 UDS 获取身份 使用 SVID 建立 mTLS 不持有静态密钥 下发 SVID Workload API 证明过程(Attestation)关键点 节点证明:Agent 向 Server 证明自己运行在可信节点上(如 AWS IID、K8s PSAT、Join Token) 工作负载证明:Agent 通过内核信息(PID、UID、cgroup、容器 ID)识别调用方,匹配注册条目 注册条目:将选择器(selector)映射到 SPIFFE ID,决定“谁可以获得什么身份” SVID 示例(X.509) URI SAN: spiffe://example.org/ns/default/sa/orders 有效期:默认 1 小时(可配置),到期自动轮换;信任包用于验证对端 SVID

为什么这对工程实践很重要

把身份从静态密钥换成 SPIFFE/SPIRE,带来的不只是“更安全”这种抽象收益,而是可观测、可运维的具体变化。第一,凭据生命周期从月/年缩短到小时级,泄露窗口大幅收窄。第二,身份与基础设施解耦:无论工作负载跑在 Kubernetes、虚拟机还是裸金属上,SPIFFE ID 的语义保持一致,跨集群、跨云的 mTLS 成为可能。第三,授权策略可以基于身份而非网络位置,例如“只有 spiffe://example.org/ns/default/sa/orders 才能访问支付服务的 /charge 接口”,这条策略在服务迁移后依然成立。

当然,引入 SPIRE 也意味着新的运维对象:Server 的高可用与备份、Agent 的 DaemonSet 部署、注册条目的版本管理、信任域联邦的配置。这些正是本课程后续要逐一展开的内容。

课程学习路径与实验环境

本课程共 30 章,整体按“概念—部署—集成—运维—进阶”推进。前几章建立 SPIFFE/SPIRE 的核心模型与术语;随后进入单机与 Kubernetes 环境的 SPIRE 部署,理解 Server、Agent、注册条目的实际配置;再往后是 Workload API 编程、mTLS 集成、与 Envoy/Istio 等数据面的配合;最后覆盖信任域联邦、可观测性、故障排查与生产加固。

实验环境建议如下,均可在一台开发机上完成:

  • 基础工具:Docker 24+、kubectl 1.28+、Helm 3.13+、openssl、jq。
  • 本地集群:kind 或 minikube,创建 1 控制面 + 2 工作节点,便于观察 Agent 的 DaemonSet 行为。
  • SPIRE 版本:以官方最新稳定版为准,示例中统一使用 spire-server 与 spire-agent 镜像。
  • 信任域命名:实验统一使用 example.org,避免与生产混淆。
  • 验证工具:spire-server entry show、spire-agent api fetch x509、openssl x509 -text 用于检查 SVID 内容。
建议在开始后续章节前,先确认 kubectl get nodes 能正常返回节点,并记录集群的节点名称与容器运行时(containerd 或 Docker),因为工作负载证明的选择器会依赖这些信息。

本章不要求你立刻部署任何组件,但需要建立一张清晰的心智地图:零信任要求对每个请求做身份验证;工作负载身份是这一要求落到服务层的答案;SPIFFE 定义身份的标准形态,SPIRE 负责在运行时把身份安全地签发和交付给进程。接下来的章节,我们会从 SPIFFE ID 与 SVID 的细节开始,逐步把这张地图变成可运行的系统。