配置聚合层

配置 聚合层 允许 Kubernetes apiserver 通过额外的 API 进行扩展,这些 API 不属于核心 Kubernetes API。

开始之前

您需要有一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与您的集群通信。建议在至少有两个节点的集群上运行本教程,这些节点不充当控制平面主机。如果您还没有集群,可以使用 minikube 创建一个,或者您可以使用以下 Kubernetes 游乐场之一

要检查版本,请输入 kubectl version

身份验证流程

与自定义资源定义 (CRD) 不同,聚合 API 除了标准 Kubernetes apiserver 之外,还涉及另一个服务器 - 您的扩展 apiserver。Kubernetes apiserver 需要与您的扩展 apiserver 通信,而您的扩展 apiserver 需要与 Kubernetes apiserver 通信。为了确保这种通信安全,Kubernetes apiserver 使用 x509 证书来向扩展 apiserver 身份验证自身。

本节介绍身份验证和授权流程的工作原理以及如何配置它们。

高级流程如下

  1. Kubernetes apiserver:验证请求用户的身份并授权其对请求的 API 路径的权限。
  2. Kubernetes apiserver:将请求代理到扩展 apiserver
  3. 扩展 apiserver:验证来自 Kubernetes apiserver 的请求
  4. 扩展 apiserver:授权来自原始用户的请求
  5. 扩展 apiserver:执行

本节的其余部分详细介绍了这些步骤。

下图显示了该流程。

aggregation auth flows

上述泳道的源代码可以在本文档的源代码中找到。

Kubernetes Apiserver 身份验证和授权

对由扩展 apiserver 提供服务的 API 路径的请求以与所有 API 请求相同的方式开始:与 Kubernetes apiserver 通信。该路径已由扩展 apiserver 注册到 Kubernetes apiserver。

用户与 Kubernetes apiserver 通信,请求访问该路径。Kubernetes apiserver 使用与 Kubernetes apiserver 配置的标准身份验证和授权来验证用户的身份并授权访问特定路径。

有关向 Kubernetes 集群进行身份验证的概述,请参阅 "向集群进行身份验证"。有关授权访问 Kubernetes 集群资源的概述,请参阅 "授权概述"

到目前为止,所有操作都是标准的 Kubernetes API 请求、身份验证和授权。

Kubernetes apiserver 现在已准备好将请求发送到扩展 apiserver。

Kubernetes Apiserver 代理请求

Kubernetes apiserver 现在将发送或代理请求到注册处理该请求的扩展 apiserver。为此,它需要了解以下几点

  1. Kubernetes apiserver 如何向扩展 apiserver 进行身份验证,告知扩展 apiserver 请求(通过网络到达)来自有效的 Kubernetes apiserver?
  2. Kubernetes apiserver 如何告知扩展 apiserver 原始请求验证的用户名和组?

为了提供这两种功能,您必须使用几个标志配置 Kubernetes apiserver。

Kubernetes Apiserver 客户端身份验证

Kubernetes apiserver 通过 TLS 连接到扩展 apiserver,使用客户端证书进行身份验证。您必须在启动时使用提供的标志向 Kubernetes apiserver 提供以下内容

  • 通过 --proxy-client-key-file 提供私钥文件
  • 通过 --proxy-client-cert-file 提供签名的客户端证书文件
  • 通过 --requestheader-client-ca-file 提供签署客户端证书文件的 CA 的证书
  • 通过 --requestheader-allowed-names 提供签名的客户端证书中的有效通用名称值 (CN)

Kubernetes apiserver 将使用 --proxy-client-*-file 指示的文件向扩展 apiserver 进行身份验证。为了使请求被符合标准的扩展 apiserver 视为有效请求,必须满足以下条件

  1. 连接必须使用由 CA 签署的客户端证书建立,该 CA 的证书位于 --requestheader-client-ca-file 中。
  2. 连接必须使用客户端证书建立,该证书的 CN 位于 --requestheader-allowed-names 中列出的名称之一。

使用这些选项启动时,Kubernetes apiserver 将

  1. 使用它们向扩展 apiserver 进行身份验证。
  2. kube-system 命名空间中创建一个名为 extension-apiserver-authentication 的配置映射,其中它将放置 CA 证书和允许的 CN。扩展 apiserver 可以检索这些内容来验证请求。

请注意,Kubernetes apiserver 使用相同的客户端证书向所有扩展 apiserver 进行身份验证。它不会为每个扩展 apiserver 创建一个客户端证书,而是创建一个证书来作为 Kubernetes apiserver 进行身份验证。此证书将被重复用于所有扩展 apiserver 请求。

原始请求用户名和组

当 Kubernetes apiserver 将请求代理到扩展 apiserver 时,它会告知扩展 apiserver 原始请求成功验证的用户名和组。它在代理请求的 http 标头中提供这些信息。您必须告知 Kubernetes apiserver 要使用的标头名称。

  • 通过 --requestheader-username-headers 提供用于存储用户名的标头
  • 通过 --requestheader-group-headers 提供用于存储组的标头
  • 通过 --requestheader-extra-headers-prefix 提供要附加到所有额外标头的前缀

这些标头名称也放置在 extension-apiserver-authentication 配置映射中,因此扩展 apiserver 可以检索和使用它们。

扩展 Apiserver 验证请求

扩展 apiserver 在收到来自 Kubernetes apiserver 的代理请求后,必须验证该请求实际上来自有效的身份验证代理(Kubernetes apiserver 正在执行的角色)。扩展 apiserver 通过以下方式进行验证

  1. kube-system 中的配置映射中检索以下内容,如上所述
    • 客户端 CA 证书
    • 允许的名称 (CN) 列表
    • 用户名、组和额外信息的标头名称
  2. 检查 TLS 连接是否使用以下客户端证书进行身份验证
    • 由 CA 签署,该 CA 的证书与检索到的 CA 证书匹配。
    • 具有 CN,该 CN 位于允许的 CN 列表中,除非该列表为空,在这种情况下,所有 CN 都允许。
    • 从相应的标头中提取用户名和组

如果上述操作通过,则该请求是来自合法身份验证代理(在本例中为 Kubernetes apiserver)的有效代理请求。

请注意,提供上述内容是扩展 apiserver 实现的责任。许多扩展 apiserver 默认提供此功能,利用 k8s.io/apiserver/ 包。其他扩展 apiserver 可能提供使用命令行选项覆盖它的选项。

为了获得检索配置映射的权限,扩展 apiserver 需要相应的角色。在 kube-system 命名空间中有一个名为 extension-apiserver-authentication-reader 的默认角色,可以将其分配给扩展 apiserver。

扩展 Apiserver 授权请求

扩展 apiserver 现在可以验证从标头中检索到的用户/组是否有权执行给定的请求。它通过向 Kubernetes apiserver 发送标准的 SubjectAccessReview 请求来实现这一点。

为了使扩展 apiserver 本身有权向 Kubernetes apiserver 提交 SubjectAccessReview 请求,它需要正确的权限。Kubernetes 包含一个名为 system:auth-delegator 的默认 ClusterRole,它具有相应的权限。可以将其授予扩展 apiserver 的服务帐户。

扩展 Apiserver 执行

如果 SubjectAccessReview 通过,则扩展 apiserver 执行请求。

启用 Kubernetes Apiserver 标志

通过以下 kube-apiserver 标志启用聚合层。您的提供商可能已经处理了这些标志。

--requestheader-client-ca-file=<path to aggregator CA cert>
--requestheader-allowed-names=front-proxy-client
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--proxy-client-cert-file=<path to aggregator proxy cert>
--proxy-client-key-file=<path to aggregator proxy key>

CA 重复使用和冲突

Kubernetes apiserver 有两个客户端 CA 选项

  • --client-ca-file
  • --requestheader-client-ca-file

如果使用不当,这些选项将独立运行,并可能相互冲突。

  • --client-ca-file:当请求到达 Kubernetes apiserver 时,如果启用了此选项,Kubernetes apiserver 将检查请求的证书。如果它由 --client-ca-file 引用的文件中列出的 CA 证书之一签署,则该请求将被视为合法请求,用户为通用名称 CN= 的值,而组为组织 O=。请参阅有关 TLS 身份验证的文档
  • --requestheader-client-ca-file:当请求到达 Kubernetes apiserver 时,如果启用了此选项,Kubernetes apiserver 将检查请求的证书。如果它由 --requestheader-client-ca-file 引用的文件中列出的 CA 证书之一签署,则该请求将被视为潜在的合法请求。然后,Kubernetes apiserver 检查通用名称 CN= 是否为 --requestheader-allowed-names 提供的列表中的名称之一。如果名称允许,则批准该请求;如果名称不允许,则拒绝该请求。

如果同时提供了 --client-ca-file--requestheader-client-ca-file,则请求首先检查 --requestheader-client-ca-file CA,然后检查 --client-ca-file。通常,每个选项使用不同的 CA(根 CA 或中间 CA);常规客户端请求与 --client-ca-file 匹配,而聚合请求与 --requestheader-client-ca-file 匹配。但是,如果两者使用相同的 CA,则通常通过 --client-ca-file 传递的客户端请求将失败,因为 CA 将与 --requestheader-client-ca-file 中的 CA 匹配,但通用名称 CN= 不会--requestheader-allowed-names 中的可接受通用名称之一匹配。这会导致您的 kubelet 和其他控制平面组件以及最终用户无法向 Kubernetes apiserver 进行身份验证。

因此,请为--client-ca-file选项使用不同的 CA 证书来授权控制平面组件和最终用户,并为--requestheader-client-ca-file选项使用不同的 CA 证书来授权聚合 API 服务器请求。

如果您未在运行 API 服务器的主机上运行 kube-proxy,则必须确保系统已启用以下kube-apiserver标志

--enable-aggregator-routing=true

注册 APIService 对象

您可以动态配置哪些客户端请求被代理到扩展 API 服务器。以下是一个注册示例


apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: <name of the registration object>
spec:
  group: <API group name this extension apiserver hosts>
  version: <API version this extension apiserver hosts>
  groupPriorityMinimum: <priority this APIService for this group, see API documentation>
  versionPriority: <prioritizes ordering of this version within a group, see API documentation>
  service:
    namespace: <namespace of the extension apiserver service>
    name: <name of the extension apiserver service>
  caBundle: <pem encoded ca cert that signs the server cert used by the webhook>

APIService 对象的名称必须是有效的路径段名称

联系扩展 API 服务器

一旦 Kubernetes API 服务器确定请求应发送到扩展 API 服务器,它需要知道如何联系它。

service节是扩展 API 服务器服务的引用。服务命名空间和名称是必需的。端口是可选的,默认为 443。

以下是一个扩展 API 服务器的示例,它被配置为在端口“1234”上调用,并使用自定义 CA 捆绑包对 ServerName my-service-name.my-service-namespace.svc 验证 TLS 连接。

apiVersion: apiregistration.k8s.io/v1
kind: APIService
...
spec:
  ...
  service:
    namespace: my-service-namespace
    name: my-service-name
    port: 1234
  caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...

下一步

上次修改时间:2023 年 12 月 29 日下午 9:47 PST:修复过时的链接/锚点 (bcc55ae7c9)