Skip to content

fix(collector): default fsGroup when volumeClaimTemplates are present#5106

Closed
ozzywalsh wants to merge 4 commits into
open-telemetry:mainfrom
ozzywalsh:fix/fsgroup-default-vct
Closed

fix(collector): default fsGroup when volumeClaimTemplates are present#5106
ozzywalsh wants to merge 4 commits into
open-telemetry:mainfrom
ozzywalsh:fix/fsgroup-default-vct

Conversation

@ozzywalsh

Copy link
Copy Markdown
Contributor

Summary

  • Collectors using persistent storage (volumeClaimTemplates) fail with permission denied on PVC mounts when running as a non-root user without fsGroup set in podSecurityContext
  • The mutating webhook now defaults podSecurityContext.fsGroup to 65532 when VCTs are present and no fsGroup is configured
  • An explicitly set fsGroup is never overwritten

Test plan

  • Unit test: TestCollectorDefaultingWebhook/StatefulSet_with_volumeClaimTemplates_gets_default_fsGroup — verifies webhook injects fsGroup: 65532
  • Unit test: TestCollectorDefaultingWebhook/StatefulSet_with_volumeClaimTemplates_preserves_explicit_fsGroup — verifies user-set value is not overwritten
  • Manual CRC verification: deployed fixed operator to OpenShift CRC, created StatefulSet collector with VCTs + file_storage sending queue + anyuid SCC — no fsGroup in CR. Webhook injected fsGroup: 65532, pod started successfully with no permission errors. Same config without the fix crashes with open /var/otelcol/storage/exporter_otlp_blackhole_traces: permission denied

@ozzywalsh ozzywalsh marked this pull request as ready for review May 20, 2026 19:52
@ozzywalsh ozzywalsh requested a review from a team as a code owner May 20, 2026 19:52
@swiatekm

Copy link
Copy Markdown
Contributor

Is there any reasoning behind picking 65532 for the GID?

@iblancasa

iblancasa commented May 21, 2026

Copy link
Copy Markdown
Member

Is there any reasoning behind picking 65532 for the GID?

I think there is a convention for distroless container images to do that for non-root users.

@swiatekm

Copy link
Copy Markdown
Contributor

If we want to make the pvcs writable by default, then we should probably add an e2e test that verifies this.

@frzifus frzifus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen when I mount a volume to persist my sending queue with the current version fsgroup: 0 and run an operator upgrade and the default fsgroup will change?

Shouldnt the collector in that case have permission issues?

@@ -1,16 +1,20 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement
change_type: bug_fix

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if that should be marked as breaking. Depending on the current configuration.

Please add some e2e tests.

ozzywalsh added 2 commits May 28, 2026 11:13
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.
@ozzywalsh ozzywalsh force-pushed the fix/fsgroup-default-vct branch from 79a2946 to f67d6dc Compare May 28, 2026 10:18
@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

 38 files  271 suites   2h 22m 23s ⏱️
115 tests 114 ✅ 1 💤 0 ❌
293 runs  291 ✅ 2 💤 0 ❌

Results for commit bc372e4.

♻️ This comment has been updated with latest results.

@ozzywalsh

ozzywalsh commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

@frzifus @swiatekm
How would we like to e2e test this?

I can for example add an assertion to this e2e test to check the produced StatefulSet has the podSecurityContext.fsGroup set. Although that doesn't offer much over what's already in the webhook test.

A test that actually attempts to write to the container would be nice. But I'm not sure if that's feasible on kind. From my investigation; it seems like kinds storage provisioner doesn't replicate the same permissions one would see in a production environment. See below for example. I'm open to correction if this is wrong.

# Deploy on kind against main branch (no fsGroup fix).
# The initContainer runs as the same user as the collector (65532)
# and tries to write to the PVC. On kind's hostpath provisioner
# (0777 volumes) this will succeed — proving that kind masks the
# real-world bug and an e2e write test is not viable in CI.
#
# On production storage (NFS, Ceph, etc.) with root:root 0755
# volumes, the same manifest would fail without fsGroup.
#
# Usage:
#   kubectl apply -f hack/test-fsgroup-kind.yaml
#   kubectl get pods -n fsgroup-test -w
#
apiVersion: v1
kind: Namespace
metadata:
  name: fsgroup-test
---
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: fsgroup-test
  namespace: fsgroup-test
spec:
  mode: statefulset
  replicas: 1
  initContainers:
    - name: write-test
      image: mirror.gcr.io/library/busybox:latest
      securityContext:
        runAsUser: 65532
        runAsGroup: 65532
      command:
        - sh
        - -c
        - |
          ls -la /data
          echo "testing write as $(id)" &&
          touch /data/write-test &&
          echo "SUCCESS: write to PVC succeeded (kind masks the bug)" &&
          rm -f /data/write-test
      volumeMounts:
        - name: storage
          mountPath: /data
  volumeMounts:
    - name: storage
      mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: storage
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 64Mi
  config:
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
    exporters:
      debug: {}
    service:
      pipelines:
        traces:
          receivers: [otlp]
          exporters: [debug]
$ kubectl -n fsgroup-test logs statefulsets/fsgroup-test-collector -c write-test 
total 0
drwxrwxrwx    1 root     root             0 May 28 12:41 .
drwxr-xr-x    1 root     root            82 May 28 12:55 ..
testing write as uid=65532 gid=65532 groups=65532
SUCCESS: write to PVC succeeded (kind masks the bug)                                                                                                                                             

@swiatekm

Copy link
Copy Markdown
Contributor

I'm really not sure we should be doing this. Largely, it should be on the user to ensure their volumes have the right permissions. Maybe there's a point in favor of making this work out of the box for the default collector image we ship, but even then I'd find this default surprising. That it's a breaking change is another argument against.

Thoughts @open-telemetry/operator-approvers ?

ozzywalsh added a commit to ozzywalsh/opentelemetry-operator that referenced this pull request Jun 18, 2026
On OpenShift, the restricted SCC injects fsGroup from the namespace
range, but permissive SCCs (e.g. anyuid) do not. When a user grants
privileges to the collector ServiceAccount, the effective SCC changes
and PVC volumes become inaccessible due to missing group ownership.

The controller now defaults podSecurityContext.fsGroup from the
namespace's supplemental-groups annotation (falling back to uid-range)
when running on OpenShift and no explicit fsGroup is configured. This
follows the same pattern used by migtools/crane and istio/istio.

An explicitly set fsGroup is never overwritten.

Closes open-telemetry#5106
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants