第四章 安全 (Security)
一、导读
1.1 本章学习目标
理解 Istio 安全体系的核心概念:身份(Identity)、认证(Authentication)和授权(Authorization)
掌握 mTLS 的工作原理及在 Istio 中的配置方法
理解 PeerAuthentication 策略的 STRICT 和 PERMISSIVE 模式及其适用场景
掌握 AuthorizationPolicy 的配置:基于服务身份的访问控制
了解 JWT 认证的实现机制和 RequestAuthentication 资源的使用
理解 Istio 的证书管理体系:根 CA、中间 CA 和工作负载证书的生命周期
掌握零信任网络模型在 Istio 中的实现方式
能够设计和实施完整的服务网格安全策略
1.2 为什么本章如此重要
安全是微服务架构中最容易被忽视却又至关重要的方面。在传统的数据中心网络中,服务间的通信通常被认为是安全的,因为它们在同一个受信任的网络边界内。然而,在云原生环境中,容器、Pod 和网络都是动态的,传统的基于网络边界的防御模型已经不再适用。一个被攻陷的 Pod 可以自由地与同一网络中的任何其他 Pod 通信,这种"扁平网络"模型带来了严重的安全隐患。
Istio 的安全能力从根本上改变了微服务的通信安全模型。通过为每个工作负载分配唯一身份,Istio 实现了基于身份而非 IP 地址的访问控制。通过自动化的 mTLS,所有服务间通信都被加密和认证,即使攻击者截获了网络流量也无法解读内容。通过细粒度的授权策略,可以精确控制哪些服务可以访问哪些服务的哪些端点,实现最小权限原则。
这些安全能力以透明的方式提供,不需要修改应用代码,也不需要应用感知安全基础设施的存在。这种"安全即基础设施"的理念,使得安全不再是开发团队的负担,而是平台提供的基本保障。本章将深入 Istio 的安全体系,从身份管理到加密通信,从认证到授权,构建完整的安全知识体系。
1.3 核心问题引导
Istio 如何为每个工作负载分配和验证身份?
mTLS 在 Istio 中是如何自动化管理的?证书的生命周期是怎样的?
PeerAuthentication 的 STRICT 和 PERMISSIVE 模式有什么区别?迁移时应该如何选择?
AuthorizationPolicy 支持哪些匹配维度?如何实现细粒度的访问控制?
如何在 Istio 中实现基于 JWT 的终端用户认证?
零信任网络模型的核心原则是什么?Istio 如何实现零信任?
在 mTLS 迁移过程中,如何避免服务中断?
二、核心概念详解
2.1 工作负载身份与 SPIFFE 标准
Istio 的安全体系建立在工作负载身份(Workload Identity)的基础之上。每个工作负载(Pod)在 Istio 中都有一个唯一的身份标识,这个标识基于 SPIFFE(Secure Production Identity Framework for Everyone)标准定义。SPIFFE ID 的格式为 spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>,例如 spiffe://cluster.local/ns/default/sa/my-service。
使用 ServiceAccount 作为身份的基础有几个重要原因:首先,ServiceAccount 是 Kubernetes 原生的身份概念,与 Pod 生命周期绑定,不需要额外的身份管理系统;其次,ServiceAccount 的粒度可以灵活控制——可以让同一服务的所有 Pod 共享一个 ServiceAccount,也可以为不同版本的 Pod 分配不同的 ServiceAccount;最后,基于 ServiceAccount 的身份与 IP 地址无关,Pod 重建后身份不变,适合云原生环境的动态特性。
工作负载身份是 mTLS 认证和授权策略的基础。在 mTLS 通信中,客户端和服务端的 Sidecar 代理使用与身份绑定的证书进行相互认证。在授权策略中,可以通过 source.principal 字段引用请求方的身份,实现基于身份的访问控制。理解身份模型是正确使用 Istio 安全功能的前提。
2.2 mTLS 与自动证书管理
mTLS(Mutual TLS)是 Istio 安全通信的核心机制。与普通 TLS 不同,mTLS 要求客户端和服务端都提供证书进行相互验证。在 Istio 中,mTLS 由 Sidecar 代理自动处理,应用完全无感知。当应用发出请求时,Outbound Sidecar 使用工作负载证书与目标服务的 Inbound Sidecar 进行 mTLS 握手,建立加密通道后转发请求。
Istio 的证书管理基于分层 CA 架构。顶层是根 CA(Root CA),负责签发中间 CA 的证书。中间 CA(由 istiod 担任)负责签发工作负载证书。工作负载证书是短期证书,默认有效期为 24 小时,并在到期前自动轮转。证书的签发流程如下:Sidecar 启动时通过 SDS(Secret Discovery Service)向 istiod 请求证书 -> istiod 验证工作负载身份(通过 Kubernetes ServiceAccount Token)-> istiod 签发证书并通过 SDS 返回给 Sidecar -> Sidecar 将证书加载到 Envoy 的 TLS 上下文中。
这种自动化的证书管理消除了手动管理证书的复杂性。证书的生命周期完全由 Istio 控制,包括签发、分发、轮转和吊销。即使根 CA 被泄露,由于工作负载证书的短期性质,攻击窗口也非常有限。Istio 还支持与外部 CA 集成(如 Vault、Cert-Manager),满足企业对证书管理的特定合规要求。
2.3 PeerAuthentication:传输层安全策略
PeerAuthentication 定义了网格中工作负载之间的传输层安全策略。它控制是否要求 mTLS 通信,有三个模式:STRICT(严格模式,只接受 mTLS 连接)、PERMISSIVE(许可模式,同时接受 mTLS 和明文连接)和 DISABLE(禁用模式,只接受明文连接)。
PeerAuthentication 可以在三个层级配置:网格级别(作用于整个网格)、命名空间级别(作用于命名空间内所有工作负载)和工作负载级别(作用于特定工作负载)。更细粒度的配置会覆盖更粗粒度的配置。在从明文迁移到 mTLS 的过程中,推荐的策略是:首先在全网格设置 PERMISSIVE 模式,确保所有 Sidecar 都能处理两种连接类型;然后逐步将各个服务切换到 STRICT 模式;最后在全网格启用 STRICT 模式。
PERMISSIVE 模式在迁移期间非常重要。当部分服务还没有 Sidecar(如遗留系统或外部服务)时,STRICT 模式会导致这些服务无法通信。PERMISSIVE 模式允许 Sidecar 同时接受 mTLS 和明文连接,确保迁移过程中的兼容性。但需要注意,PERMISSIVE 模式降低了安全性,因为明文连接仍然存在被窃听和篡改的风险。
2.4 AuthorizationPolicy:细粒度访问控制
AuthorizationPolicy 实现了基于身份的细粒度访问控制,是 Istio 安全体系的核心组件。与网络层的 ACL(基于 IP 地址)不同,AuthorizationPolicy 基于工作负载身份进行控制,更加灵活和安全。即使 Pod 的 IP 地址发生变化,只要身份不变,访问控制策略就继续有效。
AuthorizationPolicy 支持三种操作模式:ALLOW(白名单模式,只允许匹配的请求通过)、DENY(黑名单模式,拒绝匹配的请求)和 CUSTOM(自定义模式,将授权决策委托给外部授权服务)。策略的匹配维度包括:source.principal(请求方身份)、source.namespace(请求方命名空间)、request.method(HTTP 方法)、request.path(请求路径)、request.headers(请求头)等。
策略的评估顺序为:DENY 策略优先于 ALLOW 策略。如果任何 DENY 策略匹配,请求立即被拒绝;如果没有 DENY 策略匹配,则检查 ALLOW 策略——如果存在 ALLOW 策略但都不匹配,请求被拒绝;如果没有定义任何 ALLOW 策略,请求默认被允许。理解这个评估顺序对于正确配置访问控制至关重要。
2.5 RequestAuthentication 与 JWT 认证
RequestAuthentication 定义了终端用户级别的认证机制,主要用于 JWT(JSON Web Token)验证。与 PeerAuthentication 处理服务间认证不同,RequestAuthentication 处理的是来自客户端(用户或外部系统)的请求认证。
当配置了 JWT 认证后,Istio 的 Ingress Gateway 或 Sidecar 会验证请求中的 JWT Token:检查签名是否有效、Token 是否过期、Issuer 是否匹配。验证通过后,JWT 中的声明(Claims)会被提取并作为请求头传递给后端服务。后端服务可以通过这些 Header 获取用户身份信息,而无需自行解析 JWT。
RequestAuthentication 只负责认证(验证身份),不负责授权(控制访问权限)。授权需要通过 AuthorizationPolicy 配合使用,通过 request.auth.claims 字段引用 JWT 中的声明进行访问控制。例如,可以配置"只有 role=admin 的用户才能访问 /admin 路径"。
三、深入分析与讨论
3.1 mTLS 性能影响与优化
mTLS 引入了额外的 TLS 握手开销,但在 Istio 的优化下,实际影响远小于预期。Envoy 支持 TLS Session Resumption,对于同一客户端和服务端的后续连接,可以跳过完整的 TLS 握手,将延迟从约 10ms 降低到约 1ms。此外,Envoy 维护了连接池,多个请求可以复用同一个 mTLS 连接,进一步摊薄握手开销。
在实际测试中,mTLS 对请求延迟的影响通常在 1-3ms 范围内,对于绝大多数业务场景可以忽略。如果确实对延迟非常敏感(如高频交易系统),可以通过调整连接池参数(增大最大连接数、延长连接存活时间)来减少握手频率。Istio 的 Ambient Mesh 模式也在探索更高效的加密方案,通过节点级的加密代理减少 per-Pod 的开销。
3.2 零信任安全模型的实践路径
零信任(Zero Trust)安全模型的核心原则是"永不信任,始终验证"。在传统的网络模型中,内部网络被认为是安全的,一旦进入内网就可以自由访问。零信任模型打破了这种假设,要求每一次访问都经过认证和授权,无论访问来自内部还是外部。
Istio 为实现零信任提供了完整的技术基础:mTLS 确保所有通信都经过加密和身份验证,消除了"内部网络可信"的假设;基于身份的授权策略实现了最小权限原则,每个服务只能访问其需要的资源;短期证书和自动轮转减少了凭证泄露的风险窗口。实施零信任的推荐路径是:首先启用全网格 mTLS(STRICT 模式),建立加密通信基线;然后逐步添加 AuthorizationPolicy,从最关键的 service 开始,逐步收紧访问控制;最后结合外部认证(JWT)实现终端用户级别的身份验证和授权。
3.3 安全策略的调试与排错
安全策略配置错误是 Istio 使用中最常见的问题之一。排查 mTLS 问题可以从以下几个方面入手:使用 istioctl authn tls-check 检查两个服务之间的 TLS 状态;使用 istioctl proxy-config secret 查看 Sidecar 的证书状态;检查 PeerAuthentication 策略的层级覆盖关系。
排查授权问题可以使用 istioctl authorize 命令查看生效的授权策略。Envoy 的访问日志中包含了授权决策的详细信息(allowed/denied),可以帮助定位具体的策略匹配情况。当使用 CUSTOM 授权模式时,还需要检查外部授权服务的可用性和响应时间。
四、实践案例
4.1 渐进式 mTLS 迁移
某企业在已有 100+ 微服务的集群中实施 mTLS 迁移。迁移分为四个阶段:第一阶段,在全网格配置 PERMISSIVE 模式的 PeerAuthentication,同时通过 Prometheus 监控 mTLS 流量占比;第二阶段,确认所有服务都已注入 Sidecar 后,将非关键服务逐步切换到 STRICT 模式,观察服务通信是否正常;第三阶段,将所有服务切换到 STRICT 模式,mTLS 流量占比达到 100%;第四阶段,在全网格级别配置 STRICT 模式,并通过 AuthorizationPolicy 实施最小权限访问控制。整个迁移过程历时三周,未出现服务中断。
4.2 基于 JWT 的多租户访问控制
某 SaaS 平台使用 Istio 实现了多租户的访问控制。终端用户的 JWT Token 中包含 tenant_id 和 role 两个关键声明。通过 RequestAuthentication 在 Ingress Gateway 验证 JWT 签名和有效期。通过 AuthorizationPolicy 实现多层访问控制:基于 role 声明控制功能权限(admin 可以访问管理接口,user 只能访问普通接口);基于 tenant_id 声明控制数据隔离(每个租户只能访问自己的数据端点)。这种方案将认证和授权逻辑从应用代码中剥离,由基础设施层统一处理,简化了应用开发并确保策略的一致性。
五、常见误区与注意事项
误区:开启 mTLS 后就不需要应用层的认证。mTLS 认证的是服务身份(ServiceAccount),而非终端用户。一个服务的所有用户共享同一个服务身份。终端用户的认证和授权仍然需要通过 RequestAuthentication 和 AuthorizationPolicy 实现。
误区:PERMISSIVE 模式和 STRICT 模式可以随意切换。从 STRICT 切换到 PERMISSIVE 是安全的(放宽限制),但从 PERMISSIVE 切换到 STRICT 前必须确保所有客户端都已经配置了 Sidecar,否则没有 Sidecar 的服务将无法通信。
注意事项:AuthorizationPolicy 的默认行为。如果一个命名空间中没有定义任何 ALLOW 策略,该命名空间的所有服务默认允许所有请求。这意味着"忘记配置策略"和"配置了开放策略"的效果相同。建议在关键服务上始终配置明确的 ALLOW 策略。
注意事项:source.namespace 的局限性。source.namespace 匹配的是请求方 Pod 所在的命名空间,而非 ServiceAccount 的命名空间。在某些场景下(如跨命名空间共享 ServiceAccount),这个区别可能导致策略不符合预期。
注意事项:证书轮转的时间窗口。工作负载证书默认每 24 小时轮转一次。如果 istiod 不可用超过证书有效期,Sidecar 将无法获取新证书,导致 mTLS 通信失败。建议监控 istiod 的可用性,并确保证书轮转的告警阈值合理。
六、本章小结
本章深入介绍了 Istio 的安全体系。工作负载身份基于 SPIFFE 标准和 Kubernetes ServiceAccount,为每个 Pod 提供唯一且可验证的身份标识。mTLS 通过自动化的证书管理实现了服务间的加密和认证通信,PeerAuthentication 策略控制 mTLS 的强制程度。AuthorizationPolicy 提供了基于身份的细粒度访问控制,支持 ALLOW、DENY 和 CUSTOM 三种模式。RequestAuthentication 处理终端用户级别的 JWT 认证。
Istio 的安全能力以透明的方式提供,不需要修改应用代码,也不需要应用感知安全基础设施的存在。这种设计使得安全成为基础设施的基本保障,而非开发团队的额外负担。在实际应用中,安全策略的实施应该是渐进式的,从 mTLS 开始,逐步收紧访问控制,最终实现零信任安全模型。
七、思考题与练习
解释 SPIFFE 标准的核心概念,并说明 Istio 如何利用 Kubernetes ServiceAccount 实现工作负载身份。
描述 Istio 中 mTLS 证书的完整生命周期:从签发到轮转到吊销,涉及哪些组件?
设计一个 mTLS 迁移方案:一个有 50 个服务的集群,其中 10 个是遗留系统(无法注入 Sidecar)。如何确保迁移过程中服务不中断?
配置一个 AuthorizationPolicy,实现以下需求:只允许 frontend 命名空间的 service account "web-app" 访问 backend 服务的 /api/v1/* 路径,且只允许 GET 和 POST 方法。
对比 PeerAuthentication 和 RequestAuthentication 的区别,说明它们各自解决什么层面的安全问题。
分析零信任安全模型与传统边界安全模型的区别,并描述在 Istio 中实施零信任的具体步骤。
排查场景:服务 A 无法通过 mTLS 访问服务 B,返回 503 错误。请描述排查步骤和可能的原因。
设计一个多租户安全方案:使用 JWT 认证实现租户隔离,不同租户只能访问各自的 API 端点。