1 | OS-Release: CentOS7 |
问题复现
集群基于Bear Token
方式的 TLS Bootstrap 进行通信, 且使用 kubelet 客户端证书过期轮换的特性
根据 1.10.x 版本的官方文档介绍, 配置使用此特性, 这里具体列出 kubelet 上的相关配置
- 在 kubelet 的启动参数中传入
--rotate-certificates
此参数意为声明开启证书轮换机制, 为即将过期的客户端节点颁发新的证书文件 - 在 kubelet 参数配置模板文件中添加如下配置, 该配置默认开启
1 | featureGates: |
创建集群角色绑定
1 | kubectl create clusterrolebinding kubelet-bootstrap \ |
为节点创建 Bootstrap Token
1 | TOKEN=`kubeadm token create \ |
为节点创建 Bootstrap kubeconfig
1 | kubectl config set-cluster kubernetes \ |
将kubelet-bootstrap-node6752.kubeconfig
Bootstrap kubeconfig 文件分发给 kubelet 客户端
在kubelet客户端指定配置文件
- –bootstrap-kubeconfig=”/path/to/bootstrap/kubeconfig”
- –kubeconfig=kubelet.kubeconfig
注意: 这里指定的--kubeconfig
文件并不存在, 当 kubelet 完成认证, 拿到下发的证书后, 证书会存放到--cert-dir
指定的文件夹, 然后根据实际证书来创建 kubeconfig 文件并写入到--kubeconfig
指定的路径
复现问题
在启动 kubelet 服务后, 在 master 端可以看到 csr 请求, 手动审批
1 | kubectl certificate approve node-csr-32YapU7hg6hB_87Hyus7NkD6a7-ew8sX2qP09ikjUh6 |
审批后, 在 kubelet 客户端指定的证书目录下, 你可以看到如下文件:
1 | kubelet-client.crt (由 kube-controller-manager 颁发的客户端证书) |
在 kubelet 指定的 --kubeconfig
文件, 也被写入了对应的内容, 问题就出现在了这里
其中users.user.client-certificate
和users.user.client-key
的配置中, 分别指定了kubelet-client.crt
和kubelet-client.key
1 | users: |
但问题是, 当kubelet-client.crt
证书过期后, 由 Kubernetes 证书轮换特性续期的新证书, 却是以软连接的方式提供的, 而且, 软连接的名字和kubeconfig
中配置的证书名字不一致. 以下是 kube-controller-manager 颁发的新证书形式
1 | kubelet-client-2018-12-11-11-14-18.pem |
- 新的证书只有一个文件, 格式为 pem. 该文件中既包含了证书内容也包含了 key 的内容
- 新证书的实际文件名为:
kubelet-client-DATE.pem
- 新证书的软连接为:
kubelet-client-current.pem
可以看出, 当证书续期之后, 新证书的引用路径(文件名)与最开始自动创建的 kubeconfig 文件中指定的证书文件不一致. 这个问题将导致原有证书过期且 kubelet 重启后, 将无法再与 apiserver 通信, apiserver 端也将标记该节点为NotReady
解决方案
解决方案1: 手动修改 kubeconfig 文件
执行以下操作:
1 | cat kubelet-client.crt kubelet.key > kubelet-origin.pem |
原理就是在证书续期之前就手动构造证书续期之后的结构, 这样在证书续期后, 就可以无缝使用新证书了
解决方案2: 升级集群版本
通过查看官方文档, 在1.11.0
版本中, 该问题得到了修复, 你也可以通过升级集群版本来解决这个问题
注意, 集群升级后, 原有的证书都还是继续使用的, 所以升级并解决不了原来的问题, 除非你将节点删除后, 重新使用 BearToken 的方式重新申请加入集群
参考文档:
- 1.13版本 TLS Bootstrap 官方文档: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/
- 1.10版本 TLS Bootstrap 官方文档: https://github.com/kubernetes/website/blob/release-1.10/content/en/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md
- 1.11版本Changelog: https://github.com/kubernetes/kubernetes/blob/8c0542dcf126222481390cd0606e3b7f43830a64/CHANGELOG-1.11.md
- 修复该 BUG 的 PR: https://github.com/kubernetes/kubernetes/pull/62152