Kubernetes + ingress-nginx - two apps, one of which in / path - nginx

I have two apps on a Kubernetes cluster which need to be exposed. One is a OAuth2 based authenticator, the other is the client app using it.
I would like to have the client app on test.mydomain.com and the authenticator on test.mydomain.com/auth
I tried building the following ingress in Kubernetes:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
spec:
rules:
- http:
paths:
- path: /auth
backend:
serviceName: authenticator-service
servicePort: 8080
- path: /
backend:
serviceName: app-service
servicePort: 8080
For some reason, I can't get it to work, and whenever I try and hit test.mydomain.com/auth I end up hitting the main app-service. Am I doing something completely wrong? Is what I want to do even possible?

Try this -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
kubernetes.io/ingress.class: nginx
name: my-ingress
spec:
rules:
- host: test.mydomain.com
http:
paths:
- path: /(.*)
backend:
serviceName: app-service
servicePort: 8080
- path: /auth/(.*)
backend:
serviceName: authenticator-service
servicePort: 8080

Related

set rate-limits for specific apis in kubernetes nginx

I am currently using nginx-ingress-controller in my eks-cluster.
I want to set rate-limits for only specific apis like /healthz like mentioned here and not only all my APIs.
Is there a way i can do it?
Thanks in advance
For separate specific you can make another ingress resource
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/limit-rps: "15"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
labels:
name: ingress
name: ingress
spec:
rules:
- host: healthz.example.io
http:
paths:
- backend:
serviceName: hello
servicePort: 80
path: /healthz
While you can make one ingress resource for other API, without rate limit setup
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
labels:
name: ingress-2
name: ingress-2
spec:
rules:
- host: healthz.example.io
http:
paths:
- backend:
serviceName: hello
servicePort: 80
path: /data
- backend:
serviceName: hello
servicePort: 80
path: /api

ingress-nginx hide domain redirect & path based routing

I'm using ingress-nginx on kubernetes. I need to redirect incoming connections to / to a blog hosted on webflow and perform path-based routing.
Webflow provides a domain like website123.webflow.com. I would like to serve the blog without performing a redirect. I would like to mask the webflow domain and use the default instead.
Here's what I came with so far:
---
apiVersion: v1
kind: Service
metadata:
name: homepage
spec:
externalName: website123.webflow.io
type: ExternalName
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: my.custom.domain.com
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/load-balance: ewma
nginx.ingress.kubernetes.io/proxy-body-size: 4G
nginx.ingress.kubernetes.io/upstream-vhost: website123.webflow.io
service.beta.kubernetes.io/do-loadbalancer-hostname: my.custom.domain.com
labels:
source: github
name: http
namespace: panattt1
spec:
rules:
- host: my.custom.domain.com
http:
paths:
- path: /api
backend:
serviceName: http
servicePort: 80
- path: /images
backend:
serviceName: http
servicePort: 80
- path: /app
backend:
serviceName: http
servicePort: 80
- path: /game
backend:
serviceName: http
servicePort: 80
- path: /mapmaker
backend:
serviceName: http
servicePort: 80
- path: /dashboard
backend:
serviceName: http
servicePort: 80
- path: /
backend:
serviceName: homepage
servicePort: 80
tls:
- hosts:
- my.custom.domain.com
The above solution doesn't work as I'd like to. The URL in the browser changes from my.custom.domain.com to website123.webflow.io, which is not what I want.
I believe the host header reaches paths other than / which is not ideal. Not tested yet.
If remove nginx.ingress.kubernetes.io/upstream-vhost I get an error from webflow's CDN because the $host header uses a domain that is not available. Adding the custom domain produces the same error.
Any ideas if I can handle this situation gracefully using ingress-nginx?
This works for me without annotations like upstream-vhost etc.
kind: Service
metadata:
name: blog-service
namespace: panattt1
spec:
externalName: website123.webflow.io
ports:
- port: 8001
protocol: TCP
targetPort: 443
type: ExternalName
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/force-ssl-redirect: "true"
ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
name: blog-ingress
namespace: panattt1
spec:
rules:
- host: my.custom.domain.com
http:
paths:
- backend:
serviceName: blog-service
servicePort: 8001
path: /
tls:
- hosts:
- my.custom.domain.com

How to add blocking IP rules on each nginx-ingress host

I have searched a lot and I didn't find the solution. I want to block/allow ip's into each host definition in the nginx-ingress, not per locations.
This is the ingress.yaml:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: test1.test.com
#Blocking rules here, only affecting test1.test.com domain
http:
paths:
- path: /
backend:
serviceName: wordpressA
servicePort: 80
- host: test2.test.com
#Blocking rules here, only affecting test2.test.com domain
http:
paths:
- path: /
backend:
serviceName: wordpressB
servicePort: 80
Many thanks for your time
You need to split those host definitions into separate ingress rules.
Then you can use annotation to whitelist source range using following annotation :
nginx.ingress.kubernetes.io/whitelist-source-range
Something like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app1-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/24"
spec:
rules:
- host: app1.com
http:
paths:
- path: /
backend:
serviceName: app1-service
servicePort: http
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: app2-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/24"
spec:
rules:
- host: app2.com
http:
paths:
- path: /
backend:
serviceName: app2-service
servicePort: http
You can also use server snipper and add nginx config to the yaml.
Something like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
location / {
# block one workstation
deny 192.168.1.1;
# allow anyone in 192.168.1.0/24
allow 192.168.1.0/24;
# drop rest of the world
deny all;
}

nginx ingress sub path redirection

I have an ingress controller and ingress resource running with all /devops mapped to devopsservice in the backend. When I try to hit "http://hostname/devops" things work and I get a page (although without CSS and styles) with a set of hyperlinks for e.g one of them is "logs".
When I click on the "logs" hyperlink, it is redirecting me to http://hostname/logs whereas I need it to be http://hostname/devops/logs.
Any idea what I can do?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/add-base-url : "true"
spec:
rules:
- host: master1.dev.local
http:
paths:
- backend:
serviceName: devops1
servicePort: 10311
path: /devops
Looks like your ingress is not serving anything /devops/*. Try adding another path /devops/* with the same backend. Basically this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/add-base-url : "true"
spec:
rules:
- host: master1.dev.local
http:
paths:
- backend:
serviceName: devops1
servicePort: 10311
path: /devops/*
- backend:
serviceName: devops1
servicePort: 10311
path: /devops
Update: the above has been deprecated in favor of something like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: master1.dev.local
http:
paths:
- backend:
serviceName: devops1
servicePort: 10311
path: /devops(/|$)(.*)
If you access http://hostname/devops/logs directly from your browser, certainly you will get what you want. But since you click the hyperlink in the homepage, then you can only get http://hostname/logs, which will be certainly failed.
So, you need /logs backend configured in your ingress yaml to get it processed, and configure nginx.ingress.kubernetes.io/configuration-snippet to ensure /logs not get rewrote, like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/add-base-url : "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^/logs /logs break;
spec:
rules:
- host: master1.dev.local
http:
paths:
- backend:
serviceName: devops1
servicePort: 10311
path: /logs
- backend:
serviceName: devops1
servicePort: 10311
path: /devops
I met the similar issue recently.
Assuming the "logs" hyperlink in your html uses a relative path, which means the hyperlink doesn't start with '/', then I think you can try to hit the page at http://hostname/devops/ instead of http://hostname/devops. (Note a / suffix in the first url.).
Then the "logs" hyperlink will be formed as http://hostname/devops/logs.
I think it's about how the browser identifies the 'base' url. With accessing 'http://hostname/devops/, if there is no 'base' tag in the html header, the 'base' url will be figured out to be http://hostname/devops; while with 'http://hostname/devops', the base url will be http://hostname.
If it's not the case, there is discussion at https://github.com/kubernetes/ingress-nginx/issues/4149. It's suggested a workaround to use the nginx directive subs_filter with a configuration-snippet to make the href attributes relative and also add the base tag in the html header.
The ingress used is as below,
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: master1.dev.local
http:
paths:
- backend:
serviceName: devops1
servicePort: 10311
path: /devops(/|$)(.*)
The nginx.ingress.kubernetes.io/x-forwarded-prefix annotation can be used for this purpose.
It adds x-forwarded-prefix header to http request with a value from this annotation. You can use it, if your backend support such header.
For example, Spring Boot application can handle it by using property:
server.forward-headers-strategy=framework
In your case ingress would look like the following:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/x-forwarded-prefix: /devops
spec:
rules:
- host: master1.dev.local
http:
paths:
- backend:
serviceName: devops1
servicePort: 10311
path: /devops
This solution has its downsides. It forces you to declare each service in separate ingress.

Rewrite path for nginx Ingress

I need to point Ingress to images so that my Pods gets the URL, in full. I have the below config:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: solar-demo
annotations:
nginx.org/server-snippet: "proxy_ssl_verify off;"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: shmukler.example.com
http:
paths:
- path: /city/*
backend:
serviceName: solar-demo
servicePort: 3000
- path: /solar/*
backend:
serviceName: solar-demo
servicePort: 3001
If I keep the line: nginx.ingress.kubernetes.io/rewrite-target: /, my services inside the Pods get the rewritten paths, so /city/dublin becomes /dublin.
If I comment out the line nginx.ingress.kubernetes.io/rewrite-target: /, I just get 503 errors on the client side, and nothing in the logs. With rewrite, my services give me 404 because there is no route /dublin.
What am I doing wrong? How could I just pass the path on and have the Pods respond?
$ kubectl describe svc solar-demo
Name: solar-demo
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration=
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"solar-demo","namespace":"default"},"spec":{"ports":[{"name":"city","port":3000...
Selector: app=testapp
Type: ClusterIP
IP: 10.107.221.76
Port: city 3000/TCP
TargetPort: 3000/TCP
Endpoints: 172.17.0.3:3000,172.17.0.8:3000
Port: solar 3001/TCP
TargetPort: 3001/TCP
Endpoints: 172.17.0.3:3001,172.17.0.8:3001
Session Affinity: None
Events: <none>
Suggestions?
Here should be a working config:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: solar-demo
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: shmukler.example.com
http:
paths:
- path: /city
backend:
serviceName: solar-demo
servicePort: 3000
- path: /solar
backend:
serviceName: solar-demo
servicePort: 3001
What changed:
Removed * from paths
Specified ingress in the annotation
Removed re-write annotation
The path on an ingress (when using an nginx ingress) is like specifying the nginx location block. nginx does not use the * character in location blocks.

Resources