All posts

Introduction to Kargo: GitOps Promotion Pipelines for Kubernetes

· Noah Burrell · 8 min read
kubernetes kargo gitops argo-cd
Kargo logo

If you read my previous post on Argo CD, you know that GitOps gives us a powerful model for deploying applications to Kubernetes. Git becomes the source of truth, Argo CD continuously reconciles your cluster state, and every change is auditable through commit history. But once you have that foundation in place, a harder question emerges: how do you safely promote changes from one environment to the next?

This is the problem Kargo solves. Built by the same team behind the Argo project at Akuity, Kargo is a Kubernetes-native platform that brings structured promotion pipelines to GitOps workflows. It does not replace Argo CD. Instead, it sits on top of it, orchestrating how changes flow through your environments.

The Promotion Gap in GitOps

Traditional GitOps tooling handles the last mile well. Argo CD ensures that whatever is defined in Git gets deployed to your cluster. But it has no opinion about how changes should move between environments. In practice, teams end up building custom CI scripts, writing fragile shell pipelines, or relying on manual pull requests to bump image tags from staging to production.

These approaches work at small scale, but they create problems as your organization grows. Promotion logic gets scattered across CI pipelines, approval workflows are informal at best, and there is no unified view of what version is running where or what is waiting to be promoted. Kargo addresses all of this by making promotion a first-class concept.

Core Concepts

Kargo introduces a small set of Kubernetes custom resources that model the promotion lifecycle. Understanding these is key to working with the tool effectively.

Projects

A Project is the top-level organizational unit. Each Project maps to a Kubernetes namespace and provides tenancy boundaries, RBAC controls, and policy definitions. If you are managing multiple applications or teams, Projects keep everything cleanly separated.

Warehouses

A Warehouse watches for new artifact versions and packages them into units that can be promoted. You configure a Warehouse with one or more subscriptions to container image registries, Git repositories, or Helm chart repositories. When a new version appears, the Warehouse creates a new piece of Freight.

Here is an example Warehouse that monitors an Nginx container image:

apiVersion: kargo.akuity.io/v1alpha1
kind: Warehouse
metadata:
  name: my-warehouse
  namespace: my-project
spec:
  subscriptions:
    - image:
        repoURL: public.ecr.aws/nginx/nginx
        imageSelectionStrategy: SemVer
        constraint: ^1.29.0

Warehouses can subscribe to multiple sources simultaneously. For instance, you might watch a container image and a Git repository at the same time, so that Freight captures both the new image tag and the latest configuration commit as a single promotable unit.

Freight

Freight is the central abstraction in Kargo. Think of it as a shipping container that groups together a specific set of artifact versions. A single piece of Freight might reference a container image at version 1.29.1 alongside a Git commit hash and a Helm chart version. These artifacts travel together through your promotion pipeline, ensuring that related changes are always promoted as a unit.

Freight is created automatically by Warehouses when new artifact versions are detected. Once created, Freight flows through Stages in the order defined by your pipeline.

Stages

Stages are promotion targets. Each Stage represents something whose desired state needs to be updated, typically an environment like test, UAT, or production. Stages are connected in a directed acyclic graph that defines the promotion flow.

A Stage specifies three things: what Freight it accepts (and from where), how to perform the promotion (a promotion template), and optionally how to verify that the promotion succeeded.

apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
  name: uat
  namespace: my-project
spec:
  requestedFreight:
    - sources:
        stages:
          - test
      origin:
        kind: Warehouse
        name: my-warehouse
  promotionTemplate:
    spec:
      steps:
        - uses: git-clone
          config:
            repoURL: https://github.com/example/deploy-config.git
            checkout:
              - branch: main
                path: ./src
        - uses: kustomize-set-image
          config:
            path: ./src/environments/uat
            images:
              - image: public.ecr.aws/nginx/nginx
        - uses: kustomize-build
          config:
            path: ./src/environments/uat
            outPath: ./out/uat
        - uses: git-commit
          config:
            path: ./src
            messageFromSteps:
              - kustomize-set-image
        - uses: git-push
          config:
            path: ./src
        - uses: argocd-update
          config:
            apps:
              - name: my-app-uat

This Stage accepts Freight that has already passed through the test Stage. The promotion template clones a Git repository, updates the image tag using Kustomize, commits the change, pushes it, and then tells Argo CD to sync the application. Every step is declarative and versioned alongside the rest of your configuration.

How It All Fits Together

The typical Kargo pipeline follows a straightforward flow:

  1. Warehouse detects a new artifact - A new container image is pushed to your registry, or a new commit lands on a monitored branch.
  2. Freight is created - The Warehouse packages the new artifact versions into a Freight resource.
  3. Freight enters the first Stage - Depending on your auto-promotion policy, Freight either promotes automatically or waits for manual approval.
  4. Promotion executes - Kargo runs the promotion steps defined in the Stage's template, typically updating manifests in Git and triggering an Argo CD sync.
  5. Verification runs - If configured, Kargo runs verification processes (like integration tests or smoke tests) to confirm the promotion was successful.
  6. Freight becomes available downstream - Once verified in the current Stage, the Freight becomes eligible for promotion to the next Stage in the pipeline.

This continues until the Freight reaches your final Stage, typically production. At every point you have full visibility into what version is where, what is waiting to be promoted, and the complete history of every promotion that has occurred.

Installing Kargo

The quickest way to try Kargo locally is with their quickstart script, which sets up a local Kubernetes cluster with both Argo CD and Kargo pre-configured. You will need Kind and Helm v3.13.1 or later installed.

curl -L https://raw.githubusercontent.com/akuity/kargo/main/hack/quickstart/kind.sh | sh

This gives you Argo CD at http://localhost:31080 and Kargo at http://localhost:31081, both with admin as the password. From there, you can follow the quickstart guide to set up your first promotion pipeline using a fork of the demo repository.

For production installations, Kargo provides Helm charts with extensive configuration options. The installation documentation covers both basic and advanced setups, including integration with existing Argo CD instances.

Warehouse Subscription Strategies

One of Kargo's more powerful features is the flexibility of its Warehouse subscriptions. Depending on how you tag and release artifacts, you can choose from several selection strategies.

For container images, the SemVer strategy is the default and usually the best choice. It selects images based on semantic version constraints, so a constraint of ^1.29.0 will match 1.29.1 and 1.30.0 but not 2.0.0. If your images use date-based or lexicographic tags, the Lexical and NewestBuild strategies are available as alternatives.

Git repository subscriptions offer similar flexibility. The default NewestFromBranch strategy watches for new commits on a specified branch, while SemVer looks for tagged commits matching a version constraint. For monorepos, you can use includePaths and excludePaths to scope which directory changes trigger new Freight.

Auto-Promotion vs Manual Promotion

Kargo supports both automated and manual promotion workflows. The auto-promotion policy on a Stage determines the behavior:

  • NewestFreight (default) continuously promotes the newest verified Freight as soon as it becomes available. This is ideal for lower environments like dev or test where you want changes flowing through quickly.
  • MatchUpstream promotes whatever Freight is currently active in the upstream Stage. This is useful when you want a downstream Stage to always mirror a specific upstream rather than racing ahead.

For production or any environment where you need human approval, you can simply disable auto-promotion and use the Kargo CLI or UI to promote Freight manually:

kargo promote --project my-project --freight <freight-id> --stage production

The Kargo dashboard provides a visual pipeline view where you can drag Freight between Stages, making manual promotions intuitive even for team members who are not comfortable with the CLI.

Verification

Promotion is only half the story. You also need to know whether a promotion actually succeeded. Kargo supports optional verification processes that run after a promotion completes. These can invoke Argo Rollouts analysis runs, run custom test suites, or perform any validation logic you define.

If verification fails, the Freight is not marked as verified in that Stage, which means it will not be eligible for promotion to downstream Stages. This provides a natural quality gate that prevents broken changes from propagating through your pipeline.

Reusable Promotion Steps with PromotionTasks

As your pipeline grows, you will notice that promotion templates across Stages often share the same sequence of steps with minor variations (different environment paths, different Argo CD application names). Kargo addresses this with PromotionTasks, which let you define reusable promotion step sequences that can be parameterized and referenced from multiple Stages. This keeps your configuration DRY and makes it easier to update promotion logic across your entire pipeline.

Getting Started

If you have an existing Argo CD setup and want to add structured promotions, here is the path I recommend:

  1. Start with the Kargo quickstart to understand the concepts in a local environment.
  2. Identify one application with a simple pipeline (dev, staging, production) as your first candidate.
  3. Create a Warehouse that watches the artifacts for that application.
  4. Define Stages for each environment with appropriate promotion templates.
  5. Enable auto-promotion for lower environments and keep manual promotion for production.
  6. Add verification as you gain confidence.

Kargo fits naturally into an existing GitOps workflow. It does not require you to change how Argo CD deploys applications. It simply adds the orchestration layer that handles how changes move between environments.

What's Next

Kargo is under active development and the community continues to add features. In future posts I plan to explore more advanced topics like multi-artifact Freight, complex pipeline topologies with fan-in and fan-out patterns, and integration with Argo Rollouts for progressive delivery within a single Stage.

If you are looking for help adopting Kargo or building promotion pipelines for your organization, get in touch. I work with teams to design and implement GitOps workflows that scale.