Web server does not respond in spite of the fact all K8S indicators are OK

I tried it on macOS and here is the result.

My previous answers based on using Kubernetes in Rancher Desktop where I could choose a specific version, and I wasn’t sure if it works the same in Docker Desktop, but I suspected. This is why my first thought was that you need to use NodePort, but I didn’t remember why, because the NodePort is the port that is forwarded from the Kubernetes node (Docker Desktop’s virtual machine) to the container and the IP of the virtual machine is not available from the outside. When I tried it in Rancher Desktop I didn’t even think about why NodePort should not work by default, since it worked and it was enough for me.

So I went to try it in Docker Desktop and realized that you have multiple options. If it were a usual Kubernetes cluster you would be able to access the node IP, but Rancher Desktop and Docker Desktop can detect which type of service you are using and forward ports based on that.

Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: demo
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP

If you are using type: ClusterIP which is the default, you can access the port defined in “port” on the cluster ip.

apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
  namespace: default
spec:
  ports:
    - protocol: TCP
      port: 8081
      targetPort: web
  selector:
    app: demo
  type: ClusterIP

Note that I used “web” as target port which is defined in the pod. It is not the port that you can access from the host. It is the port on which the process is listening in the container. Since it is a cluster ip service, nothing is forwarded, you can only access this port from another pod in the virtual machine.

You can use NodePort like this:

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
  namespace: default
spec:
  ports:
    - protocol: TCP
      port: 8081
      targetPort: web
      nodePort: 30000
  selector:
    app: demo
  type: NodePort

Again, port 8081 is available on the cluster ip and it is forwarded to the container’s “web” port, but you also have a nodePort which will be detected by Docker Desktop and it will be forwarded from your host to the container through your virtual machine and service to the container’s port (targetPort)

NodePort can’t be lower than 30000 by default.

The last option is using LoadBalancer.

apiVersion: v1
kind: Service
metadata:
  name: nginx-lb
  namespace: default
spec:
  ports:
    - protocol: TCP
      port: 8081
      targetPort: web
  selector:
    app: demo
  type: LoadBalancer

Now “port” will become a load balancer port and this will be forwarded from the host to the container. It will create a nodePort as well, but that is available only from the virtual machine since the type is not “NodePort” in this case.