How to change request path in kubernetes

6/26/2019

Below is my Nodejs microservices pattern:

// api.ts
import { Router } from 'express';
const router = Router();
router.get(':id', ...doSomething);
router.post(':id', ...doSomething);
export default router;

// index.ts
import * as Express from 'express';
import API from './api.js';
basePath = process.env.basePath; // usually is project name
const app = Express();

// handle external call
app.use(basePath, API) // wish to remove this line 
// handle internal call from microservices
app.use(API) // preferred to be like this
...continue

Below is my kubeDeploy file inherit from colleague

apiVersion: apps/v1
kind: Deployment
metadata:
  name: $CI_PROJECT_NAME
  namespace: $KUBE_NAMESPACE
spec:
  replicas: 1
  selector:
    matchLabels:
      app: $CI_PROJECT_NAME
  template:
    metadata:
      labels:
        app: $CI_PROJECT_NAME
    spec:
      imagePullSecrets:
      - name: gitlabcred
      containers:
      - image: registry.gitlab.com/$GROUP_NAME/$CI_PROJECT_NAME:$CI_BUILD_REF_NAME
        imagePullPolicy: Always
        name: $CI_PROJECT_NAME
        ports:
        - containerPort: $PORT
        env:
          - name: basePath
            value: "$URL_PATH"
        resources: $KUBE_RESOURCES
        livenessProbe: $KUBE_LIVENESS
---
apiVersion: v1
kind: Service
metadata:
  name: $CI_PROJECT_NAME
  namespace: $KUBE_NAMESPACE
spec:
  ports:
  - port: $PORT
    protocol: TCP
    name: http
  selector:
    app: $CI_PROJECT_NAME
  sessionAffinity: ClientIP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: $CI_PROJECT_NAME
  namespace: $KUBE_NAMESPACE
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: $KUBE_DNS_NAME
    http:
      paths:
      - path: /$URL_PATH
        backend:
          serviceName: $CI_PROJECT_NAME
          servicePort: $PORT
  - http:
      paths:
      - backend:
          serviceName: $CI_PROJECT_NAME
          servicePort: $PORT

Above code and settings work fine in both internal and external call like below:

http://publicUrl.com/projectA/someId // external call, microservice receive request.path as "/projectA/someId"

http://publicUrl.com/projectB/someId // external call, microservice receive request.path as "/projectB/someId"

http://projectA/someId // internal call, microservice receive request.path as "/someId"

http://projectB/someId // internal call, microservice receive request.path as "/someId"

I wish to remove "app.use(basePath, API)" from my microservice to make it environment independant.

Is the anyway I can change my kubeDeploy to make it change the path I received inside my microservice from an external call to become "/someId"?

Update: Below is latest kubeDeploy updated by devops

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: $CI_PROJECT_NAME
  namespace: $KUBE_NAMESPACE
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: $KUBE_DNS_NAME
    http:
      paths:
      - path: /$URL_PATH(/|$)(.*)
        backend:
          serviceName: $CI_PROJECT_NAME
          servicePort: $PORT
  - http:
      paths:
      - backend:
          serviceName: $CI_PROJECT_NAME
          servicePort: $PORT

I tried above but I don't understand it become a redirect from browser side. Example: I when open http://publicUrl.com/projectA/help on my browser, somehow the url turn become http://publicUrl.com/help on browser address bar which it show "default backend - 404" due to Ingress unable to find a match path.

-- Simon
kubernetes
kubernetes-ingress

1 Answer

6/26/2019

You can use the rewrite annotations, but keep in mind these are a custom extension of the nginx controller and are not portable to all other implementations.

From their example:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /something(/|$)(.*)
-- coderanger
Source: StackOverflow