<p>I have Nginx-based service which configured to accept HTTPS-only. 
However GKE ingress answers HTTP requests in HTTP. I know that GKE Ingress doesn't know to enforce HTTP -> HTTPS redirect, but is it possible to learn it at least return HTTPS from service?</p>

<pre><code>rules:
  - http:
  paths:
  - path: /*
    backend:
      serviceName: dashboard-ui
      servicePort: 8443
</code></pre>

<p>UPDATE: I do have TSL configured on GKE ingress and my K8S service. When request comes in HTTPS everything works nice. But HTTP requests gets HTTP response. I implemented HTTP->HTTPS redirect in my service, but it didn't help. In fact, for now all communication between ingress and my service is HTTTPS because service exposes only HTTPS port</p>

<p>SOLUTION - thanks to Paul Annetts:  Nginx should check original protocol inside <em>HTTPS</em> block and redirect, like this</p>

<pre><code>if ($http_x_forwarded_proto = "http") {
   return 301 https://$host$request_uri;
}
</code></pre>

<p>Yes, you can configure the GKE Kubernetes Ingress to both terminate HTTPS for external traffic, and also to use HTTPS internally between Google HTTP(S) Load Balancer and your service inside the GKE cluster.</p>

<p>This is documented <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/ingress" rel="nofollow noreferrer">here</a>, but it is fairly complex.</p>

<p>For HTTPS to work you will need a TLS certificate and key.</p>

<p>If you have your own TLS certificate and key in the cluster as a secret, you can provide it using the <code>tls</code> section of <code>Ingress</code>:</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
spec:
  tls:
  - secretName: my-secret
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-metrics
          servicePort: 60000
</code></pre>

<p>You can also upload your TLS certificate and key directly to Google Cloud and provide a <code>ingress.gcp.kubernetes.io/pre-shared-cert</code> annotation that tells GKE Ingress to use it.</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-psc-ingress
  annotations:
    ingress.gcp.kubernetes.io/pre-shared-cert: "my-domain-tls-cert"
...
</code></pre>

<p>To use HTTPS for traffic inside Google Cloud, from the Load Balancer to your GKE cluster, you need the <code>cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'</code> annotation on your <code>NodePort</code> service. Note that your ports must be named for the HTTPS to work.</p>

<pre><code>apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-https-port
    port: 443
    targetPort: 8443
  - name: my-http-port
    port: 80
    targetPort: 50001
</code></pre>

<p>The load balancer itself doesn’t support redirection from HTTP->HTTPS, you need to find another way for that.</p>

<p>As you have NGINX as entry-point into your cluster, you can detect the protocol used to connect to the load-balancer with the <code>X-forwarded-Proto</code> HTTP header and do a redirect, something like this.</p>

<pre><code>if ($http_x_forwarded_proto = "http") {
   return 301 https://$host$request_uri;
}
</code></pre>
