How do you have a client deployment communicate with the api deployment in kubernetes

4/2/2020

All I ever get are CORS errors while on localhost and in the cloud. It works if I manually type in localhost or I manually get the service external IP and input that into the k8s deployment file before I deploy it, but the ability to automate this is impossibly if I have to launch the services, get the external IP and then put that into the configs before I launch each time.

API service

apiVersion: v1
kind: Service
metadata:
  labels:
    app: api
  name: api-service
spec:
  ports:
  - port: 8080 # expose the service on internal port 80
    protocol: TCP
    targetPort: 8080 # our nodejs app listens on port 8080
  selector:
    app: api # select this application to service
  type: LoadBalancer
status:
  loadBalancer: {}

Client Service

apiVersion: v1
kind: Service
metadata:
  name: client-service
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: client
  type: LoadBalancer
status:
  loadBalancer: {}

API deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: api
  name: api-deployment
spec:
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - image: mjwrazor/docker-js-stack-api:latest
        name: api-container
        imagePullPolicy: IfNotPresent
        resources: {}
        stdin: true
        tty: true
        workingDir: /app
        ports:
        - containerPort: 8080
        args:
        - npm
        - run
        - start
        envFrom:
        - configMapRef:
            name: server-side-configs
      restartPolicy: Always
      volumes: null
      serviceAccountName: ""
status: {}

Client Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: client
  name: client-deployment
spec:
  selector:
    matchLabels:
      app: client
  template:
    metadata:
      labels:
        app: client
    spec:
      restartPolicy: Always
      serviceAccountName: ""
      containers:
      - image: mjwrazor/docker-js-stack-client:latest
        name: client-container
        imagePullPolicy: IfNotPresent
        resources: {}
        ports:
        - containerPort: 80
status: {}

I tried adding an ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-origin: http://client-service.default
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
spec:
  rules:
    - host: api-development.default
      http:
        paths:
          - backend:
              serviceName: api-service
              servicePort: 8080

But didn't help either. here is the server.js

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: true }));

app.use(cors());

app.get("/", (req, res) => {
  res.json({ message: "Welcome" });
});

require("./app/routes/customer.routes.js")(app);

// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}.`);
});

But like I said I am trying to get this to resolve via the hostnames of the services and not have to use the external IP, is this even possible or did I misunderstand something along the way.

The client sends an axios request. Cannot use environment variables since you can't inject environment variables from k8s after the project is been build through webpack and docker into an image. I did find a really hacky way of creating a file with window global variables and then have k8s overwrite that file with new window variables. But again I have to get the external IP of the api first then do that.

-- mjwrazor
kubernetes
nginx-ingress
node.js

1 Answer

4/8/2020

As we discussed in the comments you need to get a real domain name in order to make it work as Automatic DNS resolution in your case basically requires it.

-- OhHiMark
Source: StackOverflow