I have an angular app I'm trying to deploy to Kubernetes in Google Cloud. My problem is, that whenever I try to navigate to a path within the app that's not the root path, for example http://[ip]/demo, the request isn't routed in the application but in the container: If I have a directory called 'demo' in the working directory, it'll try to return its contents, so mostly it returns 404.
I have successfully served the application from a virtual machine. My networking configurations are as follows:
service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: 2018-07-10T12:00:52Z
labels:
app: app
name: app
namespace: default
resourceVersion: "5759129"
selfLink: /api/v1/namespaces/default/services/app-service
uid: [redacted]
spec:
clusterIP: [redacted]
externalTrafficPolicy: Cluster
ports:
- nodePort: 30909
port: 80
protocol: TCP
targetPort: 80
selector:
app: app
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/backends: '{"k8s-be-30909--102c03247288a32a":"HEALTHY"}'
ingress.kubernetes.io/forwarding-rule: k8s-fw-default-app-ingress--102c03df7288a32a
ingress.kubernetes.io/target-proxy: k8s-tp-default-app-ingress--102c09bf7288a32a
ingress.kubernetes.io/url-map: k8s-um-default-app-ingress--102c9df4a288a32a
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"app-ingress","namespace":"default"},"spec":{"backend":{"serviceName":"app-service","servicePort":80}}}
creationTimestamp: 2018-07-10T12:10:08Z
generation: 1
name: app-ingress
namespace: default
resourceVersion: "5762158"
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/app-ingress
uid: [redacted]
spec:
backend:
serviceName: app-service
servicePort: 80
status:
loadBalancer:
ingress:
- ip: [redacted]
Does anyone know how to fix this?
You run into this issue, because k8s is trying to call the path /demo on your ingress, and there is no backend handling this path. This happens because of the angular history routing.
It works in dev because the the dev http server is aware of that, because of this:
rewrites": [ {
"source": "**",
"destination": "/index.html"
} ]
(check out this answer)
So, what you must achieve, is that all your URLs to your ingress are rewritten to /index.html. A rewrite target from nginx ingress is not the same, as it would translate /path/foo/bar to /foo/bar if your rewrite target is '/'
So, what are the options? You could dig into the ingress configuration. It looks like you are using the GKE ingress, you could use a different one, but a closer look didn't show up any specific configuration.
However, I would take out the crowbar for this problem and hack it off, by using a nginx container with all my custom rewrite rules and reverse proxy it to your angular app. In other words, I'm using nginx anyway if I deploy a prod angular application in a container. Just check out this guide to setup nginx for angular properly.
The result would be a docker image, containing a custom nginx with the angular and custom rules inside.