第二十一章:SPIFFE 联邦与跨域信任
“在多云多集群的世界里,信任不应该止步于一个集群的边界。”
mindmap
root((SPIFFE 联邦))
联邦信任
Bundle Endpoint
单向/双向信任
跨域验证
多集群
同 Trust Domain
不同 Trust Domain
Nested SPIRE
Service Mesh
Istio + SPIRE
Envoy SDS
Consul Connect
K8s 集成
CSI Driver
Workload Registrar
生产实践
命名规范
高可用
监控告警
21.1 为什么需要联邦信任
场景:多集群、多云、多组织
┌─────────────────┐ ┌─────────────────┐
│ AWS 集群 │ │ GCP 集群 │
│ Trust Domain: │ 联邦 │ Trust Domain: │
│ aws.example.com │◀──────▶│ gcp.example.com │
│ │ │ │
│ ┌────────────┐ │ │ ┌────────────┐ │
│ │ Service A │─┼─────────┼─│ Service B │ │
│ │ spiffe:// │ │ mTLS │ │ spiffe:// │ │
│ │ aws.../a │ │ │ │ gcp.../b │ │
│ └────────────┘ │ │ └────────────┘ │
└─────────────────┘ └─────────────────┘
没有联邦:Service A 无法验证 Service B 的 SVID(不同 Trust Domain)
有了联邦:两个 Trust Domain 交换 Trust Bundle,互相信任 ✅
21.2 Trust Domain 联邦
Bundle Endpoint
每个 SPIRE Server 可以暴露一个 Bundle Endpoint,发布自己的 Trust Bundle:
┌──────────────────┐ ┌──────────────────┐
│ SPIRE Server A │ │ SPIRE Server B │
│ aws.example.com │ │ gcp.example.com │
│ │ │ │
│ Bundle Endpoint │◀────────│ 获取 A 的 Bundle│
│ /bundle │ │ │
│ │────────▶│ Bundle Endpoint │
│ 获取 B 的 Bundle│ │ /bundle │
└──────────────────┘ └──────────────────┘
联邦建立后:
- A 的 Agent 拥有 B 的 Trust Bundle → 可以验证 B 的 SVID
- B 的 Agent 拥有 A 的 Trust Bundle → 可以验证 A 的 SVID
SPIRE Server 联邦配置
# SPIRE Server A 配置
server {
trust_domain = "aws.example.com"
# 暴露 Bundle Endpoint
federation {
bundle_endpoint {
address = "0.0.0.0"
port = 8443
}
}
}
# 联邦关系配置
plugins {
BundlePublisher "aws_s3" {
plugin_data {
bucket = "spire-bundles"
region = "us-east-1"
}
}
}
# 建立联邦关系
# Server A 信任 Server B
spire-server bundle set \
-id spiffe://gcp.example.com \
-path /path/to/gcp-bundle.json
# Server B 信任 Server A
spire-server bundle set \
-id spiffe://aws.example.com \
-path /path/to/aws-bundle.json
# 创建联邦注册项
spire-server entry create \
-spiffeID spiffe://aws.example.com/service-a \
-parentID spiffe://aws.example.com/agent/node1 \
-selector k8s:sa:service-a \
-federatesWith spiffe://gcp.example.com # 允许被 GCP 域验证
21.3 多集群场景
场景 1:同一 Trust Domain 多集群
┌─────────────────┐ ┌─────────────────┐
│ Cluster 1 │ │ Cluster 2 │
│ Trust Domain: │ 共享 │ Trust Domain: │
│ example.com │ 同一 │ example.com │
│ │ CA │ │
│ SPIRE Server 1 │◀──────▶│ SPIRE Server 2 │
│ (共享 DataStore)│ │ (共享 DataStore) │
└─────────────────┘ └─────────────────┘
方案:共享数据库(PostgreSQL),多个 Server 实例
优点:无需联邦配置,天然互信
缺点:数据库成为单点
场景 2:Nested SPIRE(嵌套部署)
┌─────────────────────────────────────────┐
│ Root SPIRE Server │
│ spiffe://example.com │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Nested Server│ │ Nested Server│ │
│ │ Cluster A │ │ Cluster B │ │
│ │ spiffe:// │ │ spiffe:// │ │
│ │ example.com │ │ example.com │ │
│ │ /cluster-a │ │ /cluster-b │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────┘
Nested SPIRE:
- 子 Server 从父 Server 获取自己的 SVID
- 子 Server 为自己集群的工作负载签发 SVID
- 所有 SVID 共享同一 Trust Domain
- 适合大规模多集群部署
21.4 与 Service Mesh 集成
Istio + SPIRE
# Istio 配置使用 SPIRE 作为 CA
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
caCertificates:
- spiffeBundleUrl: "https://spire-server:8443"
values:
pilot:
env:
PILOT_CERT_PROVIDER: spiffe
global:
caAddress: "spire-server:8081"
Envoy SDS 集成
SPIRE Agent 内置 SDS(Secret Discovery Service)服务器,Envoy 可以直接从 Agent 获取证书:
# Envoy 配置
static_resources:
clusters:
- name: service-b
type: STRICT_DNS
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: "spiffe://example.org/service-a"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: spire-agent
validation_context_sds_secret_config:
name: "spiffe://example.org"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: spire-agent
21.5 Kubernetes 集成
SPIFFE CSI Driver
自动将 SVID 挂载到 Pod 的文件系统:
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: spiffe
mountPath: /run/spire/sockets
readOnly: true
volumes:
- name: spiffe
csi:
driver: "csi.spiffe.io"
readOnly: true
Kubernetes Workload Registrar
自动为 Kubernetes 工作负载创建 SPIRE 注册项:
# 通过 Pod 注解自动注册
apiVersion: v1
kind: Pod
metadata:
name: web-server
annotations:
spiffe.io/spiffe-id: "spiffe://example.org/ns/production/sa/web-server"
spec:
serviceAccountName: web-server
containers:
- name: web
image: web-server:latest
21.6 生产环境最佳实践
Trust Domain 命名规范
推荐格式:{env}.{org}.{tld}
示例:
prod.example.com — 生产环境
staging.example.com — 预发布环境
dev.example.com — 开发环境
路径规范:
/ns/{namespace}/sa/{service-account} — K8s 工作负载
/region/{region}/service/{name} — 按区域
/cluster/{cluster}/app/{name} — 按集群
高可用部署
┌─────────────────────────────────────────┐
│ SPIRE Server 集群(3节点) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Server 1 │ │Server 2 │ │Server 3 │ │
│ │ (Leader)│ │(Follower)│ │(Follower)│ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ └───────────┼───────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ PostgreSQL │ │
│ │ (高可用集群) │ │
│ └───────────────┘ │
└─────────────────────────────────────────┘
监控指标
指标 |
说明 |
告警阈值 |
|---|---|---|
SVID 签发延迟 |
签发 SVID 的耗时 |
> 5s |
SVID 轮换失败 |
自动轮换失败次数 |
> 0 |
Agent 连接数 |
连接到 Server 的 Agent 数 |
低于预期 |
注册项数量 |
活跃的注册项总数 |
异常变化 |
CA 证书过期 |
根 CA 证书剩余有效期 |
< 30 天 |
21.7 小结
联邦信任 通过 Bundle Endpoint 交换 Trust Bundle,实现跨域互信
Nested SPIRE 适合大规模多集群部署,共享 Trust Domain
Istio + SPIRE 集成提供 Service Mesh 级别的自动 mTLS
SPIFFE CSI Driver 和 Workload Registrar 简化 Kubernetes 集成
生产部署需要关注:高可用、监控告警、Trust Domain 命名规范、灾难恢复