Kubernetes - multiple configuration in one Ingress - nginx

I have different applications running in the same Kubernetes Cluster.
I would like multiple domains to access my Kubernetes Cluster and be redirected depending the domain.
For each domain I would like different annotations/configuration.
Without the annotations I have an ingress deployment such as:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: frontdoor
namespace: myapps
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
type: LoadBalancer
tls:
- hosts:
- foo.bar.dev
- bar.foo.dev
secretName: tls-secret
rules:
- host: foo.bar.dev
http:
paths:
- backend:
serviceName: foobar
servicePort: 9000
path: /(.*)
- host: bar.foo.dev
http:
paths:
- backend:
serviceName: varfoo
servicePort: 80
path: /(.*)
But They need to have multiple configuration, for example, one need to have the following annotation
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "PHPSESSID"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
And another would have this one
nginx.ingress.kubernetes.io/backend-protocol: "FCGI"
nginx.ingress.kubernetes.io/fastcgi-index: "index.php"
nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-cm"
Those configurations are not compatible, and I can't find a way to specify a configuration by host.
I also understand that it's impossible to have 2 Ingress serving External HTTP request.
So what am I not understanding / doing wrong ?

I also understand that it's impossible to have 2 Ingress serving External HTTP request
I am not sure where you've found this but you totally can do this.
You should be able to create two separate ingress objects like following:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: frontdoor-bar
namespace: myapps
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "PHPSESSID"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
type: LoadBalancer
tls:
- hosts:
- bar.foo.dev
secretName: tls-secret-bar
rules:
- host: bar.foo.dev
http:
paths:
- backend:
serviceName: barfoo
servicePort: 80
path: /(.*)
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: frontdoor-foo
namespace: myapps
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/backend-protocol: "FCGI"
nginx.ingress.kubernetes.io/fastcgi-index: "index.php"
nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-cm"
spec:
type: LoadBalancer
tls:
- hosts:
- foo.bar.dev
secretName: tls-secret-foo
rules:
- host: foo.bar.dev
http:
paths:
- backend:
serviceName: foobar
servicePort: 9000
path: /(.*)
This is a completely valid ingress configuration, and most probably the only valid one that will solve your problem.
Each ingress object configures one domain.

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

Multiple Nginx Ingress configuration with same hostname annotations/TLS problem

I have an application accessed via hostA.com and a path '/' defined. This application needs annotations:
nginx.ingress.kubernetes.io/auth-tls-secret: ca1
nginx.ingress.kubernetes.io/auth-tls-verify-client: optional
Also, I need to access the same application via the same hostname on a special URL '/v8/something/abc' with https:// but without client authentication, so I need to remove the annotations for TLS. I tried with two different Ingress objects, but it doesn't work because the other Ingress is ignored. Merge does not work because it does not accept TLS annotations. Does anyone know how to configure this?
These below are my ingress objects:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/auth-tls-secret: mynamespace/my-ca
nginx.ingress.kubernetes.io/auth-tls-verify-client: optional
name: ingressA
namespace: mynamespace
spec:
rules:
- host: hosta.com
http:
paths:
- backend:
serviceName: myservice
servicePort: http
path: /
tls:
- hosts:
- hosta.com
secretName: mysecret
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/auth-tls-verify-client: off
name: ingressB
namespace: mynamespace
spec:
rules:
- host: hosta.com
http:
paths:
- backend:
serviceName: myservice
servicePort: http
path: /v8/something/abc
tls:
- hosts:
- hosta.com
secretName: mysecret

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.

Resources