Kubernetes 证书过期问题的处理方法
问题现象
出现 Kubernetes API 无法调取的现象,使用 kubectl 命令获取资源均返回如下报错.
Unable to connect to the server: x509: certificate has expired or is not yet valid
经网上搜索之后发现。应该是 Kubernetes 集群的证书过期了,使用命令排查证书的过期时间.
# kubeadm alpha certs check-expiration
发现确实是证书过期了。
相关介绍及问题解决
因为使用 kubeadm 部署的 Kubernetes 集群,所以更新起证书也是比较方便的,默认的证书时间有效期是一年
集群的 Kubernetes 版本是 1.15.3版本是可以使用以下命令来更新证书的,但是一年之后还是会到期,这样就很麻烦
所以我们需要了解一下 Kubernetes 的证书,然后我们来生成一个时间很长的证书,这样我们就可以不用去总更新证书了
# kubeadm alpha certs renew all --config=kubeadm.yaml # systemctl restart kubelet # kubeadm init phase kubeconfig all --config kubeadm.yaml 然后将生成的配置文件替换,重启kube-apiserver、kube-controller、kube-scheduler、etcd这4个容器即可
另外kubeadm会在控制面板升级的时候自动更新所有证书,所以使用 kubeadm 搭建得集群最佳的做法是经常升级集群,这样可以确保你的集群保持最新状态并保持合理的安全性。
但是对于实际的生产环境我们可能并不会去频繁得升级集群,所以这个时候我们就需要去手动更新证书。
下面我们通过调用 Kubernetes 的 API 来实现更新一个10年的证书。
首先在/etc/kubernetes/manifests/kube-controller-manager.yaml文件加入配置 spec: containers: - command: - kube-controller-manager # 设置证书有效期为10年 - --experimental-cluster-signing-duration=87600h - --client-ca-file=/etc/kubernetes/pki/ca.crt
修改完成后 kube-controller-manager 会自动重启生效。然后我们需要使用下面的命令为 Kubernetes 证书 API 创建一个证书签名请求。
如果你设置例如 cert-manager 等外部签名者,则会自动批准证书签名请求(CSRs)。
否者,你必须使用 kubectl certificate 命令手动批准证书。
以下 kubeadm 命令输出要批准的证书名称,然后等待批准发生:
# kubeadm alpha certs renew all --use-api --config kubeadm.yaml &
需要将全部 pending 的证书全部批准。我们还不能直接重启控制面板的几个组件
这是因为使用 kubeadm 安装的集群对应的etcd 默认是使用的 /etc/kubernetes/pki/etcd/ca.crt 这个证书进行前面的
而上面我们用命令kubectl certificate approve批准过后的证书是使用的默认的/etc/kubernetes/pki/ca.crt 证书进行签发的
所以我们需要替换 etcd 中的 CA 机构证书:
# 先拷贝静态Pod资源清单 cp -r /etc/kubernetes/manifests/ /etc/kubernetes/manifests.bak vi /etc/kubernetes/manifests/etcd.yaml ...... spec: containers: - command: - etcd # 修改为CA文件 - --peer-trusted-ca-file=/etc/kubernetes/pki/ca.crt - --trusted-ca-file=/etc/kubernetes/pki/ca.crt ...... volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki # 更改证书目录 name: etcd-certs volumes: - hostPath: path: /etc/kubernetes/pki # 将 pki 目录挂载到etcd中去 type: DirectoryOrCreate name: etcd-certs - hostPath: path: /var/lib/etcd type: DirectoryOrCreate name: etcd-data ......
由于 kube-apiserver 要连接 etcd 集群,所以也需要重新修改对应的 etcd ca 文件:
vi /etc/kubernetes/manifests/kube-apiserver.yaml ...... spec: containers: - command: - kube-apiserver # 将etcd ca文件修改为默认的ca.crt文件 - --etcd-cafile=/etc/kubernetes/pki/ca.crt ......
除此之外还需要替换 requestheader-client-ca-file 文件,默认是 /etc/kubernetes/pki/front-proxy-ca.crt 文件,现在也需要替换成默认的 CA 文件
否则使用聚合 API,比如安装了 metrics-server 后执行 kubectl top 命令就会报错:
# cp /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/front-proxy-ca.crt # cp /etc/kubernetes/pki/ca.key /etc/kubernetes/pki/front-proxy-ca.key
这样我们就得到了一个10年证书的 Kubernetes 集群,还可以通过重新编译 kubeadm 来实现一个10年证书的,这个我没有尝试,不过在初始化集群的时候也是一个方法。
参考文档: https://kubernetes.io/zh/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/