DEV Community

mikkergimenez
mikkergimenez

Posted on

IaC should be flat (and small)

There's another question I want to explore, which is essentially - is IaC an API? Or is it the implementation that uses that API? If I'm running a platform team, should I be telling folks how to build their IaC repos or should their IaC repos be in their own opinionated style? (Lots to unpack there, but as in all things the answer is "both")

In either case, the one where I'm advising a team on how to build their own IaC, or perhaps I'm building out an IaC repo for another team to use, I think IaC should be as simple, flat, and as small as possible.

By Simple and flat, I mean using as few abstractions or indirections as possible. If you're say creating the ability to generate a bunch of S3 buckets, then the top level of that should just be a list of S3 buckets. If an application requires 3 S3 buckets. It might be ok to have IaC that creates a list of those applications. What is probably not ok is to have a module that creates three of those S3 buckets added to your list of S3 buckets. Those three S3 buckets should be added on their own.

The most controversial thing I might be saying is something like. If you need 3 different environments, you shouldn't use terraform workspaces to generate 3 different environments, or maybe not even a module used to generate each of those 3 different environments. Each of those three different environments should have each of their resources listed out on their own.

By small, I mean that each IaC workspace should do just one thing. Sometimes that one thing is fairly large, like say managing a DNS zone, or networking can get pretty hairy. But definetly infrastructure that doesn't change together or dependon eachother should not be in the same workspace together.

Why?

IaC needs to be easy to read. IaC should not be like a managed codebase where people take time to become accustomed to it before they become experts in adding to it. The point of declarative code is that you are using it to declare what is being created. The more indirection you have, the more the 'how' gets mixed into the 'what'.

Takes too long to run plan and apply jobs Since terraform has to check every resource, the more resources, the longer it takes to run the job. Speed is of the essence when creating new resources. I think IaC should strive for the ideal that creating a new resources via IaC is as easy and fast as creating it with clickops.

Too many conflicts The thing about IaC is long-lived resources rarely move together elegantly. You want your dev environment to be different from your stage environment, to be different from your prod environment. Maybe permanently, like the size of the instances, maybe temporarily like version updates. You might run a test in your dev environment you don't promote to your prod environment.

Exceptions

There are probably a hundred exceptions here. If you run a big mature Platform team and are getting use out of your big complicated repos, more power to you. I've never managed terraform at a fortune five hundred.

Well-defined long-lived replicated environments This has often been mentioned as a benefit of IaC, and is often in the documentation for how one might use say - Cloudformation, but i've never been in an environment where this was really useful, I suspect like a lot of documentation examples, this is an enterprise thing. If you have a hundred dev environments you need to spin up, go forth and modularize!

Conclusion

Most IaC needs to be bulletproof solid useable by people who hate IaC. To do that minimize cleverness. Make IaC as small and declarative as possible. An IaC workspace that supports resources for an application should only support resources for that application. Don't be afraid to declare bankruptcy, because you don't have to do a full migration to start over. You can extract pieces one at a time.

Top comments (0)