mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-10 14:34:58 +09:00
The VMI webhook, the launcher pod webhook, the license copier and the budget check land separately, yet each depends on what the others write: the template annotation and label, the gpus entry names, the license copy's name, label and keys, and the volume label guest images look for. The package comment states that contract next to the names it uses, so each later piece is written and reviewed against one description rather than against the design document. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin <f@lex.la>
92 lines
4.3 KiB
Go
92 lines
4.3 KiB
Go
/*
|
|
Copyright 2026 The Cozystack Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
// Package gpu holds the names the GPU components of cozystack-controller
|
|
// and cozystack-api share. The pure capacity, budget and tenant logic
|
|
// lives in package model.
|
|
//
|
|
// # Class entries
|
|
//
|
|
// A VM or a worker pool names a GPUClass and a count in its gpus list.
|
|
// The chart renders the entries onto the VMI template as AnnotationGPUs,
|
|
// next to LabelGPUReference, which KubeVirt copies to the VMI and its
|
|
// virt-launcher pod:
|
|
//
|
|
// cozystack.io/gpus: '[{"className":"l40s-24c","count":2}]'
|
|
//
|
|
// # Starting a VMI
|
|
//
|
|
// A mutating webhook on VMI creation resolves each entry to its class and
|
|
// writes one gpus entry per unit, named with VMIGPUNamePrefix and
|
|
// requesting the class's resource name. The entries have to be complete
|
|
// at admission, since KubeVirt renders the launcher pod's requests from
|
|
// the VMI spec and nothing else can change that spec afterwards. The
|
|
// webhook refuses the VMI, naming the class, when an entry:
|
|
//
|
|
// - names a class that does not exist, is being deleted, or has a
|
|
// ResourceNameConflict condition;
|
|
// - is a vGPU class next to another vGPU class, or takes the VMI's units
|
|
// of its class above model.EffectiveMaxCount;
|
|
// - names a vGPU class in a namespace without the vGPU entitlement
|
|
// (model.Entitled);
|
|
// - names a class whose resource name the KubeVirt permittedHostDevices
|
|
// table leaves out, when the table is set (model.PermittedResourceNames),
|
|
// since KubeVirt would accept the VMI and leave it Pending with no pod.
|
|
//
|
|
// A class has ResourceNameConflict when an older class has its resource
|
|
// name (model.Conflicts), so the class tenants already run on keeps it.
|
|
// Age is the creation time: a class whose resource name is edited later
|
|
// is judged by when it was created, not by when it took the name.
|
|
//
|
|
// The webhook also refuses a labelled VMI that carries GPU entries of its own. It
|
|
// reads classes and the KubeVirt CR from the API server, not from a cache,
|
|
// writes no object besides its patch, and checks no capacity: a VM short
|
|
// of a free unit waits in Scheduling like a VM short of CPU.
|
|
//
|
|
// A second mutating webhook adds the classes' tolerations to the
|
|
// virt-launcher pod at creation, and to the temporary pod KubeVirt creates
|
|
// to bind WaitForFirstConsumer volumes. They go on the pod and not on the
|
|
// VMI, because under vmRolloutStrategy LiveUpdate KubeVirt resets a VMI's
|
|
// tolerations to the VM template's on every sync. Both webhooks select on
|
|
// LabelGPUReference and fail closed.
|
|
//
|
|
// # Licenses
|
|
//
|
|
// For each vGPU class with a license, the controller copies the hoster's
|
|
// Secret from LicenseSecretNamespace into every namespace whose
|
|
// LabelNamespaceVGPU is LabelValueTrue, named by LicenseSecretName and
|
|
// labelled LabelGPUClass, with the keys LicenseTokenKey and
|
|
// LicenseGriddConfKey. It deletes a namespace's copies when the label
|
|
// stops being LabelValueTrue, and a class's copies when the class or its
|
|
// license goes. While the hoster's Secret is missing or lacks
|
|
// LicenseTokenKey, it keeps the copies it has, writes no new ones and sets
|
|
// LicenseSecretMissing on the class. It touches no Secret without
|
|
// LabelGPUClass.
|
|
//
|
|
// The VMI webhook adds a secret volume for the copy of the VMI's licensed
|
|
// vGPU class, with LicenseVolumeLabel, and a disk for it after the VMI's
|
|
// other disks with no bootOrder. A missing copy is not refused: kubelet
|
|
// keeps the launcher pod from starting until the copy exists.
|
|
//
|
|
// # Budgets
|
|
//
|
|
// A tenant declares GPU budgets in resourceQuotas under model.ClassQuotaKey
|
|
// per class and QuotaKeyTotal over every class. They are not resource
|
|
// names a pod requests, so the tenant chart keeps them out of the
|
|
// namespace ResourceQuota, and they are checked when a VM or a pool is
|
|
// written, against the class entries it declares.
|
|
package gpu
|