How we used ArgoCD management plugin to deploy dynamic objects

Itai Goldman
Taranis Tech
Published in
3 min readApr 11, 2024

Sometimes relying only on ArgoCD “native” config management is not suitable for all of your deployment needs.
The Default management plugins are: Helm Jsonnet and Kustomize.

In this post, I will demonstrate how we utilized the ArgoCD management plugin (CMP) to create an application using our custom yaml generate command.

In Taranis, we deploy ArgoCD application for ephemeral environments. These environments are constantly changing depending on the deployed microservice and its connections to other microservices. The connections are configmaps with connection strings within the cluster to other microservices. for example:

apiVersion: v1
data:
service: my-service.namespace.svc.cluster.local:80
kind: ConfigMap
metadata:
name: my-service
---
apiVersion: v1
data:
service: my-other-service.namespace.svc.cluster.local:80
kind: ConfigMap
metadata:
name: my-other-service

Before we moved to ArgoCD, these connections were generated with a script in the deployment pipeline.

So the issue we faced was — How could ArgoCD deploy these yamls from a script?

Because, as you may know, ArgoCD is only capable of generating and applying from git/OCI/helm repositories.

After some research, I ended up developing our custom management plugin (CMP). This feature allows you to customize the way that argocd generates the manifests with your commands.

for example, you can use it to change the helm template command to be with extra flags, or like we did — use this feature to get the manifests from a remote endpoint that runs a script, without using the files in the repository.

Steps to create ArgoCD management plugin:

  1. Create a configmap with plugin.yaml describing your plugin:
apiVersion: v1
kind: ConfigMap
metadata:
name: taraniscustomplugin
data:
plugin.yaml: |
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
name: taraniscustomplugin
spec:
version: v1.0
generate:
command: ["/bin/sh", "-c", "curl -s https://yaml-endpoints/$ARGOCD_ENV_SERVICE"]

Please note:

  • The final output of the command should be a yaml file because this is what ArgoCD will attempt to apply.
  • To use parameters, you need to start the command with /bin/sh -c (I will show at the end how to pass the parameters)
  • Yes, it’s not a mistake — The data of the configmap seems like a yaml file, it should be like this.
  • I recommend that if you’re deploying ArgoCD using the helm chart, put this yaml in the extraObjects block for easy management.

If you want to view all the parameters you can add to this plugin, I suggest reading this documentation section: https://argo-cd.readthedocs.io/en/stable/operator-manual/config-management-plugins/#installing-a-config-management-plugin

2. Add to the repo-server volume of the configmap you’ve just created and a tmp emptyDir as follows:

volumes:
- name: taraniscustomplugin
configMap:
name: taraniscustomplugin
- name: cmp-tmp
emptyDir: {}

3. Add a sidecar container to the repo-server with mount to the volume:

extraContainers:
- name: taraniscustomplugin
command:
- "/var/run/argocd/argocd-cmp-server"
image: <image-to-run-the-plugin-on>
securityContext:
runAsNonRoot: true
runAsUser: 999
volumeMounts:
- mountPath: /var/run/argocd
name: var-files
- mountPath: /home/argocd/cmp-server/plugins
name: plugins
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
subPath: plugin.yaml
name: taraniscustomplugin
- mountPath: /tmp
name: cmp-tmp

The image of this container will execute the plugin, so it’s recommended to create an image containing all the necessary dependencies and to use this image instead of running all of the installations in the init/command.

Thats it! Apply the changes and create an application using your custom plugin like so:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-application
spec:
project: default
source:
repoURL: <random-repo-url>
targetRevision: HEAD
path: .
plugin:
name: taraniscustomplugin-v1.0
env:
- name: SERVICE
value: my-service
destination:
server: https://kubernetes.default.svc
namespace: default

You can see that in the application, that I used my plugin, by specifying its name and version, and passed an argument through environment variables to the plugin.

By doing so, we’ve developed a dynamic plugin that returns the desired data using a script rather than relying on static Helm or Git repositories. And the greatest advantage is that ArgoCD reconciles every 3 minutes by default. Thus, if there are any changes in the microservice’s configuration, ArgoCD will detect them and update the configmaps accordingly.

Thank you for reading; I hope you find it useful!

--

--