Cloud’s biggest breakthrough wasn’t actually being a cloud. Although it might seem that putting computing in a metaphorical cloud that you could rent through the interface made a whole difference; it made it resilient, and made managing all the aspects of infrastructure and resilience easy, making its guarantee of availability something that new generations of engineers and some of us ancient folk take for granted. Cloud did a good job of convincing its consumers that actual hardware machines do not exist.
The biggest thing, in my opinion, is that cloud technology expansion changed web software architecture by shifting the attention of architects and engineers towards more important stuff, like better architecture, faster delivery, etc.
Native to the cloud
The rise of cloud computing has made it easier to do lots of things that were originally super hard for us. More importantly, it made a promise that our lives as software engineers and architects, and especially as system administrators are going to be easier in so many ways. We suddenly had the new world to venture to.
It is also a whole new world to adapt to.
The first reflex, of course, was to just move everything from “raw iron” to the cloud… a big wave of migration projects happened - the new turf got explored along the way, not beforehand. New projects were also mostly created in the same way as before - as we would do it on servers we owned and ran ourselves for 24h a day… It was the only thing we knew how to do.
At the same time, we realized that, since we can now get resources on-demand and actually plan how we deploy and connect services, we can start exploring some architectural concepts that were hard to implement to full potential before the cloud. We started exploring microservices in-depth, working on event-driven architectures, explored scaling principles, etc.
Since all the cloud tools provided some carefree resilience, and we already worked on figuring out how to do DevOps in every scenario, we quickly promoted “move fast and break things” into the main mantra, and … we moved fast. Things getting broken along the way did not really bother us because that was what the likes of Facebook, Amazon, and Google were saying was a way forward.
Somewhere down that path, we started understanding technology a lot better conceptually, so it became clear that there is a lot more to it than just repacking what we have to this new environment.
Enter Cloud-Native, the collection of concepts that brought us lots of flexibility and a better way forward for our architecture. The actual mantra about breaking stuff was never fully revised, altho I believe initial promoters moved on from it.
Cloud-Native as the overarching concept was created in order to make delivering software more adjusted to a new state of the infrastructure and tooling world where it promises to give us better release pace and quality and easily manageable systems and tools through the deploying our software as a containerized components, highly reliable infrastructure, and vendor-agnostic tooling.
Altho this is, and always will be, only partially true, through few iterations of open source and closed projects we managed to create an infrastructure abstraction system, often also referred to as a new operating system, that is bringing a certain level of vendor agnosticism but cosmically high level of infrastructure virtualization and management - Kubernetes.
Kubernetes as the foundation
At the current moment, Kubernetes epitomizes everything that Cloud Native is, it provides the core tooling to realize fully cloud-native architectures. The struggle is - it is not simple… it is everything but simple. How could anything that gives you such a broad toolset ever be simple?
Moreover, the case of Kubernetes actually goes to the whole cloud-native space. What actually is quite a simple and straight forward concept that teaches us how to think in the space of flexible and available compute has easily created the most complex integral software engineering concept out there. What grew out of cloud-native teachings is the only set of approaches that can guide creation of the set of tools for every little non-functional piece you might need for your application.
Building blocks available (non-exclusive list):
- Kubernetes and all of its ecosystem
- All the cloud infrastructure
- Many observability and monitoring tools and concepts
- Many databases
- Many different CICD approaches and tools
- And counting
Cloud-native problem space
So, what is this all about…
Building software in cloud-native space brings forward a whole new set of challenges We are now taking a lot more emergent design approach and stepping into a new set of requirements in regards to fast delivery, scalability, resilience, developer experience etc.
I wanted to share some thoughts, approaches, and analyses about achieving high quality throughout your software development lifecycle from the side of the non-functional requirements of the system. It means that, this time, we will not be looking at the system’s functionalities but at its scalability, resilience, security, speed, and capacity to deliver new features to production, etc.
My idea is to do this through the series of articles that will live under a special category in this blog called Blueprints to which this article will serve as an intro.
So, this article covers the intro to developing software that is native to the cloud, and the next article will start unwrapping DevOps capability as such using the problem space of two scales of DevOps
While the series will cover a lot more, it will be focused on using Cloud-Native concepts and will mostly be Kubernetes-centric in order to reduce the number of variables and make it at least a bit more realistic to connect all the dots together at the end.
Just kidding, there is no end. Software development projects are never done. While there are consumers, of course. #neverdone
Our highest priority is to satisfy the customer through early and continuous delivery of valuable software. (from Manifesto for agile software development)
Developing any new system is a lot about tailoring things to fit; the same as human interaction, it is about the way things interface, about the way it all fits together end to end. You want to make it perfectly serve the purpose. Software architecture has to be clean; the general solution has to fit the purpose well; it has to be scalable, resilient, secure, and easy to change. You want to deliver it whenever needed or whenever a change is made… You want to make it work. Probably a few years down the line you want 20-30-50 engineers to actively contribute to your product. At this point, you probably want the magic coffee machine, as well as the flying carpet.
The solution, usually well known in the global cognitive machine of software development circles is the following:
As soon as any piece of software is delivered everyone wants it in production… Of course, it is Agile so we do it, no matter if it is 100% ready - we can always rollback or fix forward, as soon as that happens maintenance and operations processes start and that is also your life now. As the first thing is done, further development continues, and usually a few other features in parallel, all of them being designed as new briefs are arriving. The plan is to continuously integrate new changes into the live system, but with the operation of the existing system in mind.
It is chaos, nothing is ever 100% done, planning is easy - easy to put in, easy to cancel, easy to change (which we always do), you always need an architect, and QA and security won’t get off your back about the next release. It is chaos, but it is our chaos and we love it.
But, how do you plan for chaos? How do you set chaos up for success?
Inception of container orchestration - enter Kubernetes
As the cloud picked up the pace and we understood that now we got more time to focus on other things, like those great architectural concepts that would never work for us because of the practicalities of big on-prem machines. You can now rent a server in quite a flexible capacity range, so we can just decide what sizes we need for our smaller components, we got Docker to containerize it so it would be quite easy to just go.
Realizing that deploying containerized applications was now a central thing for cloud usage, different ways of managing container deployments started appearing, we tried most of them, and then again any would work - but none covered even a part of the solution that was needed. With every step of growth, a new problem was discovered:
- How do we manage multiple deployments?
- How can we manage resources in a more flexible way?
- How can we scale based on internal system metrics?
- How do we mount a drive?
- How do we secure a system and properly manage communication between different services and then have them communicate to the outside world through a unified interface?
- Secret management?
- Environmental variables?
- How can we manage it through centralized manifests?
- How to seamlessly deploy, rollout, and rollback?
This is a small fraction of the actual list, but illustrative enough, I hope. This called out for a robust open-ended solution with many core capabilities and a completely open way of extending the solution range, which ended up in Google brewing Kubernetes and the global community taking it over and polishing it. Along the way, there were more than a few vendor-specific and open source solutions to the same (or subset of) problems, but Kubernetes is now established as the solution in the space. As already mentioned, going forward, in this particular article series I want to use Kubernetes as the underlying infrastructure for any of the technical solutions proposed.
Kubernetes is bringing a good solid structure that is quite beneficial for any microservices project. More importantly, as you look at many challenges that your software development life cycle is bringing, Kubernetes provides capabilities and means to develop capabilities that your team needs in order to fully own their work and make the project you are working on go fast.
As you go into a new project, no matter if it is a fresh microservice architecture, monolith to microservices migration, or an upgrade to the existing system you will want to onboard the team quickly, help them set up, and start writing code as soon as possible, deploy quickly in stages, test in a flexible way, deliver to production, easily plan capacity, make it secure, etc. In a project of any magnitude, Kubernetes can be a central part to achieving the above and more, while helping provide a great experience for people who are building the software and operating it.
If you got one or many different containerized components that you need to deploy and scale, manage different versions of, and provide various testing and performance environments. If your risk factors are quick growth of a team and number of features, security, and capacity (or any of these). If you are looking for a good system to manage the growth of the influx of code and new people to the project with ease, the same ease you are managing the capacity planning, Kubernetes might be the solution for your problems. Actually, I believe that Kubernetes is the best tool to base your medium to high complexity system on.
The solution, however, might not be that easy to define and finalize, and this is where careful planning and analysis with experience can help a lot. I want to help you plan well and build the base in order to be able to move fast. I am not a big fan of breaking things, but you can choose to have that as well, it is purely depending on your preference and I believe we will get to talk about that as well further down the road.
What is next
For now, let’s identify two main groups of concerns as we are planning the development of our new system:
- Scale and complexity of the system (the product that we are building)
- The capability to own the development, delivery, and system itself end to end
The first group depends a lot on the technology you chose, but it does not change the way you approach a problem from cloud-native perspective, for this group of concerns we need to have a good set of practices to understand how to protect your new application’s architecture to cloud-native centric system. There are not a lot of moving pieces when doing this, there might be lots of small and big complexities, but understanding the concepts is pretty straight forward.
The problems from the second group, however, would take a significant part of any discussion and will be a dominant content in the core matter of this series.
In order to not get too deep into the topic of the next article, I will stop here, quickly summarize and soon follow up with a post about two scales of DevOps.
- Cloud gave us ability to think about important stuff
- The real advancements occurred as the cloud concepts matured with emergence of cloud native
- This is introduction to the the Blueprints series
- Blueprint series addresses non-functional requirements in the microservice architecture and cloud native space in hope to help you by making your software delivery smoother and your quality of service better.
- Kubernetes is taken as the foundational infrastructure component since it, along with it’s ecosystem, epitomizes cloud-native.
- I believe that Kubernetes is the best tool to base your medium to high complexity system on.
- Don’t break stuff whatever others say.