Use a VPC that spans at least two AZs (Availability Zones). Then place each part like this:
- The ALB (Application Load Balancer) goes in public subnets, one in each AZ.
- The Fargate tasks run in private subnets with no public IP.
- The RDS instance goes in private subnets too. These are often a separate set with no internet route at all. You define them with a DB subnet group that covers multiple AZs.
Security groups point to each other by reference, not by IP address:
- The ALB group allows port 443 from the internet.
- The app group allows the container port only from the ALB's security group.
- The database group allows port 5432 only from the app's security group.
Why references? Tasks start and stop all the time and get new IPs. A reference to a security group keeps working without any updates.
Tasks still need outbound access. Give it through a NAT gateway in each AZ. Or use VPC endpoints for AWS services like ECR, S3, Secrets Manager and CloudWatch Logs. A VPC endpoint is a private path to an AWS service, and it reduces NAT traffic.
- Use multiple AZs and put the ALB in public subnets.
- Put the tasks and the database in private subnets with no public IPs.
- Security groups reference each other in a chain: ALB to app to database.
- References keep working when task IPs change.
- Use a NAT gateway or VPC endpoints for outbound traffic to AWS services.
Read more