skip to Main Content

I am migrating services from Kubernetes to AWS ECS. For routing I use AWS Application Load Balancer (ALB).

The ALB has a listener on port 80 and my services are aggregated in target groups.

To route traffic between the services I use ALB listener rules.
For the routing I need to have two conditions to be met: a host-header and a path-pattern.

So I would to have something like following:

enter image description here

I tried to add multiple conditions to a rule (in Terrafom), however it is only possible to either have a host-header or a path-pattern:

Only one of host_header, http_header, http_request_method, path_pattern, query_string or source_ip can be set in a condition block

It is also not possible to add host_header together with path_pattern in the AWS Console.

How to route traffic in AWS ALB based on two conditions – host-header + path-pattern?

One possible option would be to use one ALB per host, but that would be way too expensive when the number of hosts / subdomains increases.

How it is done in Kubernetes

Simultaneous host-header and a path-pattern routing is possible in the nginx ingress router in Kubernetes. For example having these two ingress ressources:

Resource 1

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: domain-one.com
      http:
        paths:
          - path: /web
            backend:
              serviceName: web-service
              servicePort: 8080
          - path: /media/files
            backend:
              serviceName: web-service
              servicePort: 8080

    - host: another-domain.com
      http:
        paths:
          - path: /web
            backend:
              serviceName: web-service
              servicePort: 8080
          - path: /media/files
            backend:
              serviceName: web-service
              servicePort: 8080


Resource 2

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: api-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: www.domain-one.com
      http:
        paths:
          - path: /api
            backend:
              serviceName: api-service
              servicePort: 8181


For Kubernetes it is possible to define besides the path parameter also an optional host parameter.
So in the end both the host and path must match the content of an incoming request before the loadbalancer directs traffic to the corresponding backend:

enter image description here

So, how to achieve the same on AWS ALB?

Thank you.

2

Answers


  1. Chosen as BEST ANSWER

    The ALB listener rule can contain multiple conditions, but one condition can contain only one of the described blocks.

    The conditions of a single rule are processed with an AND, so all conditions must met in order to be routed to the target group.

    So it is needed to create multiple rules for multiple hosts, as answered here: https://stackoverflow.com/a/46304567/1820806

    Edit: I will verify this solution and will update the post.

    Edit 2: This solution works.


  2. I was migrating from k8s also to ECS.
    As you mentioned you need to have multiple conditions.
    This is how I do it in terraform.

    resource "aws_lb_listener_rule" "backend_api_routing" {
      depends_on = [aws_alb_target_group.main8080]
    
      listener_arn = var.https_aws_alb_listener_arn
      priority     = var.backend_api_routing_priority
    
      action {
        type             = "forward"
        target_group_arn = aws_alb_target_group.main8080.arn
      }
    
      condition {
        host_header {
          values = ["domain-one.com"]
        }
      }
    
      condition {
        path_pattern {
          values = ["/web/*", "/media/files/*"]
        }
      }
    }
    

    Also, I suggest you that you check terragrunt, it allows you to re use terraform modules.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search