Express API inside Kubernetes for react and react-native apps

4/23/2020

I am learning Kubernetes. I have Apollo-express GraphQL API, React frontend and React Native app. How do I connect (or) what service type should I use if I want GraphQL API to be able to connect with both frontend and mobile apps?

I got a route /hi that replies Hi! to check if it's up:

app.get('/hi', function (_req, res) {
  res.send('Hi!')
})

Here's my attempt for api.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: server-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: server-api
  template:
    metadata:
      labels:
        app: server-api
    spec:
      terminationGracePeriodSeconds: 5
      containers:
        - name: server-api
          imagePullPolicy: IfNotPresent
          image: my/server-api:latest
          ports:
            - name: gql
              containerPort: 8081
          env:
            - name: NODE_ENV
              value: "development"
            - name: REDIS_HOST
              value: "redis-cache"
            - name: REDIS_PORT
              value: "6379"
            - name: POSTGRES_URL
              valueFrom:
                secretKeyRef:
                  name: postgres-url
                  key: POSTGRES_URL
---
apiVersion: v1
kind: Service
metadata:
  name: server-api
spec:
  type: ClusterIP
  selector:
    app: server-api
  ports:
  - name: gql
    port: 8081
    targetPort: 8081
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: server-api-external
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - http:
        paths:
          - path: /api
            backend:
              serviceName: server-api
              servicePort: 8081

Minikube IP is 192.168.99.100. But it shows Cannot GET / at 192.168.99.100/api/hi.

What I am doing wrong? Please help.

-- Rario
express
javascript
kubernetes
node.js

1 Answer

4/23/2020

Your ingress is incorrect. With your ingress, when there is incoming request to /api/hi, ingress will match with /api path rule and rewrite the path to / acording to rewrite-target annotation.

To make it work you need to use the folowing ingress:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: server-api-external
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /api/(.*)
            backend:
              serviceName: server-api
              servicePort: 8081

Now a little explaination on how this works. Notice changes in path field and rewrite-target annotation. With this ingress, when there is incoming request to /api/hi, ingress will match /api/(.*) path rule, and then will extract whatever matches with (.*) group (that would be hi in this case). Next, ingress will use this matched group and rewrite the path to /$1, so / + first group match. At the end the path that your application receives will be /hi and this is what you are looking for.

Refer to Nginx Ingress Controller documantation for more detailed explaination of rewrite feature.

Let me know if something is not clear enough and needs more explaination.

-- HelloWorld
Source: StackOverflow