在 Kubernetes 集群里,Pod 可能因为节点故障被调度到新机器,IP 随时变化,传统基于 IP 的访问控制立刻失去意义。服务间通信如果只依赖网络层隔离,攻击者一旦突破边界就能横向移动。mTLS(双向传输层安全)要求客户端和服务端各自出示证书,双方校验通过才建立连接;容器身份则给每个工作负载一个与网络位置无关的标识。把这两者结合起来,才能实现真正的零信任:无论请求来自哪个节点,都要证明“我是谁”且“对方是我期望的对象”。

mTLS 的握手原理与容器身份注入方式
mTLS 在标准 TLS 基础上增加了客户端证书校验。服务端在握手时发送证书,客户端验证其合法性;同时服务端要求客户端提交证书,并校验是否由信任的 CA 签发。这样两端都确认了对方身份,后续流量被加密且无法被中间人篡改。在容器环境中,证书不应硬编码在镜像里,而应由身份代理动态下发,避免私钥随镜像泄露。
容器身份通常遵循 SPIFFE 规范,每个工作负载获得一个 SVID(SPIFFE Verifiable Identity Document),可以是 X.509 证书或 JWT。Sidecar 或 DaemonSet 形式的 agent 监听 Pod 启动事件,调用集群内 CA 签发短期证书,写入容器可访问的临时目录。应用通过本地 socket 或文件读取身份,无需感知证书生命周期。如下代码展示了在 Init 容器中对身份目录的挂载与校验逻辑:
package main
import (
"fmt"
"os"
"time"
)
func main() {
// 容器身份代理已将 SVID 写入 /var/run/spiffe/x509
certPath := "/var/run/spiffe/x509/svid.pem"
keyPath := "/var/run/spiffe/x509/svid.key"
if _, err := os.Stat(certPath); err != nil {
fmt.Println("身份文件不存在,等待代理注入")
time.Sleep(2 * time.Second)
return
}
fmt.Println("已加载容器身份,可用于 mTLS 客户端握手")
}
这种注入方式让业务容器和身份管理解耦。当 Pod 重建时,旧证书自动过期,新证书由 agent 重新申请,攻击者即使拿到旧 Pod 的存储也无法长期冒用身份。相比把证书打进镜像,动态注入把轮换周期从“发版”缩短到“分钟级”。
传统 IP 白名单与零信任身份模型的对比
很多团队在虚拟机时代习惯用防火墙规则限制源 IP,但在容器平台这种手段很快失效。Pod 的 IP 是调度器分配的,每次重启都可能变化;如果按 IP 段放开,等于把整个节点网络都纳入信任域。更麻烦的是,当攻击者通过某个漏洞进入集群,他拥有的正是合法节点的 IP,传统规则无法区分“正常服务”和“被控进程”。
零信任模型下,授权决策依据的是工作负载身份而不是网络位置。下表列出两种方案在典型场景中的差异:
| 维度 | IP 白名单 | mTLS+容器身份 |
|---|---|---|
| 弹性伸缩适配 | 需手动更新规则 | 身份随 Pod 自动签发 |
| 横向移动风险 | 同节点进程可仿冒 | 无合法 SVID 无法建连 |
| 证书轮换 | 不涉及 | agent 自动短期轮换 |
| 跨集群通信 | 需打通网络策略 | 联邦 CA 互信即可 |
从运维角度看,IP 白名单在规模扩大后变成配置地狱,而身份模型把信任收敛到 CA 根密钥。只要根密钥保护得当,任何新启动的容器都能在秒级获得可验证身份,不需要人工干预网络策略。这也是为什么服务网格如 Istio 默认采用 mTLS 而非 IP 限制。
基于 Sidecar 的落地实践与性能权衡
最常见的落地形态是在每个 Pod 中注入 Sidecar 代理,由它终止 mTLS 并转发给本地应用。应用只需监听 localhost,所有出向、入向流量都被 Sidecar 拦截。Sidecar 从节点上的身份 agent 拉取 SVID,定期刷新,并在握手时携带容器身份。这种方案对代码零侵入,特别适合遗留服务。
但 Sidecar 会引入额外的内存与延迟。每个代理需要维护连接池和证书缓存,在数千 Pod 的集群中资源开销不可忽视。一种优化思路是使用 eBPF 代替 Sidecar 做流量重定向,身份 agent 仍负责签发,但加密在套接字层由内核完成。以下示例展示用 Envoy 配置要求入向 mTLS 的过滤器片段:
listeners:
- name: inbound
filter_chains:
- transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: true
common_tls_context:
validation_context:
trusted_ca:
filename: /var/run/spiffe/x509/rootca.pem
如果团队暂时无法接受 Sidecar 密度,也可以先从关键支付、鉴权链路开始强制 mTLS,其他链路用宽松模式过渡。监控上要采集握手失败率和证书过期时间,避免因为 agent 异常导致大面积断连。总体而言,把容器身份作为基础能力下沉到平台层,业务侧只管调用,是迈向零信任最务实的路径。