<p><strong>Context</strong></p>

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

<p>Now I want to access the Hub on the server from an external computer via Ethernet. Therefore, I followed the <a href="https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/advanced.html" rel="nofollow noreferrer">official instructions</a> and installed <a href="https://metallb.universe.tf/" rel="nofollow noreferrer">MetalLB</a> in order to provide an external IP for my <em>proxy-public</em>-service (which correctly sets).<br>
Additionally, I installed the <a href="https://github.com/kubernetes/ingress-nginx" rel="nofollow noreferrer">nginx-ingress-controller</a> in order to be able to do an ingress, which also successfully gets an external IP (little hint: Use the <em>Helm</em>-chart; I couldn't get the service running when applying the other recommended steps).</p>

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

<pre class="lang-sh prettyprint-override"><code>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
</code></pre>

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

<p><br>
<strong>Question</strong></p>

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

Markus
<p>I missed that this can be achieved in the same way as with the <em>Kubernetes-Dashboard</em>: You have to establish an open ssh-connection (hence, open a tunnel -> <em>tunneling</em>) from the external computer.<br>
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).
<br><br><br>
<strong>How to establish this ssh-connect</strong></p>

<p>First, get the external IP-address of your <em>proxy-public</em>:</p>

<pre class="lang-sh prettyprint-override"><code>$: kubectl get services --namespace jhub
NAME           TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
hub            ClusterIP      10.99.241.72     &lt;none&gt;          8081/TCP                     95m
proxy-api      ClusterIP      10.107.175.27    &lt;none&gt;          8001/TCP                     95m
proxy-public   LoadBalancer   10.102.171.162   192.168.1.240   80:31976/TCP,443:32568/TCP   95m
</code></pre>

<p><strong>Note</strong>: The range of the external IP was defined in my <code>layer2</code> in my <em>MetalLB</em>-config.</p>

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

<pre class="lang-sh prettyprint-override"><code>$ 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
</code></pre>

<p><strong>Note1</strong>: That <code>localhost:8000</code> is configured as targetPort for <em>proxy-public</em> with <em>http</em> 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):</p>

<pre class="lang-yaml prettyprint-override"><code>kind: Service
apiVersion: v1
metadata:
  name: proxy-public
  namespace: jhub
  ...
spec:
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8000
      nodePort: 31976
    - name: https
...
</code></pre>

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