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
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!~ ^
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