Search code examples
kuberneteskubernetes-ingressnginx-ingressjupyterhub

Remote access Zero to JupyterHub over Ethernet with ingress in Kubernetes


Context

I installed Kubernetes on a bare-metal server (4 nodes) and deployed Zero to JupyterHub to it. This works fine; I can correctly access the hub from the master-node.

Now I want to access the Hub on the server from an external computer via Ethernet. Therefore, I followed the official instructions and installed MetalLB in order to provide an external IP for my proxy-public-service (which correctly sets).
Additionally, I installed the nginx-ingress-controller in order to be able to do an ingress, which also successfully gets an external IP (little hint: Use the Helm-chart; I couldn't get the service running when applying the other recommended steps).

Since I had a little trouble figuring out how to do this ingress, here is an example:

kubectl apply -f ingress.yaml --namespace jhub

#ingress.yaml:
#apiVersion: networking.k8s.io/v1beta1
#kind: Ingress
#metadata:
#  name: jupyterhub-ingress
#  annotations:
#    nginx.ingress.kubernetes.io/rewrite-target: /$1
#spec:
#  rules:
#  - host: jupyterhub.cluster
#    http:
#      paths:
#      - path: /
#        backend:
#          serviceName: proxy-public
#          servicePort: 80

Anyhow, I cannot open the external IP proxy-public provides (meaning I'm inserting the external IP in my browser).


Question

How can I remotely access my JupyterHub over the external IP; what am I missing?


Solution

  • I missed that this can be achieved in the same way as with the Kubernetes-Dashboard: You have to establish an open ssh-connection (hence, open a tunnel -> tunneling) from the external computer.
    Of course this is not the "exernal" access I had in mind, but a working and fast solution for my test-environment (and maybe yours).


    How to establish this ssh-connect

    First, get the external IP-address of your proxy-public:

    $: kubectl get services --namespace jhub
    NAME           TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
    hub            ClusterIP      10.99.241.72     <none>          8081/TCP                     95m
    proxy-api      ClusterIP      10.107.175.27    <none>          8001/TCP                     95m
    proxy-public   LoadBalancer   10.102.171.162   192.168.1.240   80:31976/TCP,443:32568/TCP   95m
    

    Note: The range of the external IP was defined in my layer2 in my MetalLB-config.

    Using this information (and assuming you're on Linux), open a terminal and use the following command:

    $ ssh pi@10.10.10.2 -L 8000:192.168.1.240:80
    # -L opens a localhost-connection
    # pi@10.10.10.2 logs me into my second node with user pi
    

    Note1: That localhost:8000 is configured as targetPort for proxy-public with http can also be seen when you describe the service and take a look at the specs respectively ports (you can also get the settings for https there):

    kind: Service
    apiVersion: v1
    metadata:
      name: proxy-public
      namespace: jhub
      ...
    spec:
      ports:
        - name: http
          protocol: TCP
          port: 80
          targetPort: 8000
          nodePort: 31976
        - name: https
    ...
    

    Finally, type http://localhost:8000/ into your browser - et voila, you get to your JupyterHub login-page!