配置聚合层

配置 聚合层 允许 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 证书匹配。
    • 具有允许的 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 选项(用于授权控制平面组件和最终用户)和 --requestheader-client-ca-file 选项(用于授权聚合 apiserver 请求)使用不同的 CA 证书。

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

--enable-aggregator-routing=true

注册 APIService 对象

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


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 对象的名称必须是有效的路径段名称.

联系扩展 apiserver

一旦 Kubernetes apiserver 确定一个请求应该发送到扩展 apiserver,它需要知道如何联系它。

service 部分是对扩展 apiserver 服务的引用。服务命名空间和名称是必需的。端口是可选的,默认值为 443。

以下是一个配置为在端口“1234”上调用的扩展 apiserver 的示例,它使用自定义 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:修复过时的链接/锚点 (bcc55ae7c9)