Post update:
December 10, 2024:
- Updating Kargo from version 0.3.1 to 1.0.3;
- Many adjustments made to the configuration files;
- Using of the Silicon Chalet meetup demo. For anyone interested in the event, you can check out the support at this link.
Introduction#
Last month I presented Flamingo, combining both Argo CD and Flux CD to take advantage of these two tools and adopt a GitOps approach.
However, GitOps or the above tools do not define a means of promoting changes that have been made from a development environment to a qualification or production environment.
In fact, Argo CD and Flux CD are responsible to deploy one or more target environments without any link or relationship between them.
However, it is possible to adopt a Branching Model to promote these changes. If you’re not familiar with the term, I recommend you take a look at this article.
Fortunately, a solution emerged a few months ago, although it is still relatively new and not yet suitable for production use. This article aims to provide an overview of the tool’s potential.
Kargo, the answer#
Who hasn’t dreamt of pressing a button to transfer changes from one environment to another? A common example is a new container image being tested in a development environment before being deployed to a qualification environment.
This is exactly what Kargo can do, although it goes even further than image version management. It is fully able to apply configuration differences to your Kubernetes objects via a Git repository or to retrieve the latest versions of your Helm Charts.
Moreover, Kargo is part of the same family as Argo CD and is a 100% open source tool. In fact, it has been designed by the creators of Argo CD!
In a nutshell, Kargo is a continuous delivery platform giving you the opportunity to orchestrate the lifecycle of applications on Kubernetes from one environment to another, using existing tools.
That’s right, Kargo works directly with Argo CD, allowing it to excel at its core function: deploying Kubernetes objects.
Features#
As mentioned above, Kargo is a relatively recent tool, but it offers several features:
- Promotion of configurations or containerised images from one environment to another;
- Writing changes to Git: As soon as a change is approved, Kargo generates a Pull Request and commits the changes;
- Ability to roll back changes in the event of an error;
- Creation of deployment strategies to validate the correct operation of an environment, particularly with Argo Rollouts;
- Canary and A/B testing can be used to deploy to a target environment.
This list maybe changed in future versions of Kargo. In fact, the team’s objective is to enhance the product in future versions in order to encourage the adoption of Kargo in production environments, even if a first major version has been released (1.x.x).
Kargo has a user interface that allows changes to be tracked at a glance:
This interface also allows you to view the images or configurations associated with the defined environments. This enables maintaining a history and auditing all actions performed within Kargo.
Finally, the large black bar at the top is called the freight line (Freight), as in the case of goods transport. Now, do you see the link between that and Kargo, right?
How does it work?#
Let’s discuss about how Kargo works and how it manages environments, especially when a new image version is available.
Here is the sequence of operations in order:
- The CI, whatever the platform, creates a new container image;
- The image is pushed in a container registry;
- Depending on the configurations defined, Kargo analyses the Git repository containing the Kubernetes objects (1) and searches for any new associated images (2);
- Depending on the new images retrieved, the developer has the choice to promote these changes on the first environment configured, which in this case will be development;
- Once the developer has validated the changes, Kargo pushes them into Git;
- With the previous action, Argo CD is triggered and detects an update to the files in the development environment;
- Argo CD synchronises the changes on the Kubernetes cluster;
- Kargo retrieves the status of the deployed objects and enables tests to be carried out;
- If everything is OK, the developer can approve these changes for the next environment.
On the installation side, Kargo is best deployed with a Helm chart, and it is recommended that it is installed as close as possible to the Argo CD, as it interacts directly with it.
Let’s get down to business#
The example that will be used is the demo that I had the opportunity to run at the Silicon Chalet GitOps meetup. You can find the associated code on GitHub just below:
Kargo demo for the Silicon Chalet Meetup
This demo uses a Helm chart to be deployed between several environments with values-*.yaml
files for each environment defined. For those who prefer an example using Kustomize, I advise you to follow Kargo’s official quickstart.
Naturally, you can check the README.md
to set up your environment and the Kubernetes cluster.
In the following, I will explain the various objects related to Kargo. You can find them in the kargo/configurations
folder.
To begin setting up the environment deployment pipeline, the first step is to create a Project
, the foundation for defining the pipeline:
apiVersion: kargo.akuity.io/v1alpha1
kind: Project
metadata:
name: siliconchalet
spec:
promotionPolicies:
- stage: development
autoPromotionEnabled: true
The Project
object will create a namespace of the same name within the cluster; this Kubernetes object is straightforward. As you can see, you can define policies for promotions (promotionPolicies
) if you want them to be automated for particular environments.
As mentioned above, Kargo provides the ability to chain one or several environments together depending on your deployment cycle. These environments are materialised as Kubernetes objects called Stages
, but before creating this object, you need to set up a Warehouse
to listen, for instance, to new image versions.
apiVersion: kargo.akuity.io/v1alpha1
kind: Warehouse
metadata:
name: siliconchalet-app
namespace: siliconchalet
spec:
subscriptions:
- image:
repoURL: public.ecr.aws/nginx/nginx
imageSelectionStrategy: SemVer
semverConstraint: ~1.27.0
In this case, the aim is to retrieve the versions associated with the image public.ecr.aws/nginx/nginx
using the semver constraint ~1.27.0
.
Kargo supports working with several types of source within the warehouse object, including image registries, Git code repositories and Helm chart registries.
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: development
namespace: siliconchalet
spec:
requestedFreight:
- origin:
kind: Warehouse
name: siliconchalet-app
sources:
direct: true
promotionTemplate:
spec:
steps:
- uses: git-clone
config:
repoURL: ${REPOSITORY_URL}
checkout:
- branch: main
path: ./repo
- uses: helm-update-image
as: update-image
config:
path: ./repo/values-development.yaml
images:
- image: public.ecr.aws/nginx/nginx
key: image.tag
value: Tag
- uses: git-commit
as: commit
config:
path: ./repo
messageFromSteps:
- update-image
- uses: git-push
config:
path: ./repo
targetBranch: main
- uses: argocd-update
config:
apps:
- name: siliconchalet-app-development
sources:
- repoURL: ${REPOSITORY_URL}
Here is an example of creating a development environment using Kargo. In the code repository, the example relies on a Helm chart located in the helm/
directory.
This chart, referenced by the REPOSITORY_URL
variable, is fairly basic. It contains a Deployment
with the well-known public.ecr.aws/nginx/nginx
image, combined with a ConfigMap
for mounting html content and, finally, a Service
for making the application accessible.
Note that a
Secret
must be created if the code repository containing the Helm sources is not public. This is automatically created by thekargo-demo.sh
script and must contain thekargo.akuity.io/cred-type: git
label.
Firstly, within this Stage
, the requestedFreight
block is used to link the Warehouse
defined above to listen for new image versions. While the promotionTemplate
block defines all the steps to update this image version:
git-clone
: Clone the Helm code repository with themain
branch within therepo
directory;helm-update-image
: This specifies the environmentvalues
file with the tag of the image to be modified;git-commit
: Used to make a commit persisting the modifications from the previous step;git-push
: Pushes all changes to the branch defined, in this casemain
;argocd-update
: Last step, Argo CD is triggered to update and deploy the changes made to the siliconchalet-app-developmentApplication
.
All the possible steps are described in the documentation, so don’t hesitate to take a look.
You recall that within the Project
, it was specified that this development Stage
would be promoted automatically with the autoPromotionEnabled: true
option. These various stages will therefore be performed without any action on the part of a user.
It’s time to go one step further and create the testing and production environments!
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: testing
namespace: siliconchalet
spec:
requestedFreight:
- origin:
kind: Warehouse
name: siliconchalet-app
sources:
stages:
- development
promotionTemplate:
spec:
steps:
- uses: git-clone
config:
repoURL: ${REPOSITORY_URL}
checkout:
- branch: main
path: ./repo
- uses: helm-update-image
as: update-image
config:
path: ./repo/values-testing.yaml
images:
- image: public.ecr.aws/nginx/nginx
key: image.tag
value: Tag
- uses: git-commit
as: commit
config:
path: ./repo
messageFromSteps:
- update-image
- uses: git-push
config:
path: ./repo
targetBranch: main
- uses: argocd-update
config:
apps:
- name: siliconchalet-app-testing
sources:
- repoURL: ${REPOSITORY_URL}
There are no major changes to the testing environment. It depends on the previous development stage, as indicated in the sources
field of the requestedFreight
block. Note that this will require user approval to make the change until the environment is deployed.
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: production
namespace: siliconchalet
spec:
requestedFreight:
- origin:
kind: Warehouse
name: siliconchalet-app
sources:
stages:
- testing
promotionTemplate:
spec:
steps:
- uses: git-clone
config:
repoURL: ${REPOSITORY_URL}
checkout:
- branch: main
path: ./repo
- uses: helm-update-image
as: update-image
config:
path: ./repo/values-production.yaml
images:
- image: public.ecr.aws/nginx/nginx
key: image.tag
value: Tag
- uses: git-commit
as: commit
config:
path: ./repo
messageFromSteps:
- update-image
# Pushing into a new branch
- uses: git-push
as: push
config:
path: ./repo
targetBranch: chore/production/update-image
# Creating a Pull Request
- uses: git-open-pr
as: open-pr
config:
provider: github
repoURL: ${REPOSITORY_URL}
sourceBranchFromStep: push
targetBranch: main
# Waiting until merge
- uses: git-wait-for-pr
as: wait-for-pr
config:
provider: github
repoURL: ${REPOSITORY_URL}
prNumberFromStep: open-pr
- uses: argocd-update
config:
apps:
- name: siliconchalet-app-production
sources:
- repoURL: ${REPOSITORY_URL}
For the production environment, it’s quite different, I’ve chosen to open a Pull request to ask for the changes to be reviewed by several people, and to be sure of the changes applied to this type of environment:
git-push
: Pushes changes to a temporarychore/production/update-image
branch;git-open-pr
: Automatically creates a pull request by specifying the source and target branches;git-wait-for-pr
: In this step, Kargo will wait for the Pull Request specified in theprNumberFromStep
field to be merged before triggering the next step, in other words deploying the changes within Argo CD with theargocd-update
step.
Here’s what Kargo can do for us at the moment. It’s pretty comprehensive and much more advanced than what I’ve been able to achieve in previous versions.
To illustrate, here are a few images of the different actions.
Let’s start with the Kargo pipeline:
The promotion mechanism can be used directly from the interface or on the command line with the kargo
CLI:
As mentioned above, the promotion will commit directly to your code repository, triggering deployment within Argo CD:
Here is the new image deployed with Argo CD for the testing environment:
As explained earlier, the production environment opens a Pull Request and waits for it to be validated. This is what you see when you look at the details in Kargo:
With the related Pull Request:
During this validation phase, Kargo waits, as confirmed by the little cogwheel continuing to spin for the environment concerned:
Once the Pull Request has been validated, Kargo will modify the image on the production environment as follows:
And there you have it, your first pipeline with Kargo, well done!
A few final words…#
Instead of relying on a CI/CD pipeline using diff
and sed
to promote changes, Kargo addresses a commonly mentioned limitation of GitOps tools: orchestration between environments.
Once again, Kargo is still very young, but I personally think it has great potential. In the future, it may even become essential with any Argo CD installation.
Some important features have not yet been implemented, such as user and role management, as proposed by Argo CD, but this should not take too long.
Don’t hesitate to follow Kargo releases and updates on GitHub.