BlueGreenDeployment (2010)
martinfowler.com
martinfowler.com
http://continuousdelivery.com/wp-content/uploads/2014/02/01_...
http://continuousdelivery.com/wp-content/uploads/2014/02/02_...
http://continuousdelivery.com/wp-content/uploads/2014/02/03_...
http://continuousdelivery.com/wp-content/uploads/2014/02/04_...
We do have a disaster recovery server, but it sits outdated for weeks after a deployment in production. When something goes wrong, the switch is not automatic and transparent to the user, we have to email EVERYONE in the user's list to please use the DR server's address. There is no router or load balancer.
Crazy.
On the other hand, the database was more or less a cache. It was very much availability over consistency, in CAP terms. If we had to keep transactional data, it would have been harder.
edit: When I started there and they described the architecture to me, I said "Cool, you're doing blue green deployment!", and the response was "What's blue green deployment?"
However, now that Elastic Beanstalk supports incremental rollouts I don't see as much value in the approach.
We use Blue/Green deployments (with AWS EB) at Mi9 to deploy all our high traffic websites
It is very sad and unfortunate that Amazon decided to limit the smaller number of instances to 1 in VPCs. In the old classic AWS you could set the minimum number of instances to 0, which allowed you to completely shutdown an environment without destroying it, effectively allowing you to turn back to it in a few seconds.
If Blue is in production and Green is on deck, how are updates to the Blue database pushed to Green?
( an example for SQL databases of this is having an 'additional info' field/table which has no value for indexing but contains additional captured info.)
The database when treated as a unique exception allows you to just get on with developing robust infrastructure.
However for this to work you need to keep code off the database and treat database changes as migrations not blue/green deploys.
I can't say this enough, treat the database as an exception, keep it clean without code on it and with 'soft' schemas (ones that tolerate minor changes well) - then you can do b/g deploys easily.
Also let someone else host the DB where possible (or the same cloud infrastructure of course), it's just not worth the pain.
Alternating on blue / green as the 'live' side works, too.
I then create symlinks such as "live" & "beta":
"live" -> "app-v1.0.0"
I rsync the code from a CI server or local host, after running bower/composer & testing, this way I deploy a "snapshot" of the entire codebase.
I find a lot of people just casually deploy their code with git, and subsequently run "bower install", tolerating downtime in between, with no solid rollback mechanism in place. I hear Capistrano works in a similar way but is git based instead of rsync. To me its really important that the updates happen atomically & roll back atomically, and as a result of running a single command.
Simple example of a "deploy.sh" I would use in a new project:
gulp production && rsync --update-after --delay-updates --exclude-from="rsync_exclude.txt" -avr ./ server-www:/var/www/html/
btw article is 4 years old
It's also worth noting that this use case is actually pretty hard to model in ansible without external tools or the like. You basically need to deploy four jobs:
- deploy new code to inactive environment
- switch persona from inactive to active
- reconfigure load balancer to send to newly active
- switch formerly active persona to inactive
within some or all of those individual tasks you might want to apply these rolling techniques. But since rollouts may not be idempotent and this process isn't transactional, you have to be very careful indeed to code this out.
after reading that articles (some months ago) I've decided to implement that in our company , we're mostly using symfony2 and postgresql, and I came up with that https://github.com/allan-simon/ansible-docker-symfony2-vagra...
basically I have
______nginx__phpfpm+code (blue)
/ \
front nginx database
\______nginx__phpfpm+code/ (green)
The front nginx play the role of "switch" between blue and green , and the database is sharedso basically for the database problem I solve by telling our dev to be aware of it, which translate into a two step process for database upgrade. (we use Dotrine's ORM with doctrine migrations for migrations, so when i talk about getter /setters I talk about the entities' )
* if we add a column which must be "not null" , we add it with a default value first , so the few second the old code is still online , but the database is already updated , if an insert happen it will not fail . Then second time we drop that default value and put in the migration the SQL statement that handle previous data.
* if we drop a column, we first commit a version of our application which remove the code using this column , or make them return default value. and then the second deployement drop the column, so that the version N-1 is already made to not care about it.
etc. the base logic is "the database version N+1 should still work with version N of the code" , I like to image that with a "crossing a small river by always keeping a feet on earth rather than jumping the two feet at once "after I have to admit that fortunately 99% of our deployment are not about database changes so this "need to do it carefully" only happen once in a while and it does not affect our productivity (especially with the gain of being able to do CI)
last thing, is that I've used this technique only on small to medium websites, nothing with HUGE traffic, so I don't know if it's 100% no downtime, my test (running several `while true; curl WEBSITE ; done ` ) shown no traffic lost.
I just wanted to say that to get opinion from more experienced people, while telling to "normal company" fellows that it's possible to achieve that without "the cloud" and old-school server hosted in a DC or at customer's office.
Edit: of course we still have a dev and staging environment on which we validate code before deploying in production.
Also: Your database changes should be entirely backwards compatible and should happen in one location (not on its own slice).