how to redirect http to https using a kubernetes ingress controller on Amazon EKS
You need to use the nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
annotation:
When using SSL offloading outside of cluster (e.g. AWS ELB) it may be useful to enforce a redirect to HTTPS even when there is no TLS certificate is available. This can be achieved by using the
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
annotation in the particular resource.
I was able to make it work!! basically I modified the ingress.yaml and service.yaml files
ingress.yaml looks like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: metabase
namespace: bigdata
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-2:***:certificate/****
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/group: metabase # name of my app
labels:
app: metabase
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: ssl-redirect
servicePort: use-annotation
- path: /*
backend:
serviceName: metabase
servicePort: 443
and my service looks like this:
apiVersion: v1
kind: Service
metadata:
name: metabase
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-2:***:certificate/***
namespace: bigdata
labels:
app: metabase
spec:
ports:
- name: https
protocol: TCP
port: 443
targetPort: http-server
- name: http
protocol: TCP
port: 80
targetPort: http-server
selector:
app: metabase
type: LoadBalancer
I have spent quite some time trying to make this work and finally succeeded. Probably someone will find it useful. I will try to describe step by step approach to setup ALB with HTTP to HTTPs redirect.
- Check that your ALB controller is up and running:
kubectl get deployment -n kube-system aws-load-balancer-controller
Printout should be similar to the one below:
NAME READY UP-TO-DATE AVAILABLE AGE
aws-load-balancer-controller 1/1 1 1 18h
If your controller does not work, no Load Balancer will be created.
Check that your yaml file is good. Below I provide a simple Yaml file that worked in my case. Some comments about this file:
a) Please use your SSL/TLS certificate ARN (I used XXXXXXX).
b) Please use your image (I used YYYYYYYYYY). My container image is stored in the ECR (Elastic Container Registry).
c) Please note that a strange service marked ssl-redirect with servicePort:
use-annotations is created according to the annotations specification.
https://kubernetes-sigs.github.io/aws-load-balancer-controller/guide/ingress/annotations/Once you run:
kubectl apply -f service.yaml
Please check two things:
a)kubectl -n default describe ingress
This command should show that reconciliation was successful: the end of the printout should show:
Normal SuccessfullyReconciled 11s (x3 over 18m) ingress Successfully reconciled
In the same printout (top of the printout) do not pay attention to the log entry:
/* ssl-redirect:use-annotation (<error: endpoints "ssl-redirect" not found>)
b)aws elbv2 describe-load-balancers --query "LoadBalancers[?contains(LoadBalancerArn,'default-nginx')].{Arn: LoadBalancerArn}" --output text | xargs -I {} aws elbv2 describe-listeners --load-balancer-arn {}
This command should show to you that a new ALB was created and two Listeners were created. Do not pay attention that the HTTP listener does not seem to have correct redirect configuration.
-- YAML --
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: default
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/tags: createdBy=aws-controller
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-central-1:XXXXXXXXXXXX:certificate/XXXXXXXXXXXXXXXXXXXXXXXXXX
labels:
app: nginx-ingress
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: ssl-redirect
servicePort: use-annotation
- path: /*
backend:
serviceName: nginx-service
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: default
name: nginx-service
spec:
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: YYYYYYYYYYYY.dkr.ecr.eu-central-1.amazonaws.com/webfe:latest
ports:
- containerPort: 80