App-FargateStack

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

and a warning will be logged to indicate that the selection was
inferred.

## SUBNET SELECTION

If no subnets are specified in the configuration, the framework will query all
subnets in the selected VPC and categorize them as either public or private.

The task will be placed in a private subnet by default. For this to succeed,
your VPC must have at least one private subnet with a route to a NAT Gateway,
or have appropriate VPC endpoints configured for ECR, S3, STS, CloudWatch Logs,
and any other services your task needs.

If subnets are explicitly specified in your configuration, the
framework will validate them and warn if they are not reachable or are
not usable for Fargate tasks.

### Task placement and Availability Zones

The framework places each task's ENI into exactly one subnet, which fixes
that task in a single AZ. A service can span multiple AZs by listing

README.md  view on Meta::CPAN

Notes on internet access and ALBs:

- Internet-facing ALB

    An internet-facing ALB must be created in public subnets. Tasks may (and
    usually should) remain in private subnets behind it.

- Egress from private subnets

    For image pulls and outbound calls, use either a NAT Gateway in each AZ
    or VPC endpoints for ECR (api and dkr) and S3.

- Egress from public subnets

    If tasks are placed in public subnets without endpoints or NAT, they
    require `assignPublicIp=ENABLED` to reach ECR/S3.

## REQUIRED SECTIONS

At minimum, your configuration must include the following:

    app:
      name: my-stack

    tasks:

README.md  view on Meta::CPAN


### Recommended pattern

Use private subnets for most Fargate workloads. Private subnets do not
route directly to the internet.

If the task needs outbound access (for example, to pull images from
ECR or call external APIs), use one of:

- A NAT Gateway (private subnet egress to the internet)
- VPC interface endpoints for ECR (ecr.api and ecr.dkr) and a
gateway endpoint for S3, so image pulls stay inside the VPC with no
public IPs

For public-facing applications, the common pattern is: tasks in
private subnets, fronted by a public Application Load Balancer in
public subnets.

### When is a public subnet acceptable?

Use a public subnet only when the task itself must have a public IP
and terminate client connections directly (uncommon). If you do:

- Set assignPublicIp=ENABLED so the task can reach the internet
via the Internet Gateway
- Keep security groups locked down and monitor egress on TCP 443

### Note on image pulls

To pull from ECR, the task needs a path to ECR API, ECR DKR, and S3:

- Public subnet: requires a public IP (assignPublicIp=ENABLED),
unless you provision VPC endpoints
- Private subnet: works via a NAT Gateway, or entirely private
via VPC endpoints (no public IPs)

## My task fails with this message:

    ResourceInitializationError: unable to pull secrets or registry auth:
    The task cannot pull registry auth from Amazon ECR: There is a
    connection issue between the task and Amazon ECR. Check your task
    network configuration. operation error ECR: GetAuthorizationToken,
    exceeded maximum number of attempts, 3, https response error
    StatusCode: 0, RequestID: , request send failed, Post
    "https://api.ecr.us-east-1.amazonaws.com/": dial tcp 44.213.79.10:443:
    i/o timeout

This error usually occurs when your task is launched in a subnet that
does not have outbound access to the internet. Internet access - or a
properly configured VPC endpoint - is required for Fargate to
authenticate with ECR and pull your container image.

### Common causes

- The task was placed in a public subnet but was not assigned a
public IP.
- The task was placed in a private subnet without access to a
NAT gateway or VPC endpoints.

Even though the subnet may have a route to an Internet Gateway (i.e.,
it is technically a "public" subnet), if the task does not receive a
public IP, it cannot use that route to reach external services like
ECR or Secrets Manager.

### How to fix it

- If using public subnets, ensure the task is assigned a public
IP.
- If using private subnets, ensure a NAT gateway is available
and the subnet has a route to it.
- Alternatively, configure VPC endpoints for ECR, Secrets
Manager, and related services to avoid needing internet access
altogether.

### Note on Subnet Selection

`App::FargateStack` attempts to prevent this situation by analyzing
your VPC configuration during planning. It categorizes subnets as
private or public and evaluates whether they provide the necessary
network access to launch a Fargate task successfully. The framework
warns if you attempt to use a subnet that lacks internet or endpoint
access.

## My task failed to start and the reason is unclear

This is one of the most common and frustrating scenarios when working
with Fargate. You run `start-service` or `run-task`, the command
seems to succeed, but then the task quickly stops. The `status`
command shows the desired count is 1 but the running count is 0, and
the logs are empty.

This often happens due to a **resource initialization error**. The
problem isn't with your container image itself, but with the
infrastructure Fargate is trying to set up for it.

Common causes include:

- **Networking Issues**: The task is in a subnet that can't pull the
image from ECR (e.g., no NAT Gateway or VPC endpoints).
- **Permissions Errors**: The task's IAM role is missing a required
permission.
- **EFS Mount Failures**: The task cannot mount an EFS volume, often due
to a misconfigured security group or incorrectly specified path.

These errors are opaque because they happen deep inside the
AWS-managed environment. The high-level ECS API only reports a generic
failure, and since it's not an API call error, it won't appear in
CloudTrail.

lib/App/EC2.pm  view on Meta::CPAN

          ]
        );
      }
    );

    my $warning = <<'END_OF_WARNING';
WARNING: %s is not in the list of subnets with a route to the internet.

Tasks in private subnets require either:
- A NAT gateway (for general internet access), or
- Properly configured VPC endpoints for ECR, S3, STS, Logs, etc.

Without one of these, your task may fail to start or access required services.
END_OF_WARNING

    foreach my $type (qw(public private)) {
      foreach my $id ( @{ $subnets->{$type} || [] } ) {
        next if any { $_ eq $id } @all_subnets;
        $self->get_logger->warn( sprintf $warning, $id );
      }
    }

lib/App/FargateStack/Checker.pm  view on Meta::CPAN


  my ( $ok_nat, $nat, $err_nat ) = try_aws(
    sub {
      $ec2->command(
        'describe-nat-gateways' => [ '--filter', 'Name=state,Values=available', '--query', 'NatGateways[].NatGatewayId' ] );
    }
  );

  my ( $ok_ep, $eps, $err_ep ) = try_aws(
    sub {
      $ec2->command( 'describe-vpc-endpoints' => [ '--query', 'VpcEndpoints[].ServiceName' ] );
    }
  );

  my $has_nat = $ok_nat && $nat && @{$nat};
  my $has_eps = $ok_ep  && $eps;

  if ( !$has_nat && !$has_eps ) {
    return row_fail( 'Egress', 'Private subnets need NAT or VPC endpoints (ECR, Logs, Secrets)' );
  }

  my %need = (
    'com.amazonaws.%s.ecr.api' => 1,
    'com.amazonaws.%s.ecr.dkr' => 1,
    'com.amazonaws.%s.logs'    => 1,
  );

  if ($need_secrets) {
    $need{'com.amazonaws.%s.secretsmanager'} = 1;

lib/App/FargateStack/Checker.pm  view on Meta::CPAN

  if ($has_eps) {
    my %have = map { $_ => 1 } @{$eps};
    my @missing;
    foreach my $tmpl ( keys %need ) {
      my $svc = sprintf $tmpl, ( $opt->{region} || 'us-east-1' );
      if ( !$have{$svc} ) {
        push @missing, $svc;
      }
    }
    if ( @missing && !$has_nat ) {
      return row_fail( 'Egress', 'Missing VPC endpoints: ' . join q{, }, @missing );
    }
    if ( @missing && $has_nat ) {
      return row_ok( 'Egress', 'Using NAT; missing optional endpoints: ' . join q{, }, @missing );
    }
  }

  return row_ok( 'Egress', $has_nat ? 'NAT available' : 'Required endpoints present' );
}

########################################################################
sub check_ecs_permissions {
########################################################################
  my ($opt) = @_;

  my $ecs = new_client( 'App::ECS', $opt );

  my ( $ok1, $clusters, $err1 ) = try_aws( sub { $ecs->command( 'list-clusters' => [ '--query' => 'clusterArns[]' ] ) } );

lib/App/FargateStack/Checker.pm  view on Meta::CPAN

sub check_secrets_hint {
########################################################################
  my ($opt) = @_;

  # The deployer does not need GetSecretValue; tasks use task role.
  # We only check control-plane reachability here.
  my $ec2 = new_client( 'App::EC2', $opt );

  my ( $ok_ep, $eps, $err_ep ) = try_aws(
    sub {
      $ec2->command( 'describe-vpc-endpoints' => [ '--query', 'VpcEndpoints[].ServiceName' ] );
    }
  );

  if ( !$ok_ep ) {
    return row_warn( 'Secrets Manager', 'Could not confirm VPC endpoints for Secrets Manager' );
  }

  my %have = map { $_ => 1 } @{ $eps || [] };
  my $svc  = sprintf 'com.amazonaws.%s.secretsmanager', ( $opt->{region} || 'us-east-1' );

  if ( !$have{$svc} ) {
    return row_warn( 'Secrets Manager', 'Missing VPC endpoint for Secrets Manager or rely on NAT' );
  }

  return row_ok( 'Secrets Manager', 'Endpoint present' );
}
########################################################################
sub check_passrole {
########################################################################
  my ($opt) = @_;
  my $role_names = $opt->get_role_names;

lib/App/FargateStack/Checker.pm  view on Meta::CPAN


=item B<--https> | B<--no-https>

Enable or disable ACM certificate checks (same region as the load balancer).
Default: B<disabled>. Turn on if you plan to deploy HTTPS.

=item B<--secrets> | B<--no-secrets>

Enable or disable Secrets Manager reachability checks. Default: B<disabled>.
When enabled, the checker verifies control-plane reachability (e.g., VPC
endpoint present or NAT available). It does not validate individual
C<GetSecretValue> permissions for task roles.

=back

=head1 OUTPUT

The main table includes rows like:

  Credentials
  Service-linked roles

lib/App/FargateStack/Checker.pm  view on Meta::CPAN

  ECR
  Events perms
  iam:PassRole
  Route 53
  ACM
  Secrets Manager

Each row has a Status of B<PASS>, B<WARN>, or B<FAIL> and a Detail string.
Typical examples:

  - Egress: PASS with NAT present; missing VPC endpoints are called out as optional.
  - Events perms: PASS when EventBridge APIs are readable (e.g., list-event-buses).
  - iam:PassRole: PASS when simulation allows passing target roles to
    C<ecs-tasks.amazonaws.com> and C<events.amazonaws.com>.

=head2 CAPABILITIES SUMMARY

After the table, a summary lists readiness for common Fargate scenarios:

  YES   = all required checks PASS
  MAYBE = at least one required check WARN (no FAILs)

lib/App/FargateStack/Checker.pm  view on Meta::CPAN


=item * Service-linked roles (SLRs)

The checker reports on SLRs relevant to ECS/ELB. EventBridge does not have a
single generic “AWSServiceRoleForEvents”; feature-specific SLRs are outside the
default scope.

=item * Egress semantics

For private subnets, NAT is sufficient for pulling images and writing logs.
VPC endpoints for ECR (api+dkr) and Logs are recommended in restricted/air-gapped
environments; missing endpoints are reported as optional when NAT is present.

=item * iam:PassRole simulation

When role names are known or derivable, the checker simulates C<iam:PassRole>
for each target role against C<ecs-tasks.amazonaws.com> and
C<events.amazonaws.com>. If role names are not available, the tool may WARN and
capabilities depending on PassRole may degrade to MAYBE.

=item * Separate DNS account

lib/App/FargateStack/Pod.pm  view on Meta::CPAN

and a warning will be logged to indicate that the selection was
inferred.

=head2 SUBNET SELECTION

If no subnets are specified in the configuration, the framework will query all
subnets in the selected VPC and categorize them as either public or private.

The task will be placed in a private subnet by default. For this to succeed,
your VPC must have at least one private subnet with a route to a NAT Gateway,
or have appropriate VPC endpoints configured for ECR, S3, STS, CloudWatch Logs,
and any other services your task needs.

If subnets are explicitly specified in your configuration, the
framework will validate them and warn if they are not reachable or are
not usable for Fargate tasks.

=head3 Task placement and Availability Zones

The framework places each task's ENI into exactly one subnet, which fixes
that task in a single AZ. A service can span multiple AZs by listing

lib/App/FargateStack/Pod.pm  view on Meta::CPAN

=over 4

=item * Internet-facing ALB

An internet-facing ALB must be created in public subnets. Tasks may (and
usually should) remain in private subnets behind it.

=item * Egress from private subnets

For image pulls and outbound calls, use either a NAT Gateway in each AZ
or VPC endpoints for ECR (api and dkr) and S3.

=item * Egress from public subnets

If tasks are placed in public subnets without endpoints or NAT, they
require C<assignPublicIp=ENABLED> to reach ECR/S3.

=back

=head2 REQUIRED SECTIONS

At minimum, your configuration must include the following:

  app:
    name: my-stack

lib/App/FargateStack/Pod.pm  view on Meta::CPAN

Use private subnets for most Fargate workloads. Private subnets do not
route directly to the internet.

If the task needs outbound access (for example, to pull images from
ECR or call external APIs), use one of:

=over 4

=item * A NAT Gateway (private subnet egress to the internet)

=item * VPC interface endpoints for ECR (ecr.api and ecr.dkr) and a
gateway endpoint for S3, so image pulls stay inside the VPC with no
public IPs

=back

For public-facing applications, the common pattern is: tasks in
private subnets, fronted by a public Application Load Balancer in
public subnets.

=head3 When is a public subnet acceptable?

lib/App/FargateStack/Pod.pm  view on Meta::CPAN


=back

=head3 Note on image pulls

To pull from ECR, the task needs a path to ECR API, ECR DKR, and S3:

=over 4

=item * Public subnet: requires a public IP (assignPublicIp=ENABLED),
unless you provision VPC endpoints

=item * Private subnet: works via a NAT Gateway, or entirely private
via VPC endpoints (no public IPs)

=back

=head2 My task fails with this message:

 ResourceInitializationError: unable to pull secrets or registry auth:
 The task cannot pull registry auth from Amazon ECR: There is a
 connection issue between the task and Amazon ECR. Check your task
 network configuration. operation error ECR: GetAuthorizationToken,
 exceeded maximum number of attempts, 3, https response error
 StatusCode: 0, RequestID: , request send failed, Post
 "https://api.ecr.us-east-1.amazonaws.com/": dial tcp 44.213.79.10:443:
 i/o timeout

This error usually occurs when your task is launched in a subnet that
does not have outbound access to the internet. Internet access - or a
properly configured VPC endpoint - is required for Fargate to
authenticate with ECR and pull your container image.

=head3 Common causes

=over 4

=item * The task was placed in a public subnet but was not assigned a
public IP.

=item * The task was placed in a private subnet without access to a
NAT gateway or VPC endpoints.

=back

Even though the subnet may have a route to an Internet Gateway (i.e.,
it is technically a "public" subnet), if the task does not receive a
public IP, it cannot use that route to reach external services like
ECR or Secrets Manager.

=head3 How to fix it

=over 4

=item * If using public subnets, ensure the task is assigned a public
IP.

=item * If using private subnets, ensure a NAT gateway is available
and the subnet has a route to it.

=item * Alternatively, configure VPC endpoints for ECR, Secrets
Manager, and related services to avoid needing internet access
altogether.

=back

=head3 Note on Subnet Selection

C<App::FargateStack> attempts to prevent this situation by analyzing
your VPC configuration during planning. It categorizes subnets as
private or public and evaluates whether they provide the necessary
network access to launch a Fargate task successfully. The framework
warns if you attempt to use a subnet that lacks internet or endpoint
access.

=head2 My task failed to start and the reason is unclear

This is one of the most common and frustrating scenarios when working
with Fargate. You run C<start-service> or C<run-task>, the command
seems to succeed, but then the task quickly stops. The C<status>
command shows the desired count is 1 but the running count is 0, and
the logs are empty.

lib/App/FargateStack/Pod.pm  view on Meta::CPAN

problem isn't with your container image itself, but with the
infrastructure Fargate is trying to set up for it.

Common causes include:

=over 4

=item *

B<Networking Issues>: The task is in a subnet that can't pull the
image from ECR (e.g., no NAT Gateway or VPC endpoints).

=item *

B<Permissions Errors>: The task's IAM role is missing a required
permission.

=item *

B<EFS Mount Failures>: The task cannot mount an EFS volume, often due
to a misconfigured security group or incorrectly specified path.

share/README.md  view on Meta::CPAN

and a warning will be logged to indicate that the selection was
inferred.

## SUBNET SELECTION

If no subnets are specified in the configuration, the framework will query all
subnets in the selected VPC and categorize them as either public or private.

The task will be placed in a private subnet by default. For this to succeed,
your VPC must have at least one private subnet with a route to a NAT Gateway,
or have appropriate VPC endpoints configured for ECR, S3, STS, CloudWatch Logs,
and any other services your task needs.

If subnets are explicitly specified in your configuration, the
framework will validate them and warn if they are not reachable or are
not usable for Fargate tasks.

### Task placement and Availability Zones

The framework places each task's ENI into exactly one subnet, which fixes
that task in a single AZ. A service can span multiple AZs by listing

share/README.md  view on Meta::CPAN

Notes on internet access and ALBs:

- Internet-facing ALB

    An internet-facing ALB must be created in public subnets. Tasks may (and
    usually should) remain in private subnets behind it.

- Egress from private subnets

    For image pulls and outbound calls, use either a NAT Gateway in each AZ
    or VPC endpoints for ECR (api and dkr) and S3.

- Egress from public subnets

    If tasks are placed in public subnets without endpoints or NAT, they
    require `assignPublicIp=ENABLED` to reach ECR/S3.

## REQUIRED SECTIONS

At minimum, your configuration must include the following:

    app:
      name: my-stack

    tasks:

share/README.md  view on Meta::CPAN


### Recommended pattern

Use private subnets for most Fargate workloads. Private subnets do not
route directly to the internet.

If the task needs outbound access (for example, to pull images from
ECR or call external APIs), use one of:

- A NAT Gateway (private subnet egress to the internet)
- VPC interface endpoints for ECR (ecr.api and ecr.dkr) and a
gateway endpoint for S3, so image pulls stay inside the VPC with no
public IPs

For public-facing applications, the common pattern is: tasks in
private subnets, fronted by a public Application Load Balancer in
public subnets.

### When is a public subnet acceptable?

Use a public subnet only when the task itself must have a public IP
and terminate client connections directly (uncommon). If you do:

- Set assignPublicIp=ENABLED so the task can reach the internet
via the Internet Gateway
- Keep security groups locked down and monitor egress on TCP 443

### Note on image pulls

To pull from ECR, the task needs a path to ECR API, ECR DKR, and S3:

- Public subnet: requires a public IP (assignPublicIp=ENABLED),
unless you provision VPC endpoints
- Private subnet: works via a NAT Gateway, or entirely private
via VPC endpoints (no public IPs)

## My task fails with this message:

    ResourceInitializationError: unable to pull secrets or registry auth:
    The task cannot pull registry auth from Amazon ECR: There is a
    connection issue between the task and Amazon ECR. Check your task
    network configuration. operation error ECR: GetAuthorizationToken,
    exceeded maximum number of attempts, 3, https response error
    StatusCode: 0, RequestID: , request send failed, Post
    "https://api.ecr.us-east-1.amazonaws.com/": dial tcp 44.213.79.10:443:
    i/o timeout

This error usually occurs when your task is launched in a subnet that
does not have outbound access to the internet. Internet access - or a
properly configured VPC endpoint - is required for Fargate to
authenticate with ECR and pull your container image.

### Common causes

- The task was placed in a public subnet but was not assigned a
public IP.
- The task was placed in a private subnet without access to a
NAT gateway or VPC endpoints.

Even though the subnet may have a route to an Internet Gateway (i.e.,
it is technically a "public" subnet), if the task does not receive a
public IP, it cannot use that route to reach external services like
ECR or Secrets Manager.

### How to fix it

- If using public subnets, ensure the task is assigned a public
IP.
- If using private subnets, ensure a NAT gateway is available
and the subnet has a route to it.
- Alternatively, configure VPC endpoints for ECR, Secrets
Manager, and related services to avoid needing internet access
altogether.

### Note on Subnet Selection

`App::FargateStack` attempts to prevent this situation by analyzing
your VPC configuration during planning. It categorizes subnets as
private or public and evaluates whether they provide the necessary
network access to launch a Fargate task successfully. The framework
warns if you attempt to use a subnet that lacks internet or endpoint
access.

## My task failed to start and the reason is unclear

This is one of the most common and frustrating scenarios when working
with Fargate. You run `start-service` or `run-task`, the command
seems to succeed, but then the task quickly stops. The `status`
command shows the desired count is 1 but the running count is 0, and
the logs are empty.

This often happens due to a **resource initialization error**. The
problem isn't with your container image itself, but with the
infrastructure Fargate is trying to set up for it.

Common causes include:

- **Networking Issues**: The task is in a subnet that can't pull the
image from ECR (e.g., no NAT Gateway or VPC endpoints).
- **Permissions Errors**: The task's IAM role is missing a required
permission.
- **EFS Mount Failures**: The task cannot mount an EFS volume, often due
to a misconfigured security group or incorrectly specified path.

These errors are opaque because they happen deep inside the
AWS-managed environment. The high-level ECS API only reports a generic
failure, and since it's not an API call error, it won't appear in
CloudTrail.



( run in 0.270 second using v1.01-cache-2.11-cpan-0ffa90cfd1c )