Amazon recently killed a rails production server of mine because they stopped supporting ruby 2.3 on their elastic beanstalk platform. I have been trying (desperately) to get new infrastructure setup using the CDK.
I was able to aws execute-command
into my task and see that 1) it has database connectivity, and 2) I can curl to localhost:3000 and get responses, so everything in the container is working.
I am certain the problem has to do with my lack of understanding of security groups…
I have a database stack which creates a security group and opens up port 5432 to itself– not sure if this is the right thing to do?
const securityGroup = new ec2.SecurityGroup(this, 'RdsSecurityGroup', {
vpc,
securityGroupName: SECURITY_GROUP_NAME,
});
securityGroup.addIngressRule(securityGroup, ec2.Port.tcp(5432));
this.database = new rds.DatabaseInstanceFromSnapshot(this, 'RdsDatabaseInstance', {
credentials: rds.SnapshotCredentials.fromSecret(rdsCredentials),
enablePerformanceInsights: true,
engine: rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_12_14 }),
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO),
multiAz: true,
publiclyAccessible: false,
snapshotIdentifier: DATABASE_SNAPSHOT,
securityGroups: [securityGroup],
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
}
});
}
}
Then my cluster stack looks up that security group and adds it to the service that creates the load balanced cluster:
const rdsSsecurityGroup = ec2.SecurityGroup.fromLookupByName(this, 'RdsSecurityGroup', SECURITY_GROUP_NAME, vpc);
const app = taskDefinition.addContainer('TaskDefinition', {
environment: {
'RDS_HOSTNAME': database.dbInstanceEndpointAddress,
'RDS_PORT': database.dbInstanceEndpointPort,
'RAILS_SERVE_STATIC_FILES': 'true',
},
image: ecs.ContainerImage.fromDockerImageAsset(dockerImageAsset),
logging: ecs.LogDriver.awsLogs({ streamPrefix: 'noteblaster-server' }),
});
app.addPortMappings({
containerPort: 3000,
protocol: ecs.Protocol.TCP,
});
const service = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'FargateService', {
cluster: cluster,
cpu: 1,
desiredCount: 1,
domainName: DOMAIN_NAME,
domainZone: hostedZone,
enableExecuteCommand: true,
memoryLimitMiB: 1024,
protocol: ApplicationProtocol.HTTPS,
publicLoadBalancer: true,
redirectHTTP: true,
securityGroups: [
rdsSsecurityGroup,
],
taskDefinition: taskDefinition,
});
}
My load balancer shows it has inbound rules for 80 and 443, and one outbound rule going to 3000, but it showed the destination being my rds security group– which seems totally wrong.
2
Answers
The problem was not security groups.. It was rails server binding to
localhost
which is inaccessible. I needed torails s -b 0.0.0.0
and then everything worked.Create 3 security groups and use security group chaining technique, example:
I hope it’s enough to get the idea.