I am struggling with running an nginx ingress controller in GKE with a simple fanout. I have three services behind three different paths. These are two microservices at paths /api/something
and /api/somethingelse
, and a frontend served at /
. The apis work fine, the frontend failes with Uncaught SyntaxError: Unexpected token '<'
in console. It fails to load the html/javascript/css properly.
I install the nging-ingress controller with the following command
helm install nginx-ingress stable/nginx-ingress \
--set rbac.create=true \
--set controller.publishService.enabled=true \
--set controller.service.type=LoadBalancer \
--set controller.service.loadBalancerIP=<static ip>
When this is done, I use this controller in my ingress:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: {{ printf "%s-ingress" (include "chart.fullname" .) }}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
labels:
{{- include "chart.labels" . | nindent 4 }}
spec:
rules:
- host: app.example.com # dns to the ip used when creating nginx ingress controller
http:
paths:
- path: "/"
backend:
serviceName: {{ include "frontend.fullname" . }}
servicePort: {{ .Values.frontend.service.port }}
- path: "/api/something(/|$)(.*)"
backend:
serviceName: {{ include "something.fullname" . }}
servicePort: {{ .Values.something.service.port }}
- path: /api/somethingelse(/|$)(.*)"
backend:
serviceName: {{ include "somethingelse.fullname" . }}
servicePort: {{ .Values.somethingelse.service.port }}
The names and ports of the services are correct, and it only "partially" fails to serve the frontend service.
EDIT:
I've figured out that the error is because of the way the controller does the url rewrite. When it matches /
, then /$2
will be the same as /
. Hence it will load the root app again and receive html where it expects for js or css. Thus the error.
The question is then, how can I map something on the root and if matched, do no url rewrite?
Solution was to create one ingress for the api that require url-rewrite, and one for the front that does not. From the question above, I replaced the one ingress with these two:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: {{ printf "%s-ingress" (include "chart.fullname" .) }}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
labels:
{{- include "chart.labels" . | nindent 4 }}
spec:
rules:
- host: app.example.com # dns to the ip used when creating nginx ingress controller
http:
paths:
- path: "/api/something(/|$)(.*)"
backend:
serviceName: {{ include "something.fullname" . }}
servicePort: {{ .Values.something.service.port }}
- path: /api/somethingelse(/|$)(.*)"
backend:
serviceName: {{ include "somethingelse.fullname" . }}
servicePort: {{ .Values.somethingelse.service.port }}
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: {{ printf "%s-frontend-ingress" (include "chart.fullname" .) }}
annotations:
kubernetes.io/ingress.class: nginx
labels:
{{- include "chart.labels" . | nindent 4 }}
spec:
rules:
- host: app.example.com # dns to the ip used when creating nginx ingress controller
http:
paths:
- path: "/"
backend:
serviceName: {{ include "frontend.fullname" . }}
servicePort: {{ .Values.frontend.service.port }}