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개 답변
1
수락된 답변

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
답변함 한 달 전
profile picture
전문가
검토됨 한 달 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠