Fractal Architectures: A Software Craftsman’s take to Infrastructure as Code
By: Angelo Agatino Nicolosi
Tags: Software Architecture, Infrastructure As Code, DevOps, Software Development, Cloud Computing

First things first, what is Infrastructure as Code? I will tweak slightly what wikipedia says about it: Infrastructure as code (IaC) is the process of managing and provisioning computational resources (data storage, network, processing power, RAM, etc.) through machine-readable definition files.

I will never forget the disappointment when I first learned what was actually behind this term. In some cases there is really nothing that can compare these files to actual code, at least to Code as Software Craftsmen mean it. So why is there a ‘C’ in ‘IaC’?

As I usually do when I do not understand, I asked around, researched on my own, and the only explanation I found was something very similar to Microsoft’s definition of IaC:

Infrastructure as Code (IaC) is the management of infrastructure (networks, virtual machines, load balancers, and connection topology) in a descriptive model, using the same versioning as DevOps team uses for source code

So it is code because it is checked-in in a code repo.

By the same logic this might very well be an example of Slides-as-Code!

Sorry, I am a bit bitter about it. But not without a reason. I am bitter about it because of the actual pain that is daily inflicted on all of us by doing IaC the way we have to do it today. We lack the tooling and the techniques to actually tackle the complexity of infrastructure installations required at the scale of todays’ enterprises. We know that much more is possible, we can feel the immense world of possibilities; we can feel it but we can’t reach it. So frustrating. Something is missing, yes, something is not right… but what?

Our colleagues in the 70s must have felt as we do today. A very similar pain connected to the friction generated by the inadequacy of software development tooling and techniques clashing against the exponentially growing demands for high-quality software across more and more industries around the globe. This pain pushed Software Engineers to seek better ways to build software based on ideas developed in the previous decade.

This is how Object-Oriented Programming (OOP) was born.

Hey, yes you are totally right! Functional programming rocks too, but this is not the point we are trying to make here. OOP was born to raise the bar; to reach a higher level of quality and velocity for software development practices.

In one of the best books ever written on the subject, Object-Oriented Software Construction, Bertrand Meyer states:

Engineering seeks quality; software engineering is the production of quality software

Bertrand defines software quality as a combination of several factors, all nicely analysed in his book. We think this is a great tool, a framework to score quality in today’s IaC solutions. Some of these factors, the ones we think are most relevant for IaC solutions, are:

Extendibility: the ease of adapting software products to changes of specification

the ease of adapting software products to changes of specification Reusability: the ability of software elements to serve for the construction of many different applications

the ability of software elements to serve for the construction of many different applications Compatibility: the ease of combining software elements with others

the ease of combining software elements with others Portability: the ease of transferring software products to various hardware and software environments

the ease of transferring software products to various hardware and software environments Ease of use: the ease with which people of various backgrounds and qualifications can learn to use software products and apply them to solve problems. It also covers the ease of installation, operation and monitoring

You can already see where we are getting at, right?

We do not really have a high-quality solution for true Infrastructure as Code yet.

Not even Terraform files, the de-facto standard for IaC today, are portable across cloud vendors. The tool in it-self is cloud agnostic in the sense that it can be used to instantiate infrastructure across multiple clouds, but you still need to write multiple .tf files for each provider. Moreover, it still requires quite some knowledge of the underlying inner-workings of the cloud provider of choice and this does not really help on the already steep learning curve.

Pulumi has a slightly easier learning curve as you can choose among already known languages, however it is very similar to (and much less used than) Terraform with its state files (you can avoid that by locking-in your infrastructure state in their SaaS solution), different providers, etc.

The rest of the tools that might make sense mentioning here are deliberately cloud vendor specific (ARM Templates for Azure, Cloud Deployment Manager for GCP, CloudFormation for AWS).

That’s the current situation. The complication is that most of the time we use these tools in the wrong way.

We focus on automating infrastructure instantiation exclusively from an operational point of view. We are so good at speaking about DevSecOps, and then we completely disregard the fact that the infrastructure is there for a specific reason: to actually run Applications. IaC solutions should solve the problem of Infrastructure Automation seen from the holistic point of view of the Software Development Lifecycle.

We must evolve IaC tooling and techniques to a level where we can be proud of actually using the term “Code” when referring to it.

Pets vs Cattle in Software Architecture

Let’s summarise what we have written above: IaC solutions should abandon their Ops-centric view of the world.

Don’t get us wrong, they are amazing solutions that we have loved (and sometimes hated) and they have been a great first shot at a huge problem space. It is now time to raise the bar.

However, in order to do so, we must demand the same from the Application layer.

If there is one thing that professionals working mostly with designing and creating software solutions must learn from the Infrastructure world it is the huge paradigm shift that has been performed at the infrastructure level with Cloud Computing, a.k.a. Pets vs Cattle.

Quoting from the great article by Randy Bias:

In the old way of doing things, we treat our servers like pets, for example Bob the mail server. If Bob goes down, it’s all hands on deck. The CEO can’t get his email and it’s the end of the world. In the new way, servers are numbered, like cattle in a herd. For example, www001 to www100. When one server goes down, it’s taken out back, shot, and replaced on the line.

We must design our applications in the same way we design our infrastructure today.

In order to explain what we mean, let’s analyse this sample application architecture for a minute.

Basic microservice architecture:

Single point of entry through an API Gateway;

A component ensuring/enforcing security across our service mesh;

BFFs for specialised operation for a specific subsets of devices;

Domain Services communicating through a broker; and so on

One way we could automate the infrastructure needed to implement the solution architecture depicted in the diagram above is as we do it today. We define the minimal amount of infrastructure resources we need, we write our nice infrastructure description files, apply them, and finally we deploy the application code.

What happens when we need to expand our functionality?

Let’s say we need a new BFF; we will need to perform some changes to the same files, mostly by copy-pasting stuff we used before and re-apply. We will have to do the same thing in case we need a new domain service. Not sure if static or monolithic are the right words for it, but this process is definitely cumbersome and error prone.

What if we look at this under a different light?

We are good Software Craftsmen. Excellent actually!

When we design applications and systems we have it very clear in our minds how it should evolve and what instead should be avoided. It is like city planning. Residential areas here, industrial area there, utility grid, roads, etc. Same thing. We just said it above, single point of entry, you are not planning to have a second gateway and you have very good reasons not to want another one. The security component needs to be highly available of course, but you do not want our identities and roles in multiple distinct entities, you want them centralised, and so on.

That part of the infrastructure is very rarely changed.

What really changes in this application architecture are the BFFs (growing with the number of different devices we want to support) and the domain services (growing together with the business requirements). When your business requires new functionality you make the decision to extend the existing services, add new ones, or aggregate different services in one instead as you might have fragmented the system too much.

These are actually standard operations that can and should be defined in code, instead of forcing people to copy-paste stuff in some definition files. A new domain service comes with a specific identity/service account. It has a very specific access to a brand new database/collection on the existing RDBMS/NoSQL DB. It connects to the broker with a variable set of accesses to specific topics/exchanges/queues, and so on. This is known at design time and it can be nicely automated.

This is the core idea behind what we at YanchWare have defined as Fractal Architectures.

Fractal Architectures

As mentioned above, we need to start designing our infrastructure in tandem with our systems and applications. This will enable us to scope and tailor them perfectly to our current needs, without falling into over-complication or over-simplifications, while enabling us to identify and define with ease the natural ways our infrastructure and application will symbiotically grow in the future.

This will allow our systems to harmonically evolve at the velocity required by our business.

A formal definition

A Fractal is a component constituted of two entities:

A Blueprint : a versioned group of components and integrations defining the infrastructural foundation of a compliant live system;

: a versioned group of components and integrations defining the infrastructural foundation of a compliant live system; An Interface: a versioned set of operations through which the fractal can be further specialised or extended through the addition, removal or modifications of components and integrations. An operation will always produce either a compliant live system or a further specialised fractal.

To ease its understanding we can make a parallel to the Object-Oriented Programming model.

The Blueprint is like a class in OOP, a static structure, not much different from the IaC files we use today. The Interface is like a set of non-static methods definitions on the Blueprint class in OOP. They define how the internal state of the system can be changed, hiding irrelevant implementation details to the callers.

When you instantiate the Fractal, you create a live system composed of the core infrastructure defined in the Blueprint. The live system is like an object in OOP, a runtime structure with a state.

Once the live system is instantiated, you can now modify its state by calling the methods on its interface.

Fractals are components that could be used in the blueprints of other Fractals. From this the name Fractal Architectures: define architectures that evolve in a self-similar manner.

As a further example, let’s get back to the microservice architecture we analysed above.

In this situation the API Gateway, the Security Component, the Broker, and so on are all part of the Blueprint. The interface is instead containing the methods needed to add and remove a BFF and to add and remove a Domain Service.

Conclusions

At YanchWare we believe that to have high quality IaC solutions is of paramount importance in order to succeed in Cloud Native Transformations at Enterprise scale. Unfortunately we are not there yet. In this article we have presented a potential framework to reduce the friction between Application Development and Infrastructure Operation laying what we think is the foundations for building better tools and practices for the benefit of our enterprises. You can start using Fractal Architectures in your automation engines already today; unfortunately it is not straightforward, but it is definitely possible: you need to aggregate the right tools in the right way (hint: Ansible + Terraform for instance is a very good starting point).

If you think you are already doing this, or something similar, we would love to hear from you, compare notes and grow together!

This is the first article of a series of 3 on this specific subject. In the next article, “DevSecOps hard parts: how to reach Enterprise scale” we will go deeper into the organisational and technical challenges of DevSecOps in Enterprises and we will show how Fractal Architectures are actually able to solve them. Finally, in “Applied Fractal Architectures: A story from the real world” we will actually go deep into a real world case study where we have adopted Fractal Architectures during the ongoing Cloud Native transformation at a large enterprise operating in the Nordics with great success.