Reputation: 331
My frontend is setup as:
this.http.post<any>(`${environment.apiUrl}/auth/login`, {email, password})
Where apiUrl: 'http://backend/api'
I built the frontend in a container and exposed it to a loadbalancer service and I am trying to hook it up through a ClusterIP service to a backend on port 3000.
Frontend YAML:
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
tier: frontend
ports:
- port: 80
targetPort: 80
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
tier: frontend
replicas: 1
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: frontend
image: <Image>
imagePullPolicy: Always
ports:
- containerPort: 80
Backend YAML:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
selector:
matchLabels:
app: app
tier: backend
replicas: 1
template:
metadata:
labels:
app: app
tier: backend
spec:
containers:
- name: frontend-container
image: <Image>
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: app
tier: backend
ports:
- protocol: TCP
port: 80
targetPort: 3000
As explained in the doc here.
But it doesn't work when I try to access it from the browser, I receive Unknown Error!!
Here are screenshots from inside the frontend making sure it is able to reach the backend internally.
I don't understand where I went wrong here. I am thinking the apiUrl var set to http://backend is not being translated correctly because if I changed that to a loadbalancer IP and rebuilt the image, exposed the backend to a LB service instead of ClusterIP. It does work.
But obviously I don't want to expose my backend to a LB service.
Any idea?
Upvotes: 2
Views: 10773
Reputation: 31
We can use nginx reverse proxy as well . In which backend-service needs not to expose using ingress or load balancer. Below steps works fine for me
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)
sample docker file :
### STAGE 1: Build ###
FROM node:16 as build
# Create app directory
WORKDIR /app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# Bundle app source
COPY . .
RUN npm run build
###STAGE 2: Run ###
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/* && rm -rf /etc/nginx/conf.d/default.conf && rm -rf /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx
COPY --from=build /app/dist/angular-frontend /usr/share/nginx/html
#Optional to mention expose as it will be taken by nginx sever , port 80 wil be taken from nginx server
EXPOSE 80
sample nginx config file :
worker_processes 1;
events {
worker_connections 1024;
}
http {
#upstream local {
#server localhost:5000;
#}
upstream backend {
server backend-service:80;
}
server {
listen 80;
#server_name localhost;
server_name backend-service;
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend;
}
#location /api/v1/ {
#proxy_pass http://local;
#}
}
}
Note: This worked fine with k8s integration . But for local testing i used wsl2 in windows machine and and once replaced k8s backend-service config with localhost backend container . I got below error : *3 connect() failed (111: Connection refused) while connecting to upstream, client: 172.17.0.1,
I think there is an issue with wsl2 integration as mentioned here . https://github.com/Budibase/budibase/issues/4996
But works fine with k8s .
Upvotes: 3
Reputation: 499
As @Elgarni said, clients' browser could not access your cluster, so http://backend/api
is not resolvable outside to cluster.
If you defined ingress, use kubectl get ingress
command and learn your external IP. then replace your ${environment.apiUrl}
to http://$EXTERNAL_IP/api/
or
define DNS record for your external IP and reach via your defined domain.
Upvotes: 1
Reputation: 256
Look at the following:
outside world | k8s cluster
|
Browser --> | Nginx-pod --> backend-pod
|
|
The url http://backend/api
is only resolvable within the cluster, but your browser is in the outside world, so it does not know what this url is.
You ideally would use an ingress
to manage routes to cluster pods.
Upvotes: 3