How do I redirect a www url to a no-www url using nginx-ingress-controller? - redirect

I am trying to get the url www.example.com to redirect itself to example.com while preserving everything about the original request in k8s 1.11.1
I am attempting to do this using a simple Ingress, and am then using annotations to redirect it.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/permanent-redirect: https://example.com
nginx.ingress.kubernetes.io/ssl-redirect: "True"
name: example-redirect
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: example
servicePort: http
The issue here is that I don't want to have any rules/backend. I simply want to redirect www.example.com to example.com using an Ingress, but k8s Ingresses require me to have rules. Are there any workarounds here?

Actually, Ingress resource has strongly defined prerequisites for the relevant API specification. You may exclude rules: field from the general configuration, however backend: should be definitely specified, in the way that Nginx Ingress controller could route network traffic to the target endpoint in case no rules declared or matched.
Whenever you create any specific settings for Nginx Ingress controller either via Annotations or ConfigMaps, both of the options doing the same job of applying some specific configuration to the underlying nginx.conf file which resides on nginx-ingress-controller Pod. It means that Ingress controller applies server {} and location {} blocks into the corresponded Nginx web server Pod for particular host:
server {
server_name www.example.com ;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
listen 443 ssl http2;
listen [::]:443 ssl http2;
.............
location / {
set $namespace "default";
set $ingress_name "example-redirect";
set $service_name "example";
set $service_port "http";
set $location_path "/";
......................
}
}
Therefore, I suppose that you can capture nginx.conf file, based on Ingress resource configuration and then apply it independently inside Ingress controller Pod.
I assume that you may consider also to use nginx.ingress.kubernetes.io/from-to-www-redirect: "true" annotation in order to achieve the goal in current scenario.

Following should do:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'www.example.com' ) {
rewrite ^ https://example.com$request_uri permanent;
}
name: example-redirect
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: example
servicePort: http

Related

Problem with SSL passthrough in Nginx Controller

I'm forced to use Nginx Ingress, but it's complicated and doesn't fulfill our requirements.
I tried to route traffic from Nginx ingress to Traefik, but it seems that redirection from HTTP to HTTPS doesn't work.
Here is how my Ingress looks like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
name: some-ingress
spec:
tls:
- hosts:
- "example.com"
secretName: some-secret
rules:
- host: "example.com"
http:
paths:
- backend:
serviceName: traefik
servicePort: 443
I don't know how to fix that. I tried different ways. Maybe there is another way to route HTTP traffic on port 80 to traefik service on port 80 and 443 to traefik service on port 443 (?)
Unfortunately, I'm not able to use any external load balancer because it's not provided. I'm aware that there is something called MetalLB, but I'm not able to fulfill all requirements.
Thank you in advance!
Did you try to add the backend-protocol annotation?
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

How to rewrite target to correct path in haproxy-ingress?

I try to use haproxy as load balance and haproxy-ingress as ingress controller in k8s.
my load balance config:
frontend MyFrontend_80
bind *:80
bind *:443
mode tcp
default_backend TransparentBack_https
backend TransparentBack_https
mode tcp
balance roundrobin
option ssl-hello-chk
server MyWebServer1 10.5.5.53
server MyWebServer2 10.5.5.54
server MyWebServer3 10.5.5.55
Ingress file:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: li
namespace: li
annotations:
# add an annotation indicating the issuer to use.
cert-manager.io/cluster-issuer: "letsencrypt-staging"
#haproxy.org/forwarded-for: true
kubernetes.io/ingress.class: haproxy
ingress.kubernetes.io/ssl-redirect: "true"
spec:
rules:
- host: a.b.c
http:
paths:
- path: /storage
backend:
serviceName: li-frontend
servicePort: 80
tls:
- hosts:
- a.b.c
secretName: longhorn-ui-tls
li-frontend is a dashboard ui service.
All is ok when I set the path field to blank in my ingress. and page is not normal when the path field seted to /storage or any non blank value.
I find some link not get correct position, e.g.
requst correct value
/main.js /storage/main.js
I found this in nginx-ingress:
#nginx.ingress.kubernetes.io/configuration-snippet: |
#rewrite ^/main(.*)$ /storage/main$1 redirect;
Does haproxy-ingress has same function?
I try these, but no effect:
ingress.kubernetes.io/app-root: /storage
ingress.kubernetes.io/rewrite-target: /storage
In addition, I use rewrite in nginx-ingress, but it don't work on websocket.
Sorry for my pool english.
for HAProxy:
you have to use haproxy annotation:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: web-ingress
namespace: default
annotations:
# replace all paths with /
haproxy.org/path-rewrite: "/"
# remove the prefix /foo... "/bar?q=1" into "/foo/bar?q=1"
haproxy.org/path-rewrite: (.*) /foo\1
# add the suffix /foo ... "/bar?q=1" into "/bar/foo?q=1"
haproxy.org/path-rewrite: ([^?]*)(\?(.*))? \1/foo\2
# strip /foo ... "/foo/bar?q=1" into "/bar?q=1"
haproxy.org/path-rewrite: /foo/(.*) /\1
spec:
# ingress specification...
Ref: => https://www.haproxy.com/documentation/kubernetes/1.4.5/configuration/ingress/

Ingress vs Direct Nginx Deployment on On-premise Kuber Cluster

I am setting up a kubernetes cluster in the On-Premise servers. Now for setting up external traffic, I can run Nginx Ingress behind Nodeport or I can run Nginx Deployment(Pods) with NodePort service exposed.
The only difference I got to know is with Ingress, I will get the sticky sessions which I anyhow do not need. So which one I should prefer and why?
Apart from this, I also have one requirement on Nginx Caching of htmls(with purging logic). So I have Nginx Deplpyment, then I can use PVC and PV. But what if I use Nginx Ingress. How will it work then.
When you expose a Nginx Deployment you essentially create a L4 load balancer with Ingress you are creating a L7 load balancer.
If you want to host multiple domains like example1.com, example2.com so on the having a L7 load balancer makes sense also you can have defaulted backend defined if you want the request to endup somewhere special like some special service or endpoint.
Coming to 2nd part of enabling cache you can do it in ingress controller as follows:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mywebsite
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-buffering: "on" # Important!
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_cache static-cache;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_404 http_500 http_502 http_503 http_504;
proxy_cache_bypass $http_x_purge;
add_header X-Cache-Status $upstream_cache_status;
say you want to enable it for 1 path not for others, like you want to enable it for /static/ path and not for / path then you can have:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mysite
annotations:
ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: 10m
spec:
tls:
- secretName: mysite-ssl
hosts:
- mysite.example.com
rules:
- host: mysite.example.com
http:
paths:
- path: /
backend:
serviceName: mysite
servicePort: http
---
# Leverage nginx-ingress cache for /static/
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mysite-static
annotations:
nginx.ingress.kubernetes.io/proxy-buffering: "on"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_cache static-cache;
proxy_cache_valid 404 10m;
proxy_cache_use_stale error timeout updating http_404 http_500 http_502 http_503 http_504;
proxy_cache_bypass $http_x_purge;
add_header X-Cache-Status $upstream_cache_status;
spec:
rules:
- host: mysite.example.com
http:
paths:
- path: /static/
backend:
serviceName: mysite
servicePort: http
Ultimately the design decision is yours, honestly its better to use ingress controller as it gives way more flexibility.
I hope this clears this up for you.

Nginx ingress controller still redirect to SSL

I am experiencing this issue. My application needs to receive connection under SSL only with WebSocket. HTTP requests should be forced to not being redirected. My ingress configuration is
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: in-camonline
namespace: cl5
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.org/websocket-services: "svc-ws-api"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
ingress.kubernetes.io/affinity: "ClientIP"
spec:
tls:
- hosts:
- foo.bar.com
secretName: cl5-secret
rules:
- host: foo.bar.com
http:
paths:
- path: /socket.io
backend:
serviceName: svc-ws-api
servicePort: 8000
- path: /
backend:
serviceName: svc-http-service
servicePort: 80
I also disabled the ssl-redirect globally adding an item into the ConfigMap
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
#use-proxy-protocol: "false"
ssl-redirect: "false"
Now if I do request using curl, requests won't being redirected. If I try to run my front-end application every request after the WSS will be forced to being redirected to use HTTPS
Request URL: http://foo.bar.com/2/symbols
Request Method: OPTIONS
Status Code: 307 Internal Redirect
Referrer Policy: no-referrer-when-downgrade
Any suggestion about how to achieve that?
Finally, I sorted it out. If someone is reading this, easy you are not alone!
Jokes aside, nginx-controller was setting header Strict-Transport-Security after the first HTTPS call (socket.io polling in my case). This header forces the browser to use TLS for the next requests. You can read more about this header here https://developer.mozilla.org/it/docs/Web/HTTP/Headers/Strict-Transport-Security
What I did is to disable the option adding the entry hsts: false on the ingress-controller's ConfigMap object.
You can find more here https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#hsts
Hope this can help you :)
There is another solution.
If you want to disable HSTS just make the max-age zero. like this!!
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($scheme = https) {
add_header Strict-Transport-Security "max-age=0;";
}
link : https://justin-g.tistory.com/176

Kubernetes NGINX Ingress configmap 301 redirect

Using an NGINX Ingresss in Kubernetes, I can't see a way to forward my traffic from non-www to www, or to another domain etc on a per-host basis
I've tried looking in configmap docs but can't see what I need. Maybe it can go in the ingress itself?
I've also seen an example using annotations but this seems to be ingress-wide, so I couldn't have specific redirects per host
Indeed a redirect is possible with a simple annotation:
nginx.ingress.kubernetes.io/permanent-redirect: https://www.gothereinstead.com
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
But as you mentioned, it's "Ingress" wide and not configurable per host, per domain or even per path. So you'll have to do it yourself through the ingress.kubernetes.io/configuration-snippet annotation, which gives you a great deal of power thanks to regular expressions:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: self-made-redirect
annotations:
ingress.kubernetes.io/configuration-snippet: |
if ($host = 'blog.yourdomain.com') {
return 301 https://yournewblogurl.com;
}
if ($host ~ ^(.+)\.yourdomain\.com$) {
return 301 https://$1.anotherdomain.com$request_uri;
}
spec:
rules:
- host: ...
If you are not quite used to NGINX, you'll know more about what's possible in the snippet, particularly what is the $host variable right in the NGINX documentation.
To redirect all traffic regardless of using HTTP or HTTPS from example.com and www.example.com to newdomain.example.com I ended up with the following solution.
In this example I'm also using cert-manager.io to request the certs for www.example.com and example.com.
The redirect is done using the annotation nginx.ingress.kubernetes.io/permanent-redirect
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: redirect-example-to-newdomain
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/permanent-redirect: https://newdomain.example.com
spec:
tls:
- hosts:
- example.com
- www.example.com
secretName: example.com-tls
rules:
- host: example.com
- host: www.example.com
I have problem with annotations server-snippet. When the certificate is renewed, the process crashes. When I remove annotations, renewed certificate is successful. Is there another solution? For example, creating a redirect 301 in separate pod?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
ingress.kubernetes.io/ssl-redirect: "true"
meta.helm.sh/release-name: DOMAIN
meta.helm.sh/release-namespace: DOMAIN
nginx.ingress.kubernetes.io/configuration-snippet: |
location ~ ^/online-web {
return 301 /online;
}
if ($host = 'DOMAIN-alias.cz') {
return 301 https://DOMAIN.cz;
}
if ($host ~ ^(.+)\.DOMAIN-alias\.cz$) {
return 301 https://$1.DOMAIN.cz$request_uri;
}
if ($host = 'DOMAIN-alias-2.cz') {
return 301 https://DOMAIN.cz;
}
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-buffer-size: 128k
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ "csas.woltair.cz") {
return 301 https://woltair.cz/zakaznik/doporuceni;
}
............
............
- host: csas.woltair.cz
http:
paths:
- backend:
service:
name: woltair-cz-fe
port:
number: 8080
path: /zakaznik/doporuceni
pathType: ImplementationSpecific