What's the best way to deploy a PHP app onto Amazon's EC2? by @scalr
Answer by Sebastian Stadil:
Deploying some code is easy and is addressed bypretty well.
Where things get complicated is when you want to deploy new code that requires a new database schema, and perhaps a different version of php, mysql, or both, when you want to do it on hundreds or thousands of machines, and when you want to do it live.
Fortunately you are using, so I have a few tricks for you. We thought about this pretty hard while designing the Deployments feature at , here's our analysis.
The first way of doing this is to update your existing servers. Simply replace your code directly, possibly via a pull / update request from your code repository, into your app directory.
This works in most cases, but if your application contains many new files (a large diff), then the update can take time during which your app might malfunction.
If so, simply put the new version in another directory and create a symlink (ln -s source_file link_name) to it. This method also gives you time to install any additional software / libraries that are dependencies of the new version. Just make sure you create the symlink after you are done installing stuff.
This method has its limits too, which are apparent when you have dependencies incompatible with your previous app version, like upgradingversions. To get around that, lets take a look at preparing environments.
Preparing the environment
There's a whole category of software calledthat helps you with preparing environments. Essentially, they let you write code that determines what an individual server should look like. My favorites are ( ) and ( ). This is waaay better than writing bash scripts, and really shines when the number of servers you have goes over 20.
(Scalr is integrated with Chef so you can assign runlists to be executed at instance start).
For smaller infrastructure these tools can be a bit overkill. An easier albeit less scalable method is simply to ssh into a server, make your changes, and take a snapshot into a new machine image. You then use this new image to create servers which will replace those of your previous image.
(in Scalr, you can remove a server from DNS to prepare it)
At scale, this method is possible with a few modifications, as theengineering team has shown, which also doesn't have the open heart surgery constraints of operating on production infrastructure. Simply clone your entire setup (be careful to clone your data too). This is a new way of doing this that has been made possible thanks to .
(Scalr allows you to easily clone your infrastructure)
Once you have the clone, you can take your time and make any changes you want. If your new version doesn't require a different database schema, then you can additionally instruct your load balancer to send a portion of your traffic to the clone, while you carefully watch your error rates for any increase that would warrant a rollback of traffic.
Preparing the database
But lets say you do need to make a database schema update (ALTER TABLE). While this sounds easy, in practice it can get quite hard. First, it takes an increasing amount of time with your database size, and locks your table for the duration. Second, you'll have to coordinate that change across all theand read replicas you might have. Third, you run the risk of having a thread die in the middle of the update, leaving you in a broken state ( allows you to perform updates as a transaction, but still doesn't with 5.6).
As part of your deployment, you'll want to include a sql script that will make the desired changes to your schema. You have three options for this:
- Include the script in your application to be executed by it. This is easier since you already have the logic to connect to the database(s) with your password.
- Execute the script directly on the database servers. Gives you more control.
- Take a look at http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932 for a seemingly great way to do this's OnlineSchemaChange at
During that critical time that follows a deployment, you need to watch your monitors very carefully for increased error rates– avoid deploying right before leaving work. You'll also want to monitor resource consumption for possible memory leaks, infinite loops, and other recurring issues.
In case of disaster, you'll want to rollback. Depending on how extensively you changed the environment, this ranges from easy to bloody-murder-difficult. At worst, you might need to make a reverse schema change, revert to a previous machine image, and re-deploy your application.
The Scalr open source project has a feature called "Deployments" that helps you deploy code and manage the whole above process. This includes:
- Deploying code from a repository
- Running pre- and post- deploy scripts to prepare the environment
- Replacing instances of an old machine image with instances of an updated one ("snapshot replace future").
- Cloning entire setups
- Configuringrunlists to be executed on instance initialization
I hope this helps you and perhaps future readers. If it does, please consider an upvote! If not, please suggest an edit.