Kubernetes Cert Renewal

Posted by Drew Bednar on October 17, 2022
Tags: TLS

Here in the lab is an old Kubernetes 1.19 cluster that I haven't checked on in a while. I lost access to the kube-apiserver, and it turns out to be caused by an expired cert. Here are the steps I used to identify the issue and resolve it.

I Got a Problem

I am actively studying for the Certified Kubernetes Administrator (CKA) and one of the tasks you are required to perform during the exam is an upgrade of a cluster. Perfect, I have a Kubernetes 1.19 cluster from many moons ago. The only problem is I can't seem to connect to it.

$ kubectl get nodes 

The connection to the server 10.0.1.159:6443 was refused - did you specify the right host or port?

Logging into the management node and checking for I errors I find:

$ journalctl -e

Oct 18 01:24:56 kube1 kubelet[696]: E1018 01:24:56.399808     696 kubelet.go:2183] node "kube1" not found 

The kube-apiserver runs inside the kube-system namespace. Since this cluster uses Docker as the container runtime I can simply check the logs

$ docker ps -a | grep kube-api

d5e5415186ff        607331163122           "kube-apiserver --ad…"   4 minutes ago       Exited (1) 4 minutes ago                        k8s_kube-apiserver_kube-apiserver-kube1_kube-system_e62e9c7b79c44695c4f889ce8dccbe97_8245
$ docker logs k8s_kube-apiserver_kube-apiserver-kube1_kube-system_e62e9c7b79c44695c4f889ce8dccbe97_8245

W1018 01:31:47.390824       1 clientconn.go:1223] grpc: addrConn.createTransport failed to connect to {https://127.0.0.1:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: x509: certificate has expired or is not yet valid: current time 2022-10-18T01:31:47Z is after 2022-09-24T19:19:54Z". Reconnecting...

Well, sure enough it seems like the issue with with the TLS cert.

$ kubeadm version

kubeadm version: &version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.2", GitCommit:"f5743093fd1c663cb0cbc89748f730662345d44d", GitTreeState:"clean", BuildDate:"2020-09-16T13:38:53Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"}

Since this is an older version of kubeadm I need to use the alpha flag to check the certs.

$ kubeadm alpha certs check-expiration

W1018 01:38:09.425304  168347 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Sep 24, 2022 19:19 UTC   <invalid>                               no
apiserver                  Sep 24, 2022 19:19 UTC   <invalid>       ca                      no
apiserver-etcd-client      Sep 24, 2022 19:19 UTC   <invalid>       etcd-ca                 no
apiserver-kubelet-client   Sep 24, 2022 19:19 UTC   <invalid>       ca                      no
controller-manager.conf    Sep 24, 2022 19:19 UTC   <invalid>                               no
etcd-healthcheck-client    Sep 24, 2022 19:19 UTC   <invalid>       etcd-ca                 no
etcd-peer                  Sep 24, 2022 19:19 UTC   <invalid>       etcd-ca                 no
etcd-server                Sep 24, 2022 19:19 UTC   <invalid>       etcd-ca                 no
front-proxy-client         Sep 24, 2022 19:19 UTC   <invalid>       front-proxy-ca          no
scheduler.conf             Sep 24, 2022 19:19 UTC   <invalid>                               no

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      Sep 21, 2030 01:01 UTC   7y              no
etcd-ca                 Sep 21, 2030 01:01 UTC   7y              no
front-proxy-ca          Sep 21, 2030 01:01 UTC   7y              no

You certainly can tell this is not my primary cluster from the fact that this has been non-operational for a couple weeks without me noticing. Anyway, I need to get this back into a working state before I can work on upgrading it.

Sweet New Certs

Now I was going to go into a long diatribe about creating certs and CSRs, but I decided to just take the easy way out.

$ kubeadm alpha certs renew all

[renew] Reading configuration from the cluster...
[renew] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[renew] Error reading configuration from the Cluster. Falling back to default configuration

W1018 20:01:29.055667  899153 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate the apiserver uses to access etcd renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for liveness probes to healthcheck etcd renewed
certificate for etcd nodes to communicate with each other renewed
certificate for serving etcd renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed

That's it. That's all you needed. Just remember the version of my kubeadm was old enough to require using the alpha subcommand. Don't worry about the cluster configuration at this time, since the kube-apiserver pod is down. I rebooted the machine, copied the admin.conf to my user's home directory, and checked to make sure I could reach the cluster nodes.

$ cp /etc/kubernetes/admin.conf ~/admin.conf
$ kubectl --kubeconfig admin.conf get nodes

NAME    STATUS   ROLES    AGE     VERSION
kube1   Ready    master   2y25d   v1.19.2
kube2   Ready    <none>   2y25d   v1.19.2
kube3   Ready    <none>   2y25d   v1.19.2

Time To Say Goodbye

Hope this serves you well in the future when you find yourself logging into that old cluster.

Tags: TLS