Is there a way to expose the API server of a Kubernetes cluster created with minikube
on a public network interface to the LAN?
minikube start --help
talks about this option (and two similar ones):
--apiserver-ips ipSlice \
A set of apiserver IP Addresses which are used in the generated \
certificate for localkube/kubernetes. This can be used if you \
want to make the apiserver available from outside the machine (default [])
So it seems to be possible. But I can't figure out how or find any further information on that.
I naively tried:
minikube start --apiserver-ips <ip-address-of-my-lan-interface>
But that just yields an utterly dysfunctional minikube cluster that I can't even access from localhost.
Following the advise in one answer below I added port forwarding to Kubernetes like this:
vboxmanage controlvm "minikube" natpf1 "minikube-api-service,tcp,,8443,,8443"
And then I can actually access the API server from a different host on the network with:
curl --insecure https://<ip-address-of-host-running-minikube>:8443
But the response is:
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
There are two problems with this:
--insecure
for the curl
call, otherwise I get a SSL validation error.The big source of your headache is that minikube runs in a VM (usually) with it's own IP address. For security, it generates some self signed certificates and configures the api command line tool, kubectl to use them. The certs are self signed with the VM IP as the host name for the cert.
You can see this if you use kubectl config view
. Here's mine:
apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/sam/.minikube/ca.crt
server: https://192.168.39.226:8443
name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
user:
client-certificate: /home/sam/.minikube/client.crt
client-key: /home/sam/.minikube/client.key
Let's unpack that.
server: https://192.168.39.226:8443
- this tells kubectl where the server is. In a vanilla minikube setup, it's https://<ip-of-the-vm>:8443
. Note that its https.
certificate-authority: /home/sam/.minikube/ca.crt
- this line tells the tool what certificate authority file to use to verify the TLS cert. Because it's a self signed cert, even in vanilla setups, you'd have to either inform curl about the certificate authority file or use --insecure
.
- name: minikube
user:
client-certificate: /home/sam/.minikube/client.crt
client-key: /home/sam/.minikube/client.key
This chunk specifies what user to authenticate as when making commands - that's why you get the unauthorized message even after use --insecure
.
So to use the minikube cluster from a different IP you'll need to: 1) Use the --apiserver-ips <target-ip-here>
(so the cert minikube generates is for the correct IP you'll be accessing it from) 2) Forward the 8443 port from the minikube vm to make it available at <target-ip-here>:8443
3) Publish or otherwise make available the cert files referenced from kubectl config view
4) Setup your kubectl config to mimic your local kubectl config, using the new ip and referencing the published cert files.
You need to forward some ports on your LAN interface to the VMs where Kubernetes are running. That will work for any service inside Minikube, not only for Kubernetes itself.
In short, if you are using VirtualBox as a VM driver, you should:
kubectl describe <servicename>
and minikube service <servicename> --url
should help you.Forward ports to the VM using vboxmanage
tool:
vboxmanage controlvm "minikube" natpf1 "http,tcp,,12345,,80"
Where minikube
- the name of the VM, natfp1
- the virtual interface of the VM, 12345
- port of the VM, 80
- local port.