Here's a rough approach to scaling any stateless app on AWS:
Run the app in an Auto Scaling Group (ASG). An ASG makes it easy to manage multiple servers, will automatically replace failed servers, and allows you to automatically scale the number of servers up or down in response to load.
To run an ASG, you need to create a Launch Configuration. This is a "template" that specifies the configuration for each server in the ASG: i.e., what type of instance to run (e.g.
t2.micro
), what AMI to run on the instance, the security group settings, etc.The AMI you run on each instance in the ASG should have your app already installed (i.e., your PHP app). You can define your AMI as code using a tool like Packer.
The app in your AMI should be configured to run on boot using a process supervisor (e.g., using systemd or supervisord; this will also ensure the app is restarted automatically if it crashes.
Every time you change something in your app, run a build process to create a new AMI, update the Launch Configuration to use this new AMI, and roll that AMI out across your ASG. For example, you could do a zero-downtime deployment by (somewhat similar to a blue-green deployment) by doubling the size of the ASG, waiting until all the new servers (from the updated Launch Configuration) launch and pass health checks, and then reducing the ASG back to its previous size (the ASG will terminate oldest instances by default).
With an ASG, you have more than one server, but you want to give your users a single endpoint to use. The typical solution to this is to deploy a load balancer in front of the ASG. If you're building a typical HTTP/HTTPs app (e.g., just about all PHP apps), you'll want to use the Application Load Balancer (ALB); if you're building an app that listens directly for TCP connections, you'll want the Load Balancer Classic or Network Load Balancer. Whichever load balancer you pick, AWS will create a domain name for it that you can use, and any requests you send to that domain name will be routed in round-robin fashion to different servers in your ASG.
You should a) configure the load balancer to perform health checks on your app so that it only routes to healthy servers and b) configure your ASG to register all of its servers in the load balancer automatically and to use the load balancer for health checks.
You can create Auto Scaling Policies for the ALB that change the number of servers in your ASG depending on various CloudWatch metrics. For example, you could configure the ASG to add servers when average CPU usage is over 80% and to remove servers when CPU usage drops below 60%.
For more info, check out A Comprehensive Guide to Building a Scalable Web App on Amazon Web Services.