nginx ingress: Cannot redirect to backend service - nginx

I have scoured the Net to try to resolve something that seems to be a common issue, but unfortunately all of the documentation and suggestions have not solve my problem. I hope that you can help me and others with it.
We are migrating from another ingress to nginx-ingress. To validate our installation, I am using httpbin as the backend service.
When I create the following ingress with a path of '/' and send the query, I receive a proper response.
curl -I -k http://abczzz.com/anything
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mikie-ingress
namespace: mikie
spec:
ingressClassName: nginx
rules:
- host: abczzz.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin-service
port:
number: 8999
What we really need is to be able to redirect to different services off of this single host, so I changed the ingress to the following, but the query always fails with a 404. Basically, I want the /httpbin to disappear and pass the path onto the backend service, httpbin.
curl -I -k http://abczzz.com/httpbin/anything
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mikie-ingress
namespace: mikie
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^(/httpbin)$ $1/ redirect;
spec:
ingressClassName: nginx
rules:
- host: abczzz.com
http:
paths:
- path: /httpbin(/|$)(.*)
pathType: Prefix
backend:
service:
name: httpbin-service
port:
number: 8999
I'd really appreciate your help to resolve what must be a simple routing issue.
Thanks for your time and interest.

I finally figured things out... Hopefully, the following snippet will help others...
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mikie-ingress
namespace: mikie
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: abczzz.com
http:
paths:
- backend:
service:
name: httpbin-service
port:
number: 8999
path: /httpbin/(.*)
pathType: Prefix

Related

Ingress rewrite to two different services from one DNS

I am trying to reach out to two services from my DNS.
Example:- myportal.com
myportal.com/app1
I have my SSO and SSL implementation on "myportal.com" and on the home page I have a button which calls a service "myportal.com/app1". I have tried multiple things but I am not able to configure both properly.
From below ingress config I am able to redirect to "myportal.com/app1" but its not working properly for "myportal.com". I have tried multiple thing including default backend and its not working for me. When I use default backend then "myportal.com" works but it stops redirecting to /app1.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myportal-ingress-test
namespace: appspace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- myportal.com
secretName: secret
rules:
- host: myportal.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: portal-service
port:
number: 8097
- pathType: Prefix
path: /app1(/|$)(.*)
backend:
service:
name: app-ui-service
port:
number: 8087
I am fairly new to kubernetes and I am not sure if it's the correct way to implement such things. I am open to new implementation too if it's using ingress and routing to different services using same dns on different path.
Thanks in advance for the help!
I was able to resolve this issue. The redirect in an ingress file would work for all the paths, so I created a separate ingress for each path with individual redirects.
Ingress 1 - myportal.com (with SSO and SSL)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gcpportal-service-test
namespace: appspace
annotations:
nginx.ingress.kubernetes.io/x-forwarded-prefix: /myportal-service
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
ingressClassName: nginx
tls:
- hosts:
- myportal.com
secretName: secret
defaultBackend:
service:
name: myportal-service
port:
number: 80
rules:
- host: myportal.com
Ingress 2 - myportal.com/app1 (application deployed)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gcpportal-service-test-1
namespace: appspace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- myportal.com
secretName: secret
rules:
- host: myportal.com
- pathType: Prefix
path: /app1(/|$)(.*)
backend:
service:
name: app1-ui-service
port:
number: 8087
This helped me to resolve this issue. I also verified that this way is also a standard way and is provided in one of the documentation of nginx.
https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/

Stripprefix Middleware in NGINX Ingress controller

We have deployed Traefik 2.2 on our Kubernetes cluster with following ingress-route created to access our application. This configuration is working fine for us and is currently the same for our Production system as well.
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: application-xyz
spec:
tls: {}
entryPoints:
- web
- websecure
routes:
- match: "HostRegexp(`application-xyz.com`) && PathPrefix(`/`)"
kind: Rule
priority: 1
services:
- name: application-xyz-service
port: 80
- match: "PathPrefix(`/application-xyz/`)"
kind: Rule
services:
- name: application-xyz-service
port: 80
middlewares:
- name: application-xyz-stripprefix
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: application-xyz-stripprefix
namespace: frontend
spec:
stripPrefix:
prefixes:
- /application-xyz/
forceSlash: false
Question 1:
We are now planning to migrate from Traefik to Nginx Ingress Controller. Is there any way we can replicate the same on Nginx similar to Traefik configuration. I'm unsure if I'm comparing this in the right way or not. Would be grateful if we can get any pointers.
Question 2:
We wish to achieve stripprefix functionality in Nginx but didn't find any helpful documentation. Any leads in this regard is highly appreciated.
StripPrefix functionality in nginx ingress you can achieve using rewrite-target annotation.
When rewrite-target is used, regexp path matching is enabled and it allows you to match eny part of path into groups and rewrite path based on that.
In your case it would look like following:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: rewrite
namespace: default
spec:
rules:
- host: application-xyz.com
http:
paths:
- backend:
serviceName: application-xyz-service
servicePort: 80
path: /(.*)
- http:
paths:
- backend:
serviceName: application-xyz-service
servicePort: 80
path: /application-xyz/(.*)
Feel free to ask questions if you feel like my answer needs more detailed explaination.
#HelloWorld, thanks for the response. I have tried this config but didn't work as expected. Please check the code below which I tried.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: application-xyz-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: cname.application-xyz.com
http:
paths:
- backend:
serviceName: application-xyz-service
servicePort: 80
path: /(.*)
- host: application-xyz.com
http:
paths:
- path: /cname-sample/(.*)
backend:
serviceName: application-xyz-service
servicePort: 80
With this config, cname.application-xyz.com is working fine but application-xyz/cname-sample/ isn't working which is the prime thing I'm looking to resolve. Please let me know your thoughts.
This issue is now fixed. We haven't deployed some of the application dependencies which put us in wrong direction. The pods were showing Running status for and the application was waiting for the dependencies to load and didn't receive any requests to serve. Thank you HelloWorld for suggesting the right approach.

We hosted a website in AWS Kubernetes Service. niginx-ingress-path issue

We hosted a website in AWS Kubernetes Service. We are having following issue.
issue1.css not working
issue2:Redirection also not working
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myapp1-alerts-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
tls:
- hosts:
- dev-api.myapp1.solutions
secretName: myapp1-alerts-tls
rules:
- host: dev-api.myapp1.solutions
http:
paths:
- path: /alerts
backend:
serviceName: myapp1-alerts
servicePort: 80
enter image description here
Take a look at the official documentation. There you will find an example below:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
| kubectl create -f -
In this ingress definition, any characters captured by (.*) will be
assigned to the placeholder $2, which is then used as a parameter in
the rewrite-target annotation.
For example, the ingress definition above will result in the following
rewrites:
rewrite.bar.com/something rewrites to rewrite.bar.com/
rewrite.bar.com/something/ rewrites to rewrite.bar.com/
rewrite.bar.com/something/new rewrites to rewrite.bar.com/new
Adjust your config accordingly and please let me know if that helped.

Kubernetes Nginx Ingress removing part of URL

I'm deploying a simple app in Kubernetes (on AKS) which is sat behind an Ingress using Nginx, deployed using the Nginx helm chart. I have a problem that for some reason Nginx doesn't seem to be passing on the full URL to the backend service.
For example, my Ingress is setup with the URL of http://app.client.com and a path of /app1g going http://app.client.com/app1 works fine. However if I try to go to http://app.client.com/app1/service1 I just end up at http://app.client.com/app1, it seems to be stripping everything after the path.
My Ingress looks like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
creationTimestamp: "2019-04-03T12:44:22Z"
generation: 1
labels:
chart: app-1.1
component: app
hostName: app.client.com
release: app
name: app-ingress
namespace: default
resourceVersion: "1789269"
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/app-ingress
uid: 34bb1a1d-560e-11e9-bd46-9a03420914b9
spec:
rules:
- host: app.client.com
http:
paths:
- backend:
serviceName: app-service
servicePort: 8080
path: /app1
tls:
- hosts:
- app.client.com
secretName: app-prod
status:
loadBalancer:
ingress:
- {}
If I port forward to the service and hit that directly it works.
So I found the answer to this. It seems that as of Nginx v0.22.0 you are required to use capture groups to capture any substrings in the request URI. Prior to 0.22.0 using just nginx.ingress.kubernetes.io/rewrite-target: / worked for any substring. Now it does not. I needed to ammend my ingress to use this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
creationTimestamp: "2019-04-03T12:44:22Z"
generation: 1
labels:
chart: app-1.1
component: app
hostName: app.client.com
release: app
name: app-ingress
namespace: default
resourceVersion: "1789269"
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/app-ingress
uid: 34bb1a1d-560e-11e9-bd46-9a03420914b9
spec:
rules:
- host: app.client.com
http:
paths:
- backend:
serviceName: app-service
servicePort: 8080
path: /app1/?(.*)
tls:
- hosts:
- app.client.com
secretName: app-prod
status:
loadBalancer:
ingress:
- {}
Removing this line should fix your problem:
nginx.ingress.kubernetes.io/rewrite-target: /
The rewrite target annotation will do exactly what it says: rewrite your request to hit the "/" location. See nginx-ingress docs for rewrite target.

nginx-ingress works well for /, but not for subpaths

I have setup a name based ingress controller, but it doesn't seem to work for anything other than /.
So http://metabase.domain.com works but http://metabase.domain.com/style/app.css does not.
This is my config:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: domain
annotations:
kubernetes.io/ingress.global-static-ip-name: "domain"
name: domain-ingress
spec:
rules:
- host: metabase.domain.com
http:
paths:
- path: /
backend:
serviceName: metabase
servicePort: 80
- host: jenkins.domain.com
http:
paths:
- path: /
backend:
serviceName: jenkins
servicePort: 80
From the nginx.conf in the everything looks normal too. For some reason the nginx access and error logs are also empty so can't find anything from there too
As you mentioned, there is no error in the log files, and everything looks normal from
your perspective. I may suggest to tune up ingress using annotations tags.
I've checked documentation of ingress-nginx and found that below annotations may help a bit.
In some scenarios, the exposed URL in the backend service differs from the specified path
in the Ingress rule. Without a rewrite, any request will return 404.
Set the annotation
nginx.ingress.kubernetes.io/rewrite-target
to the path expected by the service.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something
If the Application Root is exposed in a different path and needs to be redirected, set the annotation
nginx.ingress.kubernetes.io/app-root
to redirect requests for /.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/app-root: /app1
name: approot
namespace: default
spec:
rules:
- host: approot.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /
If the application contains relative links, it is possible to add an additional annotation
nginx.ingress.kubernetes.io/add-base-url
that will prepend a base tag in the header of the returned HTML from the backend.
I got around to solving this, turns out somehow there was another ingress on my namespace that was a very old version of the nginx controller. I cleared my cluster and relaunched my ingress. Things worked out. Thanks for all the help everyone!

Resources