Cannot access ingress subpath using nginx - nginx

I have a containerized application that I deployed to kubernetes, and I'm now working on a ingress route to add to my ingress controller so I can access the application from outside the cluster.
My application has an index root and this page contains hyperlinks for other pages. When creating the ingress route I can access the index page eg. /something, but then when I click on an hyperlink which would direct me to a new page /something/new, I get instead /new .
Accessing the pod directly I can navigate through the application just fine.
I tried changing the annotation and the regex code on the paths but nothing seems to work so far.
Here's my ingress:
metadata:
name: something-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- backend:
serviceName: svc-something
servicePort: 8000
path: /something(/|$)(.*)
Expected to access the path /something/new but get /new instead. Did anyone run into the same issue?

Related

Ingress nginx path routing

I have a React application deployed on AKS and the URL to the application landing page is https://myapp.host.com/dev/
Currently the application have multiple screens to navigate for example: /profile
When I click the profile navigation button, it redirects to this url: https://myapp.host.com/profile which is not what I want. Although the profile page is able to load, however if the page is refreshed it will return error as the application is not able to read the https://myapp.host.com/profile URL. By right, I want it to be https://myapp.host.com/dev/profile so that even if the page is refreshed, the app will able to load.
Here is my Ingress configuration:
ingress:
name: myapp-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$1
hosts:
- host: myapp.host.com
paths:
- path: /dev/(.*)
pathType: Prefix
backend:
service:
name: myapp-svc
port:
number: 8080
tls:
- hosts:
- myapp.host.com
secretName: myapp-ingress-tls-secret
What should I change in my configuration?
I'm also a newbee for ingress, but maybe it's because that
according the ingress-nginx doc,
nginx.ingress.kubernetes.io/rewrite-target means that Target URI where the traffic must be redirected.
so
nginx.ingress.kubernetes.io/rewrite-target: /$1 means when you matched /dev/profile it will redirect to /profile
so maybe you can remove it and try again?

kubernetes nginx ingress controller rewrites

We have deployed a mockserver on kubernetes. Currently, we only have one hostname which is shared by couple other applications (using a different path). However, the dashboard is not working because of the css location. What's the best way to solve this problem?
Failed to load resource: the server responded with a status of 404 (), hostname/mockserver/dashboard/static/css/main.477cab2a.chunk.css
The ingress manifest:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
app.kubernetes.io/instance: mock-server
kubernetes.io/ingress.class: nginx-ingress-protected
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: mock-server-ingress
namespace: my-namespace
spec:
rules:
- host: hostname
http:
paths:
- backend:
serviceName: mock-server-svc
servicePort: 80
path: /testing(/|$)(.*)
This works fine if I request resource like hostname/testing/mockserver/expectation, the rewrites will be sending /mockserver/exepctation to the backend.
However, if for path hostname/testing/mockserver/dashboard, it is a html page which will loads hostname/mockserver/dashboard which doesn't exist. I can't wrap my head around this. Should I create another ingress with path /mockserver just to serve the css?
Your rewrite is working as expected. However,
there are some options you can choose from:
Create a second rule for the /mockserver (the simplest solution).
Play with capture groups:
Captured groups are saved in numbered placeholders, chronologically,
in the form $1, $2 ... $n. These placeholders can be used as
parameters in the rewrite-target annotation.
Use a paid solution.
The easiest would be to go for option 1 and create a second rule which would satisfy the path for the css.

GKE - expose service with Ingress and Internal Load Balancing

I have REST API Web service on Internal GKE cluster which I would like to expose with internal HTTP load balancing.
Let's call this service "blue" service:
I would like to expose it in following mapping:
http://api.xxx.yyy.internal/blue/isalive -> http://blue-service/isalive
http://api.xxx.yyy.internal/blue/v1/get -> http://blue-service/v1/get
http://api.xxx.yyy.internal/blue/v1/create -> http://blue-service/v1/create
http://api.xxx.yyy.internal/ -> http://blue-service/ (expose Swagger)
I'm omitting deployment yaml, since it's less relevant to discussion.
But my service yaml looks like this:
apiVersion: v1
kind: Service
metadata:
name: blue-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
selector:
app: blue-service
My Ingress configuration is the following:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: blue-ingress
annotations:
kubernetes.io/ingress.class: "gce-internal"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: api.xxx.yyy.internal
http:
paths:
- path: /blue/*
backend:
serviceName: blue-service
servicePort: 80
However, I'm receiving 404 for all requests. /blue/v1/get, /blue/v1/create and /blue/isalive returns 404.
In my "blue" application I log all my notFound requests and I can clearly see that my URIs are not being rewritten, the requests hitting the application are /blue/v1/get, /blue/v1/create and /blue/isalive.
What am I missing in Ingress configuration? How can I fix those rewrites?
I solved the problem and writing it here to memo it and hopefully someone will find it as useful.
First problem is that I have mixed annotations types. one of GKE ingress controller and second for Nginx Server controller. Currently GKE ingress controller doesn't support URL rewrite feature, so I need to use nginx ingress controller.
so I need to install Nginx based ingress controller. It cloud be done easily using Helm chart or or deployment yaml. However, by default this controller will expose ingress using external load balancer and this not what I want. So we need to modify deployment charts or YAML file of this controller.
I'm not using Helm, so I downoaded yaml itself using wget command.
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/cloud/deploy.yaml
Open it in editor and find the definition of Service names ingress-nginx-controller in namespace ingress-nginx. Add the following annotation.
cloud.google.com/load-balancer-type: "Internal"
After it I can run kubectl apply -f deploy.yaml command which will create Ingress controller for me. It will take a few minutes to provision it.
In addition I need to open firewall rule which will allow master nodes access worker nodes on port 8443/tcp.
And the last item is an ingress yaml itself which should look like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
kubernetes.io/ingress.class: "nginx"
name: blue-ingress
namespace: default
spec:
rules:
- host: api.xxx.yyy.internal
http:
paths:
- backend:
serviceName: blue-service
servicePort: 80
path: /blue(/|$)(.*)

Nginx rewrite-target overwritting domain/suffix/index.php to domain/index.php

recently I have deployed an kubernetes cluster which is running wordpress instance and phpmyadmin. I'm using Nginx ingress controller to perform path based routing for both the services. However, request to / is happening without any hassle but when I request domain.com/phpmyadmin/ I get a login page after which I have been redirected to domain.com/index.php instead of domain.com/phpmyadmin/index.php. Please suggest me possible turn around for this. Thank you guys for the support :)
My ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/add-base-url : "true"
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
# ingress.kubernetes.io/rewrite-target: "^/phpmyadmin/"
spec:
rules:
- host: example.domain.com
http:
paths:
- path: /
backend:
serviceName: wordpress
servicePort: 80
- path: /phpmyadmin(/|$)(.*)
backend:
serviceName: phpmyadmin
servicePort: 80
I'd say issue is not on Nginx Ingress side.
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
...
- path: /phpmyadmin(/|$)(.*)
Should work properly for you.
However there is second part, configuration of myphpadmin. As you didn't provide this configuration I would guess what could cause this issue.
Like mentioned in phpmyadmin docs, sometimes you need to set $cfg['PmaAbsoluteUri']
In some setups (like separate SSL proxy or load balancer) you might have to set $cfg['PmaAbsoluteUri'] for correct redirection.
As I based on this configuration, many depends on how you configured PMA_ABSOLUTE_URI, is it http://somedomain.com/phpmyadmin or different?
Is important as you might encounter situation like:
When you enter to http://somedomain.com/phpmyadmin and login you will be redirected to http://somedomain.com/ so Ingress will redirect you to path: / set in ingress
If you will again enter http://somedomain.com/phpmyadmin you will be able to see phpmyadmin content, like you would be already logged in.
You could try to add env in your myphpadmin deployment. It would look similar like below:
env:
- name: PMA_ABSOLUTE_URI
value: http://somedomain.com/myphpadmin/
Last thing, its not recommended to use expose phpmyadmin without https.
For some extra information you can read this article.
In short:
Nginx ingress configuration looks ok
Check your myphpadmin configuration, especially PMA_ABSOLUTE_URI.

why redirect (server-side) to root on nginx ingress (reverse proxy) & rewrite-target

I'm using Kubernetes with Nginx ingress controller and I have two services (srv1 and srv2) on my namespace which I want to access them like this:
https://xyz.example.com/srv1/ => (point to the root of srv1)
https://xyz.example.com/srv2/ => (point to the root of srv2)
for example, if someone hit the below URL :
https://xyz.example.com/srv1/page1.aspx
then, they will hit the page1.aspx which is in the root of my application in srv1
it works just fine with the below ingress file:
Problem:
I have a second page which is page2.aspx and I placed it next to page1.aspx, so both of them are in root, now if I click on a button on the page1 which has a server-side code to redirect us to the page2.aspx, then I expected to get us into the below URL:
https://xyz.example.com/srv1/page2.aspx
but instead, it will redirect me to the below path:
https://xyz.example.com/page2.aspx
Just for clarification, I put an HTML link in the page1 which point to page2, it works just fine because it works in the client-side instead of the server-side.
so far I used the below 3 languages for the server-side redirection and all of them have the same behaviour:
C# & .net core (versions 2.1 , 2.2 , 3.0 and 3.1)
Python (version 3.7)
Ruby (version 2.7.1)
so I think the problem is from Kubernetes, anyone has any idea?
here are my ingress YAML:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ds1-ingress
namespace: ds1
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
tls:
- hosts:
- xyz.example.com
secretName: tls-secret
rules:
- host: xyz.example.com
http:
paths:
- backend:
serviceName: srv1
servicePort: 80
path: /srv1/(.*)
- backend:
serviceName: srv2
servicePort: 80
path: /srv2/*
Github's link for source-code:
https://github.com/POC-Vault/Routing
Docker-hub' link for anyone who likes to pull the image and test it.
https://hub.docker.com/repository/docker/farzadjalali/k8s-routing
How to pull the docker image:
docker push farzadjalali/k8s-routing:latest

Resources