How can I define the `limit_req_zone`? - nginx

I am working with nginx-ingress-controller (this is not the same that ingress-nginx )
I have this ingress file
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-test"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.org/location-snippets: |
limit_req zone=by_web;
spec:
ingressClassName: nginx
rules:
- host: my.domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
tls:
- hosts:
- my.domain.com
secretName: quickstart-example-tls
I was able to define a limit_req using nginx.org/location-snippets.
How can I define the limit_req_zone?
limit_req_zone $request_uri zone=by_web:10m rate=60r/m;
Regards.

According to this article from official documentation, you can define limit_req_zone by adding following ConfigMap keys to location-snippets and server-snippets annotations:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-test"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.org/location-snippets: |
geo $limit {
default 1;
10.0.0.0/8 0;
192.168.0.0/24 0;
}
map $limit $request_uri {
default '';
'1' $binary_remote_addr;
}
limit_req_zone $request_uri zone=by_web:10m rate=1r/s;
nginx.org/server-snippets: |
location / {
limit_req zone=by_web burst=10 nodelay;
}
spec:
ingressClassName: nginx
rules:
- host: my.domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
tls:
- hosts:
- my.domain.com
secretName: quickstart-example-tls
So this will let you rate limit to be defined on requests from anyone who is not on an “allowlist”

Related

How to capture subdomain in nginx ingress

I want to capture subdomain and rewrite URL with /subdomain, For example bhautik.bhau.tk rewrite to bhau.tk/bhautik.
I also https://github.com/google/re2/wiki/Syntax tried group syntax
Here is my nginx ingress config:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: subdomain
namespace: subdomain
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
# nginx.ingress.kubernetes.io/rewrite-target: /$sub
nginx.ingress.kubernetes.io/server-snippet: |
set $prefix abcd;
if ($host ~ ^(\w+).bhau\.tk$) {
// TODO?
}
nginx.ingress.kubernetes.io/rewrite-target: /$prefix/$uri
spec:
rules:
- host: "*.bhau.tk"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: subdomain
port:
number: 80
How do I capture subdomain from $host?
I believe you want a redirect instead of rewrite. Here is the server-snippet you need:
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ ^(?<subdom>\w+)\.(?<basedom>bhau\.tk)$) {
return 302 https://$basedom/$subdom/ ;
}
If you really want a rewrite where the URL that the user sees remains unchanged but instead the request will be routed to a subpath served by the same service:
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ ^(?<subdom>\w+)\.(?<basedom>bhau\.tk)$) {
rewrite ^/(.*)$ /$subdom/$1 ;
}
Remove the rewrite-target annotation that specifies $prefix. You don't need it.
The ?<capturename> and $capturename pair is the trick you are looking for.
You can try out the
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ "bhautik.bhau.tk")
{
rewrite ^ https://bhau.tk$host permanent;
}
name: test-ingress
spec:
rules:
- host: bhau.tk
http:
paths:
- backend:
serviceName: app-service
servicePort: 3000
path: (/|$)(.*)

Kubernetes nginx ingress controller Redirect

I have a website deployed in Kubernetes and ingress controller working.
I need to redirect my old subdomain to the new subdomain(old.example.com -> new.example.com).
I made some research and found that I have to use the annotation:
nginx.ingress.kubernetes.io/rewrite-target
my ingress file:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rancher-ing
namespace: test
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: "true"
ingress.kubernetes.io/secure-backends: "true"
ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
tls:
- hosts:
- new.example.com
secretName: new.example.com
rules:
- host: new.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rancher-logo-service
port:
number: 80
- host: old.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rancher-logo-service
port:
number: 80
i created an ingress controller config for the new url.
and updated the old config into this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rancher-ing-redirect
namespace: test
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: "true"
ingress.kubernetes.io/secure-backends: "true"
ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: https://new.example.com/
spec:
rules:
- host: old.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rancher-logo-service
port:
number: 80

Nginx Ingres Redirect only on path to another server

I have setup nginx ingress like this on kubernetes
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: animefanz-ktor-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
tls:
- hosts:
- mydomain.com
secretName: my-tls
rules:
- host: mydomain.com
http:
paths:
- path: /myapp(/|$)(.*)
backend:
serviceName: myservice
servicePort: 8080
So everything working fine but i want to do one thing when ever https://mydomian.com/myapp/api/history called then i want to redirect it to https://mydomain2.com/myapp2/api/history along with get params that is.
So i want to just forward one api request to another server.
I think you can configure it with nginx server-snippet/configuration-snippet annotation.
There is related stackoverflow question about that.
And examples provided by #Thanh Nguyen Van
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite /preview https://test.app.example.com$uri permanent;
spec:
rules:
- host: test.example.io
http:
paths:
- path: /
backend:
serviceName: service-1
servicePort: 80
- host: test.app.example.io
http:
paths:
- path: /preview/*
backend:
serviceName: service-2
servicePort: 80
And #Harsh Manvar
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/server-snippet: |
location ~ /preview {
rewrite /preview https://test.app.example.com$uri permanent;
}
name: staging-ingress
spec:
rules:
- host: test.example.io
http:
paths:
- path: /
backend:
serviceName: service-1
servicePort: 80
- path: /preview/*
backend:
url:
serviceName: service-2
servicePort: 80
tls:
- hosts:
- test.example.io
secretName: staging
Additionally there is related github issue about that.
Hope you find this useful.

Nginx ingress kubernetes Proxy Pass

I need configure a proxy pass in a nginx ingress.
The rule must be:
%USER%.test.domain.com to app.test.domain.com/%USER%
*It must be a proxy pass NOT a redirect
I created this Ingress but it does not work
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test02-ingress
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/server-snippet: |
server_name ~^(?<subdomain>.+)\.test\.domain\.it;
location = / {
proxy_pass https://app.test.domain.it/$subdomain/;
proxy_set_header Host $subdomain.test.domain.it;
}
spec:
rules:
- host: "*.test.domain.it"
http:
paths:
- path: /
backend:
serviceName: test01-svc
servicePort: 80
``

Is there a point of having pod-level nginx when using nginx ingress?

I was wondering if I should have the pod level nginx in the implementations below:
I was previously using a normal ingress and kube-lego after migrating from VMs and now I am using cert-manager and GKE.
My Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: myapp-static-ip
kubernetes.io/ingress.class: nginx
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/rewrite-target: /
certmanager.k8s.io/cluster-issuer: letsencrypt
namespace: default
spec:
tls:
- hosts:
- myapp.com
secretName: myapp-crt
rules:
- host:
http:
paths:
- path: /
backend:
serviceName: myapp
servicePort: http
My service:
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 32111
protocol: "TCP"
name: http
selector:
app: myapp
My Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: gcr.io/myapp-1/myapp:latest
imagePullPolicy: Always
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: cloudsql
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: cloudsql
key: password
-
name: STATIC_ROOT
value: https://storage.googleapis.com/myapp-api/static/
-
name: STATIC_URL
value: https://storage.googleapis.com/myapp-api/static/
-
name: MEDIA_ROOT
value: /myapp/media
-
name: MEDIA_URL
value: http://myapp.com/media/
-
name: nginx
image: nginx
command: [nginx, -g,'daemon off;']
imagePullPolicy: Always
volumeMounts:
-
name: api-nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
-
name: myapp-media
mountPath: /myapp/media/
ports:
- containerPort: 80
- image: b.gcr.io/cloudsql-docker/gce-proxy:1.05
name: cloudsql-proxy
command: ["/cloud_sql_proxy", "--dir=/cloudsql",
"-instances=myapp-1:europe-west1:myapp-api=tcp:5432",
"-credential_file=/secrets/cloudsql/credentials.json"]
volumeMounts:
- name: cloudsql-oauth-credentials
mountPath: /secrets/cloudsql
readOnly: true
- name: ssl-certs
mountPath: /etc/ssl/certs
- name: cloudsql
mountPath: /cloudsql
- name: myapp-media
mountPath: /myapp/media
volumes:
- name: cloudsql-oauth-credentials
secret:
secretName: cloudsql-oauth-credentials
- name: cloudsql
emptyDir:
- name: api-nginx-config
configMap:
name: api-nginx-config
-
name: myapp-media
persistentVolumeClaim:
claimName: myapp-media
my nginx conf:
apiVersion: v1
kind: ConfigMap
metadata:
name: api-nginx-config
data:
nginx.conf: |
events {
worker_connections 1024;
}
http {
upstream api {
server 127.0.0.1:8080 fail_timeout=0;
}
server {
access_log /var/log/nginx/http-access.log;
error_log /var/log/nginx/http-error.log;
listen 80;
listen [::]:80;
server_name myapp.com;
location /media/ {
alias /myapp/media;
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080/;
}
}
}
Is it serving any major purpose given I could directly map the myapp/media directly to /media in the volume mount and my tls is handled by ingress. My major concern is with the pod-level nginx as I highlighted earlier, is it useless in this case? Is it just a baggage I am carrying over from previous implementations?
Generally, there is not really a point to have an extra nginx pod. If you do, you would have something of a double ingress. An nginx ingress controller pod already has nginx in it and you can scale that up/down.
One reason you would want to keep it is for backward compatibility, if for example, you want to use an ingress but want to gradually roll it out in this sort of fashion: create new nginx ingress -> flip traffic from your own nginx only through the new nginx ingress and your own nginx, until you have flipped all your pods -> remove your own nginx gradually until you have removed them all.
Another reason is to support a very specific nginx configuration that is not supported by the nginx ingress controller yet.
You may need to run your own nginx as deployment , for the reasons listed in the above answer , plus , you may need to scale the nginx deployment , let say 10 replicas. you cant scale ingress like that. But in any case , you just need one of them.

Resources