@@ -1131,28 +1131,31 @@ def _create_job_pod(
11311131 tolerations : list [client .V1Toleration ] = []
11321132 volumes_ : list [client .V1Volume ] = []
11331133 volume_mounts : list [client .V1VolumeMount ] = []
1134+ env_vars : list [client .V1EnvVar ] = []
11341135
11351136 resources_spec = job_spec .requirements .resources
11361137 assert isinstance (resources_spec .cpu , CPUSpec )
11371138 if (cpu_min := resources_spec .cpu .count .min ) is not None :
11381139 resources_requests ["cpu" ] = str (cpu_min )
11391140 if (cpu_max := resources_spec .cpu .count .max ) is not None :
11401141 resources_limits ["cpu" ] = str (cpu_max )
1141- if (gpu_spec := resources_spec .gpu ) is not None :
1142- if (gpu_request := get_gpu_request_from_gpu_spec (gpu_spec )) > 0 :
1143- gpu_resource , node_affinity , node_taint = _get_pod_spec_parameters_for_gpu (
1144- api , gpu_spec
1142+ gpu_spec = resources_spec .gpu
1143+ if gpu_spec is not None and (gpu_request := get_gpu_request_from_gpu_spec (gpu_spec )) > 0 :
1144+ gpu_resource , node_affinity , node_taint = _get_pod_spec_parameters_for_gpu (api , gpu_spec )
1145+ logger .debug ("Requesting GPU resource: %s=%d" , gpu_resource , gpu_request )
1146+ resources_requests [gpu_resource ] = str (gpu_request )
1147+ # Limit must be set (GPU resources cannot be overcommitted) and must be equal to request.
1148+ resources_limits [gpu_resource ] = str (gpu_request )
1149+ # It should be NoSchedule, but we also add NoExecute toleration just in case.
1150+ for effect in [TaintEffect .NO_SCHEDULE , TaintEffect .NO_EXECUTE ]:
1151+ tolerations .append (
1152+ client .V1Toleration (key = node_taint , operator = Operator .EXISTS , effect = effect )
11451153 )
1146- logger .debug ("Requesting GPU resource: %s=%d" , gpu_resource , gpu_request )
1147- resources_requests [gpu_resource ] = str (gpu_request )
1148- # Limit must be set (GPU resources cannot be overcommitted)
1149- # and must be equal to request.
1150- resources_limits [gpu_resource ] = str (gpu_request )
1151- # It should be NoSchedule, but we also add NoExecute toleration just in case.
1152- for effect in [TaintEffect .NO_SCHEDULE , TaintEffect .NO_EXECUTE ]:
1153- tolerations .append (
1154- client .V1Toleration (key = node_taint , operator = Operator .EXISTS , effect = effect )
1155- )
1154+ else :
1155+ # Prevents GPU allocation if NVIDIA_VISIBLE_DEVICES with a value such as "all" is baked
1156+ # into the image (NVIDIA images and images based on them including dstackai/base)
1157+ # See https://github.com/NVIDIA/k8s-device-plugin/issues/61
1158+ env_vars .append (client .V1EnvVar (name = "NVIDIA_VISIBLE_DEVICES" , value = "void" ))
11561159 if (memory_min := resources_spec .memory .min ) is not None :
11571160 resources_requests ["memory" ] = format_memory (memory_min )
11581161 if (memory_max := resources_spec .memory .max ) is not None :
@@ -1272,6 +1275,7 @@ def _create_job_pod(
12721275 limits = resources_limits ,
12731276 ),
12741277 volume_mounts = volume_mounts ,
1278+ env = env_vars ,
12751279 )
12761280 ],
12771281 image_pull_secrets = (
0 commit comments