Skip to content

aws-ecs: circular dependency between ecs.Cluster and autoscaling.AutoScalingGroup #35210

@waissbluth

Description

@waissbluth

Describe the bug

Calling cluster.addAsgCapacityProvider(provider) does two things that cause a circular dependency, and this causes issues when the Cluster and the Capacity Provider are in different Cloudformation stacks:

  1. Add the clusterName to the autoscaling group's userData:
provider.autoScalingGroup.addUserData(
  `cluster = "${this.clusterName}"`,
)

Reference

  1. Add the capacity provider to the cluster's list:
cluster._capacityProviderNames.push(provider.capacityProviderName);

Reference

This creates a circular dependency that manifests on the following error when running yarn cdk synth:

ValidationError: 'CapacityProviderStack' depends on 'ComputeStack' (CapacityProviderStack -> ComputeStack/Cluster/Resource.Arn). Adding this dependency (ComputeStack -> CapacityProviderStack/CapacityProvider/CapacityProvider.Ref) would create a cyclic reference.
    at path [ComputeStack] in aws-cdk-lib.Stack

So, these two resources (cluster and provider) must be in the same stack for addAsgCapacityProvider to work, which is not documented and not compatible with our setup.

For this to be addressed the necessary change is quite small, since the only thing the capacity provider needs to know about the stack is it's name, not anything that is actually computed at runtime.

Regression Issue

  • Select this option if this issue appears to be a regression.

Last Known Working CDK Library Version

No response

Expected Behavior

cluster.addAsgCapacityProvider(provider) should not introduce a circular dependency between cluster and provider. It should just make cluster depend on provider

Current Behavior

cluster.addAsgCapacityProvider(provider) introduces a circular dependency.

Reproduction Steps

The following will create two stacks. One with the autoscaling group and another with the capacity provider and the ecs cluster. This will lead to the error.

import { Stack } from "aws-cdk-lib";
import * as autoscaling from "aws-cdk-lib/aws-autoscaling";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import { Construct } from "constructs";

class CapacityProviderStack extends Stack {
  autoScalingGroup: autoscaling.AutoScalingGroup;

  constructor(scope: Construct) {
    super(scope, "CapacityProviderStack");
    this.autoScalingGroup = new autoscaling.AutoScalingGroup(
      this,
      "AutoScalingGroup",
      {
        vpc: new ec2.Vpc(this, "Vpc"),
        machineImage: ec2.MachineImage.latestAmazonLinux2023(),
        instanceType: ec2.InstanceType.of(
          ec2.InstanceClass.T4G,
          ec2.InstanceSize.SMALL
        ),
      }
    );
  }
}

class ComputeStack extends Stack {
  constructor(
    scope: Construct,
    autoScalingGroup: autoscaling.AutoScalingGroup
  ) {
    super(scope, "ComputeStack");

    const cluster = new ecs.Cluster(this, "Cluster");

    const capacityProvider = new ecs.AsgCapacityProvider(
      this,
      "CapacityProvider",
      {
        autoScalingGroup,
      }
    );

    cluster.addAsgCapacityProvider(capacityProvider);
  }
}

export default function reproIssue(scope: Construct) {
  const capacityProviderStack = new CapacityProviderStack(scope);
  new ComputeStack(scope, capacityProviderStack.autoScalingGroup);
}

Possible Solution

Reimplement the addAsgCapacityProvider function to support this, e.g. by taking in the cluster name as a parameter and not introduce the Cfn dependency.

Additional Information/Context

It doesn't matter in which of the two stacks the AsgCapacityProvider is created. As long as the cluster and the ASG are in different cloudformation stacks, this happens.

AWS CDK Library version (aws-cdk-lib)

[email protected]

AWS CDK CLI version

2.1023.0 (build 45ceb89)

Node.js Version

v22.17.1

OS

MacOS 15.6

Language

TypeScript

Language Version

No response

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    @aws-cdk/aws-ecsRelated to Amazon Elastic ContainerbugThis issue is a bug.effort/mediumMedium work item – several days of effortp2

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions