CREATE_FAILED | AWS::ECS::Service + CloudFront, Cloud Map, LAX Local Zone, CDKv2

0

I'm trying to create a simple ECS service exposed to CloudFront via Cloud Map (I don't want an ALB). Why doesn't this work?

import * as cdk from 'aws-cdk-lib';
import { StackProps } from 'aws-cdk-lib';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as servicediscovery from 'aws-cdk-lib/aws-servicediscovery';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import { Construct } from 'constructs';

interface EcsDeployStackProps extends StackProps {
    dockerImageUriParam: string;
}

export class DeployStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: EcsDeployStackProps) {
        super(scope, id, props);

        const vpc = new ec2.Vpc(this, 'LosAngelesVPC', {
            cidr: '10.210.0.0/16',
            availabilityZones: ['us-west-2-lax-1a', 'us-west-2-lax-1b'],
            subnetConfiguration: [
                {
                    cidrMask: 24,
                    name: 'lax-public-subnet-1',
                    subnetType: ec2.SubnetType.PUBLIC,
                },
                {
                    cidrMask: 24,
                    name: 'lax-public-subnet-2',
                    subnetType: ec2.SubnetType.PUBLIC,
                },
                {
                    cidrMask: 24,
                    name: 'lax-private-subnet-1',
                    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
                },
                {
                    cidrMask: 24,
                    name: 'lax-private-subnet-2',
                    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
                }
            ],
        });
        // Create an ECS cluster with Fargate and Fargate Spot capacity providers
        const cluster = new ecs.Cluster(this, 'Cluster', {
            enableFargateCapacityProviders: true,
            vpc: vpc,
        });

        // Create a Cloud Map namespace for service discovery
        const namespace = new servicediscovery.PrivateDnsNamespace(this, 'Namespace', {
            name: 'search-namespace.local',
            vpc: cluster.vpc,
        });

        const dockerImageUriParameter = ssm.StringParameter.fromStringParameterName(this, 'DockerImageUriParam', props.dockerImageUriParam);

        const executionRole = new iam.Role(this, 'TaskExecutionRole', {
            assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
        });

        executionRole.addManagedPolicy(
            iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy')
        );

        // Create a task definition for your application
        const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', {
            memoryLimitMiB: 512,
            cpu: 256,
            executionRole: executionRole,
        });

        // Add your application container to the task definition
        const appContainer = taskDefinition.addContainer('AppContainer', {
            image: ecs.ContainerImage.fromRegistry(dockerImageUriParameter.stringValue),
            portMappings: [{ containerPort: 8080 }],
        });

        // Create a Fargate service with Spot capacity provider
        const service = new ecs.FargateService(this, 'Service', {
            cluster,
            taskDefinition,
            capacityProviderStrategies: [
                {
                    capacityProvider: 'FARGATE_SPOT',
                    weight: 4,
                },
                {
                    capacityProvider: 'FARGATE',
                    weight: 1,
                },
            ],
            cloudMapOptions: {
                name: 'search-service',
                cloudMapNamespace: namespace,
                dnsRecordType: servicediscovery.DnsRecordType.A,
            },
        });

        // Create a CloudFront distribution with the service as the origin
        const distribution = new cloudfront.Distribution(this, 'Distribution', {
            defaultBehavior: {
                origin: new origins.HttpOrigin(`search-service.${namespace.namespaceName}`, {
                    protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
                }),
                viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
                allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
                cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
                compress: true,
            },
            httpVersion: cloudfront.HttpVersion.HTTP3,
        });
    }
}

The error on cdk deploy is:

DeployStack | 42/44 | 11:56:31 PM | CREATE_FAILED | AWS::ECS::Service | Service/Service (ServiceD69D759B) Resource creation cancelled

  • I got past the original error by switching to an EC2 launch type, but now I'm stuck in AWS::ECS::Service CREATE_IN_PROGRESS

1 réponse
1
Réponse acceptée

Hello,

After reviewing the ECS Service Discovery documentation, I regret to inform you that the proposed setup for integrating Amazon CloudFront with an Amazon ECS service hosted in a private subnet would not be feasible. The documentation states:

The DNS records created for a service discovery service always register with the private IP address for the task, rather than the public IP address, even when public namespaces are used.

As Amazon CloudFront is an Internet-facing service, it requires access to content through a publicly accessible origin. However, Amazon ECS tasks running in a private subnet are not accessible from the Internet, thereby preventing CloudFront from retrieving the content.

Troubleshooting CloudFormation Stack Deployment

Regarding the issue with the CREATE_IN_PROGRESS state for the CloudFormation stack, I would recommend the following steps:

  1. Review the ECS Service events in the AWS Management Console for any relevant error messages or logs.
  2. Verify if the EC2 instances are successfully registering with the ECS Cluster. If they are not, please refer to the Knowledge Center article for further troubleshooting guidance.

Please let me know if you require any further assistance or have additional questions.

profile pictureAWS
répondu il y a un mois
profile picture
EXPERT
vérifié il y a un mois

Vous n'êtes pas connecté. Se connecter pour publier une réponse.

Une bonne réponse répond clairement à la question, contient des commentaires constructifs et encourage le développement professionnel de la personne qui pose la question.

Instructions pour répondre aux questions