<p>From the documentation I see</p>
<blockquote>
<p>NodePort: Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting :.</p>
</blockquote>
<blockquote>
<p>LoadBalancer: Exposes the service externally using a cloud provider’s load balancer. NodePort and ClusterIP services, to which the external load balancer will route, are automatically created</p>
</blockquote>
<p>But it doesn't mention when to choose one over the other. One of the disadvantages with Nodeport I can think of is the security (opening port in firewall rules), was wondering if there are any additional considerations for choosing one over the other.</p>

<p>A <code>NodePort</code> service exposes your service on all <code>&lt;NodeIP:NodePort&gt;</code> addresses i.e., you can reach your service an any node IP and nodePort combination. This can be natively implemented by kubernetes because kubernetes has an agent (kube-proxy) running on all the nodes to create the required configuration to forward the traffic received on the nodeIP:nodePort to the backing pods.</p>
<p>Few of disadvantages of directly using <code>Nodeport</code> service are that:</p>
<ul>
<li><p><strong>Nodes must be exposed externally:</strong> Unless your nodes themselves are exposed externally, you can't receive traffic on the <code>&lt;NodeIP:NodePort&gt;</code> address.</p>
</li>
<li><p><strong>No node-level load balancing</strong>: Clients can connect to the service at <code>&lt;NodeIP:NodePort&gt;</code> but there is no load balancing of traffic between the nodes unless the clients themselves do it. What if a node goes down? Who would inform the clients not to use the node?</p>
</li>
<li><p><strong>Non-standard port numbers</strong>: Since the <code>&lt;NodePort&gt;</code> remains same on all nodes, it must be a free port on all the nodes. Kubernetes make sure of this by picking a free port in the node port range which by default is <code>30000-32767</code>. But I might want to expose the service on a more standard port like 80, 443 etc.</p>
</li>
</ul>
<hr />
<p>We can solve all of the above problems if we have an entity that receives the traffic on an externally reachable IP on a port of our liking and then forward the traffic to the NodePort service at <code>&lt;NodePort:NodeIP</code>. This entity that receives the traffic can also load balance across the nodes by keeping a tab on what all nodes are alive and then distributing the incoming traffic to the backend nodes in the cluster. The cluster nodes can remain in a private network only reachable from this entity.</p>
<p>As this entity is something that lives outside the kubernetes cluster, kubernetes itself cannot create or manage this. But someone that has control at the topology/network level can do it i.e., your cloud provider. They can create this entity to receive the traffic on an externally reachable IP and port of your liking and forward it to your nodePort service. But there are lots of cloud providers. How do you tell a cloud provider in a uniform way that you need this functionality?</p>
<p>Here comes the <code>LoadBalancer</code> service. When you create a <code>LoadBalancer</code> service, Kubernetes will create a <code>NodePort</code> service and inform your cloud provider that you have created a service of type <code>LoadBalancer</code>. Then your cloud provider will instantiate a load balancer to receive the traffic on an externally reachable IP and forward to the cluster. It will also update the <code>status</code> section of your <code>LoadBalancer</code> service with the external IP which then you can find by querying kubernetes api-server (by doing <code>kubectl get svc</code> for example). Cloud providers usually charge for each <code>LoadBalancer</code> service that you create.</p>
<hr />
<p>What happens on vanilla <strong>bare-metal</strong> (or self provisioned) clusters if you create <code>LoadBalancer</code> type service?</p>
<p>Kubernetes would do its job of creating the <code>NodePort</code> service. Since there is no other entity like a cloud provider watching for <code>LoadBalancer</code> services, there wouldn't be any difference between <code>LoadBalancer</code> and <code>NodePort</code> on such clusters. You would see the <code>ExternalIP</code> field as <code>&lt;Pending&gt;</code> if you do <code>kubectl get svc</code> for the <code>LoadBalancer</code> services.</p>
<p><em>References:</em></p>
<p><a href="https://kubernetes.io/docs/concepts/services-networking/service/#nodeport" rel="nofollow noreferrer">1. NodePort service</a></p>
<p><a href="https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer" rel="nofollow noreferrer">2. LoadBalancer service</a></p>
<p><a href="https://www.shashankv.in/kubernetes/kubernetes-bare-metal-external-connectivity/" rel="nofollow noreferrer">3. External connectivity on bare-metal</a></p>
