Duplicate annotation key in webservice Ingress when specifying proxy-body-size

Summary

Our company manages a private GitLab EE instance with Helm and disabled the proxy body size limit for the webservice Ingress to resolve an issue with large container image artifact uploads generated by GitLab CI pipelines - here are the chart values concerned:

global:
  ingress:
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: "0"

We've also recently adopted Flux v2 for managing our Helm releases via GitOps and our GitLab HelmRelease is stuck in a non-ready state due to a duplicate annotation entry in the webservice Ingress:

flux -n gitlab get hr gitlab

Output:

NAME    REVISION        SUSPENDED       READY   MESSAGE                                                                                                              
gitlab                  False           False   Helm upgrade failed: error while running post render on files: map[string]interface {}(nil): yaml: unmarshal errors:
                                                  line 20: mapping key "nginx.ingress.kubernetes.io/proxy-body-size" already defined at line 17

Note that this does not affect client-side apply such as deploying or updating the Chart directly via Helm.

Steps to reproduce

Clone this repository, navigate to the project root and run the following commands after uncommenting the certmanager-issuer.email field:

helm dependency build
helm template test .

Notice in the rendered YAML output (attached as no-ingress-annotation.yaml) that the nginx.ingress.kubernetes.io/proxy-body-size annotation appears exactly one with the default value 512m as expected:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "test-nginx"
    kubernetes.io/ingress.provider: "nginx"
    nginx.ingress.kubernetes.io/proxy-body-size: "512m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "15"
    cert-manager.io/issuer: "test-issuer"
    acme.cert-manager.io/http01-edit-in-place: "true"
    nginx.ingress.kubernetes.io/service-upstream: "true"

Now replace the following field in values.yaml:

global:
  ingress:
    annotations: {}

With the following:

global:
  ingress:
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: "0"

And run helm template again:

helm template test .

Observe a duplicate entry for the nginx.ingress.kubernetes.io/proxy-body-size annotation in the webservice Ingress (with-ingress-annotation.yaml) with both the default 512m and 0 values specified:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "test-nginx"
    kubernetes.io/ingress.provider: "nginx"
    nginx.ingress.kubernetes.io/proxy-body-size: "512m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "15"
    cert-manager.io/issuer: "test-issuer"
    acme.cert-manager.io/http01-edit-in-place: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/service-upstream: "true"

Configuration used

global:
  ingress:
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: "0"

Current behavior

A duplicate entry appears for the nginx.ingress.kubernetes.io/proxy-body-size annotation and server-side apply with Flux v2 fails:

flux -n gitlab get hr gitlab

Output:

NAME    REVISION        SUSPENDED       READY   MESSAGE                                                                                                              
gitlab                  False           False   Helm upgrade failed: error while running post render on files: map[string]interface {}(nil): yaml: unmarshal errors:
                                                  line 20: mapping key "nginx.ingress.kubernetes.io/proxy-body-size" already defined at line 17

Expected behavior

No duplicate entry for the annotation nginx.ingress.kubernetes.io/proxy-body-size appears and the GitLab HelmRelease with Flux enters a Ready state.

Versions

  • Chart: 7.4.0
  • Platform: Rancher RKE2
  • Kubernetes: (kubectl version)
    • Client: v1.25.12
    • Server: v1.25.12+rke2r1
  • Flux: 2.1.1
  • Helm: v3.13.0-rc.1

fluxcd/helm-controller#283 (GitHub)