<p>I have some questions regarding my minikube cluster, specifically why there needs to be a tunnel, what the tunnel means actually, and where the port numbers come from.</p>
<h2>Background</h2>
<p>I'm obviously a total kubernetes beginner...and don't have a ton of networking experience.</p>
<p>Ok. I have the following docker image which I pushed to docker hub. It's a hello express app that just prints out &quot;Hello world&quot; at the <code>/</code> route.</p>
<p>DockerFile:</p>
<pre><code>FROM node:lts-slim
RUN mkdir /code
COPY package*.json server.js /code/
WORKDIR /code
RUN npm install
EXPOSE 3000 
CMD [&quot;node&quot;, &quot;server.js&quot;]
</code></pre>
<p>I have the following pod spec:</p>
<p>web-pod.yaml:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Pod
metadata:
  name: web-pod
spec:
  containers:
    - name: web
      image: kahunacohen/hello-kube:latest
      ports:
      - containerPort: 3000
</code></pre>
<p>The following service:</p>
<p>web-service.yaml</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: NodePort
  selector:
    app: web-pod
  ports:
    - port: 8080
      targetPort: 3000
      protocol: TCP
      name: http
</code></pre>
<p>And the following deployment:</p>
<p>web-deployment.yaml</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-pod
      service: web-service
  template:
    metadata:
      labels:
        app: web-pod
        service: web-service
    spec:
      containers:
      - name: web
        image: kahunacohen/hello-kube:latest
        ports:
        - containerPort: 3000
          protocol: TCP
</code></pre>
<p>All the objects are up and running and look good after I create them with kubectl.</p>
<p>I do this:</p>
<pre><code>$ kubectl get services                                                                            
NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes    ClusterIP   10.96.0.1      &lt;none&gt;        443/TCP          7h5m
web-service   NodePort    10.104.15.61   &lt;none&gt;        8080:32177/TCP   25m
</code></pre>
<ol start="4">
<li>Then, as per a book I'm reading if I do:</li>
</ol>
<pre><code>$ curl $(minikube ip):8080 # or :32177, # or :3000
</code></pre>
<p>I get no response.</p>
<p>I found when I do this, however I can access the app by going to <code>http://127.0.0.1:52650/</code>:</p>
<pre><code>$ minikube service web-service
|-----------|-------------|-------------|---------------------------|
| NAMESPACE |    NAME     | TARGET PORT |            URL            |
|-----------|-------------|-------------|---------------------------|
| default   | web-service | http/8080   | http://192.168.49.2:32177 |
|-----------|-------------|-------------|---------------------------|
🏃  Starting tunnel for service web-service.
|-----------|-------------|-------------|------------------------|
| NAMESPACE |    NAME     | TARGET PORT |          URL           |
|-----------|-------------|-------------|------------------------|
| default   | web-service |             | http://127.0.0.1:52472 |
|-----------|-------------|-------------|------------------------|
</code></pre>
<h2>Questions</h2>
<ol>
<li>what this &quot;tunnel&quot; is and why we need it?</li>
<li>what the targetPort is for (8080)?</li>
<li>What this line means when I do <code>kubectl get services</code>:</li>
</ol>
<pre><code>web-service   NodePort 10.104.15.61   &lt;none&gt;        8080:32177/TCP   25m
</code></pre>
<p>Specifically, what is that port mapping means and where <code>32177</code> comes from?</p>
<ol start="4">
<li>Is there some kind of problem with simply mapping the internal port to the same port number externally, e.g. 3000:3000? If so, do we specifically have to provide this mapping?</li>
</ol>

Aaron
<p>Let me answer on all your questions.</p>
<p>0 - There's no need to create pods separately (unless it's something to test), this should be done by creating deployments (or statefulsets, depends on the app and needs) which will create a <code>replicaset</code> which will be responsible for keeping right amount of pods in operational conditions. (you can get familiar with <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="nofollow noreferrer">deployments in kubernetes</a>.</p>
<hr />
<p>1 - <a href="https://minikube.sigs.k8s.io/docs/commands/tunnel/" rel="nofollow noreferrer">Tunnel</a> is used to expose the service from inside of VM where minikube is running to the host machine's network. Works with <code>LoadBalancer</code> service type. Please refer to <a href="https://minikube.sigs.k8s.io/docs/handbook/accessing/" rel="nofollow noreferrer">access applications in minikube</a>.</p>
<p>1.1 - Reason why the application is not accessible on the <code>localhost:NodePort</code> is NodePort is exposed within VM where <code>minikube</code> is running, not on your local machine.</p>
<p>You can find minikube VM's IP by running <code>minikube IP</code> and then <code>curl %GIVEN_IP:NodePort</code>. You should get a response from your app.</p>
<hr />
<p>2 - <code>targetPort</code> indicates the service with which port connection should be established. Please refer to <a href="https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service" rel="nofollow noreferrer">define the service</a>.</p>
<p>In <code>minikube</code> it may be confusing since it's pointed to the <code>service port</code>, not to the <code>targetPort</code> which is define within the service. I think idea was to indicate on which port <code>service</code> is accessible within the cluster.</p>
<hr />
<p>3 - As for this question, there are headers presented, you can treat them literally. For instance:</p>
<pre><code>$ kubectl get svc -o wide
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE    SELECTOR
web-service   NodePort    10.106.206.158   &lt;none&gt;        80:30001/TCP   21m    app=web-pod
</code></pre>
<p><code>NodePort</code> comes from your <code>web-service.yaml</code> for <code>service</code> object. <code>Type</code> is explicitly specified and therefore <code>NodePort</code> is allocated. If you don't specify <code>type</code> of service, it will be created as <code>ClusterIP</code> type and will be accessible only within kubernetes cluster. Please refer to <a href="https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types" rel="nofollow noreferrer">Publishing Services (ServiceTypes)</a>.</p>
<p>When service is created with <code>ClusterIP</code> type, there won't be a <code>NodePort</code> in output. E.g.</p>
<pre><code>$ kubectl get svc
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
web-service   ClusterIP   10.106.206.158   &lt;none&gt;        80/TCP    23m
</code></pre>
<p><code>External-IP</code> will pop up when <code>LoadBalancer</code> service type is used. Additionally for <code>minikube</code> address will appear once you run <code>minikube tunnel</code> in a different shell. After your service will be accessible on your host machine by <code>External-IP</code> + <code>service port</code>.</p>
<hr />
<p>4 - There are not issues with such mapping. Moreover this is a default behaviour for kubernetes:</p>
<blockquote>
<p>Note: A Service can map any incoming port to a targetPort. By default
and for convenience, the targetPort is set to the same value as the
port field.</p>
</blockquote>
<p>Please refer to <a href="https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service" rel="nofollow noreferrer">define a service</a></p>
<hr />
<p>Edit:</p>
<p>Depending on the <a href="https://minikube.sigs.k8s.io/docs/drivers/" rel="nofollow noreferrer">driver</a> of <code>minikube</code> (usually this is a <code>virtual box</code> or <code>docker</code> - can be checked on linux VM in <code> .minikube/profiles/minikube/config.json</code>), <code>minikube</code> can have different port forwarding. E.g. I have a <code>minikube</code> based on <code>docker</code> driver and I can see some mappings:</p>
<pre><code>$ docker ps -a
CONTAINER ID   IMAGE                                 COMMAND                  CREATED      STATUS      PORTS                                                                                                                                  NAMES
ebcbc898b557   gcr.io/k8s-minikube/kicbase:v0.0.23   &quot;/usr/local/bin/entr…&quot;   5 days ago   Up 5 days   127.0.0.1:49157-&gt;22/tcp, 127.0.0.1:49156-&gt;2376/tcp, 127.0.0.1:49155-&gt;5000/tcp, 127.0.0.1:49154-&gt;8443/tcp, 127.0.0.1:49153-&gt;32443/tcp   minikube
</code></pre>
<p>For instance 22 for ssh to ssh into <code>minikube VM</code>. This may be an answer why you got response from <code>http://127.0.0.1:52650/</code></p>
