<p>The <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#containerport-v1-core" rel="nofollow noreferrer">k8s docs clearly state</a> about <code>containerPorts</code>:</p>
<blockquote>
<p>List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but <strong>is primarily informational</strong>. <strong>Not specifying a port here DOES NOT prevent that port from being exposed</strong>. Any port which is listening on the default &quot;0.0.0.0&quot; address inside a container will be accessible from the network. Cannot be updated.</p>
</blockquote>
<p>But what happens when I have the following <code>containerPorts</code> configuration inside a workload (let's say a <code>Deployment</code>):</p>
<pre><code>    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
          - containerPort: 8089
            name: web
</code></pre>
<p>And in the <code>Service</code> exposing the workload I specify:</p>
<pre><code>spec:
  ports:
  - name: http
    port: 8081
    protocol: TCP
    targetPort: webz &lt;---- notice the misspelling 
  selector:
    app: nginx
  type: ClusterIP
</code></pre>
<p>The <code>Service</code> has no way to route the traffic to a <code>targetPort=webz</code>, because we've named our <code>containerPort</code> <code>web</code>.</p>
<p>What am I missing? If the <code>Service</code> won't indeed be able to route traffic to the workload, then I believe that calling this array &quot;primarily informational&quot; is a bit of an overstatement.</p>

zerohedge
<p>If you only use a port number, they are purely informational and dont influence anything native to kubernetes.</p>
<pre class="lang-yaml prettyprint-override"><code># pod
image: nginx:1.14.2
ports:
  - containerPort: 8089
</code></pre>
<p>However, as you noticed, things change a bit if you use a name. Then you can reference to the port number by name.</p>
<pre class="lang-yaml prettyprint-override"><code># pod
image: nginx:1.14.2
ports:
  - containerPort: 8089
    name: web
</code></pre>
<p>As you noticed as well, if you want to reference this name and get a corresponding port number, the name must exist in the list of ports.</p>
<p>It is still informational in that it doesn't actually change the port the container is listening on. It has no impact on the container at all. However, the information, being an information, can be used.</p>
<p>You can think of them as variables. For example:</p>
<pre class="lang-js prettyprint-override"><code>let web = 8000
let targetPort = web
</code></pre>
<p>Of course, we could also just write</p>
<pre class="lang-js prettyprint-override"><code>let targetPort = 8080
</code></pre>
<p>And exactly the second case is also possible in Kubernetes</p>
<pre class="lang-yaml prettyprint-override"><code># service
spec:
  ports:
    - port: 8081
      targetPort: 8080
  selector:
    app: nginx
</code></pre>
<p>You can see that the port is directly used in the service, and by doing this, you could omit the port list from your pod spec completely.</p>
<p>As a side note, you have the same options between ingress and service, in that you can decide to use names or port numbers.</p>
<p>So ultimately, whether you name things, is up to you. If you decide to use names, then of course the names must match.</p>
