Within software development, nothing is ever stationary. Nothing is ever constant, and the development landscape today looks vastly different from how it looked just a couple of years ago. One of the major changes in software development relates to the usage of cloud technology, and how to successfully leverage that power to develop better and better software. The cloud and its opportunities radically transform software development, large companies and even entire industries. But what makes software specifically developed for the cloud different from traditional ones?
Traditional, monolithic software design often relies on a large core application handling all application logic and communicates with an equally large relational database. Everything is then shown to the user via an interface, such as a traditional HTML web app. For smaller and simpler applications, this is definitely a viable way to go; monolithic apps are simple to build, test, deploy, troubleshoot and scale. However, as the application grows and functionality is added incrementally, the monolith becomes more and more troublesome. Let us know if you’ve ever experienced a situation in which:
- The application has grown to the extent that no individual actually understands how it works
- Changes are difficult, scary, and often bring unexpected problems or outcomes
- Adding functionality or fixing bugs becomes a massive undertaking due to the complexity of the application
- Complete system crashes or instability stemming from a single problematic component
- Introducing new technology is just not possible
- Agile workways break down
If you recognize any of these situations, perhaps you really are screwed. Or perhaps what you need is a cloud native approach.
Cloud native design
When developing applications with the cloud in mind, you’re likely to run into the term cloud native. This novel way of thinking about software development is an attempt at leveraging the full power of private and public cloud technologies, splitting the traditional monolithic app design into its various parts. It is a way for companies to speed up development, optimize deployments and testing, improve scalability, minimize risk and deliver higher value to their end users.
Instead of a large, monolithic core application, a cloud native application is an assembly of multiple smaller, separate and loosely linked services that together create the larger application. Using technologies such as containers, microservices and declarative APIs, cloud native applications are made up of several, independent services with their own, separate functionality. For example, an e-commerce platform might split the application into a catalog microservice, an ordering microservice, a basket microservice, an identity microservice, and so on. Each of these services are developed, deployed, tested and run independently. In addition, they are self-contained and include all data storage needed - removing the need for a large, relational database. Through communication protocols, the collection of services together form the complete application.
Fundamentally designed to handle rapid changes, scaling (both up and down), and to stay failure-resistant, cloud native applications enable companies like Netflix, Uber and Facebook to deploy hundreds to thousands of times each week. Companies like flourish in the virtual environment that their cloud solutions provide - fully understanding that infrastructure should be treated like cattle, not pets. This means they don’t spend time and energy caring for their servers like you would for a dear pet. Instead, they treat their machines like cattle: identical and easily replaced. Whenever a server goes down, it is simply destroyed and a new, identical one, is provisioned. All done through automation.
The twelve factor app
Many cloud native enthusiasts swear by the Twelve Factor App. The list, consisting of twelve key factors, synthesizes knowledge of successful app development into something every software development team should take a look at. These are the factors:
|1||Codebase||Keep a single code base for each microservice, in a separate repository. Track it just as any other application, with version control and deploying to multiple environments.|
|2||Dependencies||Keep explicit declarations of dependencies, and isolate them to each service.|
|3||Config||Configuration should be moved out of the microservice, and handled through an external configuration management tool.|
|4||Backing services||Treating backing services as attached resources. Data stores, caches, and message brokers should be decoupled from the resource itself.|
|5||Build, release, run||Employ strict separation of build, release and run stages.|
|6||Processes||Each microservice should execute processes separately and independently.|
|7||Port binding||Export the self-contained services via port binding.|
|8||Concurrency||Scaling takes place by scaling out identical processes as copies, not by scaling-up a single large instance.|
|9||Disposability||Each service instance is disposable, relying on quick and smooth start-up and shutdowns.|
|10||Dev/Prod parity||Environments across the application lifecycle should be as similar as possible.|
|11||Logs||Treat logs as event streams, processed with an event aggregator and propagate data to specific tools.|
|12||Admin processes||Admin and management tasks should be one-off processes, separate from the application.|
There is much more to be said about cloud native applications, and we will. In this post, we have talked about the methodology and thinking behind cloud native systems, and we’ve taken a look at the twelve factors inherent in cloud native apps. As passionate Microsoft stack users, we love what Azure, Azure DevOps and GitHub bring to the cloud native table. There are many benefits to using Azure for your cloud native development, including seamless CI/CD, efficient pipelines with Azure Pipelines or GitHub Actions, container orchestration through Azure Kubernetes Service (AKS), and more.
In the next post, we will dive a little deeper into real-life cloud native development when we describe the case at one of our customers, Kontain.