Kubernetes TLS Bootstrapping 机制详解
概述
在 Kubernetes 集群中,工作节点上的组件(kubelet 和 kube-proxy)需要与控制平面组件(特别是 kube-apiserver)进行通信。为了确保通信的私密性、防止干扰,并验证集群组件间的相互信任,我们强烈建议在节点上使用客户端 TLS 证书。
传统的工作节点组件引导过程,特别是需要证书才能安全与 kube-apiserver 通信的工作节点,往往是一个具有挑战性的过程,因为它通常超出了 Kubernetes 的范围,需要大量额外工作。这使得集群的初始化和扩展变得困难。
为了简化这一过程,Kubernetes 从 1.4 版本开始引入了证书请求和签名 API。本文将详细介绍节点初始化过程,如何为 kubelet 设置 TLS 客户端证书引导,以及其工作原理。
节点初始化过程
当工作节点启动时,kubelet 会执行以下步骤:
- 查找其
kubeconfig文件 - 从
kubeconfig文件中检索 API 服务器的 URL 和凭据(通常是 TLS 密钥和签名证书) - 尝试使用凭据与 API 服务器通信
如果 kube-apiserver 成功验证 kubelet 的凭据,它会将 kubelet 视为有效节点,并开始向其分配 Pod。
传统证书管理流程
传统证书管理流程依赖于:
- 本地主机上
kubeconfig中存在密钥和证书 - 证书由 kube-apiserver 信任的证书颁发机构 (CA) 签名
集群设置和管理人员需要负责以下工作:
- 创建 CA 密钥和证书
- 将 CA 证书分发到运行 kube-apiserver 的控制平面节点
- 为每个 kubelet 创建密钥和证书(强烈建议为每个 kubelet 使用唯一的 CN)
- 使用 CA 密钥签署 kubelet 证书
- 将 kubelet 密钥和签名证书分发到运行 kubelet 的特定节点
本文描述的 TLS 引导旨在简化并部分或完全自动化步骤 3 及以后的流程,因为这些步骤在初始化或扩展集群时最常见。
引导初始化流程
在引导初始化过程中,会发生以下步骤:
- kubelet 启动
- kubelet 发现没有
kubeconfig文件 - kubelet 搜索并找到
bootstrap-kubeconfig文件 - kubelet 读取引导文件,检索 API 服务器的 URL 和有限用途的"令牌"
- kubelet 使用令牌连接到 API 服务器并进行身份验证
- kubelet 现在拥有有限的凭据来创建和检索证书签名请求 (CSR)
- kubelet 为自己创建一个 CSR,signerName 设置为
kubernetes.io/kube-apiserver-client-kubelet - CSR 通过以下两种方式之一获得批准:
- 如果配置了,kube-controller-manager 自动批准 CSR
- 如果配置了,外部流程(可能是人工)使用 Kubernetes API 或
kubectl批准 CSR
- 为 kubelet 创建证书
- 证书颁发给 kubelet
- kubelet 检索证书
- kubelet 使用密钥和签名证书创建适当的
kubeconfig - kubelet 开始正常操作
- 可选:如果配置了,kubelet 在证书接近到期时自动请求续订
- 根据配置,续订的证书被自动或手动批准和颁发
配置要求
要配置 TLS 引导和可选的自动批准,您需要配置以下组件:
- kube-apiserver
- kube-controller-manager
- kubelet
- 集群内资源:
ClusterRoleBinding和可能的ClusterRole
此外,您还需要 Kubernetes 证书颁发机构 (CA)。
证书颁发机构 (CA)
与不使用引导时一样,您需要 CA 密钥和证书。这些将用于签署 kubelet 证书。与之前一样,您有责任将它们分发到控制平面节点。
kube-apiserver 配置
kube-apiserver 需要满足以下要求才能启用 TLS 引导:
- 识别签署客户端证书的 CA
- 将引导 kubelet 认证到
system:bootstrappers组 - 授权引导 kubelet 创建证书签名请求 (CSR)
识别客户端证书
这是所有客户端证书认证的正常要求。如果尚未设置,请将 --client-ca-file=FILENAME 标志添加到 kube-apiserver 命令以启用客户端证书认证,引用包含签名证书的证书颁发机构包,例如 --client-ca-file=/var/lib/kubernetes/ca.pem。
初始引导认证
为了使引导 kubelet 能够连接到 kube-apiserver 并请求证书,它必须首先向服务器进行身份验证。您可以使用任何可以认证 kubelet 的认证器。
虽然任何认证策略都可以用于 kubelet 的初始引导凭据,但建议使用以下两种认证器以便于配置:
- 引导令牌 (Bootstrap Tokens)
- 令牌认证文件 (Token authentication file)
使用引导令牌是一种更简单且更易于管理的方法来认证 kubelet,并且在启动 kube-apiserver 时不需要任何额外的标志。
无论您选择哪种方法,要求是 kubelet 能够作为具有以下权限的用户进行身份验证:
- 创建和检索 CSR
- 如果启用了自动批准,则自动批准请求节点客户端证书
使用引导令牌进行身份验证的 kubelet 作为 system:bootstrappers 组中的用户进行身份验证,这是标准使用方法。
授权 kubelet 创建 CSR
现在引导节点已作为 system:bootstrappers 组的一部分进行身份验证,它需要被授权创建证书签名请求 (CSR) 并在完成后检索它。幸运的是,Kubernetes 附带了一个 ClusterRole,具有这些(且仅这些)权限,即 system:node-bootstrapper。
为此,您只需要创建一个 ClusterRoleBinding,将 system:bootstrappers 组绑定到集群角色 system:node-bootstrapper。
kube-controller-manager 配置
虽然 apiserver 接收来自 kubelet 的证书请求并验证这些请求,但 controller-manager 负责颁发实际的签名证书。
controller-manager 通过证书颁发控制循环执行此功能。这采用 cfssl 本地签名器的形式,使用磁盘上的资产。目前,所有颁发的证书都具有一年的有效期和一组默认的密钥用法。
为了使 controller-manager 能够签署证书,它需要以下内容:
- 访问您创建和分发的"Kubernetes CA 密钥和证书"
- 启用 CSR 签名
访问密钥和证书
如前所述,您需要创建 Kubernetes CA 密钥和证书,并将它们分发到控制平面节点。这些将由 controller-manager 用于签署 kubelet 证书。
由于这些签名证书将依次由 kubelet 用作常规 kubelet 向 kube-apiserver 进行身份验证,因此在此阶段提供给 controller-manager 的 CA 也必须被 kube-apiserver 信任以进行身份验证。这是通过 --client-ca-file=FILENAME 标志提供给 kube-apiserver 的(例如 --client-ca-file=/var/lib/kubernetes/ca.pem),如 kube-apiserver 配置部分所述。
要向 kube-controller-manager 提供 Kubernetes CA 密钥和证书,请使用以下标志:
--cluster-signing-cert-file="/var/lib/kubernetes/ca.pem" --cluster-signing-key-file="/var/lib/kubernetes/ca-key.pem"
可以使用以下标志配置签名证书的有效期:
--cluster-signing-duration
批准
为了批准 CSR,您需要告诉 controller-manager 可以批准它们。这是通过向正确的组授予 RBAC 权限来完成的。
有两组不同的权限:
nodeclient:如果节点正在为节点创建新证书,那么它还没有证书。它使用上面列出的令牌之一进行身份验证,因此是system:bootstrappers组的一部分。selfnodeclient:如果节点正在续订其证书,那么它已经有一个证书(根据定义),它使用该证书持续作为system:nodes组的一部分进行身份验证。
kubelet 配置
最后,在正确设置控制平面节点并建立所有必要的认证和授权后,我们可以配置 kubelet。
kubelet 需要以下配置来引导:
- 存储生成的密钥和证书的路径(可选,可以使用默认值)
- 尚不存在的
kubeconfig文件的路径;它将把引导的配置文件放在这里 - 引导
kubeconfig文件的路径,以提供服务器的 URL 和引导凭据,例如引导令牌 - 可选:轮换证书的指令
引导 kubeconfig 应该位于 kubelet 可访问的路径中,例如 /var/lib/kubelet/bootstrap-kubeconfig。
要指示 kubelet 使用引导 kubeconfig,请使用以下 kubelet 标志:
--bootstrap-kubeconfig="/var/lib/kubelet/bootstrap-kubeconfig" --kubeconfig="/var/lib/kubelet/kubeconfig"
启动 kubelet 时,如果通过 --kubeconfig 指定的文件不存在,则使用通过 --bootstrap-kubeconfig 指定的引导 kubeconfig 向 API 服务器请求客户端证书。在批准证书请求并由 kubelet 接收后,将生成引用生成的密钥和获得的证书的 kubeconfig 文件写入 --kubeconfig 指定的路径。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



