@@ -27,7 +27,9 @@ import (
2727 "time"
2828
2929 log "github.com/sirupsen/logrus"
30+ corev1 "k8s.io/api/core/v1"
3031 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32+ "k8s.io/apimachinery/pkg/fields"
3133 "k8s.io/apimachinery/pkg/types"
3234 "k8s.io/apimachinery/pkg/util/wait"
3335 "k8s.io/client-go/kubernetes"
@@ -42,6 +44,7 @@ const (
4244 dcgmExporterDeployLabel = "nvidia.com/gpu.deploy.dcgm-exporter"
4345 dcgmDeployLabel = "nvidia.com/gpu.deploy.dcgm"
4446 nvsmDeployLabel = "nvidia.com/gpu.deploy.nvsm"
47+ gpuClientDeployLabel = "nvidia.com/gpu.deploy.client"
4548
4649 migStateSuccess = "success"
4750 migStateFailed = "failed"
@@ -93,6 +96,7 @@ type Reconfigure struct {
9396 dcgmExporterDeployed string
9497 dcgmDeployed string
9598 nvsmDeployed string
99+ gpuClientDeployed string
96100 currentState string
97101 migModeChangeRequired bool
98102 stoppedServices []string
@@ -255,13 +259,16 @@ func (r *Reconfigure) getCurrentNodeLabels() error {
255259 r .dcgmExporterDeployed = labels [dcgmExporterDeployLabel ]
256260 r .dcgmDeployed = labels [dcgmDeployLabel ]
257261 r .nvsmDeployed = labels [nvsmDeployLabel ]
262+ r .gpuClientDeployed = labels [gpuClientDeployLabel ]
258263 r .currentState = labels [migConfigStateLabel ]
259264
260265 log .Infof ("Current value of '%s=%s'\n " , devicePluginDeployLabel , r .pluginDeployed )
261266 log .Infof ("Current value of '%s=%s'\n " , gpuFeatureDiscoveryDeployLabel , r .gfdDeployed )
262267 log .Infof ("Current value of '%s=%s'\n " , dcgmExporterDeployLabel , r .dcgmExporterDeployed )
263268 log .Infof ("Current value of '%s=%s'\n " , dcgmDeployLabel , r .dcgmDeployed )
264269 log .Infof ("Current value of '%s=%s'\n " , nvsmDeployLabel , r .nvsmDeployed )
270+ log .Infof ("Current value of '%s=%s'\n " , gpuClientDeployLabel , r .gpuClientDeployed )
271+
265272 log .Infof ("Current value of '%s=%s'\n " , migConfigStateLabel , r .currentState )
266273
267274 return nil
@@ -371,6 +378,9 @@ func (r *Reconfigure) shutdownKubernetesGPUClients() error {
371378 dcgmDeployLabel : r .maybeSetPaused (r .dcgmDeployed ),
372379 nvsmDeployLabel : r .maybeSetPaused (r .nvsmDeployed ),
373380 }
381+ if len (r .gpuClientDeployed ) > 0 {
382+ labels [gpuClientDeployLabel ] = r .maybeSetPaused (r .gpuClientDeployed )
383+ }
374384
375385 return r .setNodeLabels (labels )
376386}
@@ -399,6 +409,11 @@ func (r *Reconfigure) waitForPodsToBeDeleted() error {
399409 return fmt .Errorf ("dcgm pod did not shutdown: %w" , err )
400410 }
401411
412+ log .Infof ("Waiting for any daemon set pods with nodeSelector key %s to shutdown" , gpuClientDeployLabel )
413+ if err := r .waitForPodsWithNodeSelector (gpuClientDeployLabel , timeout ); err != nil {
414+ return fmt .Errorf ("third-party gpu client pods did not shutdown: %w" , err )
415+ }
416+
402417 log .Info ("Removing the cuda-validator pod" )
403418 if err := r .deletePod ("app=nvidia-cuda-validator" ); err != nil {
404419 return fmt .Errorf ("failed to delete cuda-validator pod: %w" , err )
@@ -508,6 +523,9 @@ func (r *Reconfigure) restartKubernetesGPUClients() error {
508523 dcgmDeployLabel : r .maybeSetTrue (r .dcgmDeployed ),
509524 nvsmDeployLabel : r .maybeSetTrue (r .nvsmDeployed ),
510525 }
526+ if len (r .gpuClientDeployed ) > 0 {
527+ labels [gpuClientDeployLabel ] = r .maybeSetTrue (r .gpuClientDeployed )
528+ }
511529
512530 return r .setNodeLabels (labels )
513531}
@@ -540,6 +558,10 @@ func (r *Reconfigure) setState(state string) error {
540558 nvsmDeployLabel : r .maybeSetTrue (r .nvsmDeployed ),
541559 }
542560
561+ if len (r .gpuClientDeployed ) > 0 {
562+ labels [gpuClientDeployLabel ] = r .maybeSetTrue (r .gpuClientDeployed )
563+ }
564+
543565 if err := r .setNodeLabels (labels ); err != nil {
544566 log .Info ("Unable to bring up GPU client pods by setting their daemonset labels" )
545567 return err
@@ -621,6 +643,35 @@ func (r *Reconfigure) deletePod(labelSelector string) error {
621643 return nil
622644}
623645
646+ // waitForPodsWithNodeSelector waits for all daemon set pods on the given node which has the specified key in
647+ // its nodeSelector to terminate.
648+ func (r * Reconfigure ) waitForPodsWithNodeSelector (nodeSelectorKey string , timeout time.Duration ) error {
649+ return wait .PollUntilContextTimeout (r .ctx , 5 * time .Second , timeout , true , func (ctx context.Context ) (bool , error ) {
650+ podList , err := r .clientset .CoreV1 ().Pods (corev1 .NamespaceAll ).List (ctx , metav1.ListOptions {
651+ FieldSelector : fields .OneTermEqualSelector ("spec.nodeName" , r .opts .NodeName ).String (),
652+ })
653+ if err != nil {
654+ return false , fmt .Errorf ("failed to list pods on node %s: %w" , r .opts .NodeName , err )
655+ }
656+
657+ matchCount := 0
658+ for _ , pod := range podList .Items {
659+ ownerRef := metav1 .GetControllerOf (& pod )
660+ if ownerRef == nil || ownerRef .Kind != "DaemonSet" {
661+ continue
662+ }
663+ if _ , ok := pod .Spec .NodeSelector [nodeSelectorKey ]; ok {
664+ matchCount ++
665+ }
666+ }
667+
668+ if matchCount > 0 {
669+ log .Infof ("Waiting for %d daemon set pod(s) with nodeSelector key %s to terminate" , matchCount , nodeSelectorKey )
670+ }
671+ return matchCount == 0 , nil
672+ })
673+ }
674+
624675func (r * Reconfigure ) runNvidiaSMI () error {
625676 if r .opts .DriverRootCtrPath == r .opts .DevRootCtrPath {
626677 cmd := exec .Command ("chroot" , r .opts .DriverRootCtrPath , "nvidia-smi" )
0 commit comments