After the rise of Cloud Computing, the pattern of creating and maintaining infrastructures has been disruptive. With all the handy tools and Services like Containerization, Infrastructure as Code, Infrastructure as Service (also Infrastructure as APIs), Configuration Management in place, infrastructure can be seamlessly created, managed and destroyed.
Immutable infrastructure is a paradigm for infrastructure management in which servers are seldom modified after they’re deployed. If an update, fix, or modification is to be made, new servers are built from a common image or using a standard configuration management code with the appropriate changes to replace the older ones. The newly created images are then validated, deployed and old ones are finally decommissioned.
With the use of containerization, Immutable deployments can be pretty handy and something that is fairly attainable as docker containers are runtimes of images and those images are freshly created when an update is performed. But, managing legacy systems which are not containerized can be tricky specially those that make use of Virtual Machines like AWS EC2, DigitalOcean Droplets or a GCP or Azure VMs. We will look into a way by which the paradigm of immutable infrastructure can be used. Moving Further, We will be using terms and technologies familiar with AWS on this blog with the goal of performing immutable deployment of a simple Ruby on Rails Application in EC2 Instance.
Immutable V/S Mutable Deployments
Since, for every updates (be it whether a codebase change or an infrastructure change), everything is treated the same in immutable deployments i.e. the fresh infrastructure is created each time. This is not the case of mutable deployments.
The aesthetics of immutability adds the resiliency to the existing teams by strengthening the Disaster Recovery portfolio of the application. It also ensures that similarity of technologies, configuration and infrastructure being used across different environments. The testing/deployment becomes more reliable as it is ensured that the shipping package remains same as the one being tested. The deployment strategy becomes scalable as the deployment time and effort will be less dependent on the number of machines to which the code are to be deployed.
Although Immutable deployment comes up with several advantages, it is relatively complex and a huge undertaking when compared with mutable infrastructure. This blog provides you with idea on how immutable deployment can be achieved for stateless component that is the application server.
Setting up the Application
To get started with Immutable deployments, We need to start out by separating the stateful and stateless components of the application. Stateful components change their state over time where as stateless components do not change over time. In a familiar application setup, Stateful components are databases, cache, session stores etc where as application server can be thought of a stateless component. There are various strategies to separate out these components. One of the familiar ones, is to use a separate machine like AWS RDS for Databases or a separate ElastiCache Redis node for Redis or ElastiCache MemCache for storing sessions and update the application configuration accordingly. Alternately, You can also create a separate VM and setup the services there which I personally do not recommend doing. This simple segregation can be explained with this diagram show below:
Now, as the segregation among stateful and stateless components is clear. We can now focus on the application server which is the stateless component that we are focussing on to make the immutable deployment of codebase.
The application Server
The EC2 instance hosting application server should ideally contain the application, its dependency libraries, the configuration required for the application to connect to underlying services. These basic requirements of the application need to be bundled together into an AWS EC2 image or AMI. This AMI is baked with the use of AWS AMI Builder or a combination of tools like AWS CodeBuild, Packer and Ansible.
The notification of AMI Baking status can be notified to slack using Amazon SNS’s web-hook configuration. Upon the successful baking of AMI, the AMI can be used to deploy to various environments based upon the configuration of those environments.
Managing the configuration
As the Application AMI is used across environments, its not a good practice to bake all the configuration of different environments into the AMI. We can create a config stores using AWS Secrets Manager or Parameter store or Hashicorp vault and pull the configuration from there based upon the application environment during the application deployment.
Handling the Deployment
Deployment can be handled using AWS Cloudformation by wrapping the complexities with a simple script that is written to handle a variety of operations. Several other deployment services like code deploy can also be used. Blue Green and Canary deployments are the ones that are mostly used. Cloudformation support blue-green deployment by design.
The complexity of attaining immutable deployments also varies with the complexity of the application itself. Segregating the application itself into stateful and stateless components can be tricky as not all stateful components are separate services. Cron is a good example which can also be handled using background schedulers or using services like systems manager. Management Hassles on AMI may incur, AMI is the artefact for each deployment that get deployed when a new change is to be introduced, this can grow over time and may get out of hand some time around soon. As this requires the use of multitude of Services and infrastructure, the cost for managing those infrastructure can rise by a significant number which can be concern to the business stakeholders.
Finally, After knowing what immutable deployments is, its advantages and how it varies from mutable deployments. You can do a further research and build your knowledge on top of this and achieve the new goal of immutability. As We can now manage to attain the immutable infrastructure deployment for the application that cannot be hosted using docker or other containerized services. Although this blog only hints about how an immutable deployment can be setup but does not detail about the process itself (Something for the next blog). As, Immutability is a result of huge undertaking with hidden complexities that gets discovered in the process, be sure that it is something that you need to better your application’s resiliency, scalability and reliability.