According to Chad Fowler’s definition, Immutable Infrastructure can be defined as:
“[S]ervers (or whatever) are deployed once and not changed. If they are changed for some reason, they are marked for garbage collection. Software is never upgraded on an existing server. Instead, the server is replaced with a new functionally equivalent server.”
Though the idea is powerful implementing it is actually very difficult, especially with hypervisors. Thus, the DevOps community has advocated Docker from its launch to market because of its capability of building the Immutable Infrastructure, due to its layered image approach and super fast “booting” performance.
However, last week Docker introduced us all to a new feature to allow “Writable /etc/hosts, /etc/hostname and /etc/resolv.conf”:
“You can now edit /etc/hosts, /etc/hostname and /etc/resolve.conf in a running container. This is useful if you need to install bind or other services that might override one of those files. Note, however, that changes to these files are not saved during a docker build and so will not be preserved in the resulting image. The changes will only “stick” in a running container.”
It‘s an interesting move as the Writable feature opens another door. Things are no longer static, at least not 100%. For example you could change the state of a running container. The question now being asked is: Where is Docker heading to next? Are they moving away from ‘Immutable Infrastructure’ and if so, is ‘Immutable Infrastructure’ wrong?
The answer is Yes and No.
Immutability itself is a hugely valuable way to build, deploy and operate applications. But like all patterns, there is some trade-off.
One of the most discussed benefits of Docker is the consistency across different deployments: dev, qa, staging, prod, etc. However, there is always some context-specific configuration, e.g. IP, dns name. As the result, those parameters have to be set at the runtime, instead of being hard-coded in the “read-only” images. There are various ideas on how to solve this service discovery problem [1][2][3]. Yet the issue remains that all of these solutions are more or less intrusive to the code and application, which means quite some effort in testing the theories. Then, the whole thing becomes a decision based on personal preference. Even though we of course all want better ways to manage the infrastructure, the engineering cost with the 100% immutability is a concrete no go for a lot of people.
—
The new Writable feature gives us the option to non-intrusively determine the configuration at the runtime, so that it will not cost you too much effort, while at the same time retaining the immutability. Assuming you are deploying a WordPress application, which involves web-tier containers and DB containers. You certainly don’t want to hard code the DB instance’s IP, nor bring in an etcd cluster, which adds more moving parts to manage and increases the odds of faliure . Instead, an orchestration tool could do the job by leveraging the Writable feature of Docker:
As in the above diagram, the orchestration tool will take care all heavy lifting, from instance provisioning, container deployment, to a properly setup /etc/hosts file in the web containers. More importantly, if your DB instance’s IP changed, the orchestration engine will automatically rewrite /etc/hosts to fix the DB connection. And all you need to do is just to specify the following in /etc/hosts:
Pretty easy, right?
In conclusion
While Docker lays a great foundation of code deployment and it is especially useful in keeping the unit as immutable as possible, the deployment context plays an important part in the service discovery. By leveraging the new Writable feature and the Orchestration tool, one could really benefit from immutability, whilst avoiding having to change too much.
[1] smartstack [2] etcd [3] consul