From e29dd96a7ab5de7e6ee24f2062131aaa6618823a Mon Sep 17 00:00:00 2001 From: Dundy Pasupuleti Date: Tue, 1 Sep 2026 20:22:30 +0000 Subject: [PATCH 1/3] Add configurable securityContext and dnsConfig for the operator Deployment 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/gpu-operator#2533 Signed-off-by: Dundy Pasupuleti --- .../gpu-operator/templates/operator.yaml | 18 ++++++++++++++++++ deployments/gpu-operator/values.yaml | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/deployments/gpu-operator/templates/operator.yaml b/deployments/gpu-operator/templates/operator.yaml index 484f83e088..54117f997f 100644 --- a/deployments/gpu-operator/templates/operator.yaml +++ b/deployments/gpu-operator/templates/operator.yaml @@ -33,6 +33,14 @@ spec: {{- if .Values.operator.priorityClassName }} priorityClassName: {{ .Values.operator.priorityClassName }} {{- end }} + {{- with .Values.operator.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.operator.dnsConfig }} + dnsConfig: + {{- toYaml .Values.operator.dnsConfig | nindent 8 }} + {{- end }} containers: - name: gpu-operator image: {{ include "gpu-operator.fullimage" . }} @@ -80,9 +88,19 @@ spec: resources: {{- toYaml . | nindent 10 }} {{- end }} + {{- with .Values.operator.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp ports: - name: metrics containerPort: 8080 + volumes: + - name: tmp + emptyDir: {} {{- with .Values.operator.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/deployments/gpu-operator/values.yaml b/deployments/gpu-operator/values.yaml index 45947b26cc..1810e2b6dd 100644 --- a/deployments/gpu-operator/values.yaml +++ b/deployments/gpu-operator/values.yaml @@ -118,6 +118,23 @@ operator: requests: cpu: 200m memory: 100Mi + # Restricted defaults for the operator Deployment (not operand DaemonSets). + # UID/GID 1000 matches the operator image USER. + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + containerSecurityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + # Optional pod dnsConfig (nameservers, searches, options). + # dnsConfig: {} # metrics: # serviceMonitor: # interval: 15s From 0849d044b8b472eee5dd9e402751e19882c12c8c Mon Sep 17 00:00:00 2001 From: Dundy Pasupuleti Date: Tue, 1 Sep 2026 20:27:01 +0000 Subject: [PATCH 2/3] Avoid pinning operator UID so OpenShift SCC can allocate 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 --- deployments/gpu-operator/values.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deployments/gpu-operator/values.yaml b/deployments/gpu-operator/values.yaml index 1810e2b6dd..3aa0f02db1 100644 --- a/deployments/gpu-operator/values.yaml +++ b/deployments/gpu-operator/values.yaml @@ -119,12 +119,11 @@ operator: cpu: 200m memory: 100Mi # Restricted defaults for the operator Deployment (not operand DaemonSets). - # UID/GID 1000 matches the operator image USER. + # Do not pin runAsUser/runAsGroup/fsGroup: the image already uses USER 1000:1000 + # on vanilla Kubernetes, and a hardcoded UID fails OpenShift namespaces whose + # allocated range does not include 1000 (restricted-readonly SCC is MustRunAsRange). securityContext: runAsNonRoot: true - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 seccompProfile: type: RuntimeDefault containerSecurityContext: From 0046331ebc24a1acc89760026bfca5e2599400bb Mon Sep 17 00:00:00 2001 From: Dundy Pasupuleti Date: Tue, 1 Sep 2026 20:33:55 +0000 Subject: [PATCH 3/3] Apply restricted securityContext to operator hook Jobs 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 --- .../gpu-operator/templates/cleanup_crd.yaml | 21 +++++++++++++++++++ .../templates/cleanup_gpucluster.yaml | 21 +++++++++++++++++++ .../gpu-operator/templates/operator.yaml | 7 +++++-- .../gpu-operator/templates/upgrade_crd.yaml | 21 +++++++++++++++++++ deployments/gpu-operator/values.yaml | 5 +++-- 5 files changed, 71 insertions(+), 4 deletions(-) diff --git a/deployments/gpu-operator/templates/cleanup_crd.yaml b/deployments/gpu-operator/templates/cleanup_crd.yaml index 07dac810c6..50fc3fd236 100644 --- a/deployments/gpu-operator/templates/cleanup_crd.yaml +++ b/deployments/gpu-operator/templates/cleanup_crd.yaml @@ -32,10 +32,28 @@ spec: {{- end }} nodeSelector: {{- toYaml .Values.operator.nodeSelector | nindent 8 }} + {{- with .Values.operator.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.operator.dnsPolicy }} + dnsPolicy: {{ .Values.operator.dnsPolicy }} + {{- end }} + {{- with .Values.operator.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: cleanup-crd image: {{ include "gpu-operator.fullimage" . }} imagePullPolicy: {{ .Values.operator.imagePullPolicy }} + {{- with .Values.operator.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp command: - /usr/bin/manage-crds args: @@ -46,5 +64,8 @@ spec: {{- if .Values.nfd.enabled }} - --filepath=/opt/gpu-operator/nfd-api-crds.yaml {{- end }} + volumes: + - name: tmp + emptyDir: {} restartPolicy: OnFailure {{- end }} diff --git a/deployments/gpu-operator/templates/cleanup_gpucluster.yaml b/deployments/gpu-operator/templates/cleanup_gpucluster.yaml index f5d0d83744..eee2e852ff 100644 --- a/deployments/gpu-operator/templates/cleanup_gpucluster.yaml +++ b/deployments/gpu-operator/templates/cleanup_gpucluster.yaml @@ -37,12 +37,33 @@ spec: {{- end }} nodeSelector: {{- toYaml .Values.operator.nodeSelector | nindent 8 }} + {{- with .Values.operator.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.operator.dnsPolicy }} + dnsPolicy: {{ .Values.operator.dnsPolicy }} + {{- end }} + {{- with .Values.operator.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: cleanup-gpucluster image: {{ include "gpu-operator.fullimage" . }} imagePullPolicy: {{ .Values.operator.imagePullPolicy }} + {{- with .Values.operator.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp command: - /usr/bin/cleanup-gpuclusters - --gpucluster-name - {{ include "gpu-operator.gpucluster-name" . }} + volumes: + - name: tmp + emptyDir: {} restartPolicy: OnFailure diff --git a/deployments/gpu-operator/templates/operator.yaml b/deployments/gpu-operator/templates/operator.yaml index 54117f997f..1b173adc53 100644 --- a/deployments/gpu-operator/templates/operator.yaml +++ b/deployments/gpu-operator/templates/operator.yaml @@ -37,9 +37,12 @@ spec: securityContext: {{- toYaml . | nindent 8 }} {{- end }} - {{- if .Values.operator.dnsConfig }} + {{- if .Values.operator.dnsPolicy }} + dnsPolicy: {{ .Values.operator.dnsPolicy }} + {{- end }} + {{- with .Values.operator.dnsConfig }} dnsConfig: - {{- toYaml .Values.operator.dnsConfig | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} containers: - name: gpu-operator diff --git a/deployments/gpu-operator/templates/upgrade_crd.yaml b/deployments/gpu-operator/templates/upgrade_crd.yaml index bbf718f999..3c4447e1c5 100644 --- a/deployments/gpu-operator/templates/upgrade_crd.yaml +++ b/deployments/gpu-operator/templates/upgrade_crd.yaml @@ -81,10 +81,28 @@ spec: {{- end }} nodeSelector: {{- toYaml .Values.operator.nodeSelector | nindent 8 }} + {{- with .Values.operator.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.operator.dnsPolicy }} + dnsPolicy: {{ .Values.operator.dnsPolicy }} + {{- end }} + {{- with .Values.operator.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: upgrade-crd image: {{ include "gpu-operator.fullimage" . }} imagePullPolicy: {{ .Values.operator.imagePullPolicy }} + {{- with .Values.operator.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp command: - /usr/bin/manage-crds args: @@ -95,5 +113,8 @@ spec: {{- if .Values.nfd.enabled }} - --filepath=/opt/gpu-operator/nfd-api-crds.yaml {{- end }} + volumes: + - name: tmp + emptyDir: {} restartPolicy: OnFailure {{- end }} diff --git a/deployments/gpu-operator/values.yaml b/deployments/gpu-operator/values.yaml index 3aa0f02db1..99c20df95c 100644 --- a/deployments/gpu-operator/values.yaml +++ b/deployments/gpu-operator/values.yaml @@ -132,8 +132,9 @@ operator: capabilities: drop: - ALL - # Optional pod dnsConfig (nameservers, searches, options). - # dnsConfig: {} + # Empty dnsPolicy keeps the cluster default (ClusterFirst). + dnsPolicy: "" + dnsConfig: {} # metrics: # serviceMonitor: # interval: 15s