Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Use/lookup for load balancer #746

Closed
zahornyak opened this issue Mar 29, 2024 · 22 comments · Fixed by #749
Closed

[FR] Use/lookup for load balancer #746

zahornyak opened this issue Mar 29, 2024 · 22 comments · Fixed by #749
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@zahornyak
Copy link

Is your feature request related to a problem? Please describe.
Currently, I want to use existing load balancer for my preset, but I cannot do that or there are no docs that I can do that

Describe the solution you'd like
I would like to have possibility to use use/lookup for x-elbv2

Describe alternatives you've considered
didnt find any

@zahornyak zahornyak added the enhancement New feature or request label Mar 29, 2024
@JohnPreston
Copy link
Member

hello @zahornyak
That is a complete docs oversight on my end, x-elbv2.Lookup is available in version 1.x
Let me make sure to have this documented.

@JohnPreston JohnPreston added documentation Improvements or additions to documentation and removed enhancement New feature or request labels Mar 29, 2024
@zahornyak
Copy link
Author

zahornyak commented Mar 29, 2024

@JohnPreston you're right. But how to use that? When I use it like that:

x-elbv2:
  Lookup:
    loadbalancer:
      Tags:
        - Name: test-balancer

it does not work

I have errors like that:
jsonschema.exceptions.ValidationError: {'loadbalancer': {'Tags': [{'Name': 'test-balancer'}]}} is not valid under any of the given schemas

@JohnPreston
Copy link
Member

So, the error here is just telling you that the Lookup format is incorrect.
God knows why I originally had Tags: List[{key: value}] instead of just Tags: {key: value}
You can always double check with the JSON schema spec.

x-elbv2:
  Lookup:
    loadbalancer:
      Tags:
        Name: test-balancer

Should work, on top of my head

@zahornyak
Copy link
Author

@JohnPreston

x-elbv2:
  Lookup:
    loadbalancer:
      Tags:
        Name: test-balancer

didnt work.
jsonschema.exceptions.ValidationError: {'loadbalancer': {'Tags': {'Name': 'test-balancer'}}} is not valid under any of the given schemas

@JohnPreston
Copy link
Member

@zahornyak what version of compose-x are you using? Latest is 1.0.1, latest nightly is 1.1.0rc1
Also note that the logical name of the LB is missing

x-elbv2:
  my-lb-to-lookup-logical-name:
    Lookup:
      loadbalancer:
        Tags:
          Name: test-balancer

@zahornyak
Copy link
Author

Update:
After some time of investigation, I found the required parameters that should exist in the lookup which are 'TargetGroups' or 'Services'

@JohnPreston
Copy link
Member

Update: After some time of investigation, I found the required parameters that should exist in the lookup which are 'TargetGroups' or 'Services'

So is it working now? Do you mind if I tag you to review the docs when I open the PR for it?
Feel free to report anything not working :)

@zahornyak
Copy link
Author

@zahornyak what version of compose-x are you using? Latest is 1.0.1, latest nightly is 1.1.0rc1 Also note that the logical name of the LB is missing

x-elbv2:
  my-lb-to-lookup-logical-name:
    Lookup:
      loadbalancer:
        Tags:
          Name: test-balancer

yeah, I missed that part, but now I've added everything and it works as well. Thank you

@zahornyak
Copy link
Author

Update: After some time of investigation, I found the required parameters that should exist in the lookup which are 'TargetGroups' or 'Services'

So is it working now? Do you mind if I tag you to review the docs when I open the PR for it? Feel free to report anything not working :)

sure) Thanks

@zahornyak
Copy link
Author

zahornyak commented Apr 1, 2024

@JohnPreston I have an additional question regarding load balancer listener rules. As I can see, I can lookup for the listeners but can I lookup for listeners and create listener rules in that listener?
I'm currently doing this:

x-elbv2:
  lb:
    Lookup:
      loadbalancer:
        Tags:
          Name: test-deleteme
      Listeners:
        1:
          Tags:
            Name: test-deleteme
          Targets:
            - name: all-gateways
              access: test.com


    TargetGroups:
      all-gateways:
        Port: 80
        Protocol: TCP
        HealthCheck:
          HealthCheckIntervalSeconds: 17
          HealthCheckProtocol: TCP
          HealthCheckTimeoutSeconds: 10
          HealthyThresholdCount: 2
          UnhealthyThresholdCount: 2
        TargetGroupAttributes:
          deregistration_delay.timeout_seconds: "30"
        Services:
          - Name: web:web
            Port: 80

But it does not create any listener rules with a connected target group there.

@JohnPreston
Copy link
Member

JohnPreston commented Apr 1, 2024

Okay, interesting.
The way you have TargetGroups instead of using Services though is when you want multiple services to be part of a singular target group. Instead I'd say, use Services as follows

x-elbv2:
  my-lb:
    DnsAliases:
      - Names:
          - my-domain.tld
        Route53Zone: x-route53::PublicZone
    Lookup:
      loadbalancer:
        Tags:
          servicename: some-service-name
          project: project-name
          Name: lb-name
      Listeners:
        443:
          Tags:
            Name: https-listener
            Port: "443"
            Protocol: HTTPS
          Targets:
            - name: family:service:8080
              Conditions:
                - Field: host-header
                  HostHeaderConfig:
                    Values:
                      - my-domain.tld

    Services:
      family:service:8080:
        port: 8080
        protocol: HTTP
        healthcheck: 8080:HTTP:7:2:15:5:/swagger-ui.html:401

This is an actual working example that I use and works great.
I will document it all which will get me to review and check bits and bobs in the code.

@zahornyak
Copy link
Author

Thanks for the example

How did you get 8080 on family configurations? I have errors that Could not find 80 in family web

Also, I have an error TypeError: string indices must be integers when using your example.

Here's my config:

version: "3.8"

x-cluster:
  Properties:
    CapacityProviders:
      - FARGATE
    ClusterName: Test-cluster

x-vpc:
  Lookup:
    VpcId:
      Tags:
        - Name: default
    AppSubnets: {}
    PublicSubnets:
      Tags:
        - name: public
    PrivateSubnets: {}
    StorageSubnets: {}

x-elbv2:
  lb:
    Lookup:
      loadbalancer:
        Tags:
          Name: test-deleteme
      Listeners:
        1:
          Tags:
            Name: test-deleteme
          Targets:
            - name: web:api
              Conditions:
                - Field: host-header
                  HostHeaderConfig:
                    Values:
                      - my-domain.tld

    Services:
      web:api:
        port: 80
        protocol: HTTP
        healthcheck: 80:HTTP:7:2:15:5:/:401

services:
  api:
    image: nginx
    ports:
      - "80:80"
    networks:
      - public
    deploy:
      labels:
        ecs.task.family: web


networks:
  public:
    x-vpc: PublicSubnets

Did I miss something?

@zahornyak
Copy link
Author

@JohnPreston As far as I can see, error TypeError: string indices must be integers only exist when I specify:

          Targets:
            - name: web:api
              Conditions:
                - Field: host-header
                  HostHeaderConfig:
                    Values:
                      - my-domain.tld

And I have no idea why it doesn't work. And still interested in how family:service:8080 formed. I couldn't do the same

@JohnPreston
Copy link
Member

JohnPreston commented Apr 3, 2024

Thanks for the example

How did you get 8080 on family configurations? I have errors that Could not find 80 in family web

Also, I have an error TypeError: string indices must be integers when using your example.

Here's my config:

version: "3.8"

x-cluster:
  Properties:
    CapacityProviders:
      - FARGATE
    ClusterName: Test-cluster

x-vpc:
  Lookup:
    VpcId:
      Tags:
        - Name: default
    AppSubnets: {}
    PublicSubnets:
      Tags:
        - name: public
    PrivateSubnets: {}
    StorageSubnets: {}

x-elbv2:
  lb:
    Lookup:
      loadbalancer:
        Tags:
          Name: test-deleteme
      Listeners:
        1:
          Tags:
            Name: test-deleteme
          Targets:
            - name: web:api
              Conditions:
                - Field: host-header
                  HostHeaderConfig:
                    Values:
                      - my-domain.tld

    Services:
      web:api:
        port: 80
        protocol: HTTP
        healthcheck: 80:HTTP:7:2:15:5:/:401

services:
  api:
    image: nginx
    ports:
      - "80:80"
    networks:
      - public
    deploy:
      labels:
        ecs.task.family: web


networks:
  public:
    x-vpc: PublicSubnets

Did I miss something?

My example with family:service:8080 was due to my service having 8080 in ports.
This is something you want to set if the service of the same family has more than one port, each going to be a different target group, therefore the family:service goes into family:service:port as the specific port of the container is the target.

I presume you removed the AppSubnets Tags? Even if you are not going to deploy to it, AppSubnets, StorageSubnets and PublicSubnets are currently required to be found in your vpc, even if they are the same for all 3.
PrivateSubnets is not required however, unless you have a need for them of course.

Listeners:
  1: {}

I presume that you set 1 for example here? Otherwise, I highly recommend you use the actual listener port number for clarity.

For the TypeError, I imagine there is a stacktrace with that? Would you mind sharing it?
Cheers,

@zahornyak
Copy link
Author

zahornyak commented Apr 3, 2024

2024-04-03 10:36:15 [    INFO] services.web - No Launch Type defined. Using default: FARGATE
2024-04-03 10:36:16 [    INFO] Service families to process ['web']
Loaded x-vpc vpc vpc /opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/vpc
Loaded x-elbv2 elbv2 elbv2 /opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2
2024-04-03 10:36:16 [    INFO] x-elbv2.lb - Adding target web:api
2024-04-03 10:36:16 [    INFO] LB lb only has a unique service. LB will be deployed with the service stack.
2024-04-03 10:36:16 [    INFO] Processing x-vpc
2024-04-03 10:36:22 [    INFO] x-vpc - Found VPC - vpc-0bcfhjsb654ff54aa
2024-04-03 10:36:22 [    INFO] Processing x-elbv2
2024-04-03 10:36:22 [    INFO] x-elbv2.lb - Lookup via Tags
2024-04-03 10:36:25 [    INFO] x-elbv2.lb - Listener 80 found: arn:aws:elasticloadbalancing:us-east-2:1234567890:listener/app/non-prd-alb/80919aa583707f74/b209ccc8aa3a6df6
Traceback (most recent call last):
  File "/opt/homebrew/Caskroom/miniforge/base/bin/ecs-compose-x", line 8, in <module>
    sys.exit(main())
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/cli.py", line 206, in main
    root_stack = generate_full_template(settings)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/ecs_composex.py", line 251, in generate_full_template
    add_x_resources(settings)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/ecs_composex.py", line 180, in add_x_resources
    x_stack = module.stack_class(
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/__init__.py", line 78, in __init__
    resource.find_lookup_listeners()
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2.py", line 179, in find_lookup_listeners
    listener: LookupListener = LookupListener(self, listener_port, listener_def)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 82, in __init__
    self.tidy_targets()
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 143, in tidy_targets
    not in [svc["name"] for svc in self.lb.services]
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 143, in <listcomp>
    not in [svc["name"] for svc in self.lb.services]
TypeError: string indices must be integers

I presume that you set 1 for example here? Otherwise, I highly recommend you use the actual listener port number for clarity.

yes, that was an example, I'm using 80 there.

I have an error Could not find 80 in family web when I try to specify family:service:port in service and listener

@zahornyak
Copy link
Author

@JohnPreston BTW, how to change the launch type? I do not see any docs about that

@JohnPreston
Copy link
Member

@JohnPreston BTW, how to change the launch type? I do not see any docs about that

https://docs.compose-x.io/syntax/compose_x/ecs.details/deploy.html#ecs-compute-platform
Will work on a FR #742 as well in a bit. Should that be of interest to you, give a 👍

@JohnPreston
Copy link
Member

2024-04-03 10:36:15 [    INFO] services.web - No Launch Type defined. Using default: FARGATE
2024-04-03 10:36:16 [    INFO] Service families to process ['web']
Loaded x-vpc vpc vpc /opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/vpc
Loaded x-elbv2 elbv2 elbv2 /opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2
2024-04-03 10:36:16 [    INFO] x-elbv2.lb - Adding target web:api
2024-04-03 10:36:16 [    INFO] LB lb only has a unique service. LB will be deployed with the service stack.
2024-04-03 10:36:16 [    INFO] Processing x-vpc
2024-04-03 10:36:22 [    INFO] x-vpc - Found VPC - vpc-0bcfhjsb654ff54aa
2024-04-03 10:36:22 [    INFO] Processing x-elbv2
2024-04-03 10:36:22 [    INFO] x-elbv2.lb - Lookup via Tags
2024-04-03 10:36:25 [    INFO] x-elbv2.lb - Listener 80 found: arn:aws:elasticloadbalancing:us-east-2:1234567890:listener/app/non-prd-alb/80919aa583707f74/b209ccc8aa3a6df6
Traceback (most recent call last):
  File "/opt/homebrew/Caskroom/miniforge/base/bin/ecs-compose-x", line 8, in <module>
    sys.exit(main())
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/cli.py", line 206, in main
    root_stack = generate_full_template(settings)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/ecs_composex.py", line 251, in generate_full_template
    add_x_resources(settings)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/ecs_composex.py", line 180, in add_x_resources
    x_stack = module.stack_class(
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/__init__.py", line 78, in __init__
    resource.find_lookup_listeners()
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2.py", line 179, in find_lookup_listeners
    listener: LookupListener = LookupListener(self, listener_port, listener_def)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 82, in __init__
    self.tidy_targets()
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 143, in tidy_targets
    not in [svc["name"] for svc in self.lb.services]
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 143, in <listcomp>
    not in [svc["name"] for svc in self.lb.services]
TypeError: string indices must be integers

I presume that you set 1 for example here? Otherwise, I highly recommend you use the actual listener port number for clarity.

yes, that was an example, I'm using 80 there.

I have an error Could not find 80 in family web when I try to specify family:service:port in service and listener

And this is version 1.0.1, right?
I am going to add the version to the logs 🤔

@zahornyak
Copy link
Author

2024-04-03 10:36:15 [    INFO] services.web - No Launch Type defined. Using default: FARGATE
2024-04-03 10:36:16 [    INFO] Service families to process ['web']
Loaded x-vpc vpc vpc /opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/vpc
Loaded x-elbv2 elbv2 elbv2 /opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2
2024-04-03 10:36:16 [    INFO] x-elbv2.lb - Adding target web:api
2024-04-03 10:36:16 [    INFO] LB lb only has a unique service. LB will be deployed with the service stack.
2024-04-03 10:36:16 [    INFO] Processing x-vpc
2024-04-03 10:36:22 [    INFO] x-vpc - Found VPC - vpc-0bcfhjsb654ff54aa
2024-04-03 10:36:22 [    INFO] Processing x-elbv2
2024-04-03 10:36:22 [    INFO] x-elbv2.lb - Lookup via Tags
2024-04-03 10:36:25 [    INFO] x-elbv2.lb - Listener 80 found: arn:aws:elasticloadbalancing:us-east-2:1234567890:listener/app/non-prd-alb/80919aa583707f74/b209ccc8aa3a6df6
Traceback (most recent call last):
  File "/opt/homebrew/Caskroom/miniforge/base/bin/ecs-compose-x", line 8, in <module>
    sys.exit(main())
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/cli.py", line 206, in main
    root_stack = generate_full_template(settings)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/ecs_composex.py", line 251, in generate_full_template
    add_x_resources(settings)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/ecs_composex.py", line 180, in add_x_resources
    x_stack = module.stack_class(
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/__init__.py", line 78, in __init__
    resource.find_lookup_listeners()
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2.py", line 179, in find_lookup_listeners
    listener: LookupListener = LookupListener(self, listener_port, listener_def)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 82, in __init__
    self.tidy_targets()
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 143, in tidy_targets
    not in [svc["name"] for svc in self.lb.services]
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/site-packages/ecs_composex/elbv2/elbv2_stack/elbv2_listener/lookup_listener.py", line 143, in <listcomp>
    not in [svc["name"] for svc in self.lb.services]
TypeError: string indices must be integers

I presume that you set 1 for example here? Otherwise, I highly recommend you use the actual listener port number for clarity.

yes, that was an example, I'm using 80 there.
I have an error Could not find 80 in family web when I try to specify family:service:port in service and listener

And this is version 1.0.1, right? I am going to add the version to the logs 🤔

yes, 1.0.1

@JohnPreston JohnPreston linked a pull request Apr 3, 2024 that will close this issue
@JohnPreston
Copy link
Member

Hey @zahornyak
Mind trying with the fix that's in #749 ?
Clone, get to the branch

cd ecs_composex; git fetch; git checkout fix/elbv2-listener-tidy-function;
python3 -m venv compose_x
source compose_x/bin/activate
pip install .

Then run the command again.
I have tested it now with a system that does need it and it's fixed on my end. I did get the same error as you did.
Feels like a disconnect between 0.25 and 1.0 and something I haven't tested.

Running a LB 24/7 for no reason costs $ so I haven't gotten to implement lookup testing for it yet.

@zahornyak
Copy link
Author

zahornyak commented Apr 6, 2024

@JohnPreston Sorry, already deployed everything and can't test again. I've created lb instead of lookup on existing, that works for us for now, thanks for your help! BTW, your tool is great and has no great analogs at all

@raffidahmad
Copy link
Contributor

@zahornyak I have a setup similar to yours, how do you handle updates? For example you added a new service or target group.
I just end up getting

An error occurred (ValidationError) when calling the CreateChangeSet operation: Stack [microservices] already exists and cannot be created again with the changeSet [microserviceshmrszypibv].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants