Search code examples
kubernetesamazon-cloudfrontkubernetes-ingressamazon-eks

Ingress to redirect to external resource using ALB


I have some services running on the cluster, and the ALB is working fine. But I have a CloudFront distribution, and I want to use the cluster as an entry point because of some internal factors. So, I am trying to add an ingress to redirect the requests to the CloudFront distribution based on the default rule or a named host, both will work.

I tried 2 different ways, but no dice:

Creating an external name and the ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  namespace: default
annotations:
  kubernetes.io/ingress.class: alb
  alb.ingress.kubernetes.io/scheme: "internet-facing"
  alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80,"HTTPS": 443}]'
  alb.ingress.kubernetes.io/certificate-arn: <my-cert-arn>
  alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { 
  "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
  alb.ingress.kubernetes.io/group.name: <my-group-name>
spec:
  rules:
    - host: test.my-host.net
      HTTP:
        paths:
          - backend:
              serviceName: test
              servicePort: use-annotation
            path: /
---
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  type: ExternalName
  externalName: test.my-host.net

I also tried to create the ingress with the redirect with the annotation on the ALB Ingress v2 just like the docs:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: "internet-facing"
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80,"HTTPS": 443}]'
    alb.ingress.kubernetes.io/certificate-arn: <my-cert-arn>
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { 
"Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
    alb.ingress.kubernetes.io/actions.redirect-to-eks: >
      {"type":"redirect","redirectConfig":{"host":"my- 
 dist.cloudfront.net","path":"/","port":"443",
"protocol":"HTTPS","query":"k=v","statusCode":"HTTP_302"}}
    alb.ingress.kubernetes.io/group.name: <my-group-name>
spec:
  rules:
    - host: <my-host-name>
      HTTP:
        paths:
          - backend:
              serviceName: ssl-redirect
              servicePort: use-annotation

Solution

  • The reason why it isn't working with ExternalName service type is because it has no endpoints. ALB can set target only to instance or ip (documentation) so ExternalName isn't an option here.

    You can create redirect with annotation but it is a bit tricky. First, you need at least two subnets with public access for alb.ingress.kubernetes.io/subnets annotation. Subnets can be automatically discovered but I don't know if it can pick public ones from all assigned to EKS cluster, so it's better to set explicitly. Second, you need to use alb.ingress.kubernetes.io/actions.<ACTION NAME> annotation (documentation), where <ACTION NAME> must match serviceName from ingress rules. Third, you need to specify Host in redirect config or it'll be host from ingress spec.

    Here is a working example:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: test-alb
      annotations:
        kubernetes.io/ingress.class: alb
        alb.ingress.kubernetes.io/scheme: "internet-facing"
        alb.ingress.kubernetes.io/subnets: "public-subnet-id1,public-subnet-id2"
        alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80,"HTTPS": 443}]'
        alb.ingress.kubernetes.io/actions.redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Host":"example.com", "port":"443", "StatusCode": "HTTP_301"}}'
    spec:
      rules:
        - host: alb-test.host.name
          http:
            paths:
              - backend:
                  serviceName: redirect
                  servicePort: use-annotation
    

    Your ssl-redirect annotation is almost correct, except that it redirects to <my-host-name>. I recommend you to use the web console (change region in the link) https://console.aws.amazon.com/ec2/v2/home?region=eu-central-1#LoadBalancers:sort=loadBalancerName to see generated redirect rules and debug other options.

    There are other options to solve this, a dedicated deployment with nginx for example. Or you can use nginx ingress controller, from my experience it is much easier to set redirect with it.