Deploying Helm Charts using ArgoCD and Helmfile
Deploying Helm Charts with ArgoCD using Helmfile is not supported out of the box. In this article, I will show how to extend ArgoCD using config management plugins to support Helmfile.
ArgoCD provides four patterns for deploying existing Helm Charts to a Kubernetes cluster. One approach that is not supported out of the box is to use a Helmfile. In this article, I will show how to extend the ArgoCD repository server using the Config Management Plugin feature to support Helmfile.
What is ArgoCD?
Argo CD is an open-source continuous delivery (CD) tool designed for deploying and managing applications in Kubernetes clusters. It follows the GitOps approach, meaning that the desired state of the application and the configuration details are specified in a Git repository. Argo CD then continuously monitors the repository for changes and synchronizes the state of the deployed applications with the desired state specified in the Git repository.
Supported approaches to deploy Helm Charts
At the time of writing, ArgoCD supports these four approaches:
- ArgoCD application pointing to a Helm Chart in a Helm repository
- ArgoCD application pointing to a Helm Chart in a Git repository
- ArgoCD application pointing to a Helm Dependency in a Git repository
- ArgoCD application pointing to a Kustomize folder in a Git repository
What is Helmfile?
Helmfile is a declarative tool for deploying and managing Helm charts in Kubernetes clusters. It provides a higher-level abstraction and simplifies the management of Helm releases by allowing you to define and version your releases in a YAML file called the "Helmfile." Helmfile is built on top of Helm, which is a popular package manager for Kubernetes.
Take a look at the following example of a Helmfile:
repositories:
- name: christianhuth
url: https://charts.christianhuth.de
releases:
- name: popeye
namespace: security
chart: christianhuth/popeye
values:
- cronJob:
outputFormat: "prometheus"
As you can see you can define a list of Helm repositories, that contain Helm Charts, and a list of releases, that represent the installation of a Helm Chart in a particular namespace and with a defined configuration.
A given helmfile.yaml
can be installed with the command helmfile apply
.
Setting up the Config Management Plugin for ArgoCD
There are two ways to install a Config Management Plugin:
- Sidecar plugin: This is a good option for a more complex plugin that would clutter the Argo CD ConfigMap. A copy of the repository is sent to the sidecar container as a tarball and processed individually per application.
- ConfigMap plugin: The repo-server container will run your plugin's commands. But be aware that this method is deprecated and will be removed in a future version.
I highly recommend using the Sidecar plugin mechanism as it gives you more features and flexibility and is future proof.
At a higher level, we need to do the following things:
- Add a Sidecar container that runs the
helmfile
binary - Create the Config Management Plugin configuration that uses the
helmfile
binary - Include this configuration in the Sidecar container using a
ConfigMap
Depending on how you install and manage your ArgoCD installation, the way you implement these actions will differ. I will show you how to do this using the official ArgoCD Helm Chart. However, this approach can be adapted to suit your installation.
Create the Config Management Plugin configuration
In our configuration, we will use the discover
section. With this option, ArgoCD will automatically use the plugin whenever it finds a helmfile.yaml
in the source repository. If we do not define this section we would need to add a plugin
section to each ArgoCD application that should use the Helmfile plugin.
configs:
cmp:
create: true
plugins:
helmfile:
allowConcurrency: true
discover:
fileName: helmfile.yaml
generate:
command:
- bash
- "-c"
- |
if [[ -v ENV_NAME ]]; then
helmfile -n "$ARGOCD_APP_NAMESPACE" -e $ENV_NAME template --include-crds -q
elif [[ -v ARGOCD_ENV_ENV_NAME ]]; then
helmfile -n "$ARGOCD_APP_NAMESPACE" -e "$ARGOCD_ENV_ENV_NAME" template --include-crds -q
else
helmfile -n "$ARGOCD_APP_NAMESPACE" template --include-crds -q
fi
lockRepo: false
Add a Sidecar container that runs the helmfile
binary
For helmfile
to work we need the helmfile
binary, the helm
binary, and the Helm Diff plugin installed in the container. Luckily for us, we can use the already existing image hosted in the Google Container Registry at ghcr.io/helmfile/helmfile.
repoServer:
extraContainers:
- name: helmfile
image: ghcr.io/helmfile/helmfile:v0.157.0
# Entrypoint should be Argo CD lightweight CMP server i.e. argocd-cmp-server
command: ["/var/run/argocd/argocd-cmp-server"]
env:
- name: HELM_CACHE_HOME
value: /tmp/helm/cache
- name: HELM_CONFIG_HOME
value: /tmp/helm/config
- name: HELMFILE_CACHE_HOME
value: /tmp/helmfile/cache
- name: HELMFILE_TEMPDIR
value: /tmp/helmfile/tmp
securityContext:
runAsNonRoot: true
runAsUser: 999
volumeMounts:
- mountPath: /var/run/argocd
name: var-files
- mountPath: /home/argocd/cmp-server/plugins
name: plugins
# Register helmfile plugin into sidecar
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
subPath: helmfile.yaml
name: argocd-cmp-cm
# Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps mitigate path traversal attacks.
- mountPath: /tmp
name: cmp-tmp
volumes:
- name: argocd-cmp-cm
configMap:
name: argocd-cmp-cm
- name: helmfile-tmp
emptyDir: {}
Setting up the Git repository
Now, all we need to do is create a Git repository containing the Helmfile:
repositories:
- name: bitnami
url: https://charts.bitnami.com/bitnami
releases:
- name: postgresql
namespace: default
chart: bitnami/postgresql
values:
- auth:
username: my-user
password: my-password
And an ArgoCD application pointing to that Git repository:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: helmfile-example
spec:
project: default
source:
repoURL: https://github.com/christianhuth/blog-code.git
targetRevision: main
path: deploying-helm-charts-using-argocd-and-helmfile
destination:
server: https://kubernetes.default.svc
namespace: default
Et voilá
You should now have a new application in ArgoCD that uses Helmfile for deploying Helm Charts: