Summary
When creating a cluster.redpanda.com/v1alpha2 Redpanda resource and setting spec.clusterSpec.statefulset.extraVolumes plus spec.clusterSpec.statefulset.extraVolumeMounts, the extra volume is added to the generated StatefulSet, and the extra volumeMount is added to the sidecar container, but not to the main redpanda container.
Based on the conversion code, statefulset.extraVolumeMounts appears intended to apply to both containers.
Version
Observed with:
- Redpanda Operator:
v26.1.2
- Redpanda image:
v26.1.4
Reproduction
Apply a Redpanda CR like this:
apiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: redpanda
spec:
clusterSpec:
statefulset:
extraVolumes: |-
- name: redpanda-io-config
configMap:
name: redpanda-io-config
extraVolumeMounts: |-
- name: redpanda-io-config
subPath: io-config.yaml
mountPath: /etc/redpanda-io-config/io-config.yaml
additionalRedpandaCmdFlags:
- "--io-properties-file=/etc/redpanda-io-config/io-config.yaml"
Expected behavior
The generated StatefulSet should contain:
- the extra
volume in .spec.template.spec.volumes
- the extra
volumeMount in both:
.spec.template.spec.containers[name=redpanda].volumeMounts
.spec.template.spec.containers[name=sidecar].volumeMounts
Actual behavior
In the generated StatefulSet:
- the extra
volume is present
- the extra
volumeMount is present only in the sidecar container
- the extra
volumeMount is missing from the redpanda container
Relevant excerpt from the generated StatefulSet:
spec:
template:
spec:
containers:
- name: redpanda
volumeMounts:
- mountPath: /etc/redpanda
name: config
- mountPath: /tmp/base-config
name: base-config
- mountPath: /var/lifecycle
name: lifecycle-scripts
- mountPath: /var/lib/redpanda/data
name: datadir
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access
readOnly: true
- name: sidecar
volumeMounts:
- mountPath: /etc/redpanda
name: config
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access
readOnly: true
- mountPath: /etc/redpanda-io-config/io-config.yaml
name: redpanda-io-config
subPath: io-config.yaml
volumes:
- name: redpanda-io-config
configMap:
name: redpanda-io-config
Suspected cause
This looks like a bug in pod template merge logic rather than in CR conversion.
statefulset.extraVolumeMounts is first converted into statefulset.podTemplate.spec.containers[*].volumeMounts, but later the chart's strategic merge logic merges VolumeMounts by name:
func mergeContainer(original corev1.Container, override applycorev1.ContainerApplyConfiguration) corev1.Container {
merged := helmette.MergeTo[corev1.Container](override, original)
merged.Env = mergeSliceBy(original.Env, override.Env, "name", mergeEnvVar)
merged.VolumeMounts = mergeSliceBy(original.VolumeMounts, override.VolumeMounts, "name", mergeVolumeMount)
return merged
}
For VolumeMount, name is not a safe merge key because the same volume can legitimately be mounted multiple times with different mountPath/subPath. Using mountPath as the merge key seems more correct and closer to Kubernetes strategic merge behavior.
Suggested change:
func mergeContainer(original corev1.Container, override applycorev1.ContainerApplyConfiguration) corev1.Container {
merged := helmette.MergeTo[corev1.Container](override, original)
merged.Env = mergeSliceBy(original.Env, override.Env, "name", mergeEnvVar)
merged.VolumeMounts = mergeSliceBy(original.VolumeMounts, override.VolumeMounts, "mountPath", mergeVolumeMount)
return merged
}
Summary
When creating a
cluster.redpanda.com/v1alpha2Redpandaresource and settingspec.clusterSpec.statefulset.extraVolumesplusspec.clusterSpec.statefulset.extraVolumeMounts, the extravolumeis added to the generated StatefulSet, and the extravolumeMountis added to thesidecarcontainer, but not to the mainredpandacontainer.Based on the conversion code,
statefulset.extraVolumeMountsappears intended to apply to both containers.Version
Observed with:
v26.1.2v26.1.4Reproduction
Apply a
RedpandaCR like this:Expected behavior
The generated StatefulSet should contain:
volumein.spec.template.spec.volumesvolumeMountin both:.spec.template.spec.containers[name=redpanda].volumeMounts.spec.template.spec.containers[name=sidecar].volumeMountsActual behavior
In the generated StatefulSet:
volumeis presentvolumeMountis present only in thesidecarcontainervolumeMountis missing from theredpandacontainerRelevant excerpt from the generated StatefulSet:
Suspected cause
This looks like a bug in pod template merge logic rather than in CR conversion.
statefulset.extraVolumeMountsis first converted intostatefulset.podTemplate.spec.containers[*].volumeMounts, but later the chart's strategic merge logic mergesVolumeMountsbyname:For
VolumeMount,nameis not a safe merge key because the same volume can legitimately be mounted multiple times with differentmountPath/subPath. UsingmountPathas the merge key seems more correct and closer to Kubernetes strategic merge behavior.Suggested change: