If you want to make this scheme more safe you can add haproxy layer between keepalived and kube-apiserver.

Just install haproxy package into your system, and add the next configuration into /etc/haproxy/haproxy.cfg file:

defaults
maxconn 20000
mode tcp
option dontlognull
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 86400s
timeout server 86400s
timeout tunnel 86400s
frontend k8s-api
bind :::8443 v4v6
mode tcp
default_backend k8s-api
backend k8s-api
option httpchk GET /readyz HTTP/1.0
option log-health-checks
http-check expect status 200
mode tcp
balance roundrobin
default-server verify none check-ssl inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 5000 maxqueue 5000 weight 100
server node1 10.9.8.11:6443 check
server node2 10.9.8.12:6443 check
server node3 10.9.8.13:6443 check

Now you can access kubernetes api on port :8443. So this way keepalived will monitor the cluster IP, and haproxy will monitor the availability of kubernetes api-servers.

Also you have to configure timeouts for the haproxy, otherwise your kubectl exec commands will be canceled after 50 seconds

timeout client          4h
timeout server 4h

Just configure your kubelets and kubectl clients to connect on 8443 port instead 6443, and final scheme will looks like:

If we will have non working api-server on node1:

And if we will shutdown whole node:

Cheers!

This mess is mine!