Building a computing platform that allows developers to focus on the application and business problem is seen as one of the key ingredients in modern technology companies. Different organisations take different approaches but one that comes up regularly is the concept of 'immutable infrastructure'. The thinking goes that in order to move from one off builds to automated builds in the cloud, building replicas must be considered.
The goal is to use
immutable servers [to] simplify several aspects of our systemRethinking Cloud by Ben Butler-Cole but they also create challenges like the need to
centralise your logs as Florian Motlik also highlights.
Platforms like AWS often seem to relate infrastructure to machine or environment 'images', e.g. the AMI. This may not be enough though to handle complex scenarios. For some time I have been trying to increase the degree to which we can describe our build process as: always create a new server. The idea is that at any time, you can pick the current 'head' of different components of your system like:
- The operating system (with given updates applied).
- The data storage layer: separation of which we have seen is a key pre-requisite to this approach.
- The application.
If you have multiple sub-systems they can be decomposed individually in the same way and start to share some common work flows. The tasks are then decomposed into a number of streams.
- Creating your 'container' reference which you will deploy onto
- Scripting creation of a replica and change log application of your data layer
- Creating release tags of your application
There are a number of other technology problems to solve though. The main one being naming. It maybe OK for your use case to use Route53 or other DNS level solution. In this case though you will almost certainly want to use a role based named load balancer associated with the build. Standardisation of naming becomes an architectural concern as the system architect starts to see individual service applications as vertical interchangeable units. These units can be combined, a process often referred to as 'orchestration' into a release. The crucial thing is that the load balancer layer allows separation of the detail of build scale and underlying concerns.
Another common question is where do shared services like logging live. For me these should become part of the container for applications. The application developer then only need parametrize the location of their log files in order to achieve logging integration. Technologies like Puppet and Chef support these sorts of parametrized configuration options well using the concept of roles.
Always building new containers will help you focus on getting that flow right and fast. Mutations to snapshots should be committed and tracked so a system can be orchestrated from a collection of 'tags'. The application developer should not be concerned with the details of which environment they are running in, all configuration should be passed as 'flags'. Judicious use of DNS including build and roles will help make it easy to maintain infrastructure build by maximising readability. Environment concerns like logging, naming etc should be hidden from the application so that applications can be launched in different contexts to support test build deployments. By focusing on just one thing, building a new 'service' you will spend the maximum amount of time making sure that it is fast, repeatable and reliable. This has the added advantage that when you need to 'rebuild the world' you know you are ready to go.