Skip to content

Commit 2145dc8

Browse files
committed
fix(collector): default fsGroup when volumeClaimTemplates are present
Collectors using persistent storage via volumeClaimTemplates can fail with "permission denied" on PVC mounts when running as a non-root user without fsGroup set. The mutating webhook now defaults podSecurityContext.fsGroup to 65532 (the upstream collector image's nonroot UID) when VCTs are present and no fsGroup is configured. An explicitly set fsGroup is never overwritten.
1 parent 0bb8a0e commit 2145dc8

3 files changed

Lines changed: 124 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: bug_fix
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
5+
component: collector
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Collectors using persistent storage no longer fail with "permission denied" on volume mounts when running as a non-root user.
9+
10+
# One or more tracking issues related to the change
11+
issues: [5836]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext: |
17+
The mutating webhook now defaults podSecurityContext.fsGroup to 65532 when
18+
volumeClaimTemplates are present and no fsGroup is set. This ensures kubelet
19+
chowns the PVC mount so the collector process can write to it. An explicitly
20+
set fsGroup is never overwritten.

internal/webhook/collector_webhook.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111

1212
"github.com/go-logr/logr"
13+
corev1 "k8s.io/api/core/v1"
1314
autoscalingv2 "k8s.io/api/autoscaling/v2"
1415
"k8s.io/apimachinery/pkg/runtime"
1516
"k8s.io/apimachinery/pkg/util/validation"
@@ -97,6 +98,16 @@ func (c CollectorWebhook) Default(_ context.Context, otelcol *v1beta1.OpenTeleme
9798
if len(otelcol.Spec.ManagementState) == 0 {
9899
otelcol.Spec.ManagementState = v1beta1.ManagementStateManaged
99100
}
101+
if len(otelcol.Spec.VolumeClaimTemplates) > 0 {
102+
if otelcol.Spec.PodSecurityContext == nil {
103+
otelcol.Spec.PodSecurityContext = &corev1.PodSecurityContext{}
104+
}
105+
if otelcol.Spec.PodSecurityContext.FSGroup == nil {
106+
defaultFSGroup := int64(65532)
107+
otelcol.Spec.PodSecurityContext.FSGroup = &defaultFSGroup
108+
}
109+
}
110+
100111
if featuregate.EnableOperandNetworkPolicy.IsEnabled() && otelcol.Spec.NetworkPolicy.Enabled == nil {
101112
trueVal := true
102113
otelcol.Spec.NetworkPolicy.Enabled = &trueVal

internal/webhook/collector_webhook_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,99 @@ func TestCollectorDefaultingWebhook(t *testing.T) {
512512
},
513513
},
514514
},
515+
{
516+
name: "StatefulSet with volumeClaimTemplates gets default fsGroup",
517+
otelcol: v1beta1.OpenTelemetryCollector{
518+
Spec: v1beta1.OpenTelemetryCollectorSpec{
519+
Mode: v1beta1.ModeStatefulSet,
520+
StatefulSetCommonFields: v1beta1.StatefulSetCommonFields{
521+
VolumeClaimTemplates: []v1.PersistentVolumeClaim{
522+
{
523+
ObjectMeta: metav1.ObjectMeta{Name: "storage"},
524+
Spec: v1.PersistentVolumeClaimSpec{
525+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
526+
},
527+
},
528+
},
529+
},
530+
},
531+
},
532+
expected: v1beta1.OpenTelemetryCollector{
533+
ObjectMeta: metav1.ObjectMeta{
534+
Labels: map[string]string{},
535+
},
536+
Spec: v1beta1.OpenTelemetryCollectorSpec{
537+
Mode: v1beta1.ModeStatefulSet,
538+
UpgradeStrategy: v1beta1.UpgradeStrategyAutomatic,
539+
OpenTelemetryCommonFields: v1beta1.OpenTelemetryCommonFields{
540+
Replicas: &one,
541+
ManagementState: v1beta1.ManagementStateManaged,
542+
PodSecurityContext: &v1.PodSecurityContext{
543+
FSGroup: ptr.To(int64(65532)),
544+
},
545+
},
546+
StatefulSetCommonFields: v1beta1.StatefulSetCommonFields{
547+
VolumeClaimTemplates: []v1.PersistentVolumeClaim{
548+
{
549+
ObjectMeta: metav1.ObjectMeta{Name: "storage"},
550+
Spec: v1.PersistentVolumeClaimSpec{
551+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
552+
},
553+
},
554+
},
555+
},
556+
},
557+
},
558+
},
559+
{
560+
name: "StatefulSet with volumeClaimTemplates preserves explicit fsGroup",
561+
otelcol: v1beta1.OpenTelemetryCollector{
562+
Spec: v1beta1.OpenTelemetryCollectorSpec{
563+
Mode: v1beta1.ModeStatefulSet,
564+
OpenTelemetryCommonFields: v1beta1.OpenTelemetryCommonFields{
565+
PodSecurityContext: &v1.PodSecurityContext{
566+
FSGroup: ptr.To(int64(1000)),
567+
},
568+
},
569+
StatefulSetCommonFields: v1beta1.StatefulSetCommonFields{
570+
VolumeClaimTemplates: []v1.PersistentVolumeClaim{
571+
{
572+
ObjectMeta: metav1.ObjectMeta{Name: "storage"},
573+
Spec: v1.PersistentVolumeClaimSpec{
574+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
575+
},
576+
},
577+
},
578+
},
579+
},
580+
},
581+
expected: v1beta1.OpenTelemetryCollector{
582+
ObjectMeta: metav1.ObjectMeta{
583+
Labels: map[string]string{},
584+
},
585+
Spec: v1beta1.OpenTelemetryCollectorSpec{
586+
Mode: v1beta1.ModeStatefulSet,
587+
UpgradeStrategy: v1beta1.UpgradeStrategyAutomatic,
588+
OpenTelemetryCommonFields: v1beta1.OpenTelemetryCommonFields{
589+
Replicas: &one,
590+
ManagementState: v1beta1.ManagementStateManaged,
591+
PodSecurityContext: &v1.PodSecurityContext{
592+
FSGroup: ptr.To(int64(1000)),
593+
},
594+
},
595+
StatefulSetCommonFields: v1beta1.StatefulSetCommonFields{
596+
VolumeClaimTemplates: []v1.PersistentVolumeClaim{
597+
{
598+
ObjectMeta: metav1.ObjectMeta{Name: "storage"},
599+
Spec: v1.PersistentVolumeClaimSpec{
600+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
601+
},
602+
},
603+
},
604+
},
605+
},
606+
},
607+
},
515608
}
516609

517610
bv := func(_ context.Context, collector v1beta1.OpenTelemetryCollector) admission.Warnings {

0 commit comments

Comments
 (0)