0
votes

I have an issue, I am deploying an application on [hostname]/product/console, but the .css .js files are being requested from [hostname]/product/static, hence they are not being loaded and I get 404.

I have tried nginx.ingress.kubernetes.io/rewrite-target: to no avail.

I also tried using: nginx.ingress.kubernetes.io/location-snippet: | location = /product/console/ { proxy_pass http://[hostname]/product/static/; }

But the latter does not seem to be picked up by the nginx controller at all. This is my ingress.yaml

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-resource
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    # nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/location-snippet: |
      location = /product/console/ {
        proxy_pass http://[hostname]/product/static/;
        }
spec:
  rules:
    - host: {{.Values.HOSTNAME}}
      http:
        paths:
        - path: /product/console
          backend:
            serviceName: product-svc
            servicePort: prod ##25022
        - path: /product/
          backend:
            serviceName: product-svc
            servicePort: prod #25022

-- Can I ask for some pointers? I have been trying to google this out and tried some different variations, but I seem to be doing something wrong. Thanks!

1
Have you tried to run your application outside of Kubernetes? Does it work there? Have you tried to use a basic solution like kubernetes.io/ingress.class: "nginx" with no other annotations and a basic path like: "path: /*"?Dawid Kruk
Hey @DawidKruk thanks! I tried that, but still the same. What seems to be the issue is that when I go with public dns dns/product/console/ the assets are at dns/product/static. The requested URL seems to be IP Address:80. I wanted to add the proxy pass, but does not seem to work for me. I wonder if it is related to specific version, I am also on GKE.voidcraft
As I see from your configuration, the /product/console and /product/static/your_files are in the same service (hence pod). This should not create any issue when rewrite-target is not present, no additional configuration were done on nginx-ingress and path is set on /* assuming it works outside Kubernetes. I didn't hear you tried it outside of Kubernetes. Could you clarify it? I made a simple example with index.html and some css. I could post it for a reference but I am not sure this will help with this exact issue you are having.Dawid Kruk
@DawidKruk Hey, yes I did try to run it just locally and it works just fine. The exception is that when I run it on localhost, I am using localhost:port instead of public dns. I think rewriting the application so the static assets are configurable is probably the way. But if you have an example that might help, I will appreciate it nonetheless. Cheersvoidcraft
The thing that using HOSTNAME/ and localhost:port in that case should not make a difference if you do not have any things like nginx rewriting your requests on localhost. Basing on your configuration of Ingress can you confirm what are you trying to achieve is: 1) when requesting /product pass request to /product 2) when requesting /product/console pass request to /product/static. I will post my example with some troubleshooting steps.Dawid Kruk

1 Answers

5
votes

TL;DR

To diagnose the reason why you get error 404 you can check in nginx-ingress controller pod logs. You can do it with below command:

kubectl logs -n ingress-nginx INGRESS_NGINX_CONTROLLER_POD_NAME

You should get output similar to this (depending on your use case):

CLIENT_IP - - [12/May/2020:11:06:56 +0000] "GET / HTTP/1.1" 200 238 "-" "REDACTED" 430 0.003 [default-ubuntu-service-ubuntu-port] [] 10.48.0.13:8080 276 0.003 200 
CLIENT_IP - - [12/May/2020:11:06:56  +0000] "GET /assets/styles/style.css HTTP/1.1" 200 22 "http://SERVER_IP/" "REDACTED" 348 0.002 [default-ubuntu-service-ubuntu-port] [] 10.48.0.13:8080 22 0.002 200 

With above logs you can check if the requests are handled properly by nginx-ingress controller and where they are sent.

Also you can check the Kubernetes.github.io: ingress-nginx: Ingress-path-matching. It's a document describing how Ingress matches paths with regular expressions.


You can experiment with Ingress, by following below example:

  • Deploy nginx-ingress controller
  • Create a pod and a service
  • Run example application
  • Create an Ingress resource
  • Test
  • Rewrite example

Deploy nginx-ingress controller

You can deploy your nginx-ingress controller by following official documentation:

Kubernetes.github.io: Ingress-nginx

Create a pod and a service

Below is an example definition of a pod and a service attached to it which will be used for testing purposes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ubuntu-deployment
spec:
  selector:
    matchLabels:
      app: ubuntu
  replicas: 1 
  template:
    metadata:
      labels:
        app: ubuntu
    spec:
      containers:
      - name: ubuntu
        image: ubuntu
        command:
        - sleep
        - "infinity" 
---
apiVersion: v1
kind: Service
metadata:
  name: ubuntu-service
spec:
  selector:
    app: ubuntu
  ports:
    - name: ubuntu-port
      port: 8080
      targetPort: 8080
      nodePort: 30080
  type: NodePort 

Example page

I created a basic index.html with one css to simulate the request process. You need to create this files inside of a pod (manually or copy them to pod).

The file tree looks like this:

  • index.html
  • assets/styles/style.css

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="assets/styles/style.css">
  <title>Document</title>
</head>
<body>
  <h1>Hi</h1>
</body>

Please take a specific look on a line:

  <link rel="stylesheet" href="assets/styles/style.css">

style.css:

h1 {
  color: red;
}

You can run above page with python:

  • $ apt update && apt install -y python3
  • $ python3 -m http.server 8080 where the index.html and assets folder is stored.

Create an Ingress resource

Below is an example Ingress resource configured to use nginx-ingress controller:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress-example
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: 
    http:
      paths:
      - path: /
        backend:
          serviceName: ubuntu-service 
          servicePort: ubuntu-port

After applying above resource you can start to test.

Test

You can go to your browser and enter the external IP address associated with your Ingress resource.

As I said above you can check the logs of nginx-ingress controller pod to check how your controller is handling request.

If you run command mentioned earlier python3 -m http.server 8080 you will get logs too:

$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
10.48.0.16 - - [12/May/2020 11:06:56] "GET / HTTP/1.1" 200 -
10.48.0.16 - - [12/May/2020 11:06:56] "GET /assets/styles/style.css HTTP/1.1" 200 -

Rewrite example

I've edited the Ingress resource to show you an example of a path rewrite:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress-example
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: 
    http:
      paths:
      - path: /product/(.*)
        backend:
          serviceName: ubuntu-service 
          servicePort: ubuntu-port

Changes were made to lines:

    nginx.ingress.kubernetes.io/rewrite-target: /$1

and:

      - path: /product/(.*)

Steps:

  • The browser sent: /product/
  • Controller got /product/ and had it rewritten to /
  • Pod got / from a controller.

Logs from thenginx-ingress controller:

CLIENT_IP - - [12/May/2020:11:33:23 +0000] "GET /product/ HTTP/1.1" 200 228 "-" "REDACTED" 438 0.002 [default-ubuntu-service-ubuntu-port] [] 10.48.0.13:8080 276 0.001 200 fb0d95e7253335fc82cc84f70348683a
CLIENT_IP - - [12/May/2020:11:33:23 +0000] "GET /product/assets/styles/style.css HTTP/1.1" 200 22 "http://SERVER_IP/product/" "REDACTED" 364 0.002 [default-ubuntu-service-ubuntu-port] [] 10.48.0.13:8080 22 0.002 200 

Logs from the pod:

10.48.0.16 - - [12/May/2020 11:33:23] "GET / HTTP/1.1" 200 -
10.48.0.16 - - [12/May/2020 11:33:23] "GET /assets/styles/style.css HTTP/1.1" 200 -

Please let me know if you have any questions in that.