Kubernetes - Frontend pod can't reach backend pod

12/10/2021

I have a minikube Kubernetes set up with two pods, each having one container. One for my Vue frontend and one for my backend API. I've also got two services attached to the pods.

My understanding is because the frontend and backend IP addresses change when the Pod is restarted or moved to a different node, we shouldn't use the IP Addresses to link them but a Service instead.

So in my case, my frontend would call my backend through the Service (which can also be used as the hostname) e.g. Service is called myapi-service, use http://myapi-service

My problem is after I launch my front end, any request it sends using the above hostname doesn't work, it's not able to connect to my backend.

app-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapi-deployment
  labels:
    app: myrapi
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapi
  template:
    metadata:
      labels:
        app: myapi
    spec:
      containers:
      - name: myapi
        image: myapi
        imagePullPolicy: Never
        ports:
        - containerPort: 80
        env:
        - name: TZ
          value: America/Toronto
        - name: ASPNETCORE_ENVIRONMENT
          value: Development_Docker
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myui-deployment
  labels:
    app: myui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myui
  template:
    metadata:
      labels:
        app: myui
    spec:
      containers:
      - name: myui
        image: myui
        imagePullPolicy: Never
        ports:
        - containerPort: 8080
        env:
        - name: NODE_ENV
          value: Development

app-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapi-service
  labels:
    run: myapi-service
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: myapi
  type: NodePort
  
---

apiVersion: v1
kind: Service
metadata:
  name: myui-service
  labels:
    run: myui-service
spec:
  ports:
  - port: 8080
    protocol: TCP
  selector:
    app: myui
  type: NodePort

Kubernetes Service

Am I missing a piece here/doing something wrong? Thanks so much.

UPDATE: If I go into my frontend container

curl myapi-service/swagger/index.html

It's able to pull up the API's swagger page

UPDATE 2, SOLUTION:

I refactored my Dockerfile to use NGINX to serve my front end Vue app

Dockerfile

FROM node:14 as builder

# make the 'app' folder the current working directory
WORKDIR /app

# copy both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./

# install project dependencies
RUN npm install

# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY . .

# build app
RUN npm run build

FROM nginx:alpine
COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf

## Remove default nginx index pagec
RUN rm -rf /usr/share/nginx/html/*

# Copy from the stage 1
COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]

and created a folder called .nginx in my front end's root folder with the nginx.conf file inside it. nginx.conf

worker_processes 4;

events { worker_connections 1024; }

http {
    server {
        listen 80;
        root  /usr/share/nginx/html;
        include /etc/nginx/mime.types;

        location /appui {
            try_files $uri /index.html;
        }
		
		location /api/ {
            proxy_pass http://myapi-service;
        }
    }
}

No Ingress controller required. The front end was able to talk to the backend as explained in Mikolaj's answer.

Hope someone out there can find this useful!~ ^

-- jlaw2000
docker
kubectl
kubernetes
minikube

1 Answer

12/12/2021

You cannot reach your backend pod from your frontend pod using kubernetes DNS like http://myapi-service because your frontend is running in the browser - outside your cluster. The browser doesn't undestrand the kubernetes DNS therefore cannot resolve your http://myapi-service url.

If you want to communicate frontend with your backend using K8S DNS you need to use any web server like nginx. The web server that host your frontend app is actually run on the kubernetes cluster so it understands the K8S DNS.

In your frontend code you need to change the api calls. Insead of directly call the api you need to first call youe web server.

For example: replace http://api-service/api/getsomething to /api/getsomething

/api/getsomething - this will tell the browser that it will send the request to the same server that served your frontend app (nginx in this case)

Then via nginx server the call can be forwarder to your api using the K8S DNS. (It is called reverse proxy)

To forward your requests to api add some code to nginx config file.

location /api/ {
    proxy_pass http://api-service.default:port;
}

*api-service - your k8s service name

*default - name of k8s api-service namespace

*port - api-service port

From now all your frontend requests contains /api/.. phrase will be forwarded to your api-service/api/..

/api/getsomething -> http://api-service/api/getsomething

-- Mikolaj
Source: StackOverflow