How To Structure Your GitOps Repository for AKS
05.06Thanks to GitOps, you gain control, reproducibility and automation of your AKS cluster … At least in theory. Unfortunately, practice sometimes proves different. Without a well-thought-out structure for your Git repository (or repositories), your stack can quickly descend into a mess where any kind of overview is hard to find.
So, how do you prevent that? How do you divide your repositories in such a way that you benefit from the advantages of GitOps, without losing yourself in complexity or security risks? In this blog, we’ll explain how to arrive at the right structure.
Why is a good structure crucial?
A GitOps repository without a clear structure quickly leads to chaos. The core of the problem lies in responsibilities and security: who is allowed to change what? Without clear boundaries, you risk developers accidentally modifying platform settings, or the platform team becoming a bottleneck for every small update. This lack of separation also increases the risk of unauthorised changes in production.
In addition, a poor structure directly impacts efficiency. A cluttered repo significantly slows down development velocity, because it takes longer for team members to figure things out. As the number of applications, teams and environments grows, this will only get worse: complexity increases, merge conflicts become regular occurrences, and overall visibility is lost.
The result is that, instead of a streamlined process, you end up with frustration. A good repository structure is therefore not a luxury, but the foundation that forces you to think about ownership, workflows and security.
Platform vs. application
A logical starting point for your structure is to distinguish between platform components and application configurations.
- Think of platform components as the basics: ingress controllers, cert-manager, monitoring, secret management tools … All things that support the entire cluster and are often managed by a central platform team.
- Application configurations are the specific deployments, services, et cetera of your business applications, usually managed by development or platform teams.
This split is important because the responsibilities, frequency of changes and permissions differ greatly between the two. It prevents teams from interfering with each other and forms the basis for your next decision: will you choose a mono-repo or multi-repo approach?
Mono-repo vs. multi-repo
Once you’ve made the distinction between platform and application(s), you’ll need to decide how to arrange them in Git. There are two options: mono-repo and multi-repo.
In a mono-repo, everything (platform, apps, maybe even environments) sits in one large Git repository. Easier to get started with, but it can quickly become difficult to manage permissions and separate responsibilities as you grow.
In a multi-repo, you split the configuration across multiple repositories. For example, a separate repo for the platform and separate repos per application or team. This provides clarity in ownership and makes permission management easier, but it does introduce more overhead. You’ll need to configure multiple repos in AKS, and the global status of your cluster will be spread out, which can cause the platform team to lose visibility.
You might wonder what we at CloudFuel usually choose; that depends on the client, of course. We always engage in dialogue and weigh the pros and cons together to find a pragmatic approach that works for them.
Practical tips for structuring your repository
Whether you choose mono or multi, the internal structure of your repo(s) is essential. Below are a few practical tips to get you started.
Establish a consistent folder structure
Every project is different, but popular options include organising folders by cluster (e.g. clusters/dev, clusters/prod) or by application (e.g. apps/app-a, apps/app-b). Within that main structure, you can refine further depending on your tooling.
The most important thing is to choose a clear, predictable structure and apply it consistently. It’s a great help when it comes to navigation, understanding the configuration and setting up automation.
Centralise the code within your repository
A common mistake is to create a separate Git branch for each environment. However, promoting code between environments can quickly become complex, making it difficult to maintain the environments. That is why we generally recommend managing environmental differences via the directory structure within a single main branch.
As always, there are exceptions to the rule. GitHub, for instance, allows permissions at folder level, which works well in a mono-repo, but this is less straightforward in Azure DevOps. There, one branch per environment can sometimes be a good solution, for example when workflows for test and production differ greatly. Although you can vary workflows within a single branch (e.g. lighter checks for dev), this isn’t always the easiest path. So, weigh the pros and cons within your specific context.
Don’t forget your secrets… Or skip them altogether!
One last but crucial point is secret management. As we already emphasised in our blog on secure secret management, you ideally want to minimise the use of long-lived secrets. Entra Workload ID offers an excellent, secret-less alternative, but in practice secrets aren’t always avoidable.
In those cases, use dedicated tools and patterns such as External Secrets Operator (ESO), Sealed Secrets, or Mozilla SOPS. Make sure that only the reference (as with ESO) or the encrypted form (Sealed Secrets, SOPS) ends up in your Git repository, never the plain text secret itself.
What about automation?
To actually get your Git configuration onto your cluster, you’ll need a GitOps agent. At CloudFuel, we like to work with ArgoCD. A powerful feature of ArgoCD is Application Sets. It allows ArgoCD to automatically detect and deploy new applications or environments based on the folder structure in your Git repository.
For example, you can define an Application Set like this: ““Look in the apps/ directory and for every subfolder you find there, deploy the Kustomize configuration from overlays/production to the production cluster.” ArgoCD automatically picks up any new app you add following that structure. This significantly reduces manual work, increases consistency, and scales effortlessly.
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: appset namespace: argocd spec: goTemplate: true goTemplateOptions: - missingkey=error generators: - git: repoURL: <ARGOCD_GITOPSURL_PLACEHOLDER> revision: HEAD directories: - path: apps/*/overlays/dev template: metadata: name: '{{index .path.segments 1}}' spec: source: repoURL: <ARGOCD_GITOPSURL_PLACEHOLDER> targetRevision: HEAD path: '{{.path.path}}' destination: server: 'https://kubernetes.default.svc' namespace: '{{index .path.segments 1}}'
Structure equals clarity!
GitOps is incredibly powerful, but its effectiveness does stand or fall with a clear and consistent repository structure. Without it, you’ll quickly run into complexity, ambiguity and risk. It pays off to think long and hard about how you’re going to separate responsibilities, manage environments, choose your tooling, and implement automation.
The main message here is that consistency is key. Take the time to design a structure that suits your organisation or client and apply it consistently. That’s the foundation for a scalable, secure and efficient GitOps process.
Need help designing or implementing a GitOps structure for your AKS environment? Send us a message; we’re happy to think along with you.