1

I have ASP.NET CORE 6.0 application where Ocelot functions as an entry point for other microservices. All system is now deployed on Kubernetes. Besides, I have an Angular Application with RESTFUL API calls. The problem is that I cannot send Requests from the frontend to the backend using the Kubernetes services names.

I have tested the Ocelot Gateway on Kubernetes by adding a LoadBalancer Service. Everything works fine until this point. Below is the code for the Ocelot Gateway JSON file:

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "catalogapi-clusterip-srv",
          "Port": 80
        }
      ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Bearer",
        "AllowScopes": []
      }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://homey-gateway-clusterip-srv:80"
  }
}

The Kubernetes Yaml file for the Gateway:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: homey-gateway-depl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: homey-gateway
  template:
    metadata:
      labels:
        app: homey-gateway
    spec:
      containers:
        - name: homey-gateway
          image: ******
          imagePullPolicy: Always 
---
apiVersion: v1
kind: Service
metadata:
  name: homey-gateway-clusterip-srv
spec:
  type: ClusterIP
  selector:
    app: homey-gateway
  ports:
    - name: homey-gateway
      protocol: TCP
      port: 80
      targetPort: 80

I have also added a LoadBalancer for the Gateway to test if the routes are working fine

apiVersion: v1
kind: Service
metadata:
  name: homey-gateway-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: homey-gateway
  ports:
    - name: homey-gateway-port
      protocol: TCP
      port: 9090
      targetPort: 80

Apparently, The LoadBalancer functioned as expected and I can see that routes are working perfectly.

Now, the Angular application:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: homey-depl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: homey
  template:
    metadata:
      labels:
        app: homey
    spec:
      containers:
        - name: homey
          image: *****
          imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: homey-clusterip-srv
spec:
  type: ClusterIP
  selector:
    app: homey
  ports:
    - name: homey
      protocol: TCP
      port: 80
      targetPort: 80

To test it locally I have added a NodePort to make sure that I can get the application on the browser.

apiVersion: v1
kind: Service
metadata:
  name: homey-srv
  labels:
    name: homey
spec:
  type: NodePort
  selector:
    app: homey
  ports:
    - nodePort: 32391
      protocol: TCP
      port: 80
      targetPort: 80

This works also fine.

Now I want to make API HTTP calls from the frontend to the backend. I tried by imminently using the Kubernetes backend clusterip name like: http://homey-gateway-clusterip-srv:80. However, this does not work and resulted in Failed to load resource: net::ERR_NAME_NOT_RESOLVED

The only way it works is by using the port I have exported in the LoadBalancer to test the Gateway so: http://localhost:9090.

I have seen a similar issue here in Stackoverflow: Cannot make GET request to service from angular pod on kubernetes cluster

Therefore, I have added an Ingress networking for the backend and frontend as followed: Backend:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-homey-backend-srv
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
  rules:
    - http:
        paths:
          - path: /backend
            pathType: Prefix
            backend:
              service:
                name: homey-gateway-clusterip-srv
                port:
                  number: 80

and Frontend:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-homey-frontend-srv
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
    - http:
        paths:
          - path: /frontend
            pathType: Prefix
            backend:
              service:
                name: homey-clusterip-srv
                port:
                  number: 80

This approach does not work I am getting HTTP Error 404.0 - Not Found

I am not sure how to do this or how to configure it. Please help me by sharing the steps I need to follow, or at least tell me if I need to modify anything in the Ocelot Gateway file or in Kubernetes configurations. I have spent a lot of time on this with no results. Any help would be appreciated. Thanks!

Nour
  • 23
  • 4

1 Answers1

0

I've been having a very similar issue for the last few days. I have a Blazor SPA, a Duende Identity Server, and an Ocelot API gateway, which sits in front of my internal services I don't want exposed externally.

My specific issue is that my Blazor SPA (frontend) can't get past my ocelot-gateway because the gateway has trouble connecting to the identity server.

Blazor SPA ---> Ingress Proxy at (https://ocelot-gateway.com) ---> Ocelot Gateway Pod -x-> Identity Server via Ingress (https://identity.com)

I still haven't figured it out, but maybe my files can help you spot some differences in your setup and help you since our problems are pretty similar

As far as things you can try:

  1. Enabling your kubernetes cluster for ingress. For minikube, look here. For KinD, look here.

  2. Adding the host you specified in your ingress manifest (if you're running locally) to your /etc/hosts file like so. Make sure to use 127.0.0.1 instead of localhost. I can't remember where I read that, but basically I think it has to do with your local machine and docker defining localhost differently.

127.0.0.1 identity.com
127.0.0.1 pinpoint.com
127.0.0.1 ocelot-gateway.com
  1. Maybe make sure you specify what host you're using in your ingress manifest.

.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-com
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /frontend
        pathType: Prefix
        backend:
          service:
            name: homey-clusterip-srv
            port:
              number: 80
      - path: /backend
        pathType: Prefix
        backend:
          service:
            name: homey-gateway-clusterip-srv
            port:
              number: 80

I'm running my pods in a KinD K8s cluster.

I'm exposing my Blazor SPA, Identity Server, and Ocelot API gateway with Ingress objects.

ingress.blazor-spa.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: pinpoint-spa
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: selfsigned-issuer
    nginx.ingress.kubernetes.io/service-upstream: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: pinpoint.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: pinpoint-spa
                port:
                  name: http
  tls:
    - hosts:
        - pinpoint.com
      secretName: pinpoint-tls-cert

ingress.identity-server.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: identity-com
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: selfsigned-issuer
    nginx.ingress.kubernetes.io/service-upstream: "true"
spec:
  rules:
    - host: identity.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: identity-service
                port:
                  name: http
  tls:
    - hosts:
        - identity.com
      secretName: pinpoint-tls-cert

ingress.ocelot-gateway.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ocelot-gateway-com
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: selfsigned-issuer
    nginx.ingress.kubernetes.io/service-upstream: "true"
spec:
  rules:
    - host: ocelot-gateway.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: ocelot-gateway
                port:
                  name: http
  tls:
    - hosts:
        - ocelot-gateway.com
      secretName: pinpoint-tls-cert

Here are my Service manifests.

svc.blazor-spa.yaml

apiVersion: v1
kind: Service
metadata:
  name: pinpoint-spa
spec:
  type: ClusterIP
  selector:
    app: pinpoint-spa
  ports:
    - name: http
      port: 80
      targetPort: http
      protocol: TCP
    - name: https
      port: 443
      targetPort: https
      protocol: TCP

svc.identity-server.yaml

apiVersion: v1
kind: Service
metadata:
  name: identity-service
spec:
  type: ClusterIP
  selector:
    app: identity-service
  ports:
    - name: http
      port: 80
      targetPort: http
      protocol: TCP
    - name: https
      port: 443
      targetPort: https
      protocol: TCP

svc.ocelot-gateway.yaml

apiVersion: v1
kind: Service
metadata:
  name: ocelot-gateway
spec:
  type: ClusterIP
  selector:
    app: ocelot-gateway
  ports:
    - name: http
      port: 80
      targetPort: http
      protocol: TCP
    - name: https
      port: 443
      targetPort: https
      protocol: TCP

Here's my ocelot.json.

"GlobalConfiguration": {
    "BaseUrl": "https://ocelot-gateway.com",
    "ServiceDiscoveryProvider": {
      "Namespace": "default",
      "Type": "kube"
    }
  }

Hope this helps somehow!

Don Rodriguez
  • 43
  • 1
  • 9