<p>I was reading k8s docs at <a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="nofollow noreferrer">https://kubernetes.io/docs/concepts/services-networking/service/</a>.</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 routes,
is automatically created. <strong>You'll be able to contact the NodePort
Service, from outside the cluster, by requesting &lt;NodeIP&gt;:&lt;NodePort&gt;.</strong></p>
</blockquote>
<p>So, I tried checking it practically. In this LoadBalancer service, port 31724 is a NodePort and 80 is the container port. According to docs, the NodePort should be open to the outer world and the container port should not. But with nmap, I found the reverse being true.</p>
<pre><code>NAME      TYPE           CLUSTER-IP      EXTERNAL-IP               PORT(S)                  AGE
gen       LoadBalancer   10.200.32.132   10.44.9.162,10.44.9.163   80:31724/TCP,443:30039   20d
</code></pre>
<pre><code>$ nmap -p 80 10.44.9.162

Starting Nmap 6.40 ( http://nmap.org ) at 2021-04-08 12:33 UTC
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 10.44.9.162
Host is up (0.00061s latency).
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 0.02 seconds

$ nmap -p 31724 10.44.9.162

Starting Nmap 6.40 ( http://nmap.org ) at 2021-04-08 12:33 UTC
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 10.44.9.162
Host is up (0.00044s latency).
PORT      STATE  SERVICE
31724/tcp closed unknown

Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds
</code></pre>
<p>I am surely missing something. Please help me understand this. Thanks!</p>
<hr />
<p><strong>Follow-up</strong>:<br />
I know follow-up should be a different question but it seemed like the correct place.<br />
I created a NodePort service and retried the same. And it was as told in the description.</p>
<pre><code>object-controller-np      NodePort       10.200.32.240   &lt;none&gt;         7203:31206/TCP                                             5s
</code></pre>
<p>NodeIP</p>
<pre><code>eth0: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500
inet 10.46.104.20 ...
</code></pre>
<pre><code>$ nmap -p 7203 10.46.104.20

Starting Nmap 6.40 ( http://nmap.org ) at 2021-04-09 07:01 UTC
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 10.46.104.20
Host is up (0.00052s latency).
PORT     STATE  SERVICE
7203/tcp closed unknown

Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds

$ nmap -p 31206 10.46.104.20

Starting Nmap 6.40 ( http://nmap.org ) at 2021-04-09 07:01 UTC
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 10.46.104.20
Host is up (0.00050s latency).
PORT      STATE SERVICE
31206/tcp open  unknown
</code></pre>
<p>Earlier I tried with LoadBalancer, as I thought it is kind of a superset of NodePort.<br />
<strong>Question</strong>: So why the exact opposite behaviour with NodePort in NodePort-type service and LoadBalancer-type service.<br />
From a <a href="https://stackoverflow.com/a/41510604/6740589">popular answer</a>:</p>
<blockquote>
<p>NodePort<br />
If you access this service on a nodePort from the node's external IP,
it will route the request to <code>spec.clusterIp:spec.ports[*].port</code>, which
will in turn route it to your <code>spec.ports[*].targetPort</code>, if set. This
service can also be accessed in the same way as ClusterIP.
...<br />
LoadBalancer<br />
You can access this service from your load balancer's IP address,
which routes your request to a nodePort, which in turn routes the
request to the clusterIP port.</p>
</blockquote>
<p>So, for a NodePort, the request goes like:</p>
<pre><code>NodeIP:NodePort -&gt; ClusterIP:Port -&gt; ClusterIP:TargetPort
</code></pre>
<p>Above <code>Port</code> is the port specified as <code>port</code> in yaml that exposes the Kubernetes service on the specified port within the cluster. And TargetPort is the port specified by <code>targetPort</code> in yaml on which the service will send requests to, that your pod will be listening on.</p>
<p>For a LoadBalancer, the behaviour I expected was:</p>
<pre><code>ExternalLBIP:NodePort --(load-balanced across nodes)--&gt; NodeIP:NodePort -&gt; ClusterIP:Port -&gt; ClusterIP:TargetPort
</code></pre>
<p>What I see is:</p>
<pre><code>ExternalLBIP:NodePort -&gt; (doesn't work)
</code></pre>
<p>And instead, what works is:</p>
<pre><code>ExternalLBIP:Port --(load-balanced across nodes)--&gt; NodeIP:Port -&gt; ClusterIP:Port -&gt; ClusterIP:TargetPort
</code></pre>

subtleseeker
<p>What you're seeing is right because the IP you're hitting with <code>nmap</code> is the IP of the <code>LoadBalancer</code> created by the service of type <code>LoadBalancer</code>, which is meant to be open at 80 (and/or 443). While <code>NodePort</code> is accessible on the IP of the worker node on which the pod and the service are running.</p>
<p>The service you've deployed here is of type <code>LoadBalancer</code> and not <code>NodePort</code>.</p>
<p>For further read, check <a href="https://kubernetes.io/docs/tutorials/stateless-application/expose-external-ip-address/" rel="nofollow noreferrer">this</a> out.</p>
<p><strong>Answer to the follow up question</strong>:</p>
<p>What you mentioned in what you expect and what actually works, both are incorrect.</p>
<p><code>ExternalLBIP:NodePort</code> : If you look at the post you shared, <code>&lt;NodePort&gt;</code> is accessible via <code>&lt;NodeIP&gt;</code> and not with External IP of the LB.</p>
<p><code>ExternalLBIP:Port --(load-balanced across nodes)--&gt; NodeIP:Port -&gt;</code> :  LB routes requests to a NodePort, so it will be <code>NodeIP:NodePort</code>.</p>
<p>So as to your question, the behaviour with <code>NodePort</code> in NodePort-type service and LoadBalancer-type service is not opposite. You just need to remember <code>NodePort</code> is to be accessed only on <code>NodeIP</code>.</p>
<p>In service type <code>NodePort</code>:</p>
<p><code>NodeIP:NodePort -&gt; ClusterIP:Port -&gt; Pod:TargetPort</code></p>
<p>In service type <code>LoadBalancer</code>:</p>
<p><code>ExternalIPofLB:Port -&gt; NodeIP:NodePort -&gt; ClusterIP:Port -&gt; Pod:TargetPort</code></p>
<p>Eg. from a running service of type <code>LoadBalancer</code>:</p>
<pre><code>kubectl get svc -n &lt;namespace&gt; &lt;service-name&gt;
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP                                                               PORT(S)          AGE
&lt;service-name&gt;-**********   LoadBalancer   172.20.96.130   a4b63c833c2***************d4-1996967498.&lt;region&gt;.elb.amazonaws.com   8443:31010/TCP   8m49s
</code></pre>
<p>As you can see in the below snippet, request will be forwarded from <code>LB Port to NodePort</code>.</p>
<p><a href="https://i.stack.imgur.com/dqkDf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/dqkDf.png" alt="Listener of the ELB" /></a></p>
