2
votes

I have an an nginx Ingress controller and let's encrypt + cert-manager deployed using helm. Accessing the frontend works fine, the problem is that the frontend pod calls the backend pod on a clusterIP service but fails with a block mixed content error?

frontend in Angular where api_url: 'http://backend/api'

If I run the workload without nginx-ingress-let's encrypt > no issues, the call succeeds.

So I am assuming because of https on the ingress and http client call results in that error.

How do I go about solving this? If I changed the frontend code api_url: https://backend/api, it won't work either because missing TLS cert on the service.

How can I use TLS on the clusterIP service between the fronend and backend??

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

enter image description here

enter image description here

Here are screenshots from inside the frontend making sure it is able to reach the backend internally.

enter image description here

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?

2

2 Answers

2
votes

You can do the TLS termination at the ingress layer, the ingress rule contains provision for that.

The nginx service will be exposed to external world via a public IP and it runs at LoadBalancer's level only, the termination has to be done only at one level, once the traffic comes into VPN of your kubernetes cluster, there is no need to keep things internally encrypted.

you can follow this stack overflow post , it shall help I guess. The TLS certificate will be automatically created by cert-manager, you just need to do the appropriate settings in the DNS.

0
votes

The solution that worked for me was an Ingress that routes to both services; frontend, and backend on / and /api paths.

Changing the apiUrl var in frontend as well from the name of the service 'backend' to the Ingress controller address: https://ADDRESS/api as others have pointed out the call would fail to resolve from the browser because https://backend is not routeable from outside K8s, resulting in Unknown Error.