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

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.

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 - multiple configuration in one Ingress

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.

K8S Ingress 404 ssl backend

I have an issue I can't figure out. I have setup Nginx Ingress Controller on my managed k8s cluster. I'm trying to reach an SSL enabled pod behind and it does not work. I have 404 not found from Nginx and the certificate which is presented is the Nginx one. I have deployed the controller using their github repo and the default files following their doc.
I have setup a clear http pod for purpose tests and it works. It seems to be related to ssl.
I have tried many things to no avail. How can I reach an SSL pod behind nginx ?
Here's the Deployment + service (for the https one) resource I have setup :
apiVersion: apps/v1
kind: Deployment
metadata:
name: moulip-https
spec:
selector:
matchLabels:
app: moulip-https
replicas: 2
template:
metadata:
labels:
app: moulip-https
spec:
containers:
- name: "wabam"
image: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ports:
- containerPort: 443
imagePullSecrets:
- name: regcrd
---
apiVersion: v1
kind: Service
metadata:
name: https-svc
labels:
app: moulip-https
spec:
ports:
- port: 443
targetPort: 443
protocol: TCP
name: https
selector:
app: moulip-https
and my Ingress :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/rewrite-target: /
namespace: default
spec:
rules:
- host: https.moulip.lan
http:
paths:
- backend:
serviceName: https-svc
servicePort: 443
- host: test.moulip.lan
http:
paths:
- backend:
serviceName: hostname-svc
servicePort: 80
Many thanks for any guidance you could provide me with.
You are missing tls configuration in the ingress. follow sample below
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- sslexample.foo.com
secretName: testsecret-tls
rules:
- host: sslexample.foo.com
http:
paths:
- path: /
backend:
serviceName: service1
servicePort: 80

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.

Resources