Summary of rotation process:
This article describes the process to rotate the Kubernetes core components including kubelet for both Management and Workload Tanzu Kubernetes Grid (TKG) clusters.
It has been validated on TKG 1.1, 1.2, 1.3, 1.4, 1.5 & 2.x
This procedure is NOT supported on vSphere with Tanzu. If you are using vSphere with Tanzu (vSphere IaaS Control Plane) /TKGS / vSphere Kubernetes Cluster (VKS) you need to rotate certificates, please refer "Manually Replace vSphere Kubernetes Cluster/Guest Cluster Certificates" or "Replace vSphere with Tanzu Guest Cluster/vSphere Kubernetes Cluster Certificates"
If the certs have already expired, then kube-apiserver returns the following error below when running kubectl commands.
# kubectl get nodes Unable to connect to the server: x509: certificate has expired or is not yet valid
ssh capv@CONTROL-PLANE-IP sudo -i kubeadm alpha certs check-expiration Note: For TKGm 1.5.x , you can remove the "alpha" from the command above
ssh capv@CONTROL-PLANE-IP sudo -i openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
1. SSH to Control Plane node and rotate cluster component certs:
ssh capv@CONTROL-PLANE-IP sudo -i kubeadm alpha certs check-expiration kubeadm alpha certs renew all -v 6 kubeadm alpha certs check-expiration Note: For TKGm 1.5.x , you can remove the "alpha" from the 3 commands above
2. Restart cluster components, etcd, kube-apiserver, kube-controller-manager, kube-scheduler and kube-vip if present (failure to restart any of these components may lead to an unsuccessful certificate rotation and result in unexpected cluster behaviour):
crictl ps ps -fe | grep -e etcd -e kube-api -e kube-controller-manager -e kube-scheduler -e kube-vip kill PID crictl ps <-- to confirm all components have been restarted
OR
crictl ps
crictl stop <POD ID> <-- Repeat for etcd, kube-apiserver, kube-controller-manager, kube-scheduler and kube-vip (if present)
crictl ps <-- to confirm all components have been restarted
3. Repeat the above steps on all remaining Control Plane nodes.
ssh capv@CONTROL-PLANE-IP
sudo -i
grep client-certificate-data /etc/kubernetes/admin.conf | awk '{print $2}' | base64 -d | openssl x509 -noout -dates
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl get nodes
ssh capv@CONTROl-PLANE-IP vi /etc/kubernetes/admin.conf
vi ~/.kube/config
users:
- name: MGMT-CLUSTER-admin
user:
client-certificate-data: YYYYYY
client-key-data: ZZZZZZ
vi ~/.kube-tkg/config
users:
- name: MGMT-CLUSTER-admin
user:
client-certificate-data: YYYYYY
client-key-data: ZZZZZZ
kubectl get nodes
kubectl get secret -n tkg-system MGMT-CLUSTER-kubeconfig -o jsonpath='{.data.value}' | base64 -d > mgmt-kubeconfig-value
client-certificate-data and client-key-data using values from /etc/kubernetes/admin.conf:
vi mgmt-kubeconfig-value base64 mgmt-kubeconfig-value -w 0
data.value" with encoded data from previous command:
kubectl edit secret -n tkg-system MGMT-CLUSTER-kubeconfig
tkg get management-cluster kubectl config use-context MGMT-CONTEXT kubectl get nodes
tanzu mc get" . kubectl config use-context MGMT-CONTEXT kubectl get secrets -A | grep kubeconfig kubectl delete secret CLUSTER-NAME-kubeconfig -n NAMESPACE
kubectl get cluster <cluster_name> -namespace <name-namespace> -o yaml | grep -i paused
kubectl get secrets -A | grep kubeconfig tkg get credentials CLUSTER-NAME kubectl config use-context WORKLOAD-CONTEXT kubectl get nodes
tanzu cluster kubeconfig get <cluster-name> -n <namespace-name> --admin" to retrieve the kubeconfig of a cluster. # openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
ssh capv@CONTROL-PLANE-IP sudo -i mkdir /home/capv/backup mv /etc/kubernetes/kubelet.conf /home/capv/backup mv /var/lib/kubelet/pki/kubelet-client* /home/capv/backup
kubelet.conf and update cluster name and server endpoint.kubectl get nodes" or existing kubelet.conf
# check kubeadm version
kubeadm version
# if kubeadm version is v1.19.* or lower,
kubeadm alpha kubeconfig user --org system:nodes --client-name system:node:NODE > /home/capv/backup/kubelet-NODE.conf
# if kubeadm version is v1.20.* or v1.21.*,
kubeadm config --kubeconfig /etc/kubernetes/admin.conf view > kubeadm.config
kubeadm alpha kubeconfig user --org system:nodes --client-name system:node:NODE > /home/capv/backup/kubelet-NODE.conf --config kubeadm.config
# if kubeadm version is v1.22.*,
kubectl get cm -n kube-system kubeadm-config -o=jsonpath="{.data.ClusterConfiguration}" --kubeconfig /etc/kubernetes/admin.conf > kubeadm.config
kubeadm kubeconfig user --org system:nodes --client-name system:node:NODE > /home/capv/backup/kubelet-NODE.conf --config kubeadm.config
vi /home/capv/backup/kubelet-NODE.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: XXXXXX
server: https://ENDPOINT-IP:6443
name: CLUSTER-NAME
contexts:
- context:
cluster: CLUSTER-NAME
--config" for the command "kubeadm alpha kubeconfig user".--config" is not provided, we will hit error:required flag(s) "config" not setkubelet-NODE.conf to /etc/kubernetes, restart kubelet and wait for kubelet-client-current.pem to be recreated.
cp home/capv/backup/kubelet-NODE.conf /etc/kubernetes/kubelet.conf systemctl restart kubelet systemctl status kubelet ls -l /var/lib/kubelet/pki/
kubelet.conf to use new kubelet-client-current.pem
kubeadm init phase kubelet-finalize all ls -l /var/lib/kubelet/pki/ openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
kubectl get nodes
# openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
ssh capv@WORKER-IP sudo -i mkdir /home/capv/backup mv /etc/kubernetes/kubelet.conf /home/capv/backup mv /var/lib/kubelet/pki/kubelet-client* /home/capv/backup
kubelet-NODE.conf for each worker node and update cluster name and server endpoint.NODE can be retrieved from "kubectl get nodes" or existing kubelet.conf:
ssh capv@CONTROl-PLANE-IP
# check kubeadm version
kubeadm version
# if kubeadm version is v1.19.* or lower,
kubeadm alpha kubeconfig user --org system:nodes --client-name system:node:NODE > /home/capv/backup/kubelet-NODE.conf
# if kubeadm version is v1.20.* or v1.21.*,
kubeadm config --kubeconfig /etc/kubernetes/admin.conf view > kubeadm.config
kubeadm alpha kubeconfig user --org system:nodes --client-name system:node:NODE > /home/capv/backup/kubelet-NODE.conf --config kubeadm.config
# if kubeadm version is v1.22.*,
kubectl get cm -n kube-system kubeadm-config -o=jsonpath="{.data.ClusterConfiguration}" --kubeconfig /etc/kubernetes/admin.conf > kubeadm.config
kubeadm kubeconfig user --org system:nodes --client-name system:node:NODE > /home/capv/backup/kubelet-NODE.conf --config kubeadm.config
vi /home/capv/backup/kubelet-NODE.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: XXXXXX
server: https://ENDPOINT-IP:6443
name: CLUSTER-NAME
contexts:
- context:
cluster: CLUSTER-NAME
kubelet-NODE.conf to the corresponding worker node:
scp capv@CONTROL-PLANE-IP:/home/capv/backup/kubelet-NODE.conf .
scp kubelet-<NODE>.conf capv@WORKER-IP:/home/capv/backup/kubelet-NODE.conf
4. SSH to worker node, copy kubelet and restart kubelet:
cp /home/capv/backup/kubelet-<NODE>.conf /etc/kubernetes/kubelet.conf systemctl restart kubelet systemctl status kubelet
ubelet.conf to use pem file rather than raw data:
vi /etc/kubernetes/kubelet.conf
:
user:
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
systemctl restart kubelet
systemctl status kubelet
ls -l /var/lib/kubelet/pki/
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-<DATE>.pem -text -noout | grep -A2 Validity
kubectl get nodes