In the process of updating my ingress-nginx controllers to a ArgoCD application on my k8s cluster, I found myself needing to have multiple instances running within a single namespace and Argo application. OK, maybe I didn’t need to, but my sense of organisation needed to…

Of course, the first go at setting this up was to add an Argo application sourcing the helm chart twice, and basically copy-pasting the helm values from the FAQ specifically about installing multiple instances within the same namespace for the second instance. But this approach was thwarted by the documentation being wrong. Using these values results in at least one resource with a duplicate name (the controller service at least, but I didn’t check for more). Had I attempted the install with helm, this should have failed as the combination of name and resource type is unique within a namespace. Argo, however, will happily accept the duplicates and ignore all but the last generated.1

So the fix? Easy - the chart provides a nameOverride value which can be used to override the generated names of the resources. This includes, by the way, the electionID, so we can drop that specification in our values.

The resulting application definition looks a little something like the below. Note as well the annotations for the IPs requested from MetalLB. This ensure that the assigned IPs for each don’t change when moving between namespaces.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ingress-nginx
  namespace: argo
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  sources:
  - repoURL: https://kubernetes.github.io/ingress-nginx
    chart: ingress-nginx
    targetRevision: 4.10.1
    helm:
      valuesObject:
        controller:
          service:
            annotations:
              metallb.universe.tf/loadBalancerIPs: 192.168.0.1
  - repoURL: https://kubernetes.github.io/ingress-nginx
    chart: ingress-nginx
    targetRevision: 4.10.1
    helm:
      valuesObject:
        nameOverride: ingress-nginx-secondary
        controller:
          ingressClassResource:
            name: nginx-secondary
            controllerValue: k8s.io/ingress-nginx-secondary
            enabled: true
          ingressClassByName: true
          ingressClass: nginx-secondary
          service:
            annotations:
              metallb.universe.tf/loadBalancerIPs: 192.168.0.2
  destination:
    server: https://kubernetes.default.svc
    namespace: ingress-nginx
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - PruneLast=true
    automated:
      selfHeal: true
      prune: true

  1. Yes, this is expected behaviour. Yes, I am aware that this says more about the fact that I am completely abusing the multiple source feature of ArgoCD. ↩︎