Getting local url (not IP) for Z2JH minikube deployment

In setting up a minikube cluster and deploying jupyterhub, I run into the typical problem of a pending proxy-public external-ip. Google searching turns up enabling the ingress addon or using metallb. The addon did seem to have much effect. I’ve tried metallb with a configmap using 127.0.0.1 IP (to use “localhost”). The proxy-public external-ip gets assigned to that IP, but I cannot access jupyterhub on the designated port.

Is there a standard way to approach this? Ideally I’d like to be able to use a url (say, jhub.local). I’m not versed much in k8s networking, so a simplistic explanation/walkthrough is best.

Thank you.

Welcome to the forum!

Ingress should work, could you please show us your Z2JH config?

Thanks for the welcome!

My setup is using minikube 1.9.2.

$ cat config.yaml
proxy:
  secretToken: "<redacted>"
ingress:
  enabled: true
  hosts:
    - jhub.local

$ minikube start --kubernetes-version=v1.14.10
$ minikube addons enable ingress # Also tried $ helm install stable/nginx-ingress --version 1.36.3
$ kubectl create namespace jhub
$ helm upgrade --install jhub jupyterhub/jupyterhub --namespace jhub --version 0.9.0 --values config.yaml 

Via minikube service list --namespace=jhub, I can get a URL and see jupyterhub is running.

I do see nginx-ingress-controller running in the kube-system namespace. In it’s pod’s logs, I see:

W0424 20:11:48.557284       6 controller.go:920] Service "jhub/proxy-public" does not have any active Endpoint.

The external-ip is always pending, and jub.local isn’t resolved.

You shouldn’t need an external IP if you’re using ingress. The default ServiceType for z2jh is ClusterIP not LoadBalancer so I’m surprised it’s trying to obtain an external IP.

In any case your ingress should hopefully still work done. You’ll need to ensure jhub.local resolves to the minikube IP, for example by adding it to your /etc/hosts file.

I may have not been clear. It’s the proxy-public that is pending an external-ip, not the hub itself. Below is the message printed when deploying the helm chart, which presumably only works in environments with load balancer functionality.

You can find the public IP of the JupyterHub by doing:

 kubectl --namespace=jhub get svc proxy-public

You are correct that updating /etc/hosts allows the hostname to resolve. Thank you – that will help with my testing.

Is /etc/hosts the only way to ensure a hostname? Ideally, I want instructions for less experienced users to be not involve updating a system file, or worrying about a potentially dynamic IP. If not a custom hostname, then can I route from a specified localhost port?

Sorry, I mixed up hub and proxy.


The default proxy.service.type is LoadBalancer, if you change that to ClusterIP you’ll get rid of the pending external-ip. Though K8s may also assign a ClusterIP in addition anyway.

To avoid editing /etc/hosts you can also use the IP address of the Minikube cluster in the hosts section of your ingress, but you’ll need to transform it into a domain name using a (free) service such as http://xip.io that maps IP A.B.C.D to DNS A.B.C.D.xip.io since the ingress won’t handle raw IPs.

Yet another option is to set the proxy.servce.type to NodePort.
https://kubernetes.io/docs/concepts/services-networking/service/#nodeport
This will bind the service to a port on the MiniKube IP so you’d access it at e.g. A.B.C.D:32123 instead of messing with an ingress host. I don’t know of a way to bind a port on localhost though.

:+1: to @manics node port suggestion. The following snippet/config is what we use during BinderHub development to configure the JupyterHub to be reachable from your laptop while it is running on minikube. No need for metallb or ingress addon.

  proxy:
    secretToken: super-secret-values
    service:
      type: NodePort
      nodePorts:
        http: 30902

It should then respond to something like curl $(minikube ip):30902.

You can now use

minikube tunnel

and minikube will assign a “public IP” to JupyterHub.