Kubernetes dashboard is a practical way to explore a cluster. The command line is practical for achieving a given tasks because it makes it easy to manipulate the data (hello good jq friend!) but sometimes just viewing things in a web UI allows getting an overall view of the thing.

The dashboard is made to run inside the cluster, which is great for non developers to access it. But this means having a permanently running container, managing access to the dashboard and to the API server, updating it, … I prefer to start it locally when I need it, using my own account access rights on the cluster, and stop it right after. The constraint is only to ensure I do not inadvertently expose it on the network.

In order to reach the cluster I start kubectl proxy in the background which will expose an unauthenticated Kubernetes API server which delegates to the actual Kubernetes API server with my credentials. It allows me to reuse my kubeconfig which specifies how to create tokens and how to reach the server through a bastion host.

kubectl proxy --address=$(ip -br -4 addr show docker0 | awk '{print $3}' | cut -d/ -f1) --accept-hosts='.*' &

Drill down:

  1. kubectl proxy: start proxy to API server
  2. --address=$(...): make sure the proxy binds on a private network interface, the one that the container will use
    1. ip -br -4 addr show docker0: describe the IPv4 address of docker0 interface
    2. awk '{print $3}': keep just IP and mask
    3. cut -d/ -f1: keep just the IP
  3. --accept-hosts='.*': no filter on allowed hosts (by default it allows only localhost) as I make sure to mount on a private network interface
  4. &: start on the background, to avoid requiring two shells (stop it with kill %1)

Starting the dashboard requires a bit of preparation as it needs a fake token to contact API server and wants to write logs but has a readonly filesystem.

mkdir -p /tmp/dashboard
chmod -R 0777 /tmp/dashboard/
echo fake > /tmp/dashboard/token

I then instruct dashboard to use this proxy to reach the cluster:

docker run --rm -it -p 127.0.0.1:9090:9090 -v /tmp/dashboard:/tmp -v /tmp/dashboard/token:/var/run/secrets/kubernetes.io/serviceaccount/token --add-host=host.docker.internal:host-gateway kubernetesui/dashboard:v2.7.0 --apiserver-host=http://host.docker.internal:8001 --metrics-provider=none

Drill down:

  1. docker run --rm -it: start an interactive container that will be deleted on shutdown
  2. -p 127.0.0.1:9090:9090: open port 9090 on the host, but not on public networks
  3. -v /tmp/dashboard:/tmp: mount folder to write logs in
  4. -v /tmp/dashboard/token:/var/run/secrets/kubernetes.io/serviceaccount/token: mount the fake token to the folder in which Kubernetes would add service account token
  5. --add-host=host.docker.internal:host-gateway: allow the container to reach network interface docker0 as host host.docker.internal
  6. kubernetesui/dashboard:v2.7.0: run this docker image, more recent may be available on Docker hub
  7. --apiserver-host=http://host.docker.internal:8001: tell the dashboard to reach proxy via HTTP on this host/port
  8. --metrics-provider=none: disable metrics provider as I do not configure it, otherwise error logs will periodically pop

See all options dashboard will respond to.

Once this runs I can reach http://localhost:9090 (as 9090 is the default insecure port dashboard binds to) and explore my cluster.

For shutting it down I CTRL+C to stop dashboard container, and then kill proxy with kill %1 (might be different if there are other background jobs).