15

I have configured amazon certificate manager, ALB Ingress Controller and a domain names for my application. I can access my application through port 80 and port 443 (all certificates works just fine). However I would like to redirect all coming traffic from HTTP to HTTPS automatically so that people who typed the domain name by itself is redirected to HTTPS. I have followed this page and this onebut I cannot make it work

this is my ingress.yaml file:

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

  labels:
    app: metabase
spec:
  rules:
    - http:
        paths:
          - path: /*
            backend:
              serviceName: ssl-redirect
              servicePort: use-annotation
          - path: /*
            backend:
              serviceName: metabase
              servicePort: 3000

this is my service:

apiVersion: v1
kind: Service
metadata:
  name: metabase
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-2:****:certificate/****
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
  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

ad this is my deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: metabase-deployment
  namespace: bigdata
  labels:
    app: metabase
spec:
  replicas: 2
  selector:
    matchLabels:
      app: metabase
  template:
    metadata:
      labels:
        app: metabase
    spec:
      containers:
        - name: metabase
          image: metabase/metabase
          ports:
            - containerPort: 3000
              name: http-server
          resources:
            limits:
              cpu: "1"
              memory: "2Gi"

thanks for your support! :-)

Dharman
  • 30,962
  • 25
  • 85
  • 135
juanp_1982
  • 917
  • 2
  • 16
  • 37

6 Answers6

11

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
juanp_1982
  • 917
  • 2
  • 16
  • 37
  • 1
    Thanks this was helpful. I also found this reference guide helpful too: https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/tasks/ssl_redirect/ – groksrc Jul 10 '20 at 15:24
  • `note!` you have to delete your ingress for the changes to take effect and then make sure you update your DNS A records to point to the new ingress' location.. I was running in circles for a while not doing these two things – orpheus Sep 16 '22 at 05:35
7

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.

Eduardo Baitello
  • 10,469
  • 7
  • 46
  • 74
  • 1
    it didn't work :-( I commented out `kubernetes.io/ingress.class: alb` and added the line that you suggested in the ingress.yaml file. it is posible to make both classes (nginx and alb) to work together) – juanp_1982 Sep 17 '19 at 19:22
  • What Nginx Ingress version are you using? Before `0.9.0` the prefix annotation was `ingress.kubernetes.io` (without the `nginx.`) – Eduardo Baitello Sep 17 '19 at 19:55
  • 1
    `nginx.ingress.kubernetes.io/ssl-redirect: "true"` should be enough, as stated by https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/rewrite – Alexandre Cartapanis Sep 17 '19 at 22:02
  • ERR_TOO_MANY_REDIRECTS – Abdennour TOUMI Mar 06 '21 at 19:31
  • @AbdennourTOUMI in this case take a look at [this answer](https://stackoverflow.com/a/49857465/7641078). It links to a Github thread with the explanation and a workaround that I posted. – Eduardo Baitello Mar 06 '21 at 21:54
  • `nginx.ingress.kubernetes.io/force-ssl-redirect: "true"` Will only work if you're using nginx ingress. – Timothy c Aug 27 '21 at 08:23
7

Just in case you are looking for the proper new syntax (the rest is the same)

      - path: /
        pathType: Prefix
        backend:
          service:
            name: ssl-redirect
            port:
              name: use-annotation
Most Wanted
  • 6,254
  • 5
  • 53
  • 70
3

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.

  1. 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.

  1. 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/

  2. 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
Pavel
  • 111
  • 2
  • 8
  • I gotta ask Why `alb.ingress.kubernetes.io/actions.ssl-redirect:` AND a service to handle the redirect yourself? It really looks like having a dog and then doing all the barking yourself – Timothy c Aug 27 '21 at 08:27
2

AWS Load Balancer Controller v2.4 Documentation

Example Ingress Manifest

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 namespace: default
 name: ingress
 annotations:
   alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxx:certificate/xxxxxx
   alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
   alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
 ingressClassName: alb
 rules:
   - http:
       paths:
        - path: /users/*
          pathType: ImplementationSpecific
          backend:
            service:
              name: user-service
              port:
                number: 80
        - path: /*
          pathType: ImplementationSpecific
          backend:
            service:
              name: default-service
              port:
                number: 80
englishPete
  • 809
  • 10
  • 15
  • Nice `alb.ingress.kubernetes.io/ssl-redirect: '443'` was all I needed to add to my annotations. – Nick Jul 26 '23 at 23:08
0

In case some one is looking for newer syntax:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/actions.ssl-redirect:
      '{"Type": "redirect", "RedirectConfig":
      { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
    alb.ingress.kubernetes.io/certificate-arn: <cert arn>
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
    external-dns.alpha.kubernetes.io/hostname: <your domain>
    kubernetes.io/ingress.class: alb
spec:
  rules:
    - http:
        paths:
          - backend:
              service:
                name: ssl-redirect
                port:
                  name: use-annotation
            path: /
            pathType: Prefix
          - backend:
              service:
                name: nginx-service
                port:
                  number: 80
            path: /
            pathType: Prefix

---
apiVersion: v1
kind: Service
metadata:
  namespace: default
  name: nginx-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 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
badal jain
  • 53
  • 4