Skip to content

Add configurable securityContext and dnsConfig for the operator Deployment - #2843

Open
dundysm wants to merge 4 commits into
NVIDIA:mainfrom
dundysm:fix/operator-securitycontext
Open

Add configurable securityContext and dnsConfig for the operator Deployment#2843
dundysm wants to merge 4 commits into
NVIDIA:mainfrom
dundysm:fix/operator-securitycontext

Conversation

@dundysm

@dundysm dundysm commented Sep 1, 2026

Copy link
Copy Markdown

Description

The gpu-operator Deployment currently has no pod or container securityContext, so it runs with the cluster default (often unrestricted). This PR makes securityContext, containerSecurityContext, dnsConfig, and dnsPolicy configurable through Helm values and sets restricted defaults that still work on vanilla Kubernetes and OpenShift.

This also covers the Helm hook Jobs that run the same operator image (upgrade-crd, cleanup-crd, cleanup-gpucluster). Those were previously empty like the Deployment.

Not in this PR: operand DaemonSets (driver, device plugin, toolkit, MIG, and so on). Those are created later by the operator, not by this chart, and they need host privileges. ClusterPolicy already has spec.daemonsets.podSecurityContext for that path.

Defaults:

  • pod: runAsNonRoot: true, seccompProfile: RuntimeDefault
  • container: allowPrivilegeEscalation: false, readOnlyRootFilesystem: true, capabilities.drop: [ALL]
  • dnsPolicy: "" (cluster default ClusterFirst) and dnsConfig: {}

No writable /tmp is added. The Deployment is already annotated with openshift.io/scc: restricted-readonly, and that SCC sets readOnlyRootFilesystem: true, so it has been running read-only on OpenShift without one. Neither manage-crds nor cleanup-gpuclusters creates temporary files.

UID/GID/fsGroup are not pinned. The operator image already uses USER 1000:1000, so vanilla Kubernetes still runs non-root. OpenShift restricted-readonly SCC uses MustRunAsRange; a hardcoded UID fails namespaces whose allocated range does not include that ID. Pin a UID with operator.securityContext.runAsUser if you need one.

Fixes #2533

Checklist

  • No secrets, sensitive information, or unrelated changes
  • Lint checks passing (make lint)
  • Generated assets in-sync (make validate-generated-assets)
  • Go mod artifacts in-sync (make validate-modules)
  • Test cases are added for new code paths

Testing

Helm-only change (no Go, CRD, or generated-asset edits). Ran against this branch:

  • helm lint deployments/gpu-operator/ — pass (only pre-existing warning: chart version v1.0.0-devel is not SemVerV2)
  • helm template with chart defaults — operator Deployment gets the restricted pod/container securityContext; dnsPolicy/dnsConfig are omitted. Hook Jobs checked with operator.cleanupCRD=true since cleanupCRD defaults to false
  • helm template with operator.dnsPolicy=None and operator.dnsConfig.nameservers=[8.8.8.8] — both render on the Deployment and hook Jobs
  • helm template with operator.securityContext=null and operator.containerSecurityContext=null — those fields are omitted
  • helm template with operator.securityContext.runAsUser=1000 — explicit UID still overrides
  • Confirmed docker/Dockerfile ends with USER 1000:1000
  • After removing the /tmp emptyDir in faf30f8, diffed the full rendered output against the previous commit — the only change is the removed volumeMounts/volumes blocks on the four workloads; document count and everything else are identical

Did not apply this to a live GPU cluster. make lint / generated-assets / modules are unchanged because this PR does not touch Go code or generated files.

@copy-pr-bot

copy-pr-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

…yment

The gpu-operator Deployment currently leaves pod and container
securityContext empty. Default to a restricted profile matching the
image USER 1000, mount an emptyDir at /tmp for a read-only root
filesystem, and allow dnsConfig via values.

Fixes NVIDIA#2533

Signed-off-by: Dundy Pasupuleti <pasupuletidundy@gmail.com>
@dundysm
dundysm force-pushed the fix/operator-securitycontext branch from 8509025 to e29dd96 Compare September 1, 2026 20:22
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 483e0b09-0820-43b2-a5a3-4a45edc6f774

📥 Commits

Reviewing files that changed from the base of the PR and between 0046331 and faf30f8.

📒 Files selected for processing (4)
  • deployments/gpu-operator/templates/cleanup_crd.yaml
  • deployments/gpu-operator/templates/cleanup_gpucluster.yaml
  • deployments/gpu-operator/templates/operator.yaml
  • deployments/gpu-operator/templates/upgrade_crd.yaml
💤 Files with no reviewable changes (4)
  • deployments/gpu-operator/templates/cleanup_gpucluster.yaml
  • deployments/gpu-operator/templates/upgrade_crd.yaml
  • deployments/gpu-operator/templates/operator.yaml
  • deployments/gpu-operator/templates/cleanup_crd.yaml

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

The Helm chart adds restricted security defaults for GPU Operator workloads. The operator Deployment and hook Job templates conditionally apply pod-level and container-level security settings. The templates also support optional DNS policy and DNS configuration.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to faf30

The new DNS configuration may not be consistently configurable through chart values, which could leave deployments unable to apply the intended DNS settings. Resolve the values-to-template contract before merge.


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
deployments/gpu-operator/templates/operator.yaml-40-43 (1)

40-43: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Keep the dnsConfig key and template reference in sync.

This branch reads .Values.operator.dnsConfig, but deployments/gpu-operator/values.yaml contains only the commented # dnsConfig: {}. Add an active dnsConfig: {} entry in values.yaml, or remove this branch, so the supported chart values match the template.

As per path instructions, a template reference must have a matching values.yaml key.

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: b7992171-3df3-4684-ba35-243b9ab70b8c

📥 Commits

Reviewing files that changed from the base of the PR and between 4682676 and 8509025.

📒 Files selected for processing (2)
  • deployments/gpu-operator/templates/operator.yaml
  • deployments/gpu-operator/values.yaml

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment thread deployments/gpu-operator/values.yaml Outdated
Dundy Pasupuleti added 2 commits September 1, 2026 20:27
restricted-readonly uses MustRunAsRange. A hardcoded UID 1000
fails namespaces whose allocated range does not include 1000.
The image USER 1000:1000 still applies on vanilla Kubernetes.

Signed-off-by: Dundy Pasupuleti <pasupuletidundy@gmail.com>
Add discoverable dnsPolicy and dnsConfig values keys, and make dnsPolicy
configurable so ClusterFirst remains the default. Apply the same restricted
pod and container securityContext used by the operator Deployment to the
Helm hook Jobs that run the operator image.

Operand DaemonSets are unchanged; they still need host privileges.

Signed-off-by: Dundy Pasupuleti <pasupuletidundy@gmail.com>
@dundysm

dundysm commented Sep 1, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@dundysm

dundysm commented Sep 1, 2026

Copy link
Copy Markdown
Author

@rajathagasthya picking this up from #2533, including dnsConfig as you asked there.

Restricted defaults for the operator Deployment and the Helm hook Jobs that run the same image. No pinned UID, so OpenShift MustRunAsRange can still allocate. dnsPolicy / dnsConfig are configurable (dnsPolicy stays empty so ClusterFirst remains the default). Operand DaemonSets are unchanged; they still need host privileges.

This is my first PR here, so copy-pr-bot is blocking CI. If the approach looks right, would you mind an /ok-to-test?

@rajathagasthya

Copy link
Copy Markdown
Contributor

Thanks @dundysm! Will take a look at this PR soon.

@rajathagasthya

Copy link
Copy Markdown
Contributor

/ok-to-test 0046331

@rajathagasthya

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rahulait rahulait left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall, LGTM

@rahulait rahulait self-assigned this Sep 9, 2026
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: tmp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why is this needed?

@dundysm dundysm Sep 9, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

you're right, dropping it. i'd added it as insurance for readOnlyRootFilesystem: true, but checking properly: the operator Deployment is already annotated with openshift.io/scc: restricted-readonly (values.yaml), and that SCC sets readOnlyRootFilesystem: true, so it has been running with a read-only root filesystem on OpenShift without a writable /tmp.

manage-crds and cleanup-gpuclusters only read manifests from /opt/gpu-operator and apply them through the API server, no temp writes in either cmd or in crdutil.

removed the emptyDir and the mounts from all four templates in faf30f8. readOnlyRootFilesystem: true stays on the container securityContext.

- name: cleanup-crd
image: {{ include "gpu-operator.fullimage" . }}
imagePullPolicy: {{ .Values.operator.imagePullPolicy }}
{{- with .Values.operator.containerSecurityContext }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is a containerSecurityContext really needed? Shouldn't the pod Security Context suffice? I am not sure what the advantages are with being able to customise the container-level security context.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

on whether it's needed: allowPrivilegeEscalation, readOnlyRootFilesystem, and capabilities exist only on v1.SecurityContext; they aren't fields on v1.PodSecurityContext, so pod-level can't express them at any version. pss restricted requires the first two per-container, so the pod block alone can't get us admitted into a restricted namespace. pod-level here carries only runAsNonRoot and seccompProfile, which do accept pod-level.

on customisability: that's a fair challenge. i exposed it because helm create convention splits pod vs container securityContext, and because relaxing readOnlyRootFilesystem or adding back a capability is the kind of thing a downstream consumer hits on odd runtimes.

but, i take the point that clusterpolicy.spec.daemonsets only exposes podSecurityContext, so a container-level knob is new surface for this project. happy to hardcode the three restricted values and drop operator.containerSecurityContext from values.yaml if you'd prefer less api surface, the fields still have to live at container level either way.

The emptyDir was added as insurance for readOnlyRootFilesystem, but it is
not needed. The operator Deployment is already annotated with
openshift.io/scc: restricted-readonly, and that SCC sets
readOnlyRootFilesystem: true, so the Deployment has run with a read-only
root filesystem on OpenShift without a writable /tmp.

manage-crds and cleanup-gpuclusters read manifests from /opt/gpu-operator
and apply them through the API server; neither they nor crdutil create
temporary files.

The container securityContext still sets readOnlyRootFilesystem to true.

Signed-off-by: Dundy <dundysm@gmail.com>
@dundysm
dundysm force-pushed the fix/operator-securitycontext branch from 9395f3a to faf30f8 Compare September 9, 2026 13:50
@dundysm

dundysm commented Sep 9, 2026

Copy link
Copy Markdown
Author

@coderabbitai review the updates

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

@dundysm I will review the updates.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

[Feature]: Provide good securityContext by default

4 participants