Exposing kube-apiserver
This is done on your own peril but if you want to mimic managed kubernetes solutions where you can connect to an external URL/address over the internet to manage your cluster then this is how you can do it.
I won't go into detail on each step as this is just a personal memo for myself until I can automate the process in my Ansible setup.
Install Traefik
Traefik is best for this, if you already have nginx-ingress then you need another IP for Traefik. Or migrate all your nginx ingresses over to Traefik.
I use the traefik/traefik Helm chart from their own repo, just make sure you know which public IP Traefik is using.
Reason I use Traefik is because I need TCP passthrough because kube-apiserver handles its own TLS. At this moment in time I am not aware how to handle TLS termination for kube-apiserver.
Create a domain
I usually create a domain like kube-apiserver.production.zone.my-domain.tld, and point its DNS to your Traefik IP.
Add a SAN (Subject Alternative Name) in the TLS cert
You must repeat this step on each control node because they all run an instance of kube-apiserver. Then it's up to you to balance connections to them from some external load balancer like HAproxy.
The two files /etc/kubernetes/pki/apiserver.{crt,key}
contain the cert generated by kubeadm init when you installed the control node.
Move old cert and key to a backup location
mv /etc/kubernetes/pki/apiserver.{crt,key} /var/backups/
Run kubeadm init
Now we only run one phase of the kubeadm init process which will create a new cert based on the config we modified.
sudo kubeadm init phase certs apiserver --apiserver-cert-extra-sans='127.0.0.1,localhost,10.2.3.4,kube-apiserver.production.zone.my-domain.tld'
Remember to list every single name you might use to connect to your kube-apiserver.
Expose kube-apiserver as a Service
Here's an example manifest based on what I use;
apiVersion: v1
kind: Service
metadata:
name: kube-apiserver
namespace: kube-system
labels:
component: kube-apiserver
spec:
type: ClusterIP
ports:
- port: 443
targetPort: 6443
protocol: TCP
name: apiserver
selector:
component: kube-apiserver
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: kube-apiserver
namespace: kube-system
spec:
routes:
- match: HostSNI(`*`)
services:
- name: kube-apiserver
port: 443
tls:
passthrough: True