diff --git a/api/v1/slurmcluster_types.go b/api/v1/slurmcluster_types.go index 5091e60d3..a93a864af 100644 --- a/api/v1/slurmcluster_types.go +++ b/api/v1/slurmcluster_types.go @@ -549,6 +549,11 @@ type PopulateJail struct { // +kubebuilder:default="IfNotPresent" ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // ImagePullSecrets is a list of secret names in the same namespace used for pulling the container's image. + // + // +kubebuilder:validation:Optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // K8sNodeFilterName defines the Kubernetes node filter name associated with the Slurm node. // Must correspond to the name of one of [K8sNodeFilter] // @@ -1233,6 +1238,11 @@ type NodeContainer struct { // +kubebuilder:default="IfNotPresent" ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // ImagePullSecrets is a list of secret names in the same namespace used for pulling the container's image. + // + // +kubebuilder:validation:Optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // Port defines the port the container exposes // // +kubebuilder:validation:Optional diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 5f9409555..23c3dc154 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -300,6 +300,11 @@ func (in *NodeContainer) DeepCopyInto(out *NodeContainer) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]corev1.LocalObjectReference, len(*in)) + copy(*out, *in) + } if in.Resources != nil { in, out := &in.Resources, &out.Resources *out = make(corev1.ResourceList, len(*in)) @@ -636,6 +641,11 @@ func (in *PodMonitorConfig) DeepCopy() *PodMonitorConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PopulateJail) DeepCopyInto(out *PopulateJail) { *out = *in + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]corev1.LocalObjectReference, len(*in)) + copy(*out, *in) + } if in.JailSnapshotVolume != nil { in, out := &in.JailSnapshotVolume, &out.JailSnapshotVolume *out = new(NodeVolume) diff --git a/api/v1alpha1/activecheck_types.go b/api/v1alpha1/activecheck_types.go index 977b85c72..ca9fd03c0 100644 --- a/api/v1alpha1/activecheck_types.go +++ b/api/v1alpha1/activecheck_types.go @@ -142,6 +142,18 @@ type ContainerSpec struct { // +kubebuilder:validation:Optional // +kubebuilder:default="unconfined" AppArmorProfile string `json:"appArmorProfile,omitempty"` + + // ImagePullPolicy defines the image pull policy + // + // +kubebuilder:validation:Enum=Always;Never;IfNotPresent + // +kubebuilder:validation:Optional + // +kubebuilder:default="IfNotPresent" + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + + // ImagePullSecrets is a list of secret names in the same namespace used for pulling the container's image. + // + // +kubebuilder:validation:Optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` } type K8sJobSpec struct { JobContainer ContainerSpec `json:"jobContainer,omitempty"` diff --git a/api/v1alpha1/nodeset_types.go b/api/v1alpha1/nodeset_types.go index 1838a9daf..e2a583fd7 100644 --- a/api/v1alpha1/nodeset_types.go +++ b/api/v1alpha1/nodeset_types.go @@ -304,6 +304,11 @@ type NodeSetSpec struct { // +kubebuilder:validation:Optional CustomInitContainers []corev1.Container `json:"customInitContainers,omitempty"` + // ImagePullSecrets is a list of secret names in the same namespace used for pulling worker pod images. + // + // +kubebuilder:validation:Optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // endregion Scheduling } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 51c19d85a..13939a4d1 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -482,6 +482,11 @@ func (in *ContainerSpec) DeepCopyInto(out *ContainerSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerSpec. @@ -1108,6 +1113,11 @@ func (in *NodeSetSpec) DeepCopyInto(out *NodeSetSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSetSpec. diff --git a/config/crd/bases/slurm.nebius.ai_activechecks.yaml b/config/crd/bases/slurm.nebius.ai_activechecks.yaml index 581447e7e..c846e3bd1 100644 --- a/config/crd/bases/slurm.nebius.ai_activechecks.yaml +++ b/config/crd/bases/slurm.nebius.ai_activechecks.yaml @@ -1221,6 +1221,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -3364,6 +3392,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -5547,6 +5603,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -7695,6 +7779,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume diff --git a/config/crd/bases/slurm.nebius.ai_nodesets.yaml b/config/crd/bases/slurm.nebius.ai_nodesets.yaml index 8c8f32533..4d8c3e4fd 100644 --- a/config/crd/bases/slurm.nebius.ai_nodesets.yaml +++ b/config/crd/bases/slurm.nebius.ai_nodesets.yaml @@ -2568,6 +2568,26 @@ spec: type: boolean type: object type: object + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in the same + namespace used for pulling worker pod images. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array initialNumberEphemeralNodes: default: 1 description: |- diff --git a/config/crd/bases/slurm.nebius.ai_slurmclusters.yaml b/config/crd/bases/slurm.nebius.ai_slurmclusters.yaml index 33900767d..33b422cfc 100644 --- a/config/crd/bases/slurm.nebius.ai_slurmclusters.yaml +++ b/config/crd/bases/slurm.nebius.ai_slurmclusters.yaml @@ -1421,6 +1421,26 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in the + same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array jailSnapshotVolume: description: |- JailSnapshotVolume represents configuration of the volume containing the initial content of the jail root @@ -1842,6 +1862,26 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -5700,6 +5740,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -7905,6 +7966,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -8495,6 +8577,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -10687,6 +10790,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -11296,6 +11420,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -11833,6 +11978,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -14622,6 +14788,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -15164,6 +15351,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -15726,6 +15934,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -18240,6 +18469,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -18790,6 +19040,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -19358,6 +19629,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -22174,6 +22466,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. diff --git a/helm/nodesets/templates/_helpers.tpl b/helm/nodesets/templates/_helpers.tpl index 83e4f51a2..e4cd88250 100644 --- a/helm/nodesets/templates/_helpers.tpl +++ b/helm/nodesets/templates/_helpers.tpl @@ -63,7 +63,7 @@ Usage: include "nodesets.nodeExporterInitContainer" (dict "root" $ "nodeExporter {{- if $nodeExporter.enabled }} - name: pod-node-exporter image: {{ printf "%s:%s" (default $root.Values.images.nodeExporter.repository $nodeExporterImage.repository) (default $root.Values.images.nodeExporter.tag $nodeExporterImage.tag) | quote }} - imagePullPolicy: {{ default "IfNotPresent" $nodeExporterImage.pullPolicy | quote }} + imagePullPolicy: {{ default $root.Values.imagePullPolicy $nodeExporterImage.pullPolicy | quote }} restartPolicy: Always args: {{- range (default (list "--collector.disable-defaults" "--collector.netdev" "--collector.netstat" "--collector.sockstat" "--collector.conntrack") $nodeExporter.args) }} diff --git a/helm/nodesets/templates/nodeset.yaml b/helm/nodesets/templates/nodeset.yaml index f7325d6ba..288694b70 100644 --- a/helm/nodesets/templates/nodeset.yaml +++ b/helm/nodesets/templates/nodeset.yaml @@ -23,6 +23,11 @@ spec: clusterName: {{ . | quote }} {{- end }} + {{- with (default $.Values.imagePullSecrets (.slurmd.image).imagePullSecrets) }} + imagePullSecrets: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (.replicas | default 1) }} replicas: {{ . }} {{- end }} @@ -100,16 +105,14 @@ spec: {{- with .tag }} tag: {{ . | quote }} {{- end }} - - {{- with .pullPolicy }} - pullPolicy: {{ . }} - {{- end }} + pullPolicy: {{ default $.Values.imagePullPolicy .pullPolicy | quote }} {{- end }} {{- else }} repository: {{ (required ".Values.images.slurmd.repository is required as the default image is used." $.Values.images.slurmd.repository) | quote }} {{- with $.Values.images.slurmd.tag }} tag: {{ . | quote }} {{- end }} + pullPolicy: {{ $.Values.imagePullPolicy | quote }} {{- end }} {{- if .customEnv }} @@ -183,16 +186,14 @@ spec: {{- with .tag }} tag: {{ . | quote }} {{- end }} - - {{- with .pullPolicy }} - pullPolicy: {{ . }} - {{- end }} + pullPolicy: {{ default $.Values.imagePullPolicy .pullPolicy | quote }} {{- end }} {{- else }} repository: {{ (required ".Values.images.munge.repository is required as the default image is used." $.Values.images.munge.repository) | quote }} {{- with $.Values.images.munge.tag }} tag: {{ . | quote }} {{- end }} + pullPolicy: {{ $.Values.imagePullPolicy | quote }} {{- end }} {{- with (required ".Values.nodesets[*].munge.resources is required" .resources) }} @@ -228,16 +229,14 @@ spec: {{- with .tag }} tag: {{ . | quote }} {{- end }} - - {{- with .pullPolicy }} - pullPolicy: {{ . }} - {{- end }} + pullPolicy: {{ default $.Values.imagePullPolicy .pullPolicy | quote }} {{- end }} {{- else }} repository: {{ (required ".Values.images.sssd.repository is required as the default image is used." $.Values.images.sssd.repository) | quote }} {{- with $.Values.images.sssd.tag }} tag: {{ . | quote }} {{- end }} + pullPolicy: {{ $.Values.imagePullPolicy | quote }} {{- end }} resources: diff --git a/helm/nodesets/values.yaml b/helm/nodesets/values.yaml index 3c3ed6683..280bb6cf7 100644 --- a/helm/nodesets/values.yaml +++ b/helm/nodesets/values.yaml @@ -36,6 +36,12 @@ images: nodeExporter: repository: "cr.eu-north1.nebius.cloud/soperator-proxy-docker-io/prom/node-exporter" tag: "v1.10.2" +# Default image pull policy used for all NodeSet images (slurmd, munge, sssd, nodeExporter). +# Can be overridden per NodeSet/container, e.g. nodesets[*].slurmd.image.pullPolicy. +imagePullPolicy: "IfNotPresent" +# Default image pull secrets used for all NodeSet worker pods. +# Can be overridden per NodeSet, e.g. nodesets[*].slurmd.image.imagePullSecrets. +imagePullSecrets: [] nodeExporter: podMonitor: enabled: true @@ -131,7 +137,8 @@ nodesets: image: repository: "cr.eu-north1.nebius.cloud/soperator/worker_slurmd" tag: "4.1.3-slurm25.11.5" - pullPolicy: "IfNotPresent" + # pullPolicy: "IfNotPresent" + # imagePullSecrets: [] customEnv: - name: "NVIDIA_DRIVER_CAPABILITIES" value: "compute,utility,video" @@ -221,7 +228,7 @@ nodesets: repository: "cr.eu-north1.nebius.cloud/soperator/munge" # Optional tag: "4.1.3-slurm25.11.5" - pullPolicy: "IfNotPresent" + # pullPolicy: "IfNotPresent" # Munge container resources resources: cpu: "2000m" diff --git a/helm/slurm-cluster/templates/_helpers.tpl b/helm/slurm-cluster/templates/_helpers.tpl index f29e74dd8..43338b445 100644 --- a/helm/slurm-cluster/templates/_helpers.tpl +++ b/helm/slurm-cluster/templates/_helpers.tpl @@ -122,7 +122,7 @@ Usage: include "slurm-cluster.nodeExporterInitContainer" (dict "root" $ "nodeExp {{- if $nodeExporter.enabled }} - name: pod-node-exporter image: {{ default $root.Values.images.nodeExporter $nodeExporter.image | quote }} - imagePullPolicy: {{ default "IfNotPresent" $nodeExporter.imagePullPolicy | quote }} + imagePullPolicy: {{ default $root.Values.imagePullPolicy $nodeExporter.imagePullPolicy | quote }} restartPolicy: Always args: {{- range (default (list "--collector.disable-defaults" "--collector.netdev" "--collector.netstat" "--collector.sockstat" "--collector.conntrack") $nodeExporter.args) }} diff --git a/helm/slurm-cluster/templates/slurm-cluster-cr.yaml b/helm/slurm-cluster/templates/slurm-cluster-cr.yaml index 586537864..1457307d0 100644 --- a/helm/slurm-cluster/templates/slurm-cluster-cr.yaml +++ b/helm/slurm-cluster/templates/slurm-cluster-cr.yaml @@ -113,7 +113,10 @@ spec: {{- end -}} populateJail: image: {{ required "populateJail image" $populateJail | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.populateJail.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.populateJail.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.populateJail.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 4 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.populateJail.appArmorProfile | quote }} k8sNodeFilterName: {{ required "Populate Jail job k8s node filter name must be provided." .Values.populateJail.k8sNodeFilterName | quote }} priorityClass: {{ default (printf "%s-%s" (include "slurm-cluster.name" .) "slurm-populate-jail") .Values.populateJail.priorityClass | quote }} @@ -153,7 +156,10 @@ spec: {{- if .Values.slurmNodes.accounting.slurmdbd.args }} args: {{- .Values.slurmNodes.accounting.slurmdbd.args | toYaml | nindent 8 }} {{- end }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.accounting.slurmdbd.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.accounting.slurmdbd.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.accounting.slurmdbd.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.accounting.slurmdbd.appArmorProfile | quote }} {{- if .Values.slurmNodes.accounting.enabled }} port: {{ default 6819 .Values.slurmNodes.accounting.slurmdbd.port }} @@ -196,6 +202,10 @@ spec: enabled: {{ default false .Values.slurmNodes.accounting.mariadbOperator.enabled }} protectedSecret: {{ .Values.slurmNodes.accounting.mariadbOperator.protectedSecret }} image: {{ required "mariadb image" .Values.images.mariaDB | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.accounting.mariadbOperator.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.accounting.mariadbOperator.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} resources: cpu: {{ required ".Values.slurmNodes.accounting.mariadbOperator.resources.cpu must be provided." .Values.slurmNodes.accounting.mariadbOperator.resources.cpu | quote}} memory: {{ required ".Values.slurmNodes.accounting.mariadbOperator.resources.memory must be provided." .Values.slurmNodes.accounting.mariadbOperator.resources.memory | quote}} @@ -210,7 +220,10 @@ spec: {{- end }} munge: image: {{ required "munge image" .Values.images.munge | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.accounting.munge.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.accounting.munge.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.accounting.munge.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.accounting.munge.appArmorProfile | quote }} {{- if .Values.slurmNodes.accounting.munge.command }} command: {{- .Values.slurmNodes.accounting.munge.command | toYaml | nindent 8 }} @@ -239,7 +252,10 @@ spec: {{- end }} slurmctld: image: {{ required "slurmctld image" .Values.images.slurmctld | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.controller.slurmctld.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.controller.slurmctld.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.controller.slurmctld.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.controller.slurmctld.appArmorProfile | quote }} {{- if .Values.slurmNodes.controller.slurmctld.command }} command: {{- .Values.slurmNodes.controller.slurmctld.command | toYaml | nindent 8 }} @@ -262,7 +278,10 @@ spec: {{- end }} munge: image: {{ required "munge image" .Values.images.munge | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.controller.munge.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.controller.munge.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.controller.munge.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.controller.munge.appArmorProfile | quote }} {{- if .Values.slurmNodes.controller.munge.command }} command: {{- .Values.slurmNodes.controller.munge.command | toYaml | nindent 8 }} @@ -285,7 +304,10 @@ spec: {{- if .Values.slurmNodes.sssd.enabled }} sssd: image: {{ default .Values.images.sssd .Values.slurmNodes.sssd.image | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.sssd.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.sssd.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.sssd.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.sssd.appArmorProfile | quote }} {{- if .Values.slurmNodes.sssd.command }} command: {{- .Values.slurmNodes.sssd.command | toYaml | nindent 8 }} @@ -341,7 +363,10 @@ spec: {{- end }} sshd: image: {{ required "sshd image" .Values.images.sshd | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.login.sshd.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.login.sshd.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.login.sshd.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.login.sshd.appArmorProfile | quote }} {{- if .Values.slurmNodes.login.sshd.command }} command: {{- .Values.slurmNodes.login.sshd.command | toYaml | nindent 8 }} @@ -380,7 +405,10 @@ spec: {{- end }} munge: image: {{ required "sshd munge" .Values.images.munge | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.login.munge.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.login.munge.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.login.munge.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.login.munge.appArmorProfile | quote }} {{- if .Values.slurmNodes.login.munge.command }} command: {{- .Values.slurmNodes.login.munge.command | toYaml | nindent 8 }} @@ -403,7 +431,10 @@ spec: {{- if .Values.slurmNodes.sssd.enabled }} sssd: image: {{ default .Values.images.sssd .Values.slurmNodes.sssd.image | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.sssd.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.sssd.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.sssd.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.sssd.appArmorProfile | quote }} {{- if .Values.slurmNodes.sssd.command }} command: {{- .Values.slurmNodes.sssd.command | toYaml | nindent 8 }} @@ -470,7 +501,10 @@ spec: {{- end }} exporterContainer: image: {{ required "soperator exporter image" .Values.images.soperatorExporter | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.slurmNodes.exporter.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.exporter.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.exporter.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} appArmorProfile: {{ default "unconfined" .Values.slurmNodes.exporter.appArmorProfile | quote }} {{- with (default dict .Values.slurmNodes.exporter.exporterContainer) }} {{- with .livenessProbe }} @@ -500,6 +534,10 @@ spec: {{- include "slurm-cluster.customInitContainers" (dict "root" . "customInitContainers" .Values.slurmNodes.rest.customInitContainers "nodeExporter" .Values.slurmNodes.rest.nodeExporter) | nindent 6 }} rest: image: {{ required "rest image" .Values.images.slurmrestd | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.slurmNodes.rest.rest.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.slurmNodes.rest.rest.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 8 }} + {{- end }} {{- if .Values.slurmNodes.rest.rest.command }} command: {{- .Values.slurmNodes.rest.rest.command | toYaml | nindent 8 }} {{- end }} @@ -530,7 +568,10 @@ spec: {{- include "slurm-cluster.customInitContainers" (dict "root" . "customInitContainers" .Values.sConfigController.node.customInitContainers "nodeExporter" .Values.sConfigController.nodeExporter) | nindent 6 }} container: image: {{ required "sConfigController image" .Values.images.sConfigController | quote }} - imagePullPolicy: {{ default "IfNotPresent" .Values.sConfigController.container.imagePullPolicy | quote }} + imagePullPolicy: {{ default .Values.imagePullPolicy .Values.sConfigController.container.imagePullPolicy | quote }} + {{- with (default .Values.imagePullSecrets .Values.sConfigController.container.imagePullSecrets) }} + imagePullSecrets: {{- toYaml . | nindent 6 }} + {{- end }} resources: cpu: {{ required ".Values.sConfigController.container.resources.cpu must be provided." .Values.sConfigController.container.resources.cpu | quote}} memory: {{ required ".Values.sConfigController.container.resources.memory must be provided." .Values.sConfigController.container.resources.memory | quote}} diff --git a/helm/slurm-cluster/values.yaml b/helm/slurm-cluster/values.yaml index 9cffffac5..8ef1c4fc6 100644 --- a/helm/slurm-cluster/values.yaml +++ b/helm/slurm-cluster/values.yaml @@ -13,6 +13,12 @@ useDefaultAppArmorProfile: false maintenance: "none" # CUDA version used for populate-jail image selection. cudaVersion: 12.9.0 +# Default image pull policy used for all Slurm cluster images. +# Can be overridden per component below (e.g. slurmNodes.controller.slurmctld.imagePullPolicy). +imagePullPolicy: "IfNotPresent" +# Default image pull secrets used for all Slurm cluster images. +# Can be overridden per component below (e.g. slurmNodes.controller.slurmctld.imagePullSecrets). +imagePullSecrets: [] nodeExporter: podMonitor: enabled: true @@ -133,7 +139,8 @@ secrets: {} # sshdKeysName: "" # Job performing initial jail file system population populateJail: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" # Name of the k8s node filter k8sNodeFilterName: "gpu" @@ -197,7 +204,8 @@ slurmNodes: sssd: enabled: false sssdDebugLevel: 0 - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" command: [] args: [] @@ -257,7 +265,8 @@ slurmNodes: purgeTXNAfter: "12month" purgeUsageAfter: "24month" slurmdbd: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" command: [] args: [] @@ -275,7 +284,8 @@ slurmNodes: memory: "3Gi" ephemeralStorage: "10Gi" munge: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" livenessProbe: exec: @@ -320,6 +330,8 @@ slurmNodes: mariadbOperator: enabled: false protectedSecret: false + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] resources: cpu: "1000m" memory: "1Gi" @@ -405,7 +417,8 @@ slurmNodes: # If not set and create is true, a name is generated using the cluster name: -slurm-controller name: "" slurmctld: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" command: [] args: [] @@ -424,7 +437,8 @@ slurmNodes: memory: "3Gi" ephemeralStorage: "20Gi" munge: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" command: [] args: [] @@ -496,7 +510,8 @@ slurmNodes: # Controls if the pod containers can use the host user namespace # hostUsers: false sshd: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" readinessProbe: tcpSocket: @@ -529,7 +544,8 @@ slurmNodes: # Annotations to be configure on login service sshdServiceAnnotations: {} munge: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" command: [] args: [] @@ -598,8 +614,9 @@ slurmNodes: # when jobSource=accounting, the size of the time window queried from the accounting API # ([now - lookback, now + 5m]). The +5m skew tolerates clock drift between slurmrestd, slurmctld and slurmdbd. accountingJobsLookback: "1h" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] exporter: - imagePullPolicy: "IfNotPresent" appArmorProfile: "unconfined" command: [] args: [] @@ -639,7 +656,8 @@ slurmNodes: threadCount: 3 maxConnections: 10 rest: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] appArmorProfile: "unconfined" command: [] args: [] @@ -666,7 +684,8 @@ sConfigController: size: 1 customInitContainers: [] container: - imagePullPolicy: "IfNotPresent" + # imagePullPolicy: "IfNotPresent" + # imagePullSecrets: [] # livenessProbe: {} # readinessProbe: {} resources: diff --git a/helm/soperator-activechecks/templates/_helpers.tpl b/helm/soperator-activechecks/templates/_helpers.tpl index b772feacc..e9d2a432d 100644 --- a/helm/soperator-activechecks/templates/_helpers.tpl +++ b/helm/soperator-activechecks/templates/_helpers.tpl @@ -122,7 +122,12 @@ Render slurmJobSpec for an ActiveCheck. {{- $ctx := .ctx -}} {{- $spec := default dict .check.slurmJobSpec -}} {{- $jobContainerRaw := default dict $spec.jobContainer -}} -{{- $baseContainer := dict "appArmorProfile" "unconfined" "image" $ctx.Values.images.slurmJob "env" $ctx.Values.jobContainer.env "volumeMounts" $ctx.Values.jobContainer.volumeMounts "volumes" $ctx.Values.jobContainer.volumes -}} +{{- $baseContainer := dict "appArmorProfile" "unconfined" "image" $ctx.Values.images.slurmJob -}} +{{- $_ := set $baseContainer "env" $ctx.Values.jobContainer.env -}} +{{- $_ := set $baseContainer "volumeMounts" $ctx.Values.jobContainer.volumeMounts -}} +{{- $_ := set $baseContainer "volumes" $ctx.Values.jobContainer.volumes -}} +{{- $_ := set $baseContainer "imagePullPolicy" $ctx.Values.jobContainer.imagePullPolicy -}} +{{- $_ := set $baseContainer "imagePullSecrets" $ctx.Values.jobContainer.imagePullSecrets -}} {{- $jobContainer := mustMerge (omit $jobContainerRaw "extraEnv" "extraVolumeMounts" "extraVolumes") $baseContainer -}} {{- $env := default (list) $jobContainer.env -}} {{- $workingDir := default "" $jobContainer.workingDir -}} @@ -145,6 +150,13 @@ jobContainer: {{- end }} appArmorProfile: {{ $jobContainer.appArmorProfile }} image: {{ tpl $jobContainer.image $ctx | quote }} +{{- with $jobContainer.imagePullPolicy }} + imagePullPolicy: {{ . }} +{{- end }} +{{- with $jobContainer.imagePullSecrets }} + imagePullSecrets: +{{ toYaml . | indent 4 }} +{{- end }} {{- with $jobContainer.command }} command: {{ toYaml . | indent 4 }} @@ -180,6 +192,8 @@ Render k8sJobSpec for an ActiveCheck. {{- $useCommonVolumes := default true $spec.useCommonVolumes -}} {{- $includeCommonEnv := default false $spec.includeCommonEnv -}} {{- $baseContainer := dict "image" $ctx.Values.images.k8sJob -}} +{{- $_ := set $baseContainer "imagePullPolicy" $ctx.Values.jobContainer.imagePullPolicy -}} +{{- $_ := set $baseContainer "imagePullSecrets" $ctx.Values.jobContainer.imagePullSecrets -}} {{- if $useCommonVolumeMounts }}{{- $_ := set $baseContainer "volumeMounts" $ctx.Values.jobContainer.volumeMounts -}}{{- end }} {{- if $includeCommonEnv }}{{- $_ := set $baseContainer "env" $ctx.Values.jobContainer.env -}}{{- end }} {{- $jobContainer := mustMerge (omit $jobContainerRaw "extraEnv" "extraVolumeMounts" "extraVolumes") $baseContainer -}} @@ -213,6 +227,13 @@ jobContainer: {{- with $jobContainer.appArmorProfile }} appArmorProfile: {{ . }} {{- end }} +{{- with $jobContainer.imagePullPolicy }} + imagePullPolicy: {{ . }} +{{- end }} +{{- with $jobContainer.imagePullSecrets }} + imagePullSecrets: +{{ toYaml . | indent 4 }} +{{- end }} {{- if $command }} command: {{ toYaml $command | indent 4 }} diff --git a/helm/soperator-activechecks/templates/wait-for-checks-job.yaml b/helm/soperator-activechecks/templates/wait-for-checks-job.yaml index ff5095f68..68f3f0e35 100644 --- a/helm/soperator-activechecks/templates/wait-for-checks-job.yaml +++ b/helm/soperator-activechecks/templates/wait-for-checks-job.yaml @@ -10,9 +10,14 @@ spec: spec: restartPolicy: Never serviceAccountName: {{ include "soperator-activechecks.waitForChecksName" . }} + {{- with .Values.waitForChecks.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: wait-for-active-checks image: cr.eu-north1.nebius.cloud/soperator-proxy-docker-io/alpine/k8s:1.31.11 + imagePullPolicy: {{ default "IfNotPresent" .Values.waitForChecks.imagePullPolicy | quote }} command: - /bin/sh - -c diff --git a/helm/soperator-activechecks/values.yaml b/helm/soperator-activechecks/values.yaml index 72cb00226..690ceae3d 100644 --- a/helm/soperator-activechecks/values.yaml +++ b/helm/soperator-activechecks/values.yaml @@ -19,7 +19,12 @@ ncclTestsVersion: "" ncclTestsVersions: "12.9.0": "2.17.9" "13.0.2": "2.17.9" +waitForChecks: + imagePullPolicy: "IfNotPresent" + imagePullSecrets: [] jobContainer: + imagePullPolicy: "IfNotPresent" + imagePullSecrets: [] env: - name: "K8S_POD_NAME" valueFrom: diff --git a/helm/soperator-crds/templates/slurmcluster-crd.yaml b/helm/soperator-crds/templates/slurmcluster-crd.yaml index 228b8bd90..51a5d38f7 100644 --- a/helm/soperator-crds/templates/slurmcluster-crd.yaml +++ b/helm/soperator-crds/templates/slurmcluster-crd.yaml @@ -1220,6 +1220,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -3363,6 +3391,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -5546,6 +5602,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -7694,6 +7778,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -17634,6 +17746,26 @@ spec: type: boolean type: object type: object + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in the same + namespace used for pulling worker pod images. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array initialNumberEphemeralNodes: default: 1 description: |- @@ -28705,6 +28837,26 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in the + same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array jailSnapshotVolume: description: |- JailSnapshotVolume represents configuration of the volume containing the initial content of the jail root @@ -29126,6 +29278,26 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -32984,6 +33156,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -35189,6 +35382,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -35779,6 +35993,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -37971,6 +38206,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -38580,6 +38836,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -39117,6 +39394,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -41906,6 +42204,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -42448,6 +42767,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -43010,6 +43350,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -45524,6 +45885,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -46074,6 +46456,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -46642,6 +47045,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -49458,6 +49882,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. diff --git a/helm/soperator-dcgm-exporter/templates/daemonset.yaml b/helm/soperator-dcgm-exporter/templates/daemonset.yaml index 80c2aca8b..c09d8b714 100644 --- a/helm/soperator-dcgm-exporter/templates/daemonset.yaml +++ b/helm/soperator-dcgm-exporter/templates/daemonset.yaml @@ -36,7 +36,7 @@ spec: image: {{ .Values.daemonSet.nvidiaDcgmExporter.image.repository }}:{{ .Values.daemonSet.nvidiaDcgmExporter.image.tag | default .Chart.AppVersion }} - imagePullPolicy: IfNotPresent + imagePullPolicy: {{ .Values.daemonSet.nvidiaDcgmExporter.image.pullPolicy | default "IfNotPresent" }} name: nvidia-dcgm-exporter ports: - containerPort: {{ .Values.metricsPort }} @@ -69,8 +69,8 @@ spec: env: - name: KUBERNETES_CLUSTER_DOMAIN value: {{ quote .Values.kubernetesClusterDomain }} - image: cr.eu-north1.nebius.cloud/soperator/busybox:latest - imagePullPolicy: IfNotPresent + image: {{ .Values.daemonSet.createHpcJobsDir.image.repository }}:{{ .Values.daemonSet.createHpcJobsDir.image.tag }} + imagePullPolicy: {{ .Values.daemonSet.createHpcJobsDir.image.pullPolicy | default "IfNotPresent" }} resources: {} securityContext: privileged: true @@ -89,7 +89,7 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: {{ quote .Values.kubernetesClusterDomain }} image: {{ .Values.daemonSet.toolkitValidation.image.repository }}:{{ .Values.daemonSet.toolkitValidation.image.tag | default .Chart.AppVersion }} - imagePullPolicy: IfNotPresent + imagePullPolicy: {{ .Values.daemonSet.toolkitValidation.image.pullPolicy | default "IfNotPresent" }} resources: {} securityContext: privileged: true @@ -106,6 +106,10 @@ spec: schedulerName: default-scheduler securityContext: {} serviceAccountName: {{ include "soperator-dcgm-exporter.name" . }}-sa + {{- with .Values.daemonSet.nvidiaDcgmExporter.image.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 6 }} + {{- end }} terminationGracePeriodSeconds: 30 tolerations: - effect: NoSchedule diff --git a/helm/soperator-dcgm-exporter/values.yaml b/helm/soperator-dcgm-exporter/values.yaml index 9b2eb8f7a..400780b18 100644 --- a/helm/soperator-dcgm-exporter/values.yaml +++ b/helm/soperator-dcgm-exporter/values.yaml @@ -14,11 +14,20 @@ daemonSet: image: repository: cr.eu-north1.nebius.cloud/marketplace/nebius/nvidia-gpu-operator/image/gpu-operator-validator tag: v24.6.2 + pullPolicy: IfNotPresent + + createHpcJobsDir: + image: + repository: cr.eu-north1.nebius.cloud/soperator/busybox + tag: latest + pullPolicy: IfNotPresent nvidiaDcgmExporter: image: repository: cr.eu-north1.nebius.cloud/soperator/dcgm-exporter tag: 4.4.2-4.7.0-ubuntu22.04 + pullPolicy: IfNotPresent + imagePullSecrets: [] env: dcgmExporterListen: :9400 diff --git a/helm/soperator/crds/slurmcluster-crd.yaml b/helm/soperator/crds/slurmcluster-crd.yaml index 228b8bd90..51a5d38f7 100644 --- a/helm/soperator/crds/slurmcluster-crd.yaml +++ b/helm/soperator/crds/slurmcluster-crd.yaml @@ -1220,6 +1220,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -3363,6 +3391,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -5546,6 +5602,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -7694,6 +7778,34 @@ spec: type: array image: type: string + imagePullPolicy: + default: IfNotPresent + description: ImagePullPolicy defines the image pull policy + enum: + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -17634,6 +17746,26 @@ spec: type: boolean type: object type: object + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in the same + namespace used for pulling worker pod images. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array initialNumberEphemeralNodes: default: 1 description: |- @@ -28705,6 +28837,26 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in the + same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array jailSnapshotVolume: description: |- JailSnapshotVolume represents configuration of the volume containing the initial content of the jail root @@ -29126,6 +29278,26 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names in + the same namespace used for pulling the container's image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -32984,6 +33156,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -35189,6 +35382,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -35779,6 +35993,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -37971,6 +38206,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -38580,6 +38836,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -39117,6 +39394,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -41906,6 +42204,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -42448,6 +42767,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -43010,6 +43350,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -45524,6 +45885,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -46074,6 +46456,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -46642,6 +47045,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. @@ -49458,6 +49882,27 @@ spec: - Never - IfNotPresent type: string + imagePullSecrets: + description: ImagePullSecrets is a list of secret names + in the same namespace used for pulling the container's + image. + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array livenessProbe: description: LivenessProbe defines the liveness probe for the container. diff --git a/helm/soperator/templates/deployment.yaml b/helm/soperator/templates/deployment.yaml index 2123671bd..0aacfc1a3 100644 --- a/helm/soperator/templates/deployment.yaml +++ b/helm/soperator/templates/deployment.yaml @@ -109,6 +109,10 @@ spec: - ALL {{- end }} serviceAccountName: {{ include "soperator.fullname" . }}-manager + {{- with .Values.controllerManager.manager.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 6 }} + {{- end }} terminationGracePeriodSeconds: 10 {{- if .Values.certManager.enabled }} volumes: diff --git a/helm/soperator/values.yaml b/helm/soperator/values.yaml index e2835b6bb..3e055fd76 100644 --- a/helm/soperator/values.yaml +++ b/helm/soperator/values.yaml @@ -26,6 +26,7 @@ controllerManager: repository: cr.eu-north1.nebius.cloud/soperator/slurm-operator tag: 4.1.3 imagePullPolicy: Always + imagePullSecrets: [] resources: limits: memory: 128Mi diff --git a/helm/soperatorchecks/templates/deployment.yaml b/helm/soperatorchecks/templates/deployment.yaml index f86190502..73e35ea0a 100644 --- a/helm/soperatorchecks/templates/deployment.yaml +++ b/helm/soperatorchecks/templates/deployment.yaml @@ -64,4 +64,8 @@ spec: securityContext: runAsNonRoot: true serviceAccountName: {{ include "soperatorchecks.fullname" . }}-checks + {{- with .Values.checks.manager.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 6 }} + {{- end }} terminationGracePeriodSeconds: 10 diff --git a/helm/soperatorchecks/values.yaml b/helm/soperatorchecks/values.yaml index 41b99b84e..d6ba9c7f2 100644 --- a/helm/soperatorchecks/values.yaml +++ b/helm/soperatorchecks/values.yaml @@ -37,6 +37,7 @@ checks: repository: cr.eu-north1.nebius.cloud/soperator/soperatorchecks tag: 4.1.3 imagePullPolicy: Always + imagePullSecrets: [] resources: limits: memory: 128Mi diff --git a/internal/render/accounting/mariadb.go b/internal/render/accounting/mariadb.go index ed3b07e1e..c3a3d2c53 100644 --- a/internal/render/accounting/mariadb.go +++ b/internal/render/accounting/mariadb.go @@ -61,13 +61,14 @@ func RenderMariaDb( Labels: labels, }, Spec: mariadbv1alpha1.MariaDBSpec{ - Image: mariaDb.Image, - Replicas: replicas, - Replication: accounting.MariaDb.Replication, - Port: port, - Storage: mariaDb.Storage, - Database: ptr.To(consts.MariaDbDatabase), - Username: ptr.To(consts.MariaDbUsername), + Image: mariaDb.Image, + ImagePullPolicy: mariaDb.ImagePullPolicy, + Replicas: replicas, + Replication: accounting.MariaDb.Replication, + Port: port, + Storage: mariaDb.Storage, + Database: ptr.To(consts.MariaDbDatabase), + Username: ptr.To(consts.MariaDbUsername), PasswordSecretKeyRef: &mariadbv1alpha1.GeneratedSecretKeyRef{ SecretKeySelector: mariadbv1alpha1.SecretKeySelector{ LocalObjectReference: mariadbv1alpha1.LocalObjectReference{ @@ -106,6 +107,7 @@ func RenderMariaDb( Tolerations: nodeFilter.Tolerations, PodSecurityContext: mariaDb.PodSecurityContext, PriorityClassName: ptr.To(mariaDb.PriorityClassName), + ImagePullSecrets: convertImagePullSecrets(mariaDb.ImagePullSecrets), }, Metrics: &mariadbv1alpha1.MariadbMetrics{ Enabled: mariaDb.Metrics.Enabled, @@ -115,6 +117,20 @@ func RenderMariaDb( }, nil } +// convertImagePullSecrets converts []corev1.LocalObjectReference to []mariadbv1alpha1.LocalObjectReference +func convertImagePullSecrets(refs []corev1.LocalObjectReference) []mariadbv1alpha1.LocalObjectReference { + if refs == nil { + return nil + } + + converted := make([]mariadbv1alpha1.LocalObjectReference, 0, len(refs)) + for _, ref := range refs { + converted = append(converted, mariadbv1alpha1.LocalObjectReference{Name: ref.Name}) + } + + return converted +} + func getMariaDbConfig(mariaDb slurmv1.MariaDbOperator) (int32, int32, *bool) { port := int32(consts.MariaDbPort) replicas := int32(1) diff --git a/internal/render/accounting/pod.go b/internal/render/accounting/pod.go index 92997d2a5..693d31f0f 100644 --- a/internal/render/accounting/pod.go +++ b/internal/render/accounting/pod.go @@ -72,6 +72,7 @@ func BasePodTemplateSpec( }, Spec: corev1.PodSpec{ HostUsers: accounting.HostUsers, + ImagePullSecrets: accounting.ContainerAccounting.ImagePullSecrets, Affinity: nodeFilter.Affinity, Tolerations: nodeFilter.Tolerations, NodeSelector: nodeFilter.NodeSelector, diff --git a/internal/render/controller/statefulset.go b/internal/render/controller/statefulset.go index 4730c1847..5ae081b91 100644 --- a/internal/render/controller/statefulset.go +++ b/internal/render/controller/statefulset.go @@ -112,6 +112,7 @@ func RenderStatefulSet( }, }, HostUsers: controller.HostUsers, + ImagePullSecrets: controller.ContainerSlurmctld.ImagePullSecrets, Affinity: nodeFilter.Affinity, NodeSelector: nodeFilter.NodeSelector, Tolerations: nodeFilter.Tolerations, diff --git a/internal/render/exporter/pod.go b/internal/render/exporter/pod.go index 1097618a0..6e9d213b9 100644 --- a/internal/render/exporter/pod.go +++ b/internal/render/exporter/pod.go @@ -29,6 +29,7 @@ func renderPodTemplateSpec( }, Spec: corev1.PodSpec{ HostUsers: clusterValues.SlurmExporter.HostUsers, + ImagePullSecrets: clusterValues.SlurmExporter.Container.ImagePullSecrets, Affinity: nodeFilter.Affinity, Tolerations: nodeFilter.Tolerations, NodeSelector: nodeFilter.NodeSelector, diff --git a/internal/render/login/statefulset.go b/internal/render/login/statefulset.go index f3d264f2d..2deb9ace9 100644 --- a/internal/render/login/statefulset.go +++ b/internal/render/login/statefulset.go @@ -101,11 +101,12 @@ func RenderStatefulSet( Annotations: common.RenderDefaultContainerAnnotation(consts.ContainerNameSshd), }, Spec: corev1.PodSpec{ - HostUsers: login.HostUsers, - Affinity: nodeFilter.Affinity, - NodeSelector: nodeFilter.NodeSelector, - Tolerations: nodeFilter.Tolerations, - InitContainers: initContainers, + HostUsers: login.HostUsers, + ImagePullSecrets: login.ContainerSshd.ImagePullSecrets, + Affinity: nodeFilter.Affinity, + NodeSelector: nodeFilter.NodeSelector, + Tolerations: nodeFilter.Tolerations, + InitContainers: initContainers, Containers: []corev1.Container{ renderContainerSshd( clusterWithGPU, diff --git a/internal/render/populate_jail/job.go b/internal/render/populate_jail/job.go index a926b6df0..4cd697ef5 100644 --- a/internal/render/populate_jail/job.go +++ b/internal/render/populate_jail/job.go @@ -59,6 +59,7 @@ func RenderPopulateJailJob( Tolerations: nodeFilter.Tolerations, RestartPolicy: "Never", PriorityClassName: populateJail.PriorityClass, + ImagePullSecrets: populateJail.ContainerPopulateJail.ImagePullSecrets, Volumes: volumes, Containers: []corev1.Container{renderContainerPopulateJail(populateJail)}, }, diff --git a/internal/render/rest/pod.go b/internal/render/rest/pod.go index 3c20df7b9..0103771cd 100644 --- a/internal/render/rest/pod.go +++ b/internal/render/rest/pod.go @@ -39,6 +39,7 @@ func BasePodTemplateSpec( }, Spec: corev1.PodSpec{ HostUsers: valuesREST.HostUsers, + ImagePullSecrets: valuesREST.ContainerREST.ImagePullSecrets, Affinity: nodeFilter.Affinity, Tolerations: nodeFilter.Tolerations, NodeSelector: nodeFilter.NodeSelector, diff --git a/internal/render/sconfigcontroller/pod.go b/internal/render/sconfigcontroller/pod.go index fdb00ea35..39fed3b1a 100644 --- a/internal/render/sconfigcontroller/pod.go +++ b/internal/render/sconfigcontroller/pod.go @@ -50,6 +50,7 @@ func BasePodTemplateSpec( }, Spec: corev1.PodSpec{ HostUsers: sConfigController.HostUsers, + ImagePullSecrets: sConfigController.Container.ImagePullSecrets, Affinity: nodeFilter.Affinity, Tolerations: nodeFilter.Tolerations, NodeSelector: nodeFilter.NodeSelector, diff --git a/internal/render/soperatorchecks/container.go b/internal/render/soperatorchecks/container.go index b5b63e406..8558f9a5a 100644 --- a/internal/render/soperatorchecks/container.go +++ b/internal/render/soperatorchecks/container.go @@ -30,7 +30,7 @@ func renderContainerK8sCronjob(check *slurmv1alpha1.ActiveCheck) corev1.Containe Command: check.Spec.K8sJobSpec.JobContainer.Command, Args: check.Spec.K8sJobSpec.JobContainer.Args, WorkingDir: check.Spec.K8sJobSpec.JobContainer.WorkingDir, - ImagePullPolicy: corev1.PullIfNotPresent, + ImagePullPolicy: check.Spec.K8sJobSpec.JobContainer.ImagePullPolicy, Env: check.Spec.K8sJobSpec.JobContainer.Env, SecurityContext: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{ @@ -92,7 +92,7 @@ func renderContainerK8sCronjob(check *slurmv1alpha1.ActiveCheck) corev1.Containe container = corev1.Container{ Name: check.Spec.Name, Image: check.Spec.SlurmJobSpec.JobContainer.Image, - ImagePullPolicy: corev1.PullIfNotPresent, + ImagePullPolicy: check.Spec.SlurmJobSpec.JobContainer.ImagePullPolicy, Command: check.Spec.SlurmJobSpec.JobContainer.Command, Args: check.Spec.SlurmJobSpec.JobContainer.Args, WorkingDir: check.Spec.SlurmJobSpec.JobContainer.WorkingDir, diff --git a/internal/render/soperatorchecks/pod.go b/internal/render/soperatorchecks/pod.go index 2b231156b..a4d11c982 100644 --- a/internal/render/soperatorchecks/pod.go +++ b/internal/render/soperatorchecks/pod.go @@ -53,6 +53,7 @@ func renderPodTemplateSpec(check *slurmv1alpha1.ActiveCheck, labels map[string]s }, Spec: corev1.PodSpec{ HostUsers: check.Spec.HostUsers, + ImagePullSecrets: jobContainerImagePullSecrets(check), Affinity: check.Spec.Affinity, NodeSelector: check.Spec.NodeSelector, Tolerations: check.Spec.Tolerations, @@ -66,6 +67,14 @@ func renderPodTemplateSpec(check *slurmv1alpha1.ActiveCheck, labels map[string]s } } +// jobContainerImagePullSecrets returns the ImagePullSecrets of the check's main job container. +func jobContainerImagePullSecrets(check *slurmv1alpha1.ActiveCheck) []corev1.LocalObjectReference { + if check.Spec.CheckType == "k8sJob" { + return check.Spec.K8sJobSpec.JobContainer.ImagePullSecrets + } + return check.Spec.SlurmJobSpec.JobContainer.ImagePullSecrets +} + func renderVolumes(check *slurmv1alpha1.ActiveCheck) []corev1.Volume { var volumes []corev1.Volume diff --git a/internal/render/worker/statefulset.go b/internal/render/worker/statefulset.go index df5f9f5cc..0e0a88b3a 100644 --- a/internal/render/worker/statefulset.go +++ b/internal/render/worker/statefulset.go @@ -119,6 +119,7 @@ func RenderNodeSetStatefulSet( }, PriorityClassName: nodeSet.PriorityClass, ServiceAccountName: naming.BuildServiceAccountWorkerName(nodeSet.ParentalCluster.Name), + ImagePullSecrets: nodeSet.ImagePullSecrets, Affinity: nodeSet.Affinity, NodeSelector: nodeSet.NodeSelector, Tolerations: nodeSet.Tolerations, diff --git a/internal/values/slurm_jail.go b/internal/values/slurm_jail.go index 597dd7856..0fae24249 100644 --- a/internal/values/slurm_jail.go +++ b/internal/values/slurm_jail.go @@ -29,9 +29,10 @@ func buildSlurmPopulateJailFrom(clusterName string, maintenance *consts.Maintena ContainerPopulateJail: Container{ Name: consts.ContainerNamePopulateJail, NodeContainer: slurmv1.NodeContainer{ - Image: populateJail.Image, - ImagePullPolicy: populateJail.ImagePullPolicy, - AppArmorProfile: populateJail.AppArmorProfile, + Image: populateJail.Image, + ImagePullPolicy: populateJail.ImagePullPolicy, + ImagePullSecrets: populateJail.ImagePullSecrets, + AppArmorProfile: populateJail.AppArmorProfile, }, }, VolumeJail: slurmv1.NodeVolume{ diff --git a/internal/values/slurm_nodeset.go b/internal/values/slurm_nodeset.go index 69187502c..ea76a3679 100644 --- a/internal/values/slurm_nodeset.go +++ b/internal/values/slurm_nodeset.go @@ -19,11 +19,12 @@ type SlurmNodeSet struct { Name string ParentalCluster client.ObjectKey - NodeSelector map[string]string - Affinity *corev1.Affinity - Tolerations []corev1.Toleration - PriorityClass string - Annotations map[string]string + NodeSelector map[string]string + Affinity *corev1.Affinity + Tolerations []corev1.Toleration + PriorityClass string + Annotations map[string]string + ImagePullSecrets []corev1.LocalObjectReference ContainerSlurmd Container ContainerMunge Container @@ -87,11 +88,12 @@ func BuildSlurmNodeSetFrom( Name: clusterName, }, // - NodeSelector: maps.Clone(nsSpec.NodeSelector), - Affinity: nsSpec.Affinity.DeepCopy(), - Tolerations: slices.Clone(nsSpec.Tolerations), - PriorityClass: nsSpec.PriorityClass, - Annotations: maps.Clone(nsSpec.WorkerAnnotations), + NodeSelector: maps.Clone(nsSpec.NodeSelector), + Affinity: nsSpec.Affinity.DeepCopy(), + Tolerations: slices.Clone(nsSpec.Tolerations), + PriorityClass: nsSpec.PriorityClass, + Annotations: maps.Clone(nsSpec.WorkerAnnotations), + ImagePullSecrets: slices.Clone(nsSpec.ImagePullSecrets), // ContainerSlurmd: buildContainerFrom( slurmv1.NodeContainer{