I got tripped up today while attempting to load balance a couple of EC2 instances in a private subnet using the ELB. This backend architecture is typical of a highly available fault tolerant enterprise grade system. It contains a public facing DMZ with a bastion server, a "private-ish" web tier and a private API tier.
According to Amazon, when your VPC resembles this configuration you must create public subnets that reside in the same Availability Zone (AZ) as your private subnet in order to use ELB. Otherwise your ELB will never connection to the web servers in the private subnets.
"When you create a load balancer, you must add one or more public subnets to the load balancer. If your instances are in private subnets, create public subnets in the same Availability Zones as the subnets with your instances; you will add these public subnets to the load balancer. "
ELB must be associated with public subnets only. I believe this is because ELB is nothing more than HA Proxy or some other equivalent under the hood. Amazon recommends that subnets associated with ELB should be no smaller than /27, allowing 8 IPs to be used (if necessary) for ELB instances.
When you're building this stuff, it's a good idea to make sure everything is connected before code is deployed. Python contains a simple HTTP server that you can use to simulate a web server on any port. Simply create a directory, create an HTML file and execute the following in that directory:
sudo python -m SimpleHTTPServer 80 &
CORRECTION: The text "Public Subnet for ELB/DMZ 10.0.2.0/24 - us-east-1c" in the us-east-1d AZ should read: Public Subnet for ELB/DMZ 10.0.2.0/24 - us-east-1d.