How to use separate environment configuration files ArgoCD

Posted in gitops on February 13, 2025 by Adrian Wyssmann ‐ 3 min read

Problem

Our current argo setup is as follows:

platform-tooling
├argocd
|  └applications
│    ├application_name1.yaml
│    └application_name2.yaml
├application_name1
│  ├env1
│  │ └values.yaml
│  ├dev
│  │ └values.yaml
...

application_nameX is usually an applicatioSet which ensures the application is deployed to all clusters. Currently this file contains a repetitive configuration:

generators:
- list:
    elements:
    - cluster: cluster-a
      clusterid: c-abcde
      project: p-abcde
      env: env1
      notifyChannel: channel-a
      targetRevision: x.x.x.x
       
    - cluster: cluster-b
      clusterid: c-bcdef
      project: p-bcdef
      env: env2
      notifyChannel: channel-b
      targetRevision: x.x.x.x
    ...

This list grows the more cluster one has. It also does not follow the DRY-principle. So, following one of my last posts I started to use environment configurations files. So we have the common config in a folder argocd/cluster-config which contains a <environment>.yaml containing standard config. For example env1.yaml

cluster: cluster-a
clusterid: c-abcde
project: p-abcde
env: env1
notifyChannel: channel-a

In addition, as we have for each application a folder per environment, we also add a config.yaml into each folder:

platform-tooling
├argocd
|  └applications
│  │ ├application_name1.yaml
│  │ └application_name2.yaml
|  └cluster-config
│    ├env1.yaml
│    └env2.yaml
├application_name1
│  ├env1
│  │ ├config.yaml
│  │ └values.yaml
│  ├dev
│  │ ├configyaml
│  │ └values.yaml
...

The config.yaml itself contains the application specific configuration e.g. chart version or branch for the helm values:

chartVersion: 1.2.0
branch: HEAD
env: env1

Important is, that they share a common key, in our case env - we use this for []mergeKeys](https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/Generators-Merge/). Now we can use git generators to build a config for each environment

    - merge:
        mergeKeys:
          - env
        generators: # The Merge generator combines parameters produced by the base (first) generator with matching parameter sets produced by subsequent generators
          - git:
              repoURL: https://scm.intra/k8s/tooling.git
              revision: HEAD
              files:
              - path: "application_name1/*/config.yaml"
          - git:
              repoURL: https://scm.intra/tooling.git
              revision: HEAD
              files:
              - path: "argocd/cluster-config/*.yaml"

For each application_name1/<env>/config.yaml a config is created containgt the combination of config.yaml and env1.yaml - it is important to keep that order, so only when there is a application_name1/<env> it will create a config - as argocd/cluster-config/* will always contain all environments. So with that structure you can steer in which environment your application is deployed.

So in addition, you will use then the config parameters in the applicationSet as follows using branch, chartVersion and cluster:

    spec:
      destination:
        namespace: application_name1
        name: "{{.cluster}}"
      project: tooling
      sources:
      - repoURL: https://scm.intra/tooling.git
        targetRevision: "{{.branch}}"
        path: application_name1/{{.env}}
      - repoURL: https://scm.intra/tooling.git
        targetRevision: "{{.branch}}"
        ref: values
      - repoURL: https://helm.intra/virtual-helm
        targetRevision: "{{.chartVersion}}"
        chart: application_name1
        helm:
          releaseName: application_name1
          valueFiles:
          - $values/application_name1/{{.env}}/values.yaml
          - $values/application_name1/values.yaml

Advantages

  • We do not repeat config values
  • It makes the ApplicationSet more readable
  • ApplicationSet is defined once and does not have to be touched anymore
  • Any changes incl. update of chart version happens in the same folder as the value files live