Kubernetes Internal Service Axios NuxtJS

846 views Asked by At

I'm trying to learn Kubernetes as I go and I'm currently trying to deploy a test application that I made.

I have 3 containers and each container is running on its own pod

  • Front end App (Uses Nuxtjs)
  • Backend API (Nodejs)
  • MongoDB

For the Front End container I have configured an External Service (LoadBalancer) which is working fine. I can access the app from my browser with no issues.

For the backend API and MongoDB I configured an Internal Service for each. The communication between Backend API and MongoDB is working. The problem that I'm having is communicating the Frontend with the Backend API.

I'm using the Axios component in Nuxtjs and in the nuxtjs.config.js file I have set the Axios Base URL to be http://service-name:portnumber/. But that does not work, I'm guessing its because the url is being call from the client (browser) side and not from the server. If I change the Service type of the Backend API to LoadBalancer and configure an IP Address and Port Number, and use that as my axios URL then it works. However I was kind of hoping to keep the BackEnd-API service internal. Is it possible to call the Axios base URL from the server side and not from client-side.

Any help/guidance will be greatly appreciated.

Here is my Front-End YML File

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: mhov-ipp
  name: mhov-ipp
  namespace: mhov
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mhov-ipp
  template:
    metadata:
      labels:
        app: mhov-ipp
    spec:
      containers:
        - image: mhov-ipp:1.1
          name: mhov-ipp
          ports:
            - containerPort: 8080
          env:
            - name: NODE_ENV
              value: "development"
            - name: PORT
              value: "8080"
            - name: TITLE
              value: "MHOV - IPP - K8s"
            - name: API_URL
              value: "http://mhov-api-service:4000/"
---
apiVersion: v1
kind: Service
metadata:
  name: mhov-ipp-service
spec:
  selector:
    app: mhov-ipp
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 8082
      targetPort: 8080
      nodePort: 30600

Here is the backend YML File

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mhov-api-depl
  labels:
    app: mhov-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mhov-api
  template:
    metadata:
      labels:
        app: mhov-api
    spec:
      containers:
        - name: mhov-api
          image: mhov-api:1.0
          ports:
            - containerPort: 4000
          env:
            - name: mongoURI
              valueFrom:
                configMapKeyRef:
                  name: mhov-configmap
                  key: database_url
---
apiVersion: v1
kind: Service
metadata:
  name: mhov-api-service
spec:
  selector:
    app: mhov-api
  ports:
    - protocol: TCP
      port: 4000
      targetPort: 4000
1

There are 1 answers

1
moonkotte On BEST ANSWER

What is ingress and how to install it

Your guess is correct. Frontend is running in browser and browser "doesn't know" where backend is and how to reach out to it. You have two options here:

  • as you did with exposing backend outside your cluster
  • use advanced solution such as ingress

This will move you forward and will need to change some configuration of your application such as URL since application will be exposed to "the internet" (not really, but you can do it using cloud).

What is ingress:

Ingress is api object which exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

Most common option is nginx ingress - their page NGINX Ingress Controller.

Installation depends on cluster type, however I suggest using helm. (if you're not familiar with helm, it's a template engine which uses charts to install and setup application. There are quite a lot already created charts, e.g. ingress-nginx.

If you're using minikube for example, it already has built-in nginx-ingress and can be enabled as addon.

How to expose services using ingress

Once you have working ingress, it's type to create rules for it.

What you need is to have ingress which will be able to communicate with frontend and backend as well.

Example taken from official kubernetes documentation:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080

In this example, there are two different services available on different paths within the foo.bar.com hostname and both services are within the cluster. No need to expose them out of the cluster since traffic will be directed through ingress.

Actual solution (how to approach)

This is very similar configuration which was fixed and started working as expected. This is my answer and safe to share :)

As you can see OP faced the same issue when frontend was accessible, while backend wasn't.

Feel free to use anything out of that answer/repository.