2. API Server 请求流程:认证、鉴权、准入控制三个阶段详解

Kubernetes API Server 是集群所有操作的唯一入口。任何对集群状态的查询或变更请求,在到达 etcd 持久化存储之前,都必须依次通过三个严格的拦截阶段:认证(Authentication)、鉴权(Authorization) 和 准入控制(Admission Control)。理解这三个阶段的职责、顺序和交互方式,是构建安全、可靠的后端服务的基础。

核心原则:三个阶段按顺序执行,前一个阶段失败则请求立即被拒绝,不会进入后续阶段。这种“漏斗式”设计确保了安全策略的层层收紧。

2.1 三阶段总览与职责划分

下表清晰对比了三个阶段的核心职责、输入输出与典型组件:

阶段 核心职责 输入 输出 典型组件
认证 验证“你是谁?” HTTP 请求(证书、Token、Basic Auth) 用户名、UID、用户组 X.509 证书、Service Account、OIDC、Webhook Token
鉴权 验证“你能做什么?” 用户身份 + 请求动作(资源、命名空间、操作) 允许 / 拒绝 RBAC、ABAC、Node Authorization、Webhook
准入控制 验证“请求是否符合集群策略?” 经过鉴权的请求对象 修改 / 拒绝 / 通过 MutatingWebhookConfiguration、ValidatingWebhookConfiguration、内置插件(如 NamespaceLifecycle)
关键区别:认证关注身份,鉴权关注权限,准入控制关注策略合规性。准入控制是唯一可以修改(Mutate)请求对象的阶段。

2.2 第一阶段:认证(Authentication)

认证阶段是请求进入 API Server 的第一道防线。API Server 会依次尝试配置的所有认证模块,只要有一个模块认证成功,请求即进入下一阶段。如果所有模块都认证失败,则返回 401 Unauthorized 错误。

常见的认证方式包括:

  • X.509 客户端证书: 通过 TLS 握手时提供的客户端证书中的 CN(Common Name)和 O(Organization)字段提取用户名和组。这是最常用的组件间认证方式。
  • Service Account Token: Pod 内挂载的 JWT Token,用于 Pod 与 API Server 交互。Token 中包含了 Service Account 的身份信息。
  • 静态 Token / 密码文件: 通过 CSV 文件预定义 Token 或密码与用户的映射关系,适用于测试或简单场景。
  • OpenID Connect (OIDC): 集成外部身份提供商(如 Keycloak、Azure AD),实现单点登录。
  • Webhook Token 认证: 将 Token 验证委托给外部认证服务。
常见错误处理:当认证失败时,API Server 不会明确告知是哪个模块失败,只会返回 401 状态码和 Unauthorized 消息。后端服务在捕获 401 错误时,应检查客户端证书是否过期、Token 是否有效或是否被吊销。

2.3 第二阶段:鉴权(Authorization)

请求通过认证后,API Server 会提取用户的身份信息(用户名、组、UID),并连同请求的详细信息(资源类型、命名空间、操作动词)发送给鉴权模块。鉴权模块决定该用户是否有权限执行该操作。

Kubernetes 支持多种鉴权模式,通常以 RBAC(基于角色的访问控制) 为主:

  • RBAC: 通过 Role / ClusterRole 定义权限集合,再通过 RoleBinding / ClusterRoleBinding 将角色绑定到用户或组。这是生产环境的标准选择。
  • ABAC(基于属性的访问控制): 通过 JSON 策略文件定义权限,灵活性高但管理复杂,已逐渐被 RBAC 取代。
  • Node Authorization: 专门为 kubelet 设计的鉴权模式,允许节点访问其自身相关的资源。
  • Webhook: 将鉴权决策委托给外部服务,适用于自定义复杂的鉴权逻辑。

鉴权失败时,API Server 返回 403 Forbidden 错误,并在响应体中包含详细的拒绝原因,例如 User "system:serviceaccount:default:my-sa" cannot list resource "pods" in API group "" in the namespace "default"。

后端实践:在开发后端服务时,应始终使用最小权限原则创建 Service Account,并通过 RBAC 精确绑定所需权限。当捕获 403 错误时,应记录详细的错误信息,用于审计和权限调整。

2.4 第三阶段:准入控制(Admission Control)

准入控制是请求到达 etcd 前的最后一道关卡。它由一系列准入控制器(Admission Controller) 组成,这些控制器可以验证(Validating) 或修改(Mutating) 请求对象。Mutating 控制器先执行,Validating 控制器后执行。

准入控制器的类型:

  • 内置准入控制器: 如 NamespaceLifecycle(防止在删除中的命名空间创建资源)、LimitRanger(设置默认资源限制)、ResourceQuota(强制执行资源配额)。
  • 动态准入控制(Webhook): 通过 MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration 将请求发送到外部 HTTP 服务进行处理。这是实现自定义策略(如镜像签名验证、Sidecar 注入)的核心机制。

准入控制失败时,API Server 返回 403 Forbidden 或 422 Unprocessable Entity,具体取决于控制器返回的错误类型。响应体中会包含控制器的名称和拒绝原因。

性能考量:动态准入 Webhook 会引入额外的网络延迟。如果 Webhook 服务不可用,默认行为是拒绝所有请求(fail-closed)。后端服务应确保 Webhook 服务的高可用性,并设置合理的超时时间(默认 30 秒)。

2.5 完整请求流程 SVG 图

下图展示了 API Server 处理一个 kubectl create pod 请求的完整三阶段流程:

API Server 请求三阶段流程 API Server 请求三阶段流程(以创建 Pod 为例) 第一阶段:认证 验证客户端身份 证书 / Token / OIDC 第二阶段:鉴权 检查用户权限 RBAC / ABAC / Webhook 第三阶段:准入控制 策略检查与修改 Mutating / Validating 认证失败 返回 401 Unauthorized 鉴权失败 返回 403 Forbidden 准入控制失败 返回 403 / 422 请求通过 写入 etcd 说明: 1. 三个阶段按顺序执行,前一个失败则立即返回。 2. 认证失败返回 401,鉴权和准入控制失败返回 403/422。 3. 准入控制是唯一可以修改请求对象的阶段。 4. 动态准入 Webhook 的可用性直接影响集群稳定性。

2.6 错误处理与接口调用实践

后端服务在调用 API Server 时,必须根据不同的 HTTP 状态码采取相应的处理策略:

HTTP 状态码 失败阶段 典型原因 后端处理建议
401 Unauthorized 认证 Token 过期、证书无效、Token 被吊销 刷新 Token 或重新获取客户端证书;记录审计日志
403 Forbidden 鉴权 / 准入控制 RBAC 权限不足、资源配额超限、Webhook 拒绝 检查 Service Account 权限;查看 Webhook 日志;调整资源配额
422 Unprocessable Entity 准入控制 ValidatingWebhook 拒绝(如镜像签名验证失败) 解析响应体中的 message 字段,获取具体拒绝原因
429 Too Many Requests API Server 流控 请求速率超过 API Server 配置的 QPS 限制 实现指数退避重试机制;增加客户端 QPS 配置
代码示例:使用 Go 客户端处理 API Server 错误时,应使用 errors.IsForbidden()、errors.IsUnauthorized() 等工具函数进行类型判断,而不是直接比较状态码字符串。
import (
    "k8s.io/apimachinery/pkg/api/errors"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// 创建 Pod 并处理错误
pod, err := clientset.CoreV1().Pods("default").Create(ctx, podObj, metav1.CreateOptions{})
if err != nil {
    if errors.IsUnauthorized(err) {
        // 处理认证失败:刷新 Token
    } else if errors.IsForbidden(err) {
        // 处理鉴权或准入控制失败:记录详细错误
        log.Printf("Forbidden: %v", err)
    } else if errors.IsTooManyRequests(err) {
        // 处理限流:等待后重试
        time.Sleep(time.Duration(1) * time.Second)
    } else {
        // 处理其他错误
    }
}

2.7 三阶段交互细节 SVG 图

下图展示了认证、鉴权、准入控制三个阶段内部更详细的交互流程,包括多认证模块的尝试顺序和动态准入 Webhook 的调用:

三阶段内部交互细节 三阶段内部交互细节 客户端请求 认证模块链 X.509 证书认证 Service Account Token Webhook Token 认证 鉴权模块 RBAC 策略评估 返回 Allow/Deny 准入控制链 Mutating Webhook Validating Webhook 内置控制器 写入 etcd 认证失败:返回 401 鉴权失败:返回 403 关键交互细节: 1. 认证模块按配置顺序依次尝试,任一成功即停止后续模块。 2. 准入控制中,Mutating Webhook 先于 Validating Webhook 执行,内置控制器最后执行。

2.7 总结

API Server 的三阶段请求处理流程是 Kubernetes 安全架构的基石。后端开发人员必须深刻理解每个阶段的职责、失败时的错误码以及对应的处理策略。在实际开发中,应充分利用 RBAC 的最小权限原则、合理配置动态准入 Webhook,并在代码中实现健壮的错误重试和日志记录机制,以确保后端服务与 Kubernetes 集群的稳定、安全交互。