Product
|
Cloud costs
|
released
September 1, 2023
|
3
min read
|

Charting Software Delivery Flight Paths: Intro to GitOps Source Patterns

Updated

When you book a flight, you trust the airline to get you where you need to be in one piece. Ticket details like destination city, departure time, seat, and fare class comprise a declared source of truth, and the airline mobilizes its vast logistical apparatus to assign a plane, pilot, and flight plan to carry you to your destination. 

Software development benefits from a similar abstraction approach. Layers of delivery complexity have pushed teams to incorporate GitOps. The desired states of applications and infrastructure are maintained in version control (Git), and automation tools enforce changes to the target environments (Ops). Just like how I rely on the airline to engineer my transportation to Cabo, software developers can now focus on business logic while letting CD tools handle the deployment plumbing.

Implementing proper source control patterns has therefore become critical to a successful software delivery practice. Before GitOps, engineering efforts largely went toward creating tedious deployment runbooks. With imperative deployment steps automated, a core design problem now involves properly structuring the repositories hosting our declarative configurations.

Well-Architected Route Maps

Consider our air travel analogy. An airline typically organizes its routes in one of two ways. The most common choice is a hub and spoke model. The airline centralizes operations in a few cities (the hubs), and those cities serve the outlying destinations (the spokes).

Hub and Spoke (image source)

In this model, passengers generally need to go through a hub city to reach their destination, reducing the number of direct flights. However, airlines are able to better respond to emergencies and stresses on the network by surging planes and staff only within a few hubs. The hub model is less efficient on a per route basis but is overall easier to administer.

The second model is point-to-point. A point to point model connects cities directly without using central hubs. Southwest and other low-cost carriers are famous for this approach, implementing a mesh of routes connecting individual cities.

Point-to-point model (image source)

Point-to-point permits more nonstop flights (no need to connect through a hub), while also allowing airlines to easily add or remove new routes. However, managing all those route dependencies has high operational overhead. And a single route failure (say, a thunderstorm in the midwest) can have a cascading effect on the rest of the network, as it is more difficult to surge or reallocate resources than in the hub and spoke model. Routes in the point to point model are therefore more efficient but can be administratively burdensome

It turns out that these approaches can inspire how we organize our software projects.

The Monorepo Approach: Integrated and Atomic

A monorepo approach means all source files for all services live in a single repository. This is comparable to the hub model described earlier. For example, the structure of an e-commerce app for “Widgets Co.” might look like the following:

The whole team collaborates on this single repository, with some roles potentially focusing on different folders. For example, UX designers might spend the bulk of their time in frontend/, and the technical writers might camp out in docs/

Teams that choose to go the monorepo route cite some the following benefits:

  • Atomic changes: The entire codebase shares a common commit history. Each new commit, whether a feature update or rollback, is applied to the entire application.
  • Ease of refactoring: Changes in dependencies or application logic that affect multiple components can propagate all from one place. 
  • Centralized tools: CI/CD and infrastructure configurations are centralized alongside application code. It’s straightforward to ensure the entire codebase must pass build and test pipelines before deployment.
  • Reduced administrative overhead: Security policies, approval rules, and visibility tools all need to point to only one repository.

Monorepos can serve as a logical starting point for brand new initiatives. Developers can easily collaborate as they have a single point of access to the entire application. However, while monorepos handle scaling fairly well, they can encounter challenges as codebase complexity grows.

  • Repository size: Git operations can start to show strain as the size and history of the monorepo grows, though this can be somewhat remediated through interventions like Git LFS and shallow cloning.
  • Longer build times: Each build pipeline runs against the entire application, even if only a small part changed.
  • Tooling limitations: Existing security and collaboration tools need to handle a massive, complex codebase. Challenges in enforcing granular access control can lead to over-permissioning.

Organizations have successfully maintained monorepos of massive scale. Still, some teams decide that as the business grows the most proactive way to manage complexity is to break up the codebase.

The Polyrepo Approach: Focused and Decoupled

A polyrepo approach is more akin to the “point to point” airline model previously discussed. Instead of consolidating in a single repo, each application component (microservices, manifests, libraries) is version controlled separately. The example “Widgets Co” app might therefore be structured into multiple repos like this:

Each piece of the application lives in its own Git repository. Each repo then has its own version history, pipeline configurations, and access control. Developers gain granularity and tailored focus. Other benefits include:

  • Isolation: Each service has its own commit history. Changes to a single feature do not require a rebuild or rollback of the entire app. A smaller codebase means newly onboarded developers have a more manageable learning curve.
  • Decoupled CI/CD:  If each repo has its own pipelines, new builds and deploys are faster and more targeted.
  • Granular access control: Permissions can be managed at the repo level and even outsourced to a managed RBAC tool, rather than having to manage ownership of file paths in a single large repository.

The polyrepo approach encourages teams to specialize and experiment, and alleviate fears of breaking the larger whole. Yet the model does pose some challenges. 

  • Dependency management: Teams must manage tracking and securing inter-repo dependencies, and ensure updates and versions are correct across all projects.
  • Duplication: Strict modularity is difficult, and duplicated tooling or CI/CD configurations across repos can lead to configuration drift.
  • Coordination overhead: Teams must invest in communicating and coordinating changes that span multiple repositories.

Companies large and small have found success leveraging the polyrepo approach, particularly for running federated service models. Investing collaboration and dependency management is key to ensure consistency across the many codebases.

Which model works best? Leveraging Harness to manage GitOps complexity

At this point you're probably wondering which model is the “best practice”. In short, it depends. Some organizations advocate for and use monorepos with a host of custom tools and integrations, while others prefer the granularity and flexibility of polyrepos. 

As a general starting point, a team devoting the bulk of its engineering effort toward a singular core application could benefit from keeping work centralized in a monorepo while they scale. Meanwhile, teams developing a federated service model, or heavily leveraging microservices, could find a polyrepo setup to be a more natural fit.

Whichever model you choose, a robust toolset is needed to manage security and access control, application builds, and deployment pipelines. Harness provides declarative GitOps that connects to your existing source code management system, and leverages ArgoCD to continuously reconcile your repo’s declarative state with your live environment. The UI then offers visibility to a monorepo model, while also offering centralized organization if you choose to go the polyrepo route.

Looking ahead

This intro just scratches the surface of GitOps source patterns. Like modern airlines preparing intercontinental route maps, today’s software landscape requires intelligent logistical planning and strategic design decisions in order to quickly and reliably deliver features to users. The next posts in this series will dive deep into advanced GitOps patterns and practices.

In the meantime, we encourage you to get started with GitOps with a free Harness account, and then try out some of the guided tutorials to help you take to the skies on your continuous delivery journey.

Sign up now

Sign up for our free plan, start building and deploying with Harness, take your software delivery to the next level.

Get a demo

Sign up for a free 14 day trial and take your software development to the next level

Documentation

Learn intelligent software delivery at your own pace. Step-by-step tutorials, videos, and reference docs to help you deliver customer happiness.

Case studies

Learn intelligent software delivery at your own pace. Step-by-step tutorials, videos, and reference docs to help you deliver customer happiness.

We want to hear from you

Enjoyed reading this blog post or have questions or feedback?
Share your thoughts by creating a new topic in the Harness community forum.

Sign up for our monthly newsletter

Subscribe to our newsletter to receive the latest Harness content in your inbox every month.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Continuous Delivery & GitOps