Update: We have released a free ebook about our workflow: Efficiency in Development Workflows.
Last week we talked about Deployment Pipelines and Zero Downtime Deployment.
After reading Chad Fowlers excellent blogpost about immutable deployments at 6Wunderkinder, we wanted to share our views on immutability in infrastructure.
Our definition of Immutable Infrastructure:
Automate the setup and deployment for every part and every layer of your infrastructure.
Never change any part of your system once it is deployed. If you need to change it, deploy a new system.
For example, instead of deploying into an existing EC2 instance, start a new server, deploy there and point your load balancer to the new server. Then remove the old server.
Replacing a system at the lowest level you can forces you to automate every deployment step.
Immutable infrastructure and Continuous deployment work great together. Completely replacing, instead of updating, an existing part of your infrastructure makes your deployments less complex.
Test driven development, Continuous Deployment and Immutable Infrastructure are strategies we have been using on Codeship for a long time.
For Immutable Infrastructure you need cloud servers and a virtualised environment.
Cloud servers are building blocks
In his AWS re:Invent Keynote Werner Vogels talked about Cloud servers as building blocks for larger systems. Jamie Begin wrote a great blog post on cloud serves as building blocks, based on the Keynote.
Today cloud instances are still used like physical hardware in the past. You set it up once and update it whenever necessary. The problem is that cloud servers are not meant to be reliable or durable.
Their advantage is that they are standardised and easy to replace. Cloud servers are like Lego pieces that can be changed whenever necessary. If you want to have a different color or the lego piece breaks, just put in a new one. You wouldn't repair a lego piece, would you?
[caption id="attachment_382" align="alignnone" width="885"]
You wouldn't repair a lego piece. Just grab a new one.[/caption]
Our Experience with Immutable infrastructure
Our web application, the Mothership, is hosted on Heroku and has therefore always been immutable. Whenever we deploy a new version, Heroku builds the Slug and replaces current instances with it. We have enabled Herokus Zero Downtime support.
Our test server infrastructure, the Checkbot, is hosted on AWS since August 2012. Whenever we want to change the test servers, we build a completely new Amazon AMI, test it and replace the old machines with the new AMI. We will go into more detail about this in our next blogpost.
By replacing every part of our infrastructure, often several times a day, we feel very comfortable with releasing changes. This workflow allows us to improve our service very quickly.
Advantages of an Immutable Infrastructure
There are many more advantages to Immutable Infrastructure than the following, but we have found these to be the most important ones to us:
Going back to an old version is easy, as you have the old image available.
Every change to the infrastructure needs to be in a script. Any server can be removed at any time and will take manual changes with it.
It is easy to have a production-like system on development machines.
You have an incentive to speed up the time your servers need to be built. We will talk about this in future blogposts.
Setting up staging systems is easy and can be automated.
Testing the new infrastructure in isolation is possible.
Challenges with Immutable Infrastructure
Of course this approach also has its challenges. Especially around tooling.
Better and standardised tooling is necessary, although new tools like Packer make it easier.
Setting up automation for immutable infrastructure has higher costs at the beginning.
Fixing problems is slower as you can't just SSH into an existing server. It needs to be redeployed.
There needs to be a way to reliably replace a server without impacting the whole system. Queuing and proxies that can store requests for a while are helpful.
Replacing databases continuously is hard.
Conclusions
Fixing broken servers instead of replacing them is a waste of time. It slows down the development and deployment cycle.
Test-Driven Development, Continuous Deployment and Immutable Infrastructure are practices every team should use. Together these practices help build reliable and high quality software that can be changed at any time. Being able to go back to an old version of your system in seconds allows you to experiment and innovate at a much faster pace.
Over the last months different tools like Packer or Docker have been released that make Immutable Infrastructure a lot easier.
In our next blog post we will show you in detail how we deploy our testing infrastructure several times a day. In future blog posts we will introduce Packer, Docker and other tools and show you how to rebuild your infrastructure constantly. Stay tuned!
Further Info:
The Codeship Workflow part 2 – Pull Requests and Code Review
The Codeship Workflow part 3 – Deployment Pipelines and Zero Downtime Deployment