🔄 使用kubectl设置kubelet证书自动续订 — 完全掌握基于ConfigMap的rotateCertificates

逐个节点SSH连接修改配置的时代已经结束。

用一个ConfigMap控制整个集群。

>

>

通过一个ConfigMap统一控制整个集群工作节点证书续订周期的叙事 — 犹如钟表匠同时同步数十个时钟(节点)的精确性。


🎯 本文涵盖内容

  • kube-system命名空间中kubelet-config ConfigMap的结构和作用
  • 通过修改ConfigMap应用rotateCertificates: true的完整流程
  • 如何将更改反映到工作节点的/var/lib/kubelet/config.yaml
  • 如何验证自动续订是否实际工作
  • 升级时配置被覆盖的问题及应对方法

📌 引言 / 背景

kubelet客户端证书通常具有1年的有效期。随着集群规模的扩大,逐个工作节点通过SSH连接修改/var/lib/kubelet/config.yaml的方式在现实中是不可行的。

使用kubeadm配置的集群已经具备解决此问题的结构。kubeadm在利用Bootstrap Token进行TLS引导过程中,会下载kubelet-config ConfigMap并将其写入/var/lib/kubelet/config.yaml。这意味着修改kube-system中的ConfigMap,并让每个节点下载并应用它,是官方支持的流程。

当设置rotateCertificates: true时,kubelet会在证书总生命周期的约70%~90%时自动提交CSR,kube-controller-manager会监控并使用集群CA密钥对其进行签名和批准,从而实现客户端证书的自动续订。


🔍 概念说明

ConfigMap与本地config.yaml的关系

在kubeadm集群中,kubelet配置存在于两个地方

位置 作用
kube-system/kubelet-config (ConfigMap) 集群范围标准配置 (单一事实来源)
/var/lib/kubelet/config.yaml (各节点) 节点上kubelet实际读取的配置文件

这两个文件不会自动同步。修改ConfigMap后,需要每个工作节点手动下载并应用。这是关键点。

ConfigMap中存储的配置与/var/lib/kubelet/config.yaml的内容不会自动同步。要永久保留节点本地设置,必须手动更新/var/lib/kubelet/config.yaml,或者在/var/lib/kubelet/kubeadm-flags.env中添加标志,并重启kubelet。

rotateCertificates的工作原理

如果kubelet配置为使用–bootstrap-kubeconfig标志进行引导,它会使用初始证书连接到Kubernetes API并提交CSR。如果CSR满足一定标准,controller-manager会自动批准,并使用–cluster-signing-duration参数指定的期限的证书进行签名,然后将其传递给kubelet。当到期时间临近时,kubelet会在剩余时间的30%~10%之间的某个时刻自动提交新的CSR。


💻 实践 / 示例代码

步骤 0. 检查当前状态

# 检查ConfigMap名称(名称格式可能因版本而异)
kubectl get configmap -n kube-system | grep kubelet

# Kubernetes 1.24+:kubelet-config
# 旧版本:kubelet-config-1.{minor} (例如: kubelet-config-1.27)
# 检查当前ConfigMap的全部内容
kubectl get configmap kubelet-config -n kube-system -o yaml

检查输出示例中的data.kubelet部分:

data:
  kubelet: |
    apiVersion: kubelet.config.k8s.io/v1beta1
    kind: KubeletConfiguration
    authentication:
      ...
    rotateCertificates: false   # ← 将此部分更改为true

步骤 1. 修改ConfigMap (在控制平面)

方法 A — kubectl edit (交互式编辑)

kubectl edit configmap kubelet-config -n kube-system

编辑器打开后,在data.kubelet块内部找到并修改rotateCertificates项。如果不存在,则直接添加。

# 修改前
rotateCertificates: false

# 修改后
rotateCertificates: true

保存并退出编辑器后,ConfigMap将立即更新。

方法 B — kubectl patch (适用于基于脚本的自动化)

# 提取当前kubelet配置
kubectl get configmap kubelet-config -n kube-system 
  -o jsonpath='{.data.kubelet}' > /tmp/kubelet-config-current.yaml

# 检查rotateCertificates项
grep rotateCertificates /tmp/kubelet-config-current.yaml
# 使用sed更改值(false → true,或在不存在时添加)
sed -i 's/rotateCertificates: false/rotateCertificates: true/' 
  /tmp/kubelet-config-current.yaml

# 如果完全缺少rotateCertificates项
grep -q 'rotateCertificates' /tmp/kubelet-config-current.yaml || 
  echo "rotateCertificates: true" >> /tmp/kubelet-config-current.yaml
# 将修改后的内容反映到ConfigMap
kubectl create configmap kubelet-config 
  -n kube-system 
  --from-file=kubelet=/tmp/kubelet-config-current.yaml 
  --dry-run=client -o yaml | kubectl apply -f -

步骤 2. 在工作节点上应用设置

即使ConfigMap被修改,工作节点上的kubelet也不会立即识别更改。每个工作节点都必须执行以下步骤。

方法 A — 使用kubeadm upgrade node (推荐)

# 在工作节点上运行(SSH连接后)
sudo kubeadm upgrade node phase kubelet-config

# 重启kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

kubeadm upgrade node phase kubelet-config命令会下载集群中存储的kubelet-config ConfigMap,并升级该节点上的kubelet配置。

方法 B — 直接下载并替换ConfigMap

# 在工作节点上运行(需要可访问kubectl的环境)

# 从ConfigMap中提取kubelet配置
kubectl get configmap kubelet-config -n kube-system 
  -o jsonpath='{.data.kubelet}' > /tmp/kubelet-config-new.yaml

# 备份现有配置
sudo cp /var/lib/kubelet/config.yaml 
  /var/lib/kubelet/config.yaml.bak.$(date +%Y%m%d)

# 应用新设置
sudo cp /tmp/kubelet-config-new.yaml /var/lib/kubelet/config.yaml

# 确认应用
grep rotateCertificates /var/lib/kubelet/config.yaml
# 重启kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 检查重启状态
sudo systemctl status kubelet

步骤 3. 批量应用于多个节点 (脚本)

如果节点数量较多,可以使用以下脚本进行批量处理。

#!/bin/bash
# apply-kubelet-rotate.sh
# 批量应用于所有工作节点的rotateCertificates设置

WORKER_NODES=$(kubectl get nodes 
  --selector='!node-role.kubernetes.io/control-plane' 
  -o jsonpath='{.items[*].metadata.name}')

for NODE in $WORKER_NODES; do
  echo "=== 처리 중: $NODE ==="

  # 1. 下载最新的ConfigMap设置
  ssh $NODE "sudo kubeadm upgrade node phase kubelet-config"

  # 2. 重启kubelet
  ssh $NODE "sudo systemctl daemon-reload && sudo systemctl restart kubelet"

  # 3. 检查应用结果
  ssh $NODE "grep rotateCertificates /var/lib/kubelet/config.yaml"

  echo "=== $NODE 완료 ==="
  sleep 3  # 节点间间隔
done

echo "전체 완료"
chmod +x apply-kubelet-rotate.sh
./apply-kubelet-rotate.sh

步骤 4. 验证自动续订操作

# 检查rotateCertificates是否启用(在每个节点上)
sudo grep rotateCertificates /var/lib/kubelet/config.yaml

# 检查当前证书的到期日期
sudo openssl x509 
  -in /var/lib/kubelet/pki/kubelet-client-current.pem 
  -noout -enddate

# 在kubelet日志中检查证书续订尝试
sudo journalctl -u kubelet --since "1 hour ago" | grep -i rotate
sudo journalctl -u kubelet --since "1 hour ago" | grep -i certificate
# 在CSR列表中检查自动提交的请求(在控制平面上)
kubectl get csr | grep "system:node"

# 输出示例 — 如果状态为Approved,Issued则正常
# NAME        SIGNERNAME                               REQUESTOR                CONDITION
# csr-abc12   kubernetes.io/kube-apiserver-client-kubelet  system:node:worker-1   Approved,Issued
# 实时验证实际应用的kubelet设置(利用API代理)
kubectl proxy &
curl -s http://127.0.0.1:8001/api/v1/nodes/<노드명>/proxy/configz | 
  python3 -m json.tool | grep rotateCertificates

步骤 5. RBAC — 检查自动批准的前提条件

仅有rotateCertificates: true是不够的。节点组必须具有自动批准CSR的RBAC权限。

# 检查客户端证书自动续订权限
kubectl get clusterrolebinding | grep "auto-approve"
kubectl get clusterrolebinding | grep "node-client"

如果没有,请使用以下命令创建:

# 授予节点组客户端证书自动续订权限
kubectl create clusterrolebinding auto-approve-renewals 
  --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 
  --group=system:nodes

⚠️ 注意事项 / 常见错误

1. 仅修改ConfigMap并非终点 即使修改了ConfigMap,正在运行的kubelet也不会自动重新加载。必须执行kubeadm upgrade node phase kubelet-config或直接替换文件,然后systemctl restart kubelet。

2. kubeadm升级时注意覆盖 在kubeadm升级时,/var/lib/kubelet/config.yaml的内容可能会被集群范围的kubelet-config ConfigMap内容覆盖。因此,要永久保留设置,必须修改ConfigMap本身,或者在/var/lib/kubelet/kubeadm-flags.env中添加标志。

3. serving证书不会自动批准 rotateCertificates控制的是客户端证书的自动续订。serving证书(serverTLSBootstrap: true)是单独的设置,在这种情况下,controller-manager不会自动批准,需要管理员手动执行kubectl certificate approve。

4. ConfigMap名称因版本而异 kubeadm 1.24以下版本中,格式为kubelet-config-1.{minor}。请先使用以下命令确认准确名称。

kubectl get configmap -n kube-system | grep kubelet-config

5. 注意YAML缩进错误 ConfigMap的data.kubelet字段的结构是YAML字符串中嵌套了另一个YAML。使用kubectl edit时,如果缩进错误,kubelet将无法解析设置,因此在保存前务必检查。


✅ 总结 / 结束语

基于ConfigMap的rotateCertificates设置流程总结如下:

  1. 使用kubectl get configmap kubelet-config -n kube-system检查当前设置
  2. 使用kubectl edit或patch应用rotateCertificates: true
  3. 在每个工作节点上执行kubeadm upgrade node phase kubelet-config
  4. 使用systemctl restart kubelet重启
  5. 使用kubectl get csr和证书到期日期确认正常运行

这种方法的核心优势在于ConfigMap充当单一事实来源。将来添加新节点时,只需执行kubeadm join即可自动部署相同的设置。这种结构大大降低了管理复杂性。


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注