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.
kubernetes.io/ingress.class: "nginx"
with no other annotations and a basic path like:"path: /*"
? – Dawid Krukdns/product/console/
the assets are atdns/product/static
. The requested URL seems to beIP 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/product/console
and/product/static/your_files
are in the same service (hence pod). This should not create any issue whenrewrite-target
is not present, no additional configuration were done onnginx-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 withindex.html
and somecss
. I could post it for a reference but I am not sure this will help with this exact issue you are having. – Dawid KrukHOSTNAME/
andlocalhost:port
in that case should not make a difference if you do not have any things likenginx
rewriting your requests on localhost. Basing on your configuration ofIngress
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