I'm after a very simple requirement - yet seems impossible to make Traefik redirect traffic from HTTP to HTTPS when behind an external load balancer.
This is my GCE ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: platform
name: public-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "kubernetes-cluster-dev-ip"
kubernetes.io/ingress.class: "gce"
ingress.gcp.kubernetes.io/pre-shared-cert: "application-dev-ssl,application-dev-graphql-ssl"
spec:
backend:
serviceName: traefik-ingress-service
servicePort: 80
Which receive traffic from HTTP(S) then forward to Traefik to port 80.
I initially tried to using Traefik way of redirecting matching the schema with this configuration:
[entryPoints]
[entryPoints.http]
address = ":80"
compress = true
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
compress = true
[entryPoints.https.tls]
But obviously gets into an infinite redirect loop because of the load balancer always proxy traffic to Traefik port 80.
The simple solution to make this work is exactly what GCE suggests https://github.com/kubernetes/ingress-gce#ingress-cannot-redirect-http-to-https
Being able to check for the http_x_forwarded_proto
header and redirect based on that.
Nginx equivalent
# Replace '_' with your hostname.
server_name _;
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
Can someone advice what's the best way of handling this with Traefik, please!
To recap, you have a GCE L7 (Layer 7) load balancer proxying another L7 load balancer in Traefik that you can potentially use it to proxy to another backend service. So looks like you have something like this:
GCE L7 LB HTTP 80
=> Forwarded to Traefik HTTP 80
=> Redirect initial request to HTTPS 443
=> The client thinks it needs to talk to GCE L7 LB HTTPS 443
=> GCE L7 LB HTTP 443
=> Forwarded to Traefik HTTP 80
=> Infinite loop
and you need to have something like this:
GCE L7 LB HTTP 80
=> Forwarded to Traefik HTTP 80
=> Redirect initial request to HTTPS 443
=> The client thinks it needs to talk to GCE L7 LB HTTPS 443
=> GCE L7 LB HTTP 443
=> Forwarded to Traefik HTTP 443
It's not documented anywhere if Traefik redirects to HTTPS based on the value of http_x_forwarded_proto
being http
, but that would be the general assumption. In any case, the Ingress
doesn't know anything about an HTTPS backend (you didn't specify how you configured the HTTPS GCE LB endpoint).
You can see that it's documented here how to make the GCE LB directly create an HTTPS endpoint that forward directly to your HTTPS backend. Basically, you can try adding the service.alpha.kubernetes.io/app-protocols
annotation to the HTTPS Traefik service:
apiVersion: v1
kind: Service
metadata:
name: traefik-https
annotations:
service.alpha.kubernetes.io/app-protocols: '{"my-https-port":"HTTPS"}'
labels:
app: echo
spec:
type: NodePort
ports:
- port: 443
protocol: TCP
name: my-https-port
selector:
app: traefik
So you would have something like this:
GCE L7 LB HTTP 80
=> Forwarded to Traefik HTTP 80
=> Redirect initial request to HTTPS 443
=> The client thinks it needs to talk to GCE L7 LB HTTPS 443
=> GCE L7 LB HTTP 443
=> Forwarded to Traefik HTTPS service
=> Service forward to Traefik port 443
Hope this helps.