1
votes

I am using Kubernetes within Google Cloud Kubernetes Engine and have setup the following: - Nginx docker image (nginx:latest), which is hosting a web application - Kubernetes Deployment (yaml file) - Kubernetes Service (yaml file) - Kubernetes Secret with existing key and certificates (Wildcard PositiveSSL) - Kubernetes Ingress

Currently I have both HTTP and HTTPS working. However, I want to redirect any and all HTTP calls to HTTPS automatically, but don't seem to get it to be working.

I have tried many variations of the conf and script files below, and it doesn't seem to be able to redirect HTTP to HTTPS.

Any idea what I might be doing wrong here?

Please see below for my conf, yaml and docker files.

Nginx Conf:

server {
  listen 80;
  charset utf-8;
  root /usr/share/nginx/html;

  location / {
    proxy_set_header        Host $host:$server_port;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_redirect  http:// https://;
    proxy_pass              http://portal.domain.com;
    proxy_http_version 1.1;
    proxy_request_buffering off;
  }
}

server {
  listen 443 ssl;

  charset utf-8;
  root /usr/share/nginx/html;

  ssl_certificate       /etc/nginx/ssl/domain_com_full.crt;
  ssl_certificate_key   /etc/nginx/ssl/domain_com.key;

  location / {
    proxy_set_header        Host $host:$server_port;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_redirect  http:// https://;
    proxy_pass              http://portal.domain.com;
    proxy_http_version 1.1;
    proxy_request_buffering off;
  }
}

Docker file:

FROM nginx:latest
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY domain_com_full.crt /etc/nginx/ssl/domain_com_full.crt
COPY domain_com.key /etc/nginx/ssl/domain_com.key
COPY dist /usr/share/nginx/html
EXPOSE 443 80

Deployment YAML (I use a script to fill in the revision part of the image):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: domain-frontend-prd
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
        maxSurge: 1
        maxUnavailable: 0
  selector:
    matchLabels:
      run: domain-frontend-prd
  template:
    metadata:
      labels:
        run: domain-frontend-prd
    spec:
      containers:
      - name: domain-frontend-image
        image: eu.gcr.io/domain-service/domain-frontend-image:{{REVISION_ID}}
        ports:
        - containerPort: 80
        - containerPort: 443
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
          successThreshold: 1

Service YAML:

apiVersion: v1
kind: Service
metadata:
  name: domain-frontend-service-prd
spec:
  type: NodePort
  selector:
    run: domain-frontend-prd
  ports:
  - protocol: TCP
    port: 443
    targetPort: 443
    name: https-port
  - protocol: TCP
    port: 80
    targetPort: 80
    name: http-port

Ingress YAML (The Secret is working, as the HTTPS call also works + static IP is also there and working):

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: domain-frontend-ingress-prd
  annotations:
    kubernetes.io/ingress.global-static-ip-name: kubernetes-ingress
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - portal.domain.com
    secretName: domain-tls
  backend:
    serviceName: domain-frontend-service-prd
    servicePort: 80
  rules:
  - host: portal.domain.com
    http:
      paths:
        - path: /
          backend:
            serviceName: domain-frontend-service-prd
            servicePort: 80
1
Your config is very very messy. It is hard to understand what are you trying to achieve. Where you want to actually terminate SSL? On load balancer? On Nginx ingress? In backend nginx? Also do you use GKE ingress or Nginx ingress controller? Those are two completely different things. It looks like you are trying to use both type of annotations, which is also useless. - Vasili Angapov
What I am trying to achieve is to setup the web application in an ingress docker image, and make it approachable through HTTPS only, so when the user enters the URL with HTTP, they are immediately redirected to HTTPS. Do you have any suggestions on the right way to achieve this? - vv01
That's kinda obvious. Where you want to terminate SSL? Ok, if you have no idea, then simple question - do you have Nginx ingress installed or not? Do you have something in ingress-nginx namespace? - Vasili Angapov
I don't have ingress-nginx installed, there is no namespace for that in my cluster. - vv01
Can you change your backend Nginx config for 80 port to look like this: server { listen 80; server_name _; return 301 https://$host$request_uri; } - Vasili Angapov

1 Answers

2
votes

Through extensive search I have found out that apparently the standard Ingress controller in Google Cloud Kubernetes engine, does not support redirect to HTTPS.

In order to be able to resend traffic to HTTPS (from HTTP), you need to install the NGINX Ingress controller according to this tutorial/documentation:

https://cloud.google.com/community/tutorials/nginx-ingress-gke

This has resolved my issue.