Multi Container ASP.NET Core app in a Kubernetes Pod gives error address already in use

3/20/2021

I have an ASP.NET Core Multi-Container docker app which I am now trying to host to Kubernetes cluster on my local PC. But unfortunately one container is starting and other is giving error address already in use.

The Deployment file is given below:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: multi-container-dep
  labels:
    app: aspnet-core-multi-container-app
spec:
  replicas: 1
  selector: 
    matchLabels:
      component: multi-container
  template:
    metadata: 
      labels:
        component: multi-container
    spec:
      containers:
        - name: cmultiapp
          image: multiapp
          imagePullPolicy: Never
          ports:
            - containerPort: 80
        - name: cmultiapi
          image: multiapi
          imagePullPolicy: Never
          ports:
            - containerPort: 81

The full logs of the container which is failing is:

Unable to start Kestrel.
  System.IO.IOException: Failed to bind to address http://[::]:80: address already in use.
   ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use
   ---> System.Net.Sockets.SocketException (98): Address already in use
     at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
     at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
     at System.Net.Sockets.Socket.Bind(EndPoint localEP)
     at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.<Bind>g__BindSocket|13_0(<>c__DisplayClass13_0& )
     --- End of inner exception stack trace ---
     at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.<Bind>g__BindSocket|13_0(<>c__DisplayClass13_0& )
     at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
     at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
     at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint endPoint, ConnectionDelegate connectionDelegate, EndpointConfig endpointConfig)

Note that I already tried putting another port to that container in the YAML file

ports:
    - containerPort: 81

But it seems to not working. How to fix it?

-- yogihosting
asp.net-core
docker
kubernetes

4 Answers

3/20/2021

Check whether your images exposes the same port or try to use the same port (see in the images Dockerfile).

I suppose, it is because of your images may be trying to start anything in the same port, so when first one get created it create perfectly but during second container creation it tries to use the same port, and it gets bind: address already in use error.

You can see the pod logs for one of your container (by kubectl logs <pod_name> <container_name>) then you will be clear.

I tried applying your yaml with one of my docker image (which used to start a server in 8080 port), then after applying the below yaml I got the same error as you got.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: multi-container-dep
  labels:
    app: aspnet-core-multi-container-app
spec:
  replicas: 1
  selector:
    matchLabels:
      component: multi-container
  template:
    metadata:
      labels:
        component: multi-container
    spec:
      containers:
        - name: cmultiapp
          image: shahincsejnu/httpapiserver:v1.0.5
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
        - name: cmultiapi
          image: shahincsejnu/httpapiserver:v1.0.5
          imagePullPolicy: Always
          ports:
            - containerPort: 8081

I saw the first pod's log which ran successfully by kubectl logs pod/multi-container-dep-854c78cfd4-7jd6n cmultiapp and the result is :

int port :  :8080
start called

Then I saw the second pod's log which crashed by kubectl logs pod/multi-container-dep-854c78cfd4-7jd6n cmultiapi and seen the below error:

int port :  :8080
start called
2021/03/20 13:49:24 listen tcp :8080: bind: address already in use  # this is the reason of the error

So, I suppose your images also do something like that.

What works

This below yamls ran successfully both container:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: multi-container-dep
  labels:
    app: aspnet-core-multi-container-app
spec:
  replicas: 1
  selector:
    matchLabels:
      component: multi-container
  template:
    metadata:
      labels:
        component: multi-container
    spec:
      containers:
        - name: cmultiapp
          image: shahincsejnu/httpapiserver:v1.0.5
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
        - name: cmultiapi
          image: nginx
          imagePullPolicy: Always
          ports:
            - containerPort: 80
apiVersion: apps/v1
kind: Deployment
metadata:
  name: multi-container-dep
  labels:
    app: aspnet-core-multi-container-app
spec:
  replicas: 1
  selector:
    matchLabels:
      component: multi-container
  template:
    metadata:
      labels:
        component: multi-container
    spec:
      containers:
        - name: cmultiapp
          image: shahincsejnu/httpapiserver:v1.0.5
          imagePullPolicy: Always
          ports:
            - containerPort: 80
        - name: cmultiapi
          image: nginx
          imagePullPolicy: Always
          ports:
            - containerPort: 8081
-- Sahadat Hossain
Source: StackOverflow

3/20/2021
  • If you have a docker compose yaml, please use Kompose Tool to convert it into Kubernetes Objects.

Below is the documentation link

https://kubernetes.io/docs/tasks/configure-pod-container/translate-compose-kubernetes/

  • Please use kubectl explain to understand every field of your deployment yaml

As can be seen in below explanation for ports, ports list in deployment yaml is primarily informational. Since both the containers in the Pod share the same Network Namespace, the processes running inside the containers cannot use the same ports.

kubectl explain deployment.spec.template.spec.containers.ports
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: ports <[]Object>

DESCRIPTION:
     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 is primarily informational. Not specifying a port here DOES NOT
     prevent that port from being exposed. Any port which is listening on the
     default "0.0.0.0" address inside a container will be accessible from the
     network. Cannot be updated.

     ContainerPort represents a network port in a single container.

FIELDS:
   containerPort        <integer> -required-
     Number of port to expose on the pod's IP address. This must be a valid port
     number, 0 < x < 65536.

   hostIP       <string>
     What host IP to bind the external port to.

   hostPort     <integer>
     Number of port to expose on the host. If specified, this must be a valid
     port number, 0 < x < 65536. If HostNetwork is specified, this must match
     ContainerPort. Most containers do not need this.

   name <string>
     If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
     named port in a pod must have a unique name. Name for the port that can be
     referred to by services.

   protocol     <string>
     Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP".
  • Please provide the Dockerfile for both images and docker compose files or docker run commands or docker service create commands for the existing multi container docker application for futher help.
-- Sagar Velankar
Source: StackOverflow

3/23/2021

I solved this by using environment variables and assigning aspnet url to port 81.

- name: cmultiapi
  image: multiapi
  imagePullPolicy: Never
  ports:
    - containerPort: 81
  env:
    - name: ASPNETCORE_URLS
      value: http://+:81

I would also like to mention the url where I got the necessary help. Link is here.

-- yogihosting
Source: StackOverflow

3/22/2021

To quote this answer: https://stackoverflow.com/a/62057548/12201084

containerPort as part of the pod definition is only informational purposes.

This means that setting containerPort does not have any influence on what port application opens. You can even skip it and don't set it at all.

If you want your application to open a specific port you need to tell it to the applciation. It's usually done with flags, envs or configfiles. Setting a port in pod/container yaml definition won't change a thing.

You have to remember that k8s network model is different than docker and docker compose's model.


So why does the containerPort field exist if is doesn't do a thing? - you may ask

Well. Actually is not completely true. It's main puspose is indeed for informational/documenting purposes but it may also be used with services. You can name a port in pod definition and then use this name to reference the port in service definition yaml (this only applies to targetPort field).

-- Matt
Source: StackOverflow