i am having troubles setting up my AWS VPC via cdk. I want to create a VPC with 2 subnets, one public and one private_isolated, with no nat gateways and one internet gateway. In the public i will host my node web server and in the private my java microservice. Since i don't know a lot about networking in general, i used a private dns namespace and got the 2 services communicate to each other via AWS Service Discovery*. The thing is, when i deploy my stack, it gets stuck in creating the java fargate service, and i think the problem is because of the private_isolated subnet. So i added interface endpoints for ecr_docker and ecr and even an s3 gateway endpoint, but the service still remains stuck on create in progress. Here's my code:
export class EcsServiceDiscoveryStack extends Stack {
readonly serviceBack = "back-service";
readonly servicePdf = "pdf-service";
readonly namespace = "env.test";
readonly vpc: Vpc;
readonly cluster: Cluster;
readonly dnsNamespace: PrivateDnsNamespace;
readonly ingressSecurityGroup: SecurityGroup;
readonly egressSecurityGroup: SecurityGroup;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
/* ----------------------------------- VPC ---------------------------------- */
const subnetConfig: ec2.SubnetConfiguration[] = [
{
name: "test-public-subnet",
subnetType: SubnetType.PUBLIC,
},
{
name: "test-private-subnet",
subnetType: SubnetType.PRIVATE_ISOLATED,
},
];
this.vpc = new ec2.Vpc(this, "test-vpc", {
maxAzs: 1,
subnetConfiguration: subnetConfig,
gatewayEndpoints: {
S3: { service: ec2.GatewayVpcEndpointAwsService.S3 },
},
});
/* ------------------------- INTERFACE VPC ENDPOINT ------------------------- */
this.vpc.addInterfaceEndpoint("aws-ecr_docker-endpoint", {
service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
privateDnsEnabled: true,
subnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
open: true,
});
this.vpc.addInterfaceEndpoint("aws-ecr-endpoint", {
service: ec2.InterfaceVpcEndpointAwsService.ECR,
privateDnsEnabled: true,
subnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
open: true,
});
/* --------------------------------- CLUSTER -------------------------------- */
this.cluster = new ecs.Cluster(this, "test-cluster", {
clusterName: "test-cluster",
vpc: this.vpc,
});
/* ------------------------------ DNS NAMESPACE ----------------------------- */
this.dnsNamespace = new servicediscovery.PrivateDnsNamespace(
this,
"DnsNamespace",
{
name: this.namespace,
vpc: this.vpc,
description: "Private DnsNamespace for test environment",
}
);
/* -------------------------------- TASK ROLE ------------------------------- */
//NODE
const backTaskrole = new iam.Role(this, "backTaskExecutionRole", {
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
});
backTaskrole.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AmazonECSTaskExecutionRolePolicy"
)
);
//JAVA
const pdfTaskRole = new iam.Role(this, "pdfTaskExecutionRole", {
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
});
pdfTaskRole.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AmazonECSTaskExecutionRolePolicy"
)
);
/* ---------------------------- TASKS DEFINITIONS ---------------------------- */
//NODE
const backFargateTaskDefinition = new ecs.FargateTaskDefinition(
this,
`${this.serviceBack}ServiceTaskDef`,
{
cpu: 256,
memoryLimitMiB: 512,
taskRole: backTaskrole,
}
);
//JAVA
const pdfFargateTaskDefinition = new ecs.FargateTaskDefinition(
this,
`${this.servicePdf}ServiceTaskDef`,
{
cpu: 256,
memoryLimitMiB: 512,
taskRole: pdfTaskRole,
}
);
/* ---------------------------- SERVICE LOG GROUP --------------------------- */
//NODE
const backServiceLogGroup = new logs.LogGroup(
this,
`${this.serviceBack}ServiceLogGroup`,
{
logGroupName: `/ecs/${this.serviceBack}Service`,
removalPolicy: RemovalPolicy.DESTROY,
}
);
//JAVA
const pdfServiceLogGroup = new logs.LogGroup(
this,
`${this.servicePdf}ServiceLogGroup`,
{
logGroupName: `/ecs/${this.servicePdf}Service`,
removalPolicy: RemovalPolicy.DESTROY,
}
);
/* ------------------------------- LOG DRIVER ------------------------------- */
//NODE
const backServiceLogDriver = new ecs.AwsLogDriver({
logGroup: backServiceLogGroup,
---
streamPrefix: `${this.serviceBack}Service`,
});
//JAVA
const pdfServiceLogDriver = new ecs.AwsLogDriver({
logGroup: pdfServiceLogGroup,
streamPrefix: `${this.servicePdf}Service`,
});
/* ---------------------------- REPOISTORY (ECR) ---------------------------- */
//NODE
const repoBackNode = Repository.fromRepositoryName(
this,
"back-nodejs",
"task-nodejs-test"
);
//JAVA
const repoBackJava = Repository.fromRepositoryName(
this,
"pdf-java",
"task-nodejs-test"
);
/* -------------------------------- CONTAINER ------------------------------- */
//NODE
const backServiceContainer = backFargateTaskDefinition.addContainer(
`${this.serviceBack}ServiceContainer`,
{
containerName: `${this.serviceBack}ServiceContainer`,
essential: true,
image: ecs.ContainerImage.fromEcrRepository(repoBackNode),
logging: backServiceLogDriver,
portMappings: [{ containerPort: 80 }],
environment: {
PORT: "80",
NAME: "back-nodejs",
PDF_HOST: `http://${this.servicePdf}.${this.namespace}:80`,
},
}
);
//JAVA
const pdfServiceContainer = pdfFargateTaskDefinition.addContainer(
`${this.servicePdf}ServiceContainer`,
{
containerName: `${this.servicePdf}ServiceContainer`,
image: ecs.ContainerImage.fromEcrRepository(repoBackJava),
logging: pdfServiceLogDriver,
portMappings: [{ containerPort: 80 }],
environment: {
PORT: "80",
NAME: "pdf-java",
PDF_HOST: this.servicePdf,
},
}
);
/* ----------------------------- SECURITY GROUP ----------------------------- */
//VPC
this.ingressSecurityGroup = new ec2.SecurityGroup(
this,
`IngressSecurityGroup`,
{
allowAllOutbound: true,
securityGroupName: `IngressSecurityGroup`,
vpc: this.vpc,
description: "IngressSecurityGroup for the VPC",
}
);
this.ingressSecurityGroup.connections.allowFromAnyIpv4(ec2.Port.tcp(80));
//NODE
const backServiceSecGroup = new ec2.SecurityGroup(
this,
`${this.serviceBack}ServiceSecurityGroup`,
{
allowAllOutbound: true,
securityGroupName: `${this.serviceBack}ServiceSecurityGroup`,
vpc: this.vpc,
description: "Security Group for the nodejs server",
}
);
backServiceSecGroup.connections.allowFrom(
new ec2.Connections({
securityGroups: [this.ingressSecurityGroup],
}),
ec2.Port.tcp(80),
"Allow traffic on port 80 from the VPC ingress security group"
);
//JAVA
const pdfServiceSecGroup = new ec2.SecurityGroup(
this,
`${this.servicePdf}ServiceSecurityGroup`,
{
allowAllOutbound: true,
securityGroupName: `${this.servicePdf}ServiceSecurityGroup`,
vpc: this.vpc,
description: "Security Group for the java pdf service",
}
);
pdfServiceSecGroup.connections.allowFrom(
new ec2.Connections({
securityGroups: [backServiceSecGroup],
}),
ec2.Port.tcp(80),
"Allow traffic on port 80 from the backService security group"
);
/* ----------------------------- FARGATE SERVICE ---------------------------- */
//NODE
const backFargateService = new ecs.FargateService(
this,
`${this.serviceBack}Service`,
{
cluster: this.cluster,
taskDefinition: backFargateTaskDefinition,
assignPublicIp: true,
desiredCount: 1,
securityGroups: [backServiceSecGroup],
cloudMapOptions: {
name: this.serviceBack,
cloudMapNamespace: this.dnsNamespace,
dnsRecordType: servicediscovery.DnsRecordType.A,
},
}
);
//JAVA
const pdfFargateService = new ecs.FargateService(
this,
`${this.servicePdf}Service`,
{
cluster: this.cluster,
taskDefinition: pdfFargateTaskDefinition,
desiredCount: 1,
securityGroups: [pdfServiceSecGroup],
cloudMapOptions: {
name: this.servicePdf,
cloudMapNamespace: this.dnsNamespace,
dnsRecordType: servicediscovery.DnsRecordType.A,
},
}
);
}
}
Where did i do wrong? Thanks in advance for your time
*i did a try with only public subnet, in order to verify service discovery was working