4
votes

I have a web app hosted in the Google Cloud platform that sits behind a load balancer, which itself sits behind an ingress. The ingress is set up with an SSL certificate and accepts HTTPS connections as expected, with one problem: I cannot get it to redirect non-HTTPS connections to HTTPS. For example, if I connect to it with the URL http://foo.com or foo.com, it just goes to foo.com, instead of https://foo.com as I would expect. Connecting to https://foo.com explicitly produces the desired HTTPS connection.

I have tried every annotation and config imaginable, but it stubbornly refuses, although it shouldn't even be necessary since docs imply that the redirect is automatic if TLS is specified. Am I fundamentally misunderstanding how ingress resources work?

Update: Is it necessary to manually install nginx ingress on GCP? Now that I think about it, I've been taking its availability on the platform for granted, but after coming across information on how to install nginx ingress on the Google Container Engine, I realized the answer may be a lot simpler than I thought. Will investigate further.

Kubernetes version: 1.8.5-gke.0

Ingress YAML file:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: https-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    ingress.kubernetes.io/ssl-redirect: "true" 
    ingress.kubernetes.io/secure-backends: "true"    
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  tls:
    - hosts:
      - foo.com
      secretName: tls-secret
  rules:
    - host: foo.com
      http:
        paths:
          - path: /*
            backend:
              serviceName: foo-prod
              servicePort: 80

kubectl describe ing https-ingress output

Name:             https-ingress
Namespace:        default
Address:
Default backend:  default-http-backend:80 (10.56.0.3:8080)
TLS:
  tls-secret terminates foo.com
Rules:
  Host            Path  Backends
  ----            ----  --------
  foo.com
                  /*   foo-prod:80 (<none>)
Annotations:
  force-ssl-redirect:  true
  secure-backends:     true
  ssl-redirect:        true
Events:                <none>
2

2 Answers

7
votes

The problem was indeed the fact that the Nginx Ingress is not standard on the Google Cloud Platform, and needs to be installed manually - doh!

However, I found installing it to be much more difficult than anticipated (especially because my needs pertained specifically to GCP), so I'm going to outline every step I took from start to finish in hopes of helping anyone else who uses that specific cloud and has that specific need, and finds generic guides to not quite fit the bill.

  1. Get Cluster Credentials

This is a GCP specific step that tripped me up for a while - you're dealing with it if you get weird errors like

kubectl unable to connect to server: x509: certificate signed by unknown authority

when trying to run kubectl commands. Run this to set up your console:

gcloud container clusters get-credentials YOUR-K8s-CLUSTER-NAME --z YOUR-K8S-CLUSTER-ZONE

  1. Install Helm

Helm by itself is not hard to install, and the directions can be found on GCP's own docs; what they neglect to mention, however, is that on new versions of K8s, RBAC configuration is required to allow Tiller to install things. Run the following after helm init:

kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
  1. Install Nginx Ingress through Helm

Here's another step that tripped me up - rbac.create=true is necessary for the aforementioned RBAC factor.

helm install --name nginx-ingress-release stable/nginx-ingress --set rbac.create=true

  1. Create your Ingress resource

This step is the simplest, and there are plenty of sample nginx ingress configs to tweak - see @JahongirRahmonov's example above. What you MUST keep in mind is that this step takes anywhere from half an hour to over an hour to set up - if you change the config and check again immediately, it won't be set up, but don't take that as implication that you messed something up! Wait for a while and see first.

It's hard to believe this is how much it takes just to redirect HTTP to HTTPS with Kubernetes right now, but I hope this guide helps anyone else stuck on such a seemingly simple and yet so critical need.

2
votes

GCP has a default ingress controller which at the time of this writing cannot force https.

You need to explicitly manage an NGINX Ingress Controller.

See this article on how to do that on GCP.

Then add this annotation to your ingress:

kubernetes.io/ingress.allow-http: "false"

Hope it helps.