How to route Angular in Kubernetes?

7/11/2018

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?

-- Fleuri
angular
angular-routing
google-cloud-platform
kubernetes

1 Answer

7/11/2018

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.

-- David Steiman
Source: StackOverflow