What is GitOps and Why Should You Care

In this Areopa Academy webinar — episode 121 — Tobias Fenster (General Manager at 4PS Germany, Chief Engineer at Hilti, Microsoft MVP for Business Central and Azure) and Markus Lippert (Team and Technical Lead at COSMO CONSULT, Product Manager for COSMO Alpaca) walk through what GitOps is, why Infrastructure as Code alone is not enough, and how a practical stack of Kubernetes, Crossplane, and Argo CD enables self-healing, auditable infrastructure. The session is moderated by Tine Starič.

ClickOps vs. Infrastructure as Code

Tobias opens by asking the audience a straightforward question: are you still doing ClickOps — clicking through the Azure Portal to create and configure resources — or have you moved to Infrastructure as Code (IaC)?

ClickOps is error-prone and hard to reproduce. Different team members may configure the same resource differently, there is no version history, and the reasoning behind a change is never recorded anywhere in the portal.

Azure Portal showing the Create Virtual Machine wizard — an example of ClickOps
▶ Watch this segment

Infrastructure as Code improves things significantly. Definitions are stored as code — such as the Bicep snippet below — and can be checked into a Git repository alongside application code, enabling versioning, pull requests, and reproducible deployments.

Bicep IaC code defining a Windows 11 virtual machine in Germany West Central
▶ Watch this segment

But IaC still has blind spots. Tobias identifies three key limitations:

  • Drift: Someone opens the portal and changes a setting. The code says one thing; reality is now different.
  • Push-only updates: Changes only apply when a human or pipeline explicitly pushes them. If that step is skipped, the definition and the real environment diverge silently.
  • Limited traceability: It is still possible to run scripts locally or trigger pipelines ad hoc, making it hard to know exactly which version of the definition produced what you see in production.
Slide listing the limitations of Infrastructure as Code: drift, push-only updates, and limited traceability
▶ Watch this segment

What is GitOps?

GitOps addresses all three of those gaps. Tobias describes the four base concepts:

  • Declarative: You describe the desired state — what you want — not the steps to get there. IaC can be declarative or imperative (e.g. PowerShell scripts); GitOps is always declarative.
  • Git as the single source of truth: No local execution with local dependencies. Everything goes through Git, enabling security and compliance checks at the pull request level.
  • Pull-based: Instead of telling the cloud what to do (push), a GitOps engine continuously watches Git and pulls changes. The system ensures reality matches the desired state automatically.
  • Drift detection and reconciliation: If someone makes a manual change that deviates from the Git definition, the GitOps tool detects it and automatically reverts the drift — or raises an alert if the revert would require a destructive change.
Slide summarising GitOps base concepts: declarative, Git as single source of truth, pull-based, and drift reconciliation
▶ Watch this segment
📖 Docs: OpenGitOps — the CNCF sandbox project that formalises the four GitOps principles (Declarative, Versioned and Immutable, Pulled Automatically, Continuously Reconciled) as a vendor-neutral specification.

The Tech Stack: Kubernetes, Crossplane, and Argo CD

Tobias introduces the three tools used in the demo:

  • Kubernetes: The de-facto standard container orchestration engine, originally from Google and now part of the CNCF. Used by Netflix, Shopify, PayPal, and many Microsoft services — and increasingly by smaller organisations running cloud-native workloads.
  • Crossplane: A Kubernetes-native, GitOps-friendly IaC tool for provisioning cloud resources such as Azure storage accounts or AKS clusters. Created by Upbound, now part of the CNCF.
  • Argo CD: The GitOps engine. It watches a Git repository, detects changes, and reconciles the Kubernetes cluster (and, via Crossplane, Azure resources) with whatever is defined in Git. Created by Applatix, now part of the CNCF.
Tech stack overview slide showing Kubernetes, Crossplane, and Argo CD with their logos
▶ Watch this segment

The overall flow is: commit a change to the Git repository → Argo CD pulls it → Argo CD uses Crossplane to apply it to the AKS cluster and any dependent Azure resources → reality matches the definition.

📖 Docs: Argo CD documentation — covers installation, core concepts, declarative setup, and the GitOps application model for Kubernetes.
📖 Docs: Crossplane documentation — explains managed resources, providers, and composition for provisioning cloud infrastructure through the Kubernetes API.

Deep Dive and Live Demo

Markus takes over to run a live demo using the repository cosmoconsult/ppi-directions-emea-2025-gitops — a simple repo containing YAML definitions for an Azure storage account and blob containers managed by Crossplane and Argo CD.

GitHub repository ppi-directions-emea-2025-gitops showing StorageAccount.yml and BlobContainer.yml files
▶ Watch this segment

The demo covers four scenarios:

1. Creating a new resource

Markus creates a feature branch in VS Code, copies an existing blob container YAML, renames it, adjusts the metadata, commits, and opens a pull request. After merging to main, Argo CD detects the new resource. A manual refresh in the Argo CD UI shows the new blob container in the application tree, and clicking Sync triggers Crossplane to create the container in the Azure storage account.

Argo CD application tree showing the storage account and blob containers synced from Git
▶ Watch this segment

2. Modifying and reverting a resource

Markus edits the metadata value directly on the main branch, pushes the change, and refreshes Argo CD. The UI shows the application is out of sync and displays a diff of the old and new values. After syncing, Crossplane applies the update to the real Azure resource. To revert, Markus runs git revert <commit-id>, commits the revert, pushes it, and syncs again — the metadata value in Azure is restored within seconds.

3. Drift detection

Markus manually edits the container metadata directly in the Azure Portal — simulating an accidental or unauthorised change made outside the GitOps workflow. He then triggers a manual reconciliation request to Crossplane, which detects the discrepancy between the Git-defined state and reality and reverts the manual change automatically.

Azure Portal storage browser showing a manual metadata change made outside the GitOps workflow
▶ Watch this segment

4. Deleting a resource

To delete the second blob container, Markus removes the YAML file from the repo and commits. Argo CD marks the resource for pruning. Deletion requires explicitly enabling the prune option in the sync dialog — a deliberate safety step. After syncing, the second container is removed from Azure; only the original container remains.

The Git commit history captures the full lifecycle: container created, metadata changed, metadata reverted, container deleted — a complete, timestamped audit trail.

Real-World Example: Six AKS Clusters at COSMO CONSULT and 4PS

Markus describes how COSMO CONSULT uses GitOps in production for COSMO Alpaca, their toolset for running Business Central containers. The setup manages six AKS clusters — four at COSMO CONSULT and two at 4PS — all defined and operated through Git.

Everything stored in Git falls into three categories:

  1. Infrastructure: The AKS clusters themselves — Kubernetes version, node pools, node sizes, location — defined in YAML and consistent across clusters.
  2. Apps: Applications running on the clusters, such as the Alpaca API and observability tooling, along with their versions and per-cluster configuration overrides (e.g. replica counts, DNS names, container image tags).
  3. Configs and secrets: Cluster-wide configuration files, including Business Central development licenses stored encrypted in Git and decrypted by Argo CD during synchronisation.
Azure DevOps pull request automatically created by the build service to bump the observability app version
▶ Watch this segment

When a new release of an API is ready, an automated build service creates pull requests in each GitOps repository proposing the version bump. The only manual step is approving the PR — Argo CD handles the rollout from there. Progressing changes from the test cluster to customer clusters to the 4PS cluster is a matter of merging pull requests in sequence.

Best Practices and Lessons Learned

Markus closes with practical advice on when and how to adopt GitOps:

Best practices slide: when GitOps works well and what to consider before starting
▶ Watch this segment

When GitOps works well:

  • Cloud-native scenarios running on Kubernetes — including applications, networking, and storage.
  • Managing Azure or other cloud infrastructure alongside the clusters — Crossplane and equivalent tools cover most Azure resources.
  • Multiple similar environments (dev, staging, production) where changes can be progressed by merging branches or pull requests.

What to consider before starting:

  • Setting up a well-structured GitOps workflow — tooling, repository layout, access controls, declarative definitions — takes time. Plan for it.
  • For initial exploration of new services or settings, ClickOps is actually the right starting point. Experiment first, then codify the result once the configuration is stable.
  • Verify that the resources and providers you need are available declaratively before committing to the approach.

Tobias adds that while the stack may look complex at first, it becomes a simplification once the team is comfortable with it. At COSMO CONSULT and 4PS, the move from Terraform (and its shared-state challenges) to GitOps on Kubernetes removed entire classes of problems and made rollbacks trivial.

The recommendation for getting started: pick a small pilot project, start with minimal structures and simple processes, and grow from there.


This post was drafted with AI assistance based on the webinar transcript and video content.