跳过正文
SPIFFE/SPIRE 工作负载身份实战:零信任网络的身份基石

SPIFFE/SPIRE 工作负载身份实战:零信任网络的身份基石

·1567 字·8 分钟·
目录

为什么要搞工作负载身份
#

在"零信任"这个词被过度营销之前,我对它的第一反应是"又是一个新瓶装旧酒的词"。真正让我改观的一次事故是 2023 年的某次内网穿透演练:攻击者拿到一台运维跳板机的 SSH 密钥,通过密钥连上 VPN,然后在内网里畅通无阻地访问了几十个微服务,因为那些服务之间互相信任 VPC 内网 IP。整个事件里没有任何一个身份校验环节,大家都在信"你从内网来"

工作负载身份(Workload Identity)要解决的就是这个问题:让每一个服务、每一个进程、每一个 Pod 都有一个可验证、可撤销、短生命周期的身份凭据,服务之间互相调用必须双向验证身份,而不是信任 IP/网段/机器。SPIFFE(Secure Production Identity Framework For Everyone)是 CNCF 毕业的一套身份标准,SPIRE 是这套标准的参考实现,也是目前最成熟的开源实现,被 Uber、Bloomberg、Square、Netflix 等大规模部署。

这篇文章我会从 SPIFFE 的核心概念讲起,然后用一个真实的"Kubernetes + 虚拟机混合部署"场景把 SPIRE 从零部署一遍,最后讲我们在生产运营 SPIRE 两年多踩过的所有坑。本文基于 SPIRE 1.10+(2025 年下半年版本)。

一、核心概念:SPIFFE ID、SVID、信任域
#

1.1 SPIFFE ID
#

SPIFFE ID 是一个长得像 URI 的字符串,格式:

spiffe://<trust-domain>/<path>

举例:

spiffe://prod.example.com/ns/payments/sa/checkout-service
spiffe://prod.example.com/vm/db-proxy/region/us-west-2
spiffe://prod.example.com/ci/runner/pipeline/12345

它的作用是唯一标识一个工作负载。信任域(trust domain)是一个组织边界,类似 Kerberos 的 Realm 或者 X.509 的 CA。一个工作负载只属于一个信任域,跨信任域通信需要"联邦"(federation)。

关键设计哲学:SPIFFE ID 不是给人看的,是给机器看的。它不携带授权信息(是不是 admin、有没有 read 权限),只携带身份。授权是上层的事情(比如 OPA、Istio AuthorizationPolicy)。

1.2 SVID:身份的可验证载体
#

SVID (SPIFFE Verifiable Identity Document) 是 SPIFFE ID 的可验证形式,有两种:

  • X.509-SVID:一张 X.509 证书,SPIFFE ID 放在 SAN URI 字段里,用于 mTLS
  • JWT-SVID:一个 JWT,SPIFFE ID 放在 sub 字段里,用于 HTTP Authorization 头

两者各有场景:mTLS 走 X.509,REST API 和 Webhook 一般走 JWT。生产里我们两种都用,X.509 用得更多。

重点:SVID 的生命周期非常短,默认 1 小时,可以配置到 5 分钟。短生命周期意味着即便 SVID 泄漏,攻击者能利用的时间窗口也极短。这是 SPIFFE 和传统长期证书最大的不同。

1.3 SPIRE 架构
#

 ┌────────────────────────────────────────────────────────────────┐
 │                      SPIRE Server                              │
 │                                                                │
 │  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐  │
 │  │ Node Attestor│  │ Registration │  │  Signing CA          │  │
 │  │  (k8s, aws,  │  │  Entry Store │  │  (self/ upstream)    │  │
 │  │   join-token)│  │  (DB)        │  │                      │  │
 │  └──────────────┘  └──────────────┘  └──────────────────────┘  │
 └───────────────▲────────────────────────────────▲───────────────┘
                 │ node attestation               │ SVID issuance
        ┌────────┴───────────┐            ┌───────┴────────┐
        │  SPIRE Agent (k8s) │            │ SPIRE Agent(VM)│
        │                    │            │                │
        │  Workload API      │            │ Workload API   │
        │  (unix socket)     │            │ (unix socket)  │
        └──────┬─────────────┘            └───────┬────────┘
               │ attest + fetch SVID              │
        ┌──────▼───────┐                    ┌─────▼────────┐
        │ Pod A (app1) │                    │ nginx on VM  │
        │ Pod B (app2) │                    │ postgres     │
        └──────────────┘                    └──────────────┘

SPIRE Server 是全局单点(一般 3~5 副本 HA),负责:

  • 管理注册表(哪个选择器对应哪个 SPIFFE ID)
  • 签发 SVID
  • 管理信任域的签名 CA(也可以桥接外部 CA,比如 AWS PCA、Vault PKI)

SPIRE Agent 部署在每个节点(Kubernetes 里是 DaemonSet,VM 上是 systemd),负责:

  • 通过节点证明(node attestation)向 Server 证明自己在哪台机器上
  • 通过工作负载证明(workload attestation)识别本机的工作负载
  • 暴露 Workload API(一个 Unix socket)给应用调用,返回 SVID

1.4 双重证明:节点证明 + 工作负载证明
#

这是 SPIRE 最巧妙的设计。传统方案里,让一个应用"证明自己是谁"是个鸡生蛋的问题——你总得先有一把密钥,密钥从哪来?SPIRE 的答案是:先证明机器,再在机器内部通过进程选择器证明应用

  • 节点证明:Agent 启动时,使用"机器身份"向 Server 认证。机器身份可以是 EC2 instance identity document、EKS ServiceAccount token、云厂商元数据、或者预共享的 join token。
  • 工作负载证明:Agent 拿到 SVID 后,Pod/进程通过 Unix socket 请求 SVID。Agent 查看调用者的进程信息(PID、UID、K8s labels、namespace、container image hash…),匹配到对应的注册表条目,然后才发 SVID。

关键:应用本身不需要持有任何长期凭据。连接 Unix socket 就能拿到当前"该我拥有"的 SVID。这是为什么 SPIFFE 能做到"零密钥分发"。

二、生产部署:SPIRE on Kubernetes
#

2.1 选择部署方式:Helm、Operator 还是手写 manifest
#

2025 年的生产环境我强烈推荐使用 spire-controller-manager + spire-crds 的模式,通过 ClusterSPIFFEIDClusterFederatedTrustDomain 这两个 CRD 声明式管理,不再手动调 SPIRE Server API 注册工作负载。官方 Helm chart spiffe/spire 已经把这一套封装好了。

老的"纯 Helm + manual registration API 调用"模式维护成本高,不推荐新项目采用。

2.2 Helm values 示例
#

global:
  spire:
    clusterName: us-prod
    trustDomain: prod.example.com
    jwtIssuer: https://spire.prod.example.com
    recommendations:
      create: true

spire-server:
  replicaCount: 3
  ca_subject:
    country: US
    organization: Example Corp
    common_name: SPIRE Server CA (prod)
  ca_ttl: 87600h            # CA 10 年
  default_x509_svid_ttl: 1h
  default_jwt_svid_ttl: 5m

  dataStore:
    sql:
      databaseType: postgres
      host: spire-db.prod.internal
      port: 5432
      databaseName: spire
      username: spire
      # 密码走 External Secrets 注入
      passwordSecretRef:
        name: spire-db-password
        key: password

  nodeAttestor:
    k8sPsat:
      enabled: true
      serviceAccountAllowList: ["spire:spire-agent"]

  keyManager:
    awsKms:
      enabled: true
      region: us-west-2
      keyMetadata:
        kmsKeyPolicy: "arn:aws:kms:..."

  controllerManager:
    enabled: true
    identities:
      clusterSPIFFEIDs:
        default:
          enabled: false   # 我们不用 "catch-all",强制显式声明

spire-agent:
  sockets:
    hostBasePath: /run/spire
  nodeAttestor:
    k8sPsat:
      enabled: true
  workloadAttestors:
    k8s:
      enabled: true
      useNewContainerLocator: true   # 1.10+ 新的容器定位器,支持 containerd 2.0
      disableContainerSelectors: false

几个关键选择的理由:

  1. PostgreSQL 作为 datastore:SQLite 只能单副本,生产必须用外部 SQL。MySQL/PostgreSQL 都行,我们选 PostgreSQL 因为 RDS 管理方便。datastore 每个 trust domain 一个,不要多集群共享。
  2. AWS KMS 作为 KeyManager:SPIRE 的 CA 私钥如果存本地磁盘,HA 部署时需要同步,麻烦且不安全。用 KMS 把私钥托管起来,三副本共享同一把 KMS key,Server 崩溃重建后无感恢复。阿里云环境可以用 KMS,自建可以用 HashiCorp Vault Transit。
  3. k8s_psat(Projected Service Account Token)节点证明:比老的 k8s_sat 安全,因为 token 有 audience、有过期时间、绑定 Pod。
  4. default identity 关掉:默认 chart 会给所有 Pod 一个 catch-all 身份,这会让你失去"谁没身份"的可见性。我坚持强制显式声明。

2.3 给 Pod 发身份:ClusterSPIFFEID
#

apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
  name: payments-checkout
spec:
  spiffeIDTemplate: "spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}"
  podSelector:
    matchLabels:
      app: checkout-service
  namespaceSelector:
    matchLabels:
      spiffe.io/managed: "true"
  dnsNameTemplates:
    - "checkout.payments.svc.cluster.local"
    - "checkout.payments.internal"
  ttl: 30m
  workloadSelectorTemplates:
    - "k8s:ns:{{ .PodMeta.Namespace }}"
    - "k8s:sa:{{ .PodSpec.ServiceAccountName }}"
    - "k8s:pod-label:app:{{ index .PodMeta.Labels \"app\" }}"

注意几个点:

  • spiffeIDTemplatens/<namespace>/sa/<sa> 结构,和 K8s 原生的 ServiceAccount 对齐,IAM 做映射时非常方便。
  • dnsNameTemplates 会写进 X.509 的 SAN DNS 字段,客户端校验证书时可以按 DNS 名验证(便于和传统 PKI 客户端兼容)。
  • ttl: 30m 是个折中。设太短(5m)会给 SPIRE Server 和 CA 带来压力,设太长则"撤销"变得无意义。30m 对于大多数业务够用。
  • workloadSelectorTemplates 是工作负载证明的选择器,必须同时匹配才会下发 SVID。加 pod-label 是为了让同名 SA 下不同 app 的 Pod 拿到不同身份。

2.4 应用怎么用 SVID
#

最简单的用法是通过 SPIFFE Workload API 的 SDK。Go 版本:

import (
    "context"
    "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
    "github.com/spiffe/go-spiffe/v2/workloadapi"
)

func main() {
    ctx := context.Background()
    source, err := workloadapi.NewX509Source(ctx,
        workloadapi.WithClientOptions(
            workloadapi.WithAddr("unix:///run/spire/sockets/agent.sock"),
        ),
    )
    if err != nil { log.Fatal(err) }
    defer source.Close()

    tlsConfig := tlsconfig.MTLSClientConfig(
        source, source,
        tlsconfig.AuthorizeMemberOf(spiffeid.RequireTrustDomainFromString("prod.example.com")),
    )
    client := &http.Client{
        Transport: &http.Transport{TLSClientConfig: tlsConfig},
    }
    resp, err := client.Get("https://checkout.payments.internal:8443/api/v1/orders")
    ...
}

NewX509Source 会在后台自动续期,应用永远用的是新鲜 SVID,不需要关心证书到期。服务端类似,用 tlsconfig.MTLSServerConfig,并通过 AuthorizeAny() 或者 AuthorizeID(spiffeid.Must(...)) 限定能调自己的身份列表。

对于无法改代码的遗留应用,有三种选择:

  1. spiffe-helper:一个 sidecar,它把 SVID 和信任包(trust bundle)写成文件,定时 rotate,应用像读传统证书一样读文件即可。
  2. Istio + SPIRE 集成:Istio 1.14+ 支持用 SPIRE 作为 CA,Envoy 直接从 SPIRE 取 SVID,应用完全无感。
  3. SPIFFE-CSI driver:把 Agent socket 挂到 Pod 里,不需要每个 Pod 都走 hostPath。

我们生产里三种都在用,Istio 场景最多,次之是 spiffe-helper。

2.5 Istio 集成
#

Istio 1.14 之后支持 pilot-agent 从 SPIRE Workload API 取证书。核心配置:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    trustDomain: prod.example.com
    defaultConfig:
      proxyMetadata:
        ISTIO_META_CERT_SIGNER: spire
  values:
    global:
      caAddress: "unix:///run/spire/sockets/agent.sock"
    pilot:
      env:
        ENABLE_CA_SERVER: "false"
        PILOT_CERT_PROVIDER: spiffe

Istio sidecar 启动时会挂载 SPIRE Agent 的 socket,从中取 X.509-SVID 作为 Envoy 的工作负载证书。这样 Istio 的 mTLS 就完全基于 SPIFFE 身份,而不是 Istio 内建的 Citadel。好处是:

  • 统一身份:VM 上的传统服务也用 SPIFFE 身份,和 K8s Pod 互信
  • 可验证:Envoy 的 metric 里能看到对端 SPIFFE ID,审计方便
  • CA 托管:用 KMS 管 CA 私钥,比 Citadel 默认本地存安全

三、混合场景:把虚拟机纳入 SPIFFE 信任域
#

很多公司 K8s 之外还跑着大量 VM(数据库、老业务、Windows 工作负载),让这些 VM 也进入 SPIFFE 信任域是零信任落地的关键一步。

3.1 VM 上部署 Agent
#

# Ubuntu 22.04 示例
curl -L https://github.com/spiffe/spire/releases/download/v1.10.2/spire-1.10.2-linux-amd64-musl.tar.gz | \
  sudo tar -xz -C /opt

sudo useradd --system --home /var/lib/spire spire
sudo install -d -o spire -g spire /var/lib/spire /run/spire /etc/spire

sudo tee /etc/spire/agent.conf <<'EOF'
agent {
  data_dir = "/var/lib/spire"
  log_level = "INFO"
  server_address = "spire.prod.example.com"
  server_port = "8081"
  socket_path = "/run/spire/agent.sock"
  trust_domain = "prod.example.com"
  trust_bundle_path = "/etc/spire/bootstrap.crt"
}

plugins {
  NodeAttestor "aws_iid" {
    plugin_data { }
  }
  KeyManager "disk" {
    plugin_data {
      directory = "/var/lib/spire"
    }
  }
  WorkloadAttestor "unix" {
    plugin_data {
      discover_workload_path = true
    }
  }
  WorkloadAttestor "systemd" {
    plugin_data { }
  }
}
EOF

sudo systemctl enable --now spire-agent

几个关键点:

  • aws_iid 节点证明:利用 EC2 instance identity document,每台机器都有唯一的 IID,SPIRE Server 可以绑定到 instance ID、region、账号,拒绝不符合的。
  • systemd 工作负载证明:可以根据 systemd unit name 发 SVID,非常适合 VM 上的传统服务。
  • bootstrap.crt:Agent 首次连接 Server 需要信任 Server 的 CA,这个是通过离线分发的 bootstrap 证书建立的。生产里通过 cloud-init 或者 Ansible 推下去。

3.2 为 systemd 服务发身份
#

apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
  name: db-proxy-vm
spec:
  spiffeIDTemplate: "spiffe://prod.example.com/vm/db-proxy/{{ .NodeMeta.Hostname }}"
  nodeSelector:
    matchLabels:
      node.type: "vm"
      node.role: "db-proxy"
  workloadSelectorTemplates:
    - "systemd:unit:db-proxy.service"
    - "unix:uid:999"

注意 VM 场景用 ClusterSPIFFEID 的方式要通过 spire-controller-manager 的 VM 适配模式(1.9+ 支持)。老版本需要手动 spire-server entry create 命令行注册。

3.3 spiffe-helper 给非感知应用签证书
#

# /etc/spire/helper.conf
agent_address = "/run/spire/agent.sock"
cmd = "/bin/systemctl"
cmd_args = "reload nginx"
cert_dir = "/etc/nginx/spiffe"
svid_file_name = "svid.crt"
svid_key_file_name = "svid.key"
svid_bundle_file_name = "bundle.crt"
renew_signal = "SIGHUP"

运行 spiffe-helper 进程,它会每 30 秒检查 SVID 是否快过期,过期前重新从 Workload API 取新的,写到 cert_dir,然后发 SIGHUP 给应用。nginx/postgres 都能用这种方式平滑换证。

四、信任域联邦:跨集群、跨云互信
#

生产环境很少只有一个信任域,比如:

  • 不同集群(us-prod / cn-prod)一个信任域一个
  • 不同环境(prod / staging)必须隔离

跨信任域通信需要联邦:两个信任域互相交换 trust bundle,让对方的 CA 被己方信任。

SPIRE 从 1.5 开始支持声明式联邦,1.10 里已经非常稳定。配置方式:

apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterFederatedTrustDomain
metadata:
  name: cn-prod
spec:
  trustDomain: cn.prod.example.com
  bundleEndpointURL: https://spire.cn.prod.example.com/bundle
  bundleEndpointProfile:
    type: https_spiffe
    endpointSPIFFEID: spiffe://cn.prod.example.com/spire/server
  trustDomainBundle: |-
    -----BEGIN CERTIFICATE-----
    MIID....(bootstrap bundle)
    -----END CERTIFICATE-----

联邦后,us-prod 的 Pod 可以和 cn.prod.example.com 下的工作负载做 mTLS,AuthorizeID 里指定对方的 SPIFFE ID 即可:

tlsConfig := tlsconfig.MTLSClientConfig(
    source, source,
    tlsconfig.AuthorizeID(spiffeid.RequireFromString(
        "spiffe://cn.prod.example.com/ns/data/sa/sync-service",
    )),
)

关键权限模型:联邦只是"互相认识对方的 CA",不等于"互相授权"。授权依然需要上层策略(比如 OPA)决定哪个 SPIFFE ID 能调哪个 API。我们的实践是:

  1. 联邦在 SPIRE 层建立
  2. 调用授权在 Istio AuthorizationPolicy 或者 OPA 层决定
  3. 业务层再做细粒度授权(tenant、user)

五、运营实战:真实踩坑与经验
#

5.1 datastore 必须定期备份
#

SPIRE Server 的 datastore 存了所有 entry 和 CA 信息。datastore 一丢,整个信任域就没了,所有 Agent 需要重新 bootstrap,所有应用需要重连,是一次全站事故。

我们的备份策略:

  • PostgreSQL RDS 每日快照 + 点时间恢复
  • 每周导出一次 entry 列表为 JSON 到 S3:
    spire-server entry show -output json > entries-$(date +%F).json
    aws s3 cp entries-$(date +%F).json s3://spire-backup/
    
  • CA 配置文件 + KMS key ARN 放在 Git,用 sealed-secrets 加密

5.2 Agent 崩溃怎么办?
#

Agent 崩溃是最容易被忽略的故障,因为它对控制面无感(SPIRE Server 不会 crash),但对数据面是灾难:Agent 所在节点的所有 Pod 无法获取新的 SVID,30 分钟后 SVID 过期,所有 mTLS 连接报错。

防御措施:

  1. Agent DaemonSet 配 liveness probe:探测 /run/spire/agent.sock 是否响应,不响应就重启
  2. Prometheus 监控 spire_agent_svids_issued_total 增长率,若某节点 10 分钟无增长告警
  3. 应用侧做重试和降级:go-spiffe SDK 在连不上 Agent 时会返回错误,应用要能处理(至少重试几次,不能让一个 Agent 问题雪崩到整个业务)

真实案例:2025 年 3 月某次 kubelet 滚动重启时 Agent 进入 CrashLoopBackOff(因为 hostPath socket 残留了坏 symlink),整个节点的 Pod 连续 15 分钟无法续签,直到我们手动删 symlink。事后我们给 Agent 加了 initContainer 清理残留 socket:

initContainers:
  - name: cleanup-socket
    image: busybox:1.36
    command: ["sh", "-c", "rm -f /run/spire/sockets/agent.sock"]
    volumeMounts:
      - name: spire-agent-socket
        mountPath: /run/spire/sockets

5.3 SPIRE Server HA 的 split-brain 风险
#

SPIRE Server 三副本共享同一个 datastore,但 CA 签名状态需要协调。1.8 之前偶发 split-brain(两个 Server 同时认为自己是 CA leader),1.9 引入了基于 datastore 的 lease,1.10 更稳了。但即便如此,我建议:

  • 不要跨 Region 部署一个 SPIRE Server(延迟对 lease 不友好)
  • 每个 Region 一个独立的信任域(region.prod.example.com),通过联邦互信
  • Server 副本数 3,不要 5 或 7(datastore lease 的协调成本平方级增长)

5.4 注册表膨胀
#

spire-controller-manager 会为每个匹配的 Pod 创建 registration entry。一个 5000 Pod 集群 entry 数量就是 5000+,大量短生命周期 Pod(CronJob、CI runner)会导致 entry 频繁增删,datastore 压力大。

优化:

  • CronJob/Job 类工作负载用父选择器+通配的方式注册,不要给每个 Pod 单独 entry
  • 把 entry 的 admin 字段关掉(减少访问控制开销)
  • spire-controller-managergcInterval 可以调到 5 分钟一次(默认 10 秒太频繁)

5.5 可观测性
#

SPIRE 本身暴露 Prometheus metrics,关键指标:

# Server 端
spire_server_registration_entries{} gauge     # entry 总数
spire_server_svid_x509_signed_total           # 签发速率
spire_server_datastore_sql_errors_total       # datastore 错误
spire_server_node_attestation_success_total   # 节点证明成功数

# Agent 端
spire_agent_svids_updated_total               # SVID 更新次数
spire_agent_workload_api_fetch_x509_svid_total # 工作负载请求数
spire_agent_manager_cache_size                # 本地缓存大小

告警规则示例:

- alert: SpireAgentDown
  expr: up{job="spire-agent"} == 0
  for: 2m
  labels: { severity: critical }
- alert: SpireSignRateAbnormal
  expr: |
    rate(spire_server_svid_x509_signed_total[5m])
      / rate(spire_server_svid_x509_signed_total[1h] offset 1h) > 3
  for: 10m
  annotations:
    summary: "SPIRE 签发速率异常升高,可能有 Agent 风暴"

六、和 Vault/External Secrets 的对比
#

经常有人问:“我都有 Vault 了,还需要 SPIRE 吗?” 简短回答:需要,它们解决的是不同层次的问题

维度Vault / External SecretsSPIRE
解决的问题密钥/配置分发工作负载身份
凭据类型长期凭据(DB 密码、API key)短期 SVID
身份来源需要 bootstrap secret 或 K8s SA基于机器证明+进程证明
适用场景应用需要的第三方服务凭据服务间 mTLS、零信任
可不可以互补可以且应该可以且应该

典型组合:Vault Agent 用 SPIRE SVID 作为认证方式向 Vault 取 DB 密码。这样 Vault 的 auth/spiffe 后端验证 SVID,就不需要预先分发 token。

七、和传统 PKI 的兼容
#

不是所有服务都能改成调 Workload API。很多 Java 老服务只认 JKS 文件,怎么办?

  1. spiffe-helper 输出 PKCS12(1.9+ 支持),Java 能直接用
  2. cert-manager 的 SPIFFE 集成:cert-manager 1.15+ 支持把 SPIRE 作为 issuer,自动生成 Certificate 资源
  3. 把 SPIRE 作为一个证书转换器:SPIRE 签发 SVID,应用侧挂 spiffe-helper 转换成传统 PEM/JKS/P12

我们的一个老 Spring Boot 服务就是走第三条路,spiffe-helper 写出 keystore.p12truststore.p12,Spring 的 SSL 配置指向这两个文件,每 10 分钟 rotate 一次。业务零改动。

八、落地路线图建议
#

最后给一个循序渐进的落地建议,供还没开始的团队参考:

第 1 阶段(1~2 个月):只部署 SPIRE Server + Agent,发 SVID 但不强制使用。让开发团队熟悉 SPIFFE ID 的命名约定。

第 2 阶段(2~4 个月):选一个简单业务做 pilot,跑通 Go/Java SDK 集成,验证 SVID 续期、故障回滚。同时搞定 Istio 集成,让大部分 mTLS 流量切到 SPIFFE 证书。

第 3 阶段(4~6 个月):推广到所有 K8s 业务,强制新服务用 SPIFFE 身份。开始接入非 K8s 工作负载(VM、数据库代理、CI runner)。

第 4 阶段(6~12 个月):打通联邦,多集群互信;Vault 对接 SPIFFE 认证;老 PKI 替换下线。

SPIFFE/SPIRE 不是"一键搞定"的工具,是一整套身份体系的建设。我们跑了两年多才真正让它从"写 PPT 的 slogan"变成每天能用的生产能力。配合 Falco + Cilium L7 + Kyverno,身份、调用、策略这三层都能落到可审计的工程实践上,这是我愿意继续投入的方向。

Wenzhuo Huang
作者
Wenzhuo Huang
搞运维的工程师,写代码的运维人。专注 Kubernetes、AWS、GitOps 与基础设施可靠性。这个博客既是我的技术笔记本,也是我踩过的坑的受害者档案。

相关文章

Kubernetes NetworkPolicy 网络隔离实战

·2505 字·12 分钟
系统讲解 Kubernetes NetworkPolicy 的工作机制与生产实战配置,覆盖 deny-all 基础模板、常见隔离场景、Cilium 扩展、多租户设计、测试验证方法及常见陷阱。

Istio Service Mesh 落地实战:从 Sidecar 注入到灰度发布

·973 字·5 分钟
记录 Istio Service Mesh 从零落地的完整过程,包括 sidecar 注入原理、VirtualService 灰度发布流量切分、DestinationRule 熔断与负载均衡配置、PeerAuthentication mTLS 加固,以及用 istioctl analyze 排查常见问题。