@@ -240,24 +240,24 @@ section above apply here unchanged.
240240#### Retrofitting an existing pool
241241
242242For a GPU node pool that already exists, do the retrofit in this order:
243- standalone driver ready ** first** , then the opt-out label, then the GPU
244- Operator. The label takes effect the moment it lands, disabling the
245- kube-system DaemonSet whose init container finalizes GKE's managed driver
246- install — so on a labeled pool still set to ` gpu-driver-version=default ` (or
247- ` latest ` ), every node created in the interim (autoscaling, upgrade,
248- auto-repair) comes up ** driverless ** . Deploying the standalone installer
249- alone does not close that gap either — Google's ` nvidia-driver-installer `
250- DaemonSet
251- [ ignores nodes configured for automatic driver installation ] ( https://cloud.google.com/kubernetes-engine/docs/troubleshooting/gpus#gpu_device_plugins_fail_with_crashloopbackoff_errors ) ,
252- so it skips every node of a pool whose driver mode is still ` default ` . Only
253- the sequence below keeps the pool functional at every step.
254-
255- ** Step 1 — apply the standalone
256- [ ` nvidia-driver-installer ` DaemonSet ] ( https://cloud.google.com/kubernetes-engine/docs/how-to/gpus#installing_drivers ) . **
257- Applying it early is safe: it skips automatic-install nodes, so it is a
258- no-op until step 2 flips the pool's driver mode.
259-
260- ** Step 2 — switch the pool to ` gpu-driver-version=disabled ` ** (restate the
243+ driver mode first, then the opt-out label, then the bundle. The bundle
244+ carries the driver installer, so — unlike the hand-applied arrangement this
245+ replaces — there is nothing to apply out-of-band, but the installer only
246+ arrives with the bundle in step 3: between step 1 and step 3 the pool has a
247+ scheduling gap, described per step below. Plan the retrofit as one sitting
248+ with the bundle generated in advance.
249+
250+ ** Step 0 — if migrating from a hand-applied installer, delete it first. **
251+ The bundle's DaemonSet shares the name ` nvidia-driver-installer ` in
252+ ` kube-system ` , and Helm will not adopt a pre-existing object — step 3 would
253+ fail. Nodes keep their loaded drivers; only the provisioning workload is
254+ replaced.
255+
256+ ``` bash
257+ kubectl delete daemonset -n kube-system nvidia-driver-installer --ignore-not-found
258+ ```
259+
260+ ** Step 1 — switch the pool to ` gpu-driver-version=disabled ` ** (restate the
261261pool's actual accelerator type and count):
262262
263263``` bash
@@ -267,31 +267,20 @@ gcloud container node-pools update POOL_NAME \
267267 --accelerator type=nvidia-h100-80gb,count=8,gpu-driver-version=disabled
268268```
269269
270- The driver-mode update may re-create the pool's nodes; with the standalone
271- installer already applied, re-created and future nodes come up with a
272- driver, and GKE's device plugin (not yet disabled) keeps advertising
273- ` nvidia.com/gpu ` — the pool stays schedulable throughout.
274-
275- ** Step 3 — verify the driver before touching the label.** Every GPU node
276- should be running the installer's pods and still report non-zero allocatable
277- ` nvidia.com/gpu ` (advertised, for now, by GKE's plugin):
278-
279- ``` bash
280- kubectl get pods -n kube-system -l k8s-app=nvidia-driver-installer -o wide
281- kubectl get nodes -l cloud.google.com/gke-accelerator \
282- -o custom-columns=' NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu'
283- ```
284-
285- ** Step 4 — apply the opt-out label.** This begins the handoff: the label
286- immediately evicts GKE's managed plugin, so from this point until step 5's
287- Operator plugin registers, the pool has ** no** ` nvidia.com/gpu ` advertiser
288- and GPU pods will not schedule. That brief advertiser-free window is the
289- accepted cost of the handoff direction — do ** not** invert it by deploying
290- the Operator's plugin onto a still-unlabeled pool, which would put two
291- advertisers on the same nodes (the dual-advertisement state the
270+ The driver-mode update may re-create the pool's nodes. Until step 3's
271+ installer runs, re-created nodes come up ** driverless while GKE's plugin
272+ still advertises** ` nvidia.com/gpu ` on them — GPU pods scheduled there will
273+ fail. Avoid scheduling GPU work from here until the handoff completes
274+ (cordon the pool's nodes for GPU workloads if the cluster is busy).
275+
276+ ** Step 2 — apply the opt-out label.** This evicts GKE's managed plugin, so
277+ from this point until step 3's Operator plugin registers, the pool has
278+ ** no** ` nvidia.com/gpu ` advertiser — which also stops the driverless nodes
279+ from being advertised. Do ** not** invert the order by deploying the bundle
280+ onto a still-unlabeled pool: that would put two advertisers on the same
281+ nodes (the dual-advertisement state the
292282[ allocation-policy gates] ( #the-three-bundle-installer-settings ) exist to
293- prevent). Have the bundle from step 5 generated in advance to keep the
294- window short, and avoid scheduling GPU work during it.
283+ prevent).
295284Note that ` --node-labels ` on update ** replaces** the pool's full user-label
296285set: first list the labels the pool already carries, then pass the complete
297286set with the new label appended:
@@ -315,18 +304,22 @@ expects — without it, `value(config.labels)` joins entries with semicolons,
315304which the update rejects. Omitting an existing label removes it from the
316305pool's nodes, which can break scheduling that depends on it.
317306
318- ** Step 5 — deploy the GPU Operator and wait for its plugin.** Deploy the
319- AICR bundle generated with ` --profile gpuStack=bundle-installer ` , then wait
320- until the Operator's device-plugin pods are Running on the labeled nodes and
321- every GPU node again reports non-zero allocatable ` nvidia.com/gpu ` — that
322- closes the advertiser-free window opened in step 4. Confirm the full result
323- with the checks in [ Verifying the handoff] ( #verifying-the-handoff ) .
307+ ** Step 3 — deploy the bundle.** Deploy the AICR bundle generated with
308+ ` --profile gpuStack=bundle-installer ` . Its ` gcp-driver-installer ` DaemonSet
309+ installs the pinned driver on the labeled, driver-mode-disabled nodes
310+ (nodes that already have a loaded driver are skipped), and the GPU
311+ Operator's device plugin registers once the driver is ready — closing the
312+ window opened in steps 1–2. Wait until every GPU node again reports
313+ non-zero allocatable ` nvidia.com/gpu ` , then confirm the full result with
314+ the checks in [ Verifying the handoff] ( #verifying-the-handoff ) .
324315
325316** Rollback:** if the Operator's device plugin fails to come up after the
326317label lands, remove the label (another ` --node-labels ` update passing the
327- full set with the opt-out label omitted) — GKE's plugin returns and the pool
328- resumes advertising GPUs, with the driver still supplied by the standalone
329- installer.
318+ full set with the opt-out label omitted) — GKE's plugin returns and the
319+ pool resumes advertising GPUs. Nodes the bundle's installer already
320+ provisioned keep their driver; nodes re-created before step 3 ran are
321+ driverless until the pool's driver mode is restored
322+ (` gpu-driver-version=default ` ) or the bundle deploys.
330323
331324#### Verifying the handoff
332325
@@ -426,7 +419,7 @@ stay `Pending`, even though the driver is present and healthy.
426419(yet) registered. The label immediately evicts GKE's managed plugin, so
427420until the Operator's plugin comes up, the node has no ` nvidia.com/gpu `
428421advertiser at all. A brief window in this state is the expected
429- intermediate step of the retrofit handoff (step 4 of
422+ intermediate step of the retrofit handoff (step 2 of
430423[ Retrofitting an existing pool] ( #retrofitting-an-existing-pool ) ); it is a
431424problem only when nothing closes it.
432425
0 commit comments