What is the best way to convert a kubernetes non-HA control plane into an HA control plane?
I have started with my cluster as a non-HA control plane - one master node and several worker nodes. The cluster is already running with a lots of services.
Now I would like to add additional master nodes to convert my cluster into a HA control plane. I have setup and configured a load balancer. But I did not figure out how I can change the -control-plane-endpoint to my load balancer IP address for my existing master node.
Calling kubeadm results in the following error:
sudo kubeadm init --control-plane-endpoint "my-load-balancer:6443" --upload-certs
[init] Using Kubernetes version: v1.20.1
[preflight] Running pre-flight checks
[WARNING SystemVerification]: missing optional cgroups: hugetlb
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR Port-6443]: Port 6443 is in use
[ERROR Port-10259]: Port 10259 is in use
[ERROR Port-10257]: Port 10257 is in use
[ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
[ERROR Port-10250]: Port 10250 is in use
[ERROR Port-2379]: Port 2379 is in use
[ERROR Port-2380]: Port 2380 is in use
[ERROR DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
The error message seems to be clear as my master is already running. Is there a way how I can easily tell my existing master node to use the new load balancer to run as a HA control plane?
The best approach to convert
a non-HA control plane to an HA control plane is to create a completely new HA control plane and after that to migrate all your applications there.
Below I will try to help you to achieve your goal but I do not recommend using this procedure on any cluster that will ever be considered as production cluster. It work for my scenario, it also might help you.
First of all, kube-apiserver uses a certificate
to encrypt control plane traffic and this certificate
have something known as SAN (Subject Alternative Name).
SAN is a list of IP addresses that you will use to access the API, so you need to add there IP address of your LoadBalancer
and probably the hostname
of your LB
as well.
To do that, you have to get kubeadm
configuration e.g. using command:
$ kubeadm config view > kubeadm-config.yaml
and then add certSANs
to kubeadm-config.yaml
config file under apiServer
section, it should looks like below example: (you may also need to add controlPlaneEndpoint
to point to your LB
).
apiServer:
certSANs:
- "192.168.0.2" # your LB address
- "loadbalancer" # your LB hostname
extraArgs:
authorization-mode: Node,RBAC
...
controlPlaneEndpoint: "loadbalancer" # your LB DNS name or DNS CNAME
...
Now you can update kube-apiserver
cert using:
BUT please remember you must first delete/move your old kube-apiserver
cert and key from /etc/kubernetes/pki/
!
$ kubeadm init phase certs apiserver --config kubeadm-config.yaml.
Finally restart your kube-apiserver
.
Next step is to update the kubelet
, scheduler
and controller manager
to communicate with the kube-apiserver
using LoadBalancer
.
All three of these components use standard kubeconfig files:
/etc/kubernetes/kubelet.conf
, /etc/kubernetes/scheduler.conf
, /etc/kubernetes/controller-manager.conf
to communicate with kube-apiserver
.
The only thing to do is to edit the server:
line to point to LB
instead of kube-apiserver
directly and then restart these components.
The kubelet
is systemd
service so to restart it use:
systemctl restart kubelet
the controller manager
and schedulers
are deployed as pods.
Next it is time to update kubeconfig
file for kube-proxy
and same as before - the only thing to do is to edit the server:
line to point to LoadBalancer
instead of kube-apiserver
directly.
This kubeconfig
is in fact a configmap
, so you can edit it directly using:
$ kubectl edit cm kube-proxy -n kube-system
or first save it as manifest file:
$ kubectl get cm kube-proxy -n kube-system -o yaml > kube-proxy.yml
and then apply changes.
Don't forget to restart kube-proxy
after these changes.
At the end upload new kubeadm-config
configmap
(with certSANs
and controlPlaneEndpoint
entries) to the cluster, it's especially important when you want to add new node to the cluster.
$ kubeadm config upload from-file --config kubeadm-config.yaml
if command above doesn't work, try this:
$ kubeadm upgrade apply --config kubeadm-config.yaml