<p>In order to access the Kubernetes dashboard you have to run kubectl proxy on your local machine, then point your web browser to the proxy. Similarly, if you want to submit a Spark job you again run kubectl proxy on your local machine then run spark-submit against the localhost address.</p>

<p>My question is, why does Kubernetes have this peculiar arrangement? The dashboard service is running on the Kubernetes cluster, so why am I not pointing my web browser at the cluster directly? Why have a proxy? In some cases the need for proxy is inconvenient. For example, from my Web server I want to submit a Spark job. I can't do that--I have to run a proxy first, but this ties me to a specific cluster. I may have many Kubernetes clusters.</p>

<p>Why was Kubernetes designed such that you can only access it through a proxy?</p>

<p>You can access your application in the cluster in different ways:</p>

<ol>
<li>by using <a href="https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#manually-constructing-apiserver-proxy-urls" rel="noreferrer">apiserver as a proxy</a>, but you need to pass authentication and authorization stage.</li>
<li>by using <a href="http://alesnosek.com/blog/2017/02/14/accessing-kubernetes-pods-from-outside-of-the-cluster/" rel="noreferrer">hostNetwork</a>. When a pod is configured with hostNetwork: true, the applications running in such a pod can directly see the network interfaces of the host machine where the pod was started.</li>
<li>by using <a href="http://alesnosek.com/blog/2017/02/14/accessing-kubernetes-pods-from-outside-of-the-cluster/" rel="noreferrer">hostPort</a>. The container port will be exposed to the external network at <code>hostIP:hostPort</code>, where the <code>hostIP</code> is the IP address of the Kubernetes node where the container is running and the <code>hostPort</code> is the port requested by the user.</li>
<li>by using Services with type: <a href="https://kubernetes.io/docs/concepts/services-networking/service/#proxy-mode-iptables" rel="noreferrer">ClusterIP</a>. ClusterIP Services accessible only for pods in the cluster and cluster nodes.</li>
<li>by using Services with type: <a href="https://kubernetes.io/docs/concepts/services-networking/service/#nodeport" rel="noreferrer">NodePort</a>. In addition to ClusterIP, this service gets random or specified by user port from range of <code>30000-32767</code>. All cluster nodes listen to that port and forward all traffic to corresponding Service.</li>
<li>by using Services with type: <a href="https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer" rel="noreferrer">LoadBalancer</a>. It works only with supported Cloud Providers and with <a href="https://github.com/google/metallb" rel="noreferrer">Metallb</a> for On Premise clusters. In addition to opening NodePort, Kubernetes creates cloud load balancer that forwards traffic to <code>NodeIP:Nodeport</code> for that service. </li>
</ol>

<p>So, basically: <code>[[[ Kubernetes Service type:ClusterIP] + NodePort ] + LoadBalancer ]</code></p>

<ol start="7">
<li>by using Ingress (ingress-controller+Ingress object). Ingress-controller is exposed by Nodeport or LoadBalancer service and works as L7 reverse-proxy/LB for the cluster Services. It has access to ClusterIP Services so, you don't need to expose Services if you use Ingress.  You can use it for SSL termination and for forwarding traffic based on URL path. The most popular ingress-controllers are:

<ul>
<li><a href="https://github.com/kubernetes/ingress-nginx" rel="noreferrer">kubernetes/nginx-ingress</a>, </li>
<li><a href="https://github.com/nginxinc/kubernetes-ingress" rel="noreferrer">nginxinc/kubernetes-ingress</a>, </li>
<li><a href="https://www.haproxy.com/blog/haproxy_ingress_controller_for_kubernetes/" rel="noreferrer">HAProxy-ingress</a>, </li>
<li><a href="https://docs.traefik.io/user-guide/kubernetes/" rel="noreferrer">Traefik</a>.</li>
</ul></li>
</ol>

<p>Now, about <code>kubectl proxy</code>. It uses the first way to connect to the cluster. Basically, it reads the cluster configuration in .kube/config and uses credentials from there to pass cluster API Server authentication and authorization stage. Then it creates communication channel from local machine to API-Server interface, so, you can use local port to send requests to Kubernetes cluster API without necessity to specify credentials for each request.</p>
