set rate-limits for specific apis in kubernetes nginx - 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

Related

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

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

Using master - minion Nginx ingress with oauth2-proxy authentication

I have an app running in a kubernetes cluster that uses TLS and oauth2 authentication as part of the Nginx ingress. It all runs fine but I now want to split my ingresses so that I have a master and a number of minions, making sure that all the authentication is handles for the complete host domain. When I do this the forced signin breaks. I can still reach it if I add the path manually but it is no longer required to reach the application. Is this possible to solve?
Example
Regular ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/auth-url: "https://my-app.com/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://my-app.com/oauth2/start?rd=https%3A%2F%2F$host$request_uri"
spec:
tls:
- secretName: my-app-com-tls
hosts:
- my-app.com
rules:
- host: my-app.com
http:
paths:
- path: /(.*)
backend:
serviceName: my-app
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: oauth2-proxy
annotations:
cert-manager.io/cluster-issuer: letsencrypt
kubernetes.io/ingress.class: nginx
labels:
app: oauth2-proxy
app.kubernetes.io/managed-by: Helm
chart: oauth2-proxy-3.1.0
heritage: Helm
release: oauth2-proxy
spec:
rules:
- host: my-app.com
http:
paths:
- backend:
serviceName: oauth2-proxy
servicePort: 80
path: /oauth2
tls:
- hosts:
- my-app.com
secretName: my-app-com-tls
Master - minion
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-app-ingress-master
annotations:
kubernetes.io/ingress.class: nginx
nginx.org/mergeable-ingress-type: "master"
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/auth-url: "https://my-app.com/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://my-app.com/oauth2/start?rd=https%3A%2F%2F$host$request_uri"
spec:
tls:
- secretName: my-app-com-tls
hosts:
- my-app.com
rules:
- host: my-app.com
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-app-ingress-minion
annotations:
kubernetes.io/ingress.class: nginx
nginx.org/mergeable-ingress-type: "minion"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: my-app.com
http:
paths:
- path: /(.*)
backend:
serviceName: my-app
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: oauth2-proxy
annotations:
kubernetes.io/ingress.class: nginx
nginx.org/mergeable-ingress-type: minion
labels:
app: oauth2-proxy
app.kubernetes.io/managed-by: Helm
chart: oauth2-proxy-3.1.0
heritage: Helm
release: oauth2-proxy
spec:
rules:
- host: my-app.com
http:
paths:
- backend:
serviceName: oauth2-proxy
servicePort: 80
path: /oauth2
It turns out that I had unintentionally found features that were defined in two different nginx-ingress-controller packages (nginxinc and kubernetes). So the reason that it breaks is simply that there is no support for master - minion hierarchy in the controller I am actually using in my cluster. And there seems not to be any support for the authentication in the other package.
I have created a feature suggestion.

Ability to exclude one page from https redirection in nginx ingress controller

I have an app in Kubernetes which is served over https. So now I would like to exclude one URL from that rule and use HTTP to serve it for performance reasons. I am struggling with that the whole day and it seems impossible.
These are my ingress YAML:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
field.cattle.io/publicEndpoints: '[{"addresses":["172.31.1.11"],"port":443,"protocol":"HTTPS","serviceName":"myservice:myservice","ingressName":"myservice:myservice","hostname":"app.server.test.mycompany.com","path":"/","allNodes":true}]'
kubernetes.io/ingress.class: nginx
creationTimestamp: "2020-02-17T13:14:19Z"
generation: 1
labels:
app-kubernetes-io/instance: mycompany
app-kubernetes-io/managed-by: Tiller
app-kubernetes-io/name: mycompany
helm.sh/chart: mycompany-1.0.0
io.cattle.field/appId: mycompany
name: mycompany
namespace: mycompany
resourceVersion: "565608"
selfLink: /apis/extensions/v1beta1/namespaces/mycompany/ingresses/mycompany
uid: c6b93108-a28f-4de6-a62b-487708b3f5d1
spec:
rules:
- host: app.server.test.mycompany.com
http:
paths:
- backend:
serviceName: mycompany
servicePort: 80
path: /
tls:
- hosts:
- app.server.test.mycompany.com
secretName: mycompany-tls-secret
status:
loadBalancer:
ingress:
- ip: 172.31.1.11
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
field.cattle.io/publicEndpoints: '[{"addresses":["172.31.1.1"],"port":80,"protocol":"HTTP","serviceName":"mycompany:mycompany","ingressName":"mycompany:mycompany-particular-service","hostname":"app.server.test.mycompany.com","path":"/account_name/particular_service/","allNodes":true}]'
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
creationTimestamp: "2020-02-17T13:14:19Z"
generation: 1
labels:
app-kubernetes-io/instance: mycompany
app-kubernetes-io/managed-by: Tiller
app-kubernetes-io/name: mycompany
helm.sh/chart: mycompany-1.0.0
io.cattle.field/appId: mycompany
name: mycompany-particular-service
namespace: mycompany
resourceVersion: "565609"
selfLink: /apis/extensions/v1beta1/namespaces/mycompany/ingresses/mycompany-particular-service
uid: 88127a02-e0d1-4b2f-b226-5e8d160c1654
spec:
rules:
- host: app.server.test.mycompany.com
http:
paths:
- backend:
serviceName: mycompany
servicePort: 80
path: /account_name/particular_service/
status:
loadBalancer:
ingress:
- ip: 172.31.1.11
So as you can see from above I would like to server /particular_service/ over HTTP. Ingress, however, redirects to HTTPS as TLS is enabled for that host in the first ingress.
Is there any way to disable TLS just for that one specific path when the same host is being used for configuration?
In short summary I would like to have:
https://app.server.test.mycompany.com
but
http://app.server.test.mycompany.com/account_name/particular_service/
I've tested with 2 ingress of the same domain, the first one with tls enabled and the second without tls and it worked.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: echo-https
spec:
tls:
- hosts:
- myapp.mydomain.com
secretName: https-myapp.mydomain.com
rules:
- host: myapp.mydomain.com
http:
paths:
- backend:
serviceName: echo-svc
servicePort: 80
path: /
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
name: echo-http
spec:
rules:
- host: myapp.mydomain.com
http:
paths:
- backend:
serviceName: echo-svc
servicePort: 80
path: /insecure
By the Nginx docs:
By default the controller redirects HTTP clients to the HTTPS port 443 using a 308 Permanent Redirect response if TLS is enabled for that Ingress.
This can be disabled globally using ssl-redirect: "false" in the NGINX config map, or per-Ingress with the nginx.ingress.kubernetes.io/ssl-redirect: "false" annotation in the particular resource.
Please let me if that helps.
Also add nginx.ingress.kubernetes.io/ssl-redirect ": "false". It had worked for me previously. You can give it a try.

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;
}

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