How To create an Argo CD Plugin?
Using Carvel's kbld as an example

Cloud Native Pilgrim | Kubernetes Enthusiast | Serverless Believer | Customer Experience Architect @ Pulumi | (he/him) | CK{A,AD} |
Search for a command to run...
Using Carvel's kbld as an example

Cloud Native Pilgrim | Kubernetes Enthusiast | Serverless Believer | Customer Experience Architect @ Pulumi | (he/him) | CK{A,AD} |
can we provide my value path in $HELM_VALUES
Hi I Read your article it is great , I would like to know few thing regarding in which value.yaml file do we need to add the kbld config.
GPU scheduling in Kubernetes has always felt like buying a mansion when you need a studio apartment. A small inference workload that needs 2GB of GPU memory gets scheduled on an entire 80GB A100, and there's nothing you can do about it. The device pl...

TL;DR: The code https://github.com/dirien/quick-bites Nothing is more controversial in the Kubernetes community than whether to use Helm or Kustomize. I always advocate the philosophy of using the right tool for the right job. It avoids the problem...

TL;DR Le code https://github.com/dirien/quick-bites Introduction This article is part three of my series on secret management on Kubernetes with the help of Pulumi. In my first article, we talked about the Sealed Secrets controller. The second arti...

With AWS Lambda

Disaster Recovery, Data Migration made easy!

The recent tweet from the argoproj, was the motivation to get my hands "dirty" and play a little with kbld. But I install thought about try to integrate kbld with the Argo CD management plugin system. Always wanted to do something with this interesting looking functionality.
kbld is a tool for building Docker images and resolving image references. We are not using in this tutorial the building part of kbld. Instead, we focus on the image references resolving part.
When you apply kbld an on existing manifest, you will see that image digest reference (e.g.
index.docker.io/your-username/your-repo@sha256:
4c8b96...) was used inserted instead of a tagged reference (e.g. kbld:docker-io...).
Because tags are mutable, they have a certain disadvantages when you use them to deploy an image:
In Kubernetes, deploying by tag can result in unexpected behaviours. For example, assume that you have an existing Deployment resource that references a container image by tag 0.0.1. To fix a bug or make a small change, your build process creates a new image but with the same tag 0.0.1
New Pods that are created from your Deployment resource can end up using either the old or the new image, even if you don't change your Deployment resource specification.
Digest references are preferred to other image reference forms as they are immutable, hence provide a guarantee that exact version of built software will be deployed.
Argo CD allows us to integrate more config management tools using config management plugins. Most prominent inbuilt tools are helm and kustomize.
We have to option, when it comes to create our own Config Management Plugin (CMP):
According tho the official documentation of Argo CD this is a good option for a simple plugin that requires only a few lines of code. As it would still nicely fit into the Argo CD ConfigMap.
This option is the way to go for more complex plugins, which would bloat our Argo CD ConfigMap.
In this blog, I am going to use the option 1. And I will use the helm chart to deploy Argo CD.
Tha means I going to to add the following lines to my values.yaml file:
config:
configManagementPlugins: |
- name: kbld
generate:
command: ["bash", "-c"]
args: ['helm template --release-name "$ARGOCD_APP_NAME" -f <(echo "$HELM_VALUES") . > kbld.yaml && kbld -f kbld.yaml >> final.yaml && cat final.yaml']
Keep in mind, that a plug consist of the commands: init and generate. The init command is optional and takes care to initialize application source directory.
The generate command must print a valid YAML or JSON stream to stdout.
If you need both, your definition would look like this:
...
- name: pluginName
init:
command: ["sample command"]
args: ["sample args"]
generate:
command: ["sample command"]
args: ["sample args"]
...
To pass any helm values, I created the HELM_VALUES environment variable. The other variable ARGOCD_APP_NAME is one of the default environment variables of Argo CD.
The second part we need now to do now, to get this plugin to work is to download the kbld binary and add it to the argocd_repo_server
For this, we're going to use an init container and a shared volume.
The init container will download the kbld binary and save it to shared volume. The shared volume will be then mounted to the argocd_repo_server container.
repoServer:
initContainers:
- name: download-tools
image: busybox:1.35.0
command: [ sh, -c ]
env:
- name: KBLD_VERSION
value: "0.33.0"
args:
- wget -q https://github.com/vmware-tanzu/carvel-kbld/releases/download/v${KBLD_VERSION}/kbld-linux-amd64 &&
mv kbld-linux-amd64 /custom-tools/kbld &&
chmod +x /custom-tools/kbld
volumeMounts:
- mountPath: /custom-tools
name: custom-tools
volumes:
- name: custom-tools
emptyDir: { }
volumeMounts:
- mountPath: /usr/local/bin/kbld
name: custom-tools
subPath: kbld
If you prefer to use option 2, providing the CMP as a sidecar to the repo-server Pod check out the Argo CD docs
For this example, I am going to use the Rancher Desktop for my local Kubernetes cluster.
Depending on your operating system, you may have a different way of installing Rancher Desktop. Check the installation guide on their website. -> https://docs.rancherdesktop.io/getting-started/installation
I put both snippets into a values file (argocd-values.yaml) and installed the ArgoCD Helm chart.
helm upgrade -i my-argo-cd argo/argo-cd --version 4.5.4 -f argocd-values.yaml
So let's test the plugin. All we need to do is to create a new application in Argo CD. The application manifest will look like this:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: test
namespace: default
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
project: default
source:
chart: minecraft-exporter
plugin:
env:
- name: HELM_VALUES
value: |
replicaCount: 1
name: kbld
repoURL: https://dirien.github.io/minecraft-prometheus-exporter
targetRevision: 0.5.0
Take note of the new plugin section. We are using here the name of the plugin we created earlier. And as mentioned before, we are using the HELM_VALUES environment variable to pass any helm values.
If everything is working, you should see all the images tags are replaced with their image digest reference.
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kbld.k14s.io/images: |
- origins:
- resolved:
tag: 0.13.0
url: ghcr.io/dirien/minecraft-exporter:0.13.0
url: ghcr.io/dirien/minecraft-exporter@sha256:4a6a3acd7fdcdf7f93817dcba54b2928aa02b33b132b44ddcc608f693f8e8723
labels:
app: minecraft-exporter
...
spec:
containers:
- image: >-
ghcr.io/dirien/minecraft-exporter@sha256:4a6a3acd7fdcdf7f93817dcba54b2928aa02b33b132b44ddcc608f693f8e8723
imagePullPolicy: IfNotPresent
...
This is just one little example, on how to use the Argo CD CMP functionality. And its actually a quite good example, because we avoid using the tag reference, but instead use the digest reference.
Feel free to check the Argo CD docs for more information about the usage of plugins
Not much of a code, but at least the `values.yaml´ -> https://github.com/dirien/rancher-argocd-plugins