Add a custom header per rule on Kubernetes Ingress with Traefik - kubernetes

I'm moving to kubernetes using traefik as my Ingress Controller.
I have a single backend that should respond to 3000+ websites. Depending on the host, I need to add a custom header to the request before proxy passing it to the backend.
I can use the ingress.kubernetes.io/custom-request-headers annotation to add a custom header to the request but it's an annotation for the whole Ingress, so I would need to create 3000+ Ingresses, one for each website.
Is there another way to do this? Creating 3000+ Ingresses is the same thing as creating one Ingress with 3000+ rules?

Yes, you need to create one Ingress object per one host, if you want different headers her host.
You can do it by Traefik:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traeffic-custom-request-header
annotations:
ingress.kubernetes.io/custom-request-headers: "mycustomheader: myheadervalue"
spec:
rules:
- host: custom.configuration.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /
Also, the same thing you can do by Nginx Ingress Controller.
It has the support for configuration snipper. Here is an example of using it to set a custom header per Ingress object:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-configuration-snippet
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Request-Id: $request_id";
spec:
rules:
- host: custom.configuration.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /
BTW, you can use several different ingress controllers on your cluster, so it does not need to migrate everything to only one type of Ingress.

Related

how to setup yaml ingress in google cloud with redirect

I’m setting up an environment in Google Cloud with an ingress and load balancers.
I know how to setup hosts and paths to it but I can't figure out how to setup when a user goes to a specific site http://example.com/ I want him to redirect to http://example.com/en.
Note:
http => https
/ => /en
UPDATED
I added app-root: /en (but it doesn't do anything).
This is my current yaml:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: gce
kubernetes.io/ingress.global-static-ip-name: our-frontend-static-ip
networking.gke.io/managed-certificates: example-certificate
appgw.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/app-root: /en
name: example-ingress
namespace: default
spec:
rules:
- host: anotherexample.com
http:
paths:
- backend:
serviceName: anotherexample-service
servicePort: 80
- host: example.com
http:
paths:
- path: /nl
backend:
serviceName: example-nl-service
servicePort: 80
- path: /en
backend:
serviceName: example-en-service
servicePort: 80
So, there are 2 hosts in my yaml and I want: when the url is correct for 1 of the hosts: example.com it must go to example.com/en (this is for Multilanguage purposes)
We can change the settings in the loadbalancer ban after the sync from the ingress in changes it back.
Kubernetes supports multiple Ingress Controllers which are different from each other. For example, you are trying to use the Ingress GCE and there is also a popular Nginx Ingress.
The main problem in your use case is that the Ingress GCE is not supporting rewrites. An on-going feature request regarding that can be found here.
To be able to use the rewrites you will need to deploy the Nginx Ingress Controller and switch annotation in your yaml from:
kubernetes.io/ingress.class: "gce"
to:
kubernetes.io/ingress.class: "nginx"
The sources that will help you out with this are as follows:
Installation Guide
Rewrite
An example

why annotation: rewrite-target are required in ingress service

I created an ingress service from the kubernetes documentation, but I found that not putting below annotation made service unavailable. Why was this so?
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
Main reason to ask this question was that in K8s documentation, I found below code for ingress, but this did not work until and unless I put the above annotation. So, why does the below code not work?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-wear-watch
namespace: app-space
spec:
rules:
- http:
paths:
- path: /wear
pathType: Prefix
backend:
service:
name: wear-service
port:
number: 8080
- path: /watch
pathType: Prefix
backend:
service:
name: video-service
port:
number: 8080
Based on k8s docs, all you need to know in this specific case is that
you can use Kubernetes annotations to attach arbitrary non-identifying metadata to objects. Clients such as tools and libraries can retrieve this metadata.
[annotations are] Directives from the end-user to the implementations to modify behavior or engage non-standard features.
So basically this specific annotations are used to modify behaviour of ingress and are specififc to nginx ingress controller (this means that if you use different controller, this annotations wont work).
All supported annotations for nginx ingress controler are explained in Nginx Ingress Controller documention.

How to allow multiple IPs only on ingress

I have number of IPs and I want only to allow those IP into my ingress
I know I can do this with in my ingress annotations,
nginx.ingress.kubernetes.io/whitelist-source-range: 10.0.0.0/16
But what I want is that I have multiple IPS and not only 10.0.0.0/16
So If for example I have IPs like 178.1.0.2/17,10.0.0.0/16,178.2.0.3/18 and I only want to allow this IPs to my ingress then how can I acheive that.
If you are using Nginx Ingress you can do it adding specific annotation whitelist-source-range.
nginx.ingress.kubernetes.io/whitelist-source-range
You can specify allowed client IP source ranges through the nginx.ingress.kubernetes.io/whitelist-source-range annotation. The value is a comma separated list of CIDRs, e.g. 10.0.0.0/24,172.10.0.1.
To configure this setting globally for all Ingress rules, the whitelist-source-range value may be set in the NGINX ConfigMap.
Also keep in mind that:
Adding an annotation to an Ingress rule overrides any global restriction.
Also if you would like to use Ingress Whitelist IP for Path you can check this thread.
Example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/whitelist-source-range: 10.0.0.0/16,178.2.0.3/18,178.1.0.2/17
spec:
rules:
- host: something.something.com
http:
paths:
- path: /app1
backend:
serviceName: app1
servicePort: 80
- path: /api
backend:
serviceName: api
servicePort: 8000
ingress.extensions/frontend created

Kubernetes Ingress rule define multiple DNS name

I am running bare metal v1.9 cluster. I was able define one DNS name app1-dev.com for the ingress rule, Is it possible to define multiple name for the same ingress rule?
like
app1-dev.com
appdev.com
Here is my rule:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/rewrite-target: /
name: ingress-dev
namespace: default
spec:
rules:
- host: app1-dev.com
http:
paths:
- path: /web
backend:
serviceName: nginx-svc
servicePort: 80
You can only use sub-domain wildcards in host field (e.g. - host: "*.domain.com"), but there is no way to set multiple values so you have to repeat entire rule for each domain.

Troubleshooting kubernetes nginx controller routing

I can't get the nginx controller to route based on the hostname. The YAML below doesn't work - traffic goes to the default back-end / I get a 404. However, if I remove the value for host, the ingress controller successfully routes traffic to my-service. The service works successfully if I place it behind a load balancer but I want to have multiple services working for different host names so I want to use an ingress controller and use a single IP. Thoughts?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: test1.mydomain.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 80
The yaml looks slightly different than the rewrite example located here. The yaml is valid and kubectl apply or create should work but not produce the results you are expecting. Do you need the rewrite annotation or could you remove it and the back end service will respond without issue? If you don't need to rewrite anything try removing the yaml to just look like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
spec:
rules:
- host: test1.mydomain.com
http:
paths:
- backend:
serviceName: my-service
servicePort: 80