Skip to main content

Kargo Quickstart

This guide presents a basic introduction to Kargo. Together, we will:

  1. Install Kargo and its dependencies into an existing, local Kubernetes cluster.

    OR

    Create a new local Kubernetes cluster with Kargo and its dependencies already installed.

  2. Install the Kargo CLI.

  3. Demonstrate how Kargo can progress changes through multiple stages by interacting with your GitOps repository and Argo CD Application resources.

  4. Clean up.

info

If you're looking to contribute to Kargo, you may wish to consult the contributor guide instead.

Starting a Local Cluster

Any of the following approaches require Helm v3.13.1 or greater to be installed.

If you are a Docker Desktop user, you can follow these instructions to enable its built-in Kubernetes support.

info

Although this is one of the fastest paths to a local Kubernetes cluster, be aware that Docker Desktop supports only a single Kubernetes cluster. If that cluster reaches a state you are dissatisfied with, resetting it will remove not just Kargo-related resources, but all your workloads and data.

curl -L https://raw.githubusercontent.com/akuity/kargo/release-0.5/hack/quickstart/install.sh | sh
note

If Kargo installation fails with a 401, verify that you are using Helm v3.13.1 or greater.

If Kargo installation fails with a 403, it is likely that Docker is configured to authenticate to ghcr.io with an expired token. The Kargo chart and images are accessible anonymously, so this issue can be resolved simply by logging out:

docker logout ghcr.io

At the end of this process:

  • The Argo CD dashboard will be accessible at localhost:31443.

    The username and password are both admin.

  • The Kargo dashboard will be accessible at localhost:31444.

    The admin password is admin.

  • You can safely ignore all cert errors for both of the above.

Installing the Kargo CLI

To download the Kargo CLI:

arch=$(uname -m)
[ "$arch" = "x86_64" ] && arch=amd64
curl -L -o kargo https://github.com/akuity/kargo/releases/download/v0.5.2/kargo-$(uname -s | tr '[:upper:]' '[:lower:]')-${arch}
chmod +x kargo

Then move kargo to a location in your file system that is included in the value of your PATH environment variable.

Trying It Out

Create a GitOps Repository

Let's begin by creating a repository on GitHub to house variations of our application manifests for three different stages of a sample application: test, UAT, and production.

  1. Visit https://github.com/akuity/kargo-demo and fork the repository into your own GitHub account.

  2. You can explore the repository and see that the main branch contains common configuration in a base/ directory as well as stage-specific overlays in paths of the form stages/<stage name>/.

    note

    This layout is typical of a GitOps repository using Kustomize for configuration management and is not at all Kargo-specific.

    Kargo also works just as well with Helm.

  3. We'll be using it later, so save the location of your GitOps repository in an environment variable:

    export GITOPS_REPO_URL=<your repo URL, starting with https://>

Create Argo CD Application Resources

In this step, we will use an Argo CD ApplicationSet resource to create and manage three Argo CD Application resources that deploy the sample application at three different stages of its lifecycle, with three slightly different configurations, to three different namespaces in our local cluster:

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: kargo-demo
namespace: argocd
spec:
generators:
- list:
elements:
- stage: test
- stage: uat
- stage: prod
template:
metadata:
name: kargo-demo-{{stage}}
annotations:
kargo.akuity.io/authorized-stage: kargo-demo:{{stage}}
spec:
project: default
source:
repoURL: ${GITOPS_REPO_URL}
targetRevision: stage/{{stage}}
path: stages/{{stage}}
destination:
server: https://kubernetes.default.svc
namespace: kargo-demo-{{stage}}
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF

If you visit your Argo CD dashboard, you will notice all three Argo CD Applications have not yet synced because they're not configured to do so automatically, and in fact, the branches referenced by their targetRevision fields do not even exist yet.

info

Our three stages all existing in a single cluster is for the sake of expediency. A single Argo CD control plane can manage multiple clusters, so these could just as easily have been spread across multiple clusters.

Hands on with the Kargo CLI

Up to this point, we haven't done anything with Kargo -- in fact everything we've done thus far should be familiar to anyone who's already using Argo CD and Kustomize. Now it's time to see what Kargo can do!

To get started, you will need a GitHub personal access token with adequate permissions to read from and write to the repository you forked in the previous section.

  1. Save your GitHub handle and your personal access token in environment variables:

    export GITHUB_USERNAME=<your github handle>
    export GITHUB_PAT=<your personal access token>
  2. Then, log into Kargo:

    kargo login https://localhost:31444 \
    --admin \
    --password admin \
    --insecure-skip-tls-verify
  3. Next, we'll create several Kargo resource:

    1. A Project, which, when reconciled, will effect all boilerplate project initialization, including the creation of a specially-labeled Namespace with the same name as the Project

    2. A Secret containing credentials for our GitOps repository

    3. A Warehouse that subscribes to a container image repository

    4. Three Stage resources -- test, uat, and prod

    cat <<EOF | kargo apply -f -
    apiVersion: kargo.akuity.io/v1alpha1
    kind: Project
    metadata:
    name: kargo-demo
    ---
    apiVersion: v1
    kind: Secret
    type: Opaque
    metadata:
    name: kargo-demo-repo
    namespace: kargo-demo
    labels:
    kargo.akuity.io/cred-type: git
    stringData:
    repoURL: ${GITOPS_REPO_URL}
    username: ${GITHUB_USERNAME}
    password: ${GITHUB_PAT}
    ---
    apiVersion: kargo.akuity.io/v1alpha1
    kind: Warehouse
    metadata:
    name: kargo-demo
    namespace: kargo-demo
    spec:
    subscriptions:
    - image:
    repoURL: nginx
    semverConstraint: ^1.24.0
    ---
    apiVersion: kargo.akuity.io/v1alpha1
    kind: Stage
    metadata:
    name: test
    namespace: kargo-demo
    spec:
    subscriptions:
    warehouse: kargo-demo
    promotionMechanisms:
    gitRepoUpdates:
    - repoURL: ${GITOPS_REPO_URL}
    writeBranch: stage/test
    kustomize:
    images:
    - image: nginx
    path: stages/test
    argoCDAppUpdates:
    - appName: kargo-demo-test
    appNamespace: argocd
    ---
    apiVersion: kargo.akuity.io/v1alpha1
    kind: Stage
    metadata:
    name: uat
    namespace: kargo-demo
    spec:
    subscriptions:
    upstreamStages:
    - name: test
    promotionMechanisms:
    gitRepoUpdates:
    - repoURL: ${GITOPS_REPO_URL}
    writeBranch: stage/uat
    kustomize:
    images:
    - image: nginx
    path: stages/uat
    argoCDAppUpdates:
    - appName: kargo-demo-uat
    appNamespace: argocd
    ---
    apiVersion: kargo.akuity.io/v1alpha1
    kind: Stage
    metadata:
    name: prod
    namespace: kargo-demo
    spec:
    subscriptions:
    upstreamStages:
    - name: uat
    promotionMechanisms:
    gitRepoUpdates:
    - repoURL: ${GITOPS_REPO_URL}
    writeBranch: stage/prod
    kustomize:
    images:
    - image: nginx
    path: stages/prod
    argoCDAppUpdates:
    - appName: kargo-demo-prod
    appNamespace: argocd
    EOF
info

Kargo uses semver to handle semantic versioning constraints.

  1. Use the CLI to view our Warehouse resource:

    kargo get warehouses --project kargo-demo

    Sample output:

    NAME         SHARD   AGE
    kargo-demo 13s
  2. Use the CLI to view our three Stage resources:

    kargo get stages --project kargo-demo

    Sample output:

    NAME   SHARD   CURRENT FREIGHT   HEALTH   PHASE           AGE
    prod NotApplicable 20s
    test NotApplicable 20s
    uat NotApplicable 20s
  3. Our Warehouse, which subscribes to the nginx image repository, also should have already produced Freight:

    kargo get freight --project kargo-demo

    Sample output:

    NAME                                       ALIAS              AGE
    f5f87aa23c9e97f43eb83dd63768ee41f5ba3766 mortal-dragonfly 35s
    info

    Freight is a set of references to one or more versioned artifacts, which may include:

    • Container images (from image repositories)

    • Kubernetes manifests (from Git repositories)

    • Helm charts (from chart repositories)

    This introductory example has Freight that references only a specific version of the nginx container image.

  4. We'll use it later, so save the ID of the Freight to an environment variable:

    export FREIGHT_ALIAS=$(kargo get freight --project kargo-demo --output jsonpath={.alias})
  5. Now, let's promote the Freight into the test Stage:

    kargo promote --project kargo-demo --freight-alias $FREIGHT_ALIAS --stage test

    Sample output:

    Promotion Created: "test.01hj7grh2m556rqxq72ame6a3z.f5f87aa"

    Query for Promotion resources within our project to see one has been created:

    kargo get promotions --project kargo-demo

    Our Promotion may briefly appear to be in a Pending phase, but more than likely, it will almost immediately be Running, or even Succeeded:

    NAME                                      STAGE   FREIGHT                                    PHASE     AGE
    test.01hj7grh2m556rqxq72ame6a3z.f5f87aa test f5f87aa23c9e97f43eb83dd63768ee41f5ba3766 Running 7s

    Once the Promotion has succeeded, we can again view all Stage resources in our project, and at a glance, see that the test Stage is now either in a Progressing or Healthy state.

    kargo get stages --project kargo-demo

    Sample output:

    NAME   CURRENT FREIGHT                            HEALTH    PHASE           AGE
    prod NotApplicable 118s
    test f5f87aa23c9e97f43eb83dd63768ee41f5ba3766 Healthy Steady 119s
    uat NotApplicable 118s

    We can repeat the command above until our test Stage is in a Healthy state and we can further validate the success of this entire process by visiting the test instance of our site at localhost:30081.

    If we once again view the status of our test Stage in more detail, we will see that it now reflects its current Freight, and the history of all Freight that have passed through this stage. (The collection is ordered most to least recent.)

    kargo get stage test --project kargo-demo --output jsonpath-as-json={.status}

    Truncated sample output:

    {
    "currentFreight": {
    "id": "f5f87aa23c9e97f43eb83dd63768ee41f5ba3766",
    "images": [
    {
    "digest": "sha256:2bdc49f2f8ae8d8dc50ed00f2ee56d00385c6f8bc8a8b320d0a294d9e3b49026",
    "repoURL": "nginx",
    "tag": "1.25.3"
    }
    ],
    },
    ...
    "history": [
    {
    "id": "f5f87aa23c9e97f43eb83dd63768ee41f5ba3766",
    "images": [
    {
    "digest": "sha256:2bdc49f2f8ae8d8dc50ed00f2ee56d00385c6f8bc8a8b320d0a294d9e3b49026",
    "repoURL": "nginx",
    "tag": "1.25.3"
    }
    ],
    }
    ]
    }
  6. If we look at our Freight in greater detail, we'll see that by virtue of the test Stage having achieved a Healthy state, the Freight is now verified in test, which designates it as eligible for promotion to the next Stage -- in our case, uat.

    note

    Although this example does not demonstrate it, it is also possible to verify the Freight in a Stage using user-defined processes. See the relevant section of the concepts page to learn more.

    kargo get freight --alias $FREIGHT_ALIAS --project kargo-demo --output jsonpath-as-json={.status}

    Sample output:

    {
    "verifiedIn": {
    "test": {}
    }
    }

Behind the Scenes

So what has Kargo done behind the scenes?

Visiting our fork of https://github.com/akuity/kargo-demo, we will see that Kargo has recently created a stage/test branch for us. It has taken the latest manifests from the main branch as a starting point, run kustomize edit set image within the stages/test/ directory, and written the modified configuration to a stage-specific branch -- the same branch referenced by the test Argo CD Applicaton's targetRevision field.

info

Although not strictly required for all cases, using stage-specific branches is a suggested practice that enables Kargo to transition each Stage into any new or previous state, at any time, with a new commit that replaces the entire contents of the branch -- all without disrupting the main branch.

Promote to UAT and then Production

Unlike our test Stage, which subscribes directly to an image repository, our uat and prod Stages both subscribe to other, upstream Stages, thereby forming a pipeline:

  1. uat subscribes to test
  2. prod subscribes to uat.

We leave it as an exercise to the reader to use the kargo promote command to progress the Freight from test to uat and again from uat to prod.

info

The uat and prod instances of our site should be accessible at:

info

It is possible to automate promotion of new, qualified Freight for designated Stages and also possible to used RBAC to limit who can trigger manual promotions for each Stage, however, both these topics are beyond the scope of this introduction.

Cleaning up

Congratulations! You've just gotten hands on with Kargo for the first time!

Now let's clean up!

Docker Desktop supports only a single Kubernetes cluster. If you are comfortable deleting not just just Kargo-related resources, but all your workloads and data, the cluster can be reset from the Docker Desktop Dashboard.

If, instead, you wish to preserve non-Kargo-related workloads and data, you will need to manually uninstall Kargo and its prerequisites:

curl -L https://raw.githubusercontent.com/akuity/kargo/release-0.5/hack/quickstart/uninstall.sh | sh