The module lifecycle stage: Generally available version
The module has requirements for installation
v0.8.1
Release date: 2026-10-01
The agent deletes BlockDevice resources that have stayed Missing past a configurable retention, the scheduler extender no longer promises the same free space twice in HA mode, and inactive thin volumes are activated again.
Highlights
Changes in this release:
- New module setting
missingBlockDeviceRetentionHours(24 by default): aBlockDevicewhose device has been gone for that long and that noLVMVolumeGroupuses is deleted, so nodes with dynamically mapped LUNs no longer collectMissingresources forever. - With two replicas of
sds-common-scheduler-extender(HA mode), space reservations are served by one elected replica, so two Pods can no longer be promised the same free space of a thin pool. - A thin
LVMLogicalVolumedeactivated while its thin pool stayed active is activated again by the agent.
New features
This release adds:
- Module setting
missingBlockDeviceRetentionHours(hours, 0 to 8760, 24 by default). ABlockDevicethat is not consumable is not deleted when its device disappears: it gets theMissingcondition,Trueafter 10 minutes of absence. The agent now deletes such a resource of its node onceMissinghas beenTruefor the retention, provided noLVMVolumeGrouplists it instatus.nodesand itsstatus.lvmVolumeGroupNamedoes not name an existingLVMVolumeGroup, so a Physical Volume lost from under a live Volume Group stays visible. If the device returns, the resource is created again.0disables the deletion. The new metricsds_node_configurator_block_devices_missing{node,reason}counts theMissing=Trueresources that remain; each deletion is logged by the agent. - On DKP 1.78 and later, the module’s access roles follow the capability/scope RBAC scheme: the ClusterRoles
d8:system-capability:sds-node-configurator:viewandd8:system-capability:sds-node-configurator:editgrant read-only and full access toBlockDevice,LVMVolumeGroup,LVMVolumeGroupSet,LVMLogicalVolumeandLVMLogicalVolumeSnapshot. Below 1.78 the module keeps thed8:manage:permission:module:sds-node-configurator:viewand:editroles.
Fixes
This release fixes:
- In HA mode, the two
sds-common-scheduler-extenderreplicas each kept their own space reservations in memory, so scheduling requests answered by different replicas could be promised the same free space and overcommit a thin pool. The replicas now elect a leader over the Leased8-sds-node-configurator/sds-common-scheduler-extender; only the leader serves filtering, scoring and reservation requests, and the other replica forwards them to it, answering503while no leader is reachable. - A thin
LVMLogicalVolumedeactivated on its own (for example, withlvchange -an) while its thin pool stayed active was never activated again, so the volume stayed unavailable. The agent now runsvgchange -ayfor its Volume Group as it already did for thick volumes and thin pools. Logical volumes carrying the activation skip flag, which the module never sets, are still left inactive.
Upgrade notes
Before upgrading, note the following:
- Deletion of
Missingresources is on by default. Right after the update, the agent deletes everyBlockDevicethat has already beenMissing=Truefor more than 24 hours and is not used by anLVMVolumeGroup. To keep them, setmissingBlockDeviceRetentionHoursto0or to a larger value before updating. - On DKP 1.78 and later, the
d8:manage:permission:module:sds-node-configurator:viewand:editClusterRoles are replaced byd8:system-capability:sds-node-configurator:viewand:edit. Bindings that reference the old role names directly have to be switched to the new ones.
Docs
Documentation changes:
- The Russian reference for
BlockDevicenow coversstatus.conditionsand its fields.
Dependencies
Dependency updates:
LVM2 (lvm,dmsetupon the nodes):main snapshot→2.03.42(changelog)- The static
lvmanddmsetupthe module installs on the nodes now come from the LVM2 2.03.42 release. The previous build pinned a revision but never checked it out, so nodes got an unreleased snapshot of the LVM2 main branch.
- The static
v0.8.0
Release date: 2026-09-24
The module’s files on the node move from /opt/deckhouse/sds to /var/lib/deckhouse/sds, the agent stops reading LVM from virtual machine disks, and thin snapshots no longer depend on the dm_snapshot kernel module.
Highlights
Changes in this release:
- The module’s node tree moves to
/var/lib/deckhouse/sds, which stays writable on nodes whose/optis read-only, and thefileDevicesDirectorydefault becomes/var/lib/deckhouse/sds/file-devices. Existingspec.fileDevicesentries under the old directory keep working where they are. - On a node that runs virtual machines, the Volume Groups a nested cluster builds on its disks no longer turn into
LVMVolumeGroupandBlockDeviceresources of the host cluster. LVMLogicalVolumeSnapshot, restores from a VolumeSnapshot and clones of thin volumes work on nodes without thedm_snapshotkernel module.
Improvements
This release improves:
- New metrics:
sds_node_configurator_published_block_devicesandsds_node_configurator_published_devices_directory_presentshow how many devices the agent keeps out of LVM on each node and whether it found kubelet’s directory of published block volumes there, andsds_node_configurator_legacy_file_devices_directory_lvgscounts theLVMVolumeGroupresources whosespec.fileDevicesstill name/opt/deckhouse/sds/file-devices; the module log lists their names.
Fixes
This release fixes:
- On a node that runs virtual machines (DVP), the agent read LVM inside VM disks: a guest cluster’s Volume Groups appeared as
LVMVolumeGroupresources and its disks asBlockDeviceresources of the host cluster. The agent’slvmcommands now reject every device kubelet has published to a Pod as a block volume, with its partitions and whatever is stacked on it, for any CSI driver. Resources created this way before the update leaveReadyand can be deleted; the Volume Group inside the VM is not touched. - A Volume Group tagged
storage.deckhouse.io/lvmVolumeGroupName=<name>for anLVMVolumeGroupthat does not exist in this cluster was imported as a new resource, although only the module in another cluster (for example, inside a virtual machine) writes that tag. It is no longer imported: the agent logs the refusal once and counts it insds_node_configurator_lvm_volume_group_import_refused_total. A Volume Group handed over withstorage.deckhouse.io/enabled=trueand no name tag is imported as before, and so is a file-backed one. - Creating an
LVMLogicalVolumeSnapshot, restoring from a VolumeSnapshot and cloning a thinLVMLogicalVolumefailed on nodes without thedm_snapshotkernel module loaded, withsnapshot: Required device-mapper target(s) not detected in your kernel. Thin snapshots are now created without that module. The agent still loadsdm_snapshoton every node with thin provisioning, and a node where it is missing no longer keeps the agent from starting. - The bundled
lvmcould not load a missing device-mapper kernel module by itself and reported the target as not detected instead. It now calls the node’s/sbin/modprobe.
Breaking changes
Changes that affect backward compatibility:
- The module no longer installs
lvmanddmsetupunder/opt/deckhouse/sds/bin, and removes the old copies from nodes. Scripts outside the module that run them from there have to use/var/lib/deckhouse/sds/bin/.
Upgrade notes
Before upgrading, note the following:
- Nothing has to be done by hand. Once the agent Pod has restarted on a node, the next bashible run removes the files the module used to install under
/opt/deckhouse/sds; files of other modules and backing files there are left in place. Scripts that ran/opt/deckhouse/sds/bin/lvmordmsetuphave to switch to/var/lib/deckhouse/sds/bin/. spec.fileDevices[].directoryis immutable, so entries created with the old default/opt/deckhouse/sds/file-deviceskeep naming it, and the agent keeps accepting it. Do not move their backing files by hand; the FAQ describes how to move an entry to the new directory online. Create new entries under the new default. AfileDevicesDirectoryset explicitly in the module config is kept as is.
Docs
Documentation changes:
- FAQ: a section on backing files created before the base directory moved, with a procedure that moves an entry to the new directory using
pvmove.
v0.7.5
Release date: 2026-09-14
The scheduler extender now runs on the control-plane nodes, next to the kube-scheduler that consults it.
Highlights
Changes in this release:
- The
sds-common-scheduler-extenderPod is placed on control-plane nodes instead of system ones, and tolerates their taints.
Fixes
This release fixes:
- The
sds-common-scheduler-extenderDeployment asked for system nodes and carried thesystemtolerations, which tolerate neither the control-plane taint nor custom ones, so the Pod could not be placed on a control-plane node. It now selects master nodes — falling back to system nodes in clusters that expose no master role — and tolerates any node, which puts it next to the kube-scheduler that calls it on every scheduling attempt of the modules that register it.
v0.7.4
Release date: 2026-09-11
Controller and scheduler extender metrics are now published through a kube-rbac-proxy, and percent-sized LVMLogicalVolumes are no longer rejected or left in Failed once they reach their requested size.
Highlights
Changes in this release:
- The
/metricsendpoints of the controller and the scheduler extender are no longer reachable without authentication: both bind on127.0.0.1and a kube-rbac-proxy publishes them, so a scrape needsgetondeployments/prometheus-metrics. - A percent-sized
LVMLogicalVolume—100%FREEof a whole volume group, the shape sds-elastic uses for one OSD per disk — is no longer refused at creation and no longer parked inFailedwithunable to extend LV, err: not enough space. - An LVM scan that reaches a multipath map with no remaining paths no longer blocks the agent, so the node keeps reporting its block devices and its RWO volumes can move to another node.
Improvements
This release improves:
- Metrics of the scheduler extender are collected for the first time: the manager had always bound the port, but nothing declared or scraped it.
utils_commands_execution_count_totalandutils_commands_errors_count_totalare exported at last. Both were incremented in about forty places in the agent and the controller but never registered, so nothing they counted was visible.- All binaries of the module log through one shared logger. The name of the component that emitted a record is now a field of the record (
logger) rather than a bracketed prefix inside the message text.
Fixes
This release fixes:
LVMLogicalVolumewith a percentage inspec.sizeis computed against a capacity LVM reports as the raw device sum, which is not extent-aligned. Rounding the request up landed one extent past that capacity, so a request for 100% of a volume group was judged not to fit into it: creation was refused, and the extender put an already full-size volume intoFailed. Percent sizes are now floored to the extent boundary.- An
LVMLogicalVolumethat had been markedFailedbecause the group’s free space still lagged behind the just-created LV stayedFailedfor the rest of its life, since later passes returned early on a volume that was already at its requested size. Such a volume now moves toCreated. - The agent could report
block device size is invalidfor a healthy device: the ioctl output variable lived on the stack and a stack growth during the call moved it, so the size was written to the old address and stayed zero. - An LVM scan that reached a multipath map whose paths were all gone blocked in the kernel instead of failing, and every stuck scan held the map open. That stalled the agent, kept
multipath -ffrom removing the map, and left the volume inNode.status.volumesInUse, so it could not be attached elsewhere. Such maps — ampath-device-mapper UUID with no slaves — are now rejected in theglobal_filterof every LVM command.
Security updates
Security updates in this release:
- Anonymous access to the controller and scheduler extender metrics is closed. Previously the endpoints authenticated no one, were reachable from every pod in the cluster, and the ServiceMonitor sent the Prometheus ServiceAccount token to them over plain HTTP.
golang.org/x/cryptoused by the module hooks is updated to 0.56.0, which closes CVE-2026-56854 (critical, authentication bypass inx/crypto/ssh), CVE-2026-56855 and CVE-2026-78662.
Upgrade notes
Before upgrading, note the following:
- Nothing has to be done by hand for metrics: the ServiceMonitor shipped with the module already scrapes the proxy over HTTPS with a token. Only a collector of your own that used to read the controller metrics directly over HTTP has to be pointed at the proxy port and granted
getondeployments/prometheus-metrics. - Log records changed shape, so a filter that matched the component name inside the message text has to match the
loggerfield instead.
v0.7.3
- Added the Missing condition to BlockDevice: a missing but still occupied device (e.g., part of an LVM Physical Volume) no longer remains forever with a stale status.path. It is first set to Unknown; True is set only if the device is continuously absent for 10 minutes, so a flapping iSCSI path that recovers on its own is not marked. The condition is cleared as soon as the device is found again; the object itself is not deleted to avoid breaking references from LVMVolumeGroup and LVMLogicalVolume
- Fix: the agent no longer crashes on a cached logical volume without LVM attributes
- Fix: VPA ceilings for the agent, scheduler-extender, and controller are raised to match measured consumption
- Fix: the release image is no longer built from a cache with an outdated changelog.yaml — git-mapping dependencies are tied to the install stage where the file is copied
- Updated base images to v2.1.3 and lib-helm to 1.72.14
- Documentation: described virtual disk serial numbers
- Internal build changes for the module
v0.7.2
- Bugfix: the controller is granted permission to write events (create and patch) - previously the event write was denied by RBAC
- CVE fixes
- Internal build changes: CI updated, crds, docs and openapi are shipped in the release image
v0.7.1
- Correction: one “orphaned” device-mapper device without a disk no longer stops BlockDevice detection on the entire node - previously, because of it, the agent did not create a single BlockDevice on the node, including healthy disks
- Correction: LVMVolumeGroup with a single PV whose name could not be determined immediately no longer hangs in Pending forever - empty status.nodes post and no retry in the absence of udev events have been fixed
- Correction: the agent substitutes the serial number inherited from the parent device if direct reading of the serial number fails (multipath participants, crypt/dm devices) - previously such devices were skipped when detecting BlockDevice
- Optional resources (VerticalPodAutoscaler, PodMonitor/ServiceMonitor) are now enabled based on the presence of a CRD in the API, and not based on the enabledModules list
- Documentation: fixed duplication of the description key in the Russian CRD LVMVolumeGroup, which broke docs-builder, added the missing status.extentSize description and restored the blockDevice description
v0.7.0
- Correction: the agent no longer accepts LVM structures inside block devices given to virtual machines as its own - the /dev/loop exception was returned in the LVM global_filter. Fixed the resulting LVMVolumeGroup failures with CacheEmpty and ScanFailed causes - the VG name is no longer considered an identifier, and the LVM warning about a duplicate of someone else’s name is not attributed to our group
- Added support for LVM on files: spec.fileDevices field of LVMVolumeGroup and LVMVolumeGroupSet. The agent creates a file, connects it as a loop device and uses it as a PV, which gives LVM storage on a node without a free disk; the blockDeviceSelector field has become optional
- The scheduler (scheduler-extender) takes into account the PVCs listed in the extra-pvcs pod annotation
- LVMLogicalVolume, LVMLogicalVolumeSnapshot and LVMVolumeGroupSet publish status.conditions; BlockDevice now has a Consumable condition, explaining why the device cannot be used; processing of LVMVolumeGroup conditions has been brought to a general form
- Correction: a volume created from a snapshot or clone is expanded to the requested size - previously the PVC remained in Pending waiting for a size that never appeared
- Correction: thin pool set by percentage of VG size no longer gets stuck at VGConfigurationApplied=False due to LVM rounding by one extent
- Correction: an idle call to lvextend is recognized as harmless on LVM 2.03.16 - otherwise LVMVolumeGroup remained in NotReady
- Correction: when taking control of an existing VG, blockDeviceSelector no longer remains empty
- Correction: after pvcreate and vgcreate the agent calls udevadm to update the udev database
- Correction: when storage-foundation is enabled, the agent loads the dm_snapshot kernel module
- Removed outdated CRD LvmVolumeGroupBackup, left over from a one-time migration: the new hook removes finalizers from leftovers and removes the CRD itself
- Added an experimental mode for detecting block devices via netlink, enabled by the ENABLE_NETLINK_BLOCK_DEVICE_DISCOVERY flag
- Updating base images to v1.3.25, Go 1.26.5 and lib-helm to 1.72.13
- Fixed vulnerabilities in golang.org/x/net, golang.org/x/sys and golang.org/x/crypto
- Internal changes in module assembly and CI, the set of e2e tests has been significantly expanded
v0.6.10
- The general accept rule was removed from LVM global_filter, which led to scanning of non-standard paths (/dev/disk/by-diskseq/*) and duplication of VG names
v0.6.9
- The agent now ignores “foreign” block devices (rbd, drbd, nbd, loop) when scanning LVM
- Fixed handling of duplicate VG names: LVMVolumeGroup status is no longer corrupted
- The blocking of the agent pod launch has been eliminated; added timeouts for LVM commands
- Improved stability of legacy block device names: matching by serial number or WWN prevents re-creation when name changes
- Fixed BlockDevice selector validation: the In operator is now the only valid one
v0.6.8
- Fixed race in scheduler-extender when PVC.Status.Phase is empty: PVC binding decision is now made based on Spec.VolumeName, nodes without a suitable LVMVolumeGroup are always rejected
- Agent is now also scheduled on sds-elastic data nodes
- Updating base images and lib-helm to 1.72.0
v0.6.7
- Update base images, Go 1.25.10 and lib-helm 1.71.12
- Internal changes in module structure and assembly
v0.6.6
- Internal changes in module structure and assembly
v0.6.5
- Update base images, Go 1.25.10 and lib-helm 1.71.11
- Internal changes to the module assembly
v0.6.4
- Corrections to the module structure
v0.6.3
- scheduler-extender: PVCs with a missing StorageClass no longer block pod scheduling
v0.6.2
- CI changes: DistroPackagesProxy and env proxy in werf, improvements to CVE scans (role_name, checkout)
- Added user-authz cluster roles in templates
v0.6.1
- Added detection of mount points via the mountinfo parser in the agent
- Added locality of replicas to scheduler-extender for replicated volumes
- Fixed reconciliation races and loops in LVG/LLV controllers
- ExtentSize was taken into account when comparing in discoverer and fallback 4Mi was added in the LLV controller
- Removed false marking of LLV as Failed when actualSize > spec.size
- Fixed double subtraction of Failed LLV from actualSize when calculating free space in scheduler-extender
- Updating base images and lib-helm
v0.6.0
- CVE fixes
- Transition to a common scheduler for SDS
- Replacing a fixed resize delta with automatic determination of the LVM partition size delta
- Automatic activation of LVM partitions during volume operations
v0.5.16
- Added a hook for clearing resources when the module is turned off
- Removed the enableThinProvisioning setting, we assume that thin provisioning is always enabled
- Module-sdk update for CVE fix, golang update
v0.5.15
- Added metrics for LVM volumes
- Module-sdk update for CVE fix
- Refactoring manifests
v0.5.14
- Updated base images and lib-helm versions
- Set default value for
enableThinProvisioningtotrue - Docs improvements
- Fixed templates security context
- Added support for HA mode
v0.5.13
- Updated base images versions
v0.5.12
- Updated Go version to 1.24.9
- Updated lib-helm to deckhouse_lib_helm-1.64.1
- Documentation updates
v0.5.11
- Fixed volume cleanup for thin volumes in some OSes
v0.5.10
- Removed obsolete python requirements
v0.5.9
- Fixed bug with unactivation of logical volumes
v0.5.8
- Added release notes
v0.5.7
- Fix sys-fs-cgroup error for containerdv2 support
v0.5.6
- Added additional mounts for containerd v2 support
v0.5.5
- CVE fixes
v0.5.4
- CVE fixes
- Internal changes for containerd v2 support
v0.5.3
- Fixed bug preventing LVG status updates when missed/notready nodes are present in the cluster
v0.5.2
- Removed support for sds-drbd module
- Added hiding of csi-scsi-generic devices
v0.5.1
- Technical release, module refactoring
v0.5.0
- Added ability to wipe data in enterprise versions
- Multiple documentation fixes
v0.4.6
- Technical release. Removed “Preview” status from documentation
v0.4.5
- Numerous documentation fixes
- Added LVMVolumeGroupSet and LVMLogicalVolumeSnapshots
- Fixed work with labels and finalizers in some internal objects
- Added dm_snapshot loading when needed
v0.4.3
- Fixed crash of BlockDevices migration script when finalizers are missing on resources
v0.4.2
- Fix for supporting BlockDevice serial numbers up to 63 characters long
v0.4.1
- Fixed potential issue with missing labels in LvmVolumeGroup->LVMVolumeGroup migration hook
- Added controller that tracks labels on BlockDevice resources for quick updates of LVMVolumeGroup resources
v0.4.0
- LvmVolumeGroups resources will be migrated to LVMVolumeGroups
- Exact BlockDevices lists in LVMVolumeGroups will be migrated to selectors
- Multiple fixes in controllers and documentation
v0.3.2
- Fix in sds-health-watcher-controller which could incorrectly handle the status of some nodes
v0.3.1
- Updated golang to current 1.22.6 to close known vulnerabilities
v0.3.0
- Added thin provisioning configuration in mc for automatic dm_thin_pool module loading
- Images moved to distroless
- Added labels to BlockDevices entity (for future use in BlockDevicesSelectors)
- Multiple bug fixes and documentation improvements
v0.2.5
- Added metrics and their collection in Prometheus, health check ports moved to correct ones
v0.2.4
- Added auto-expansion for thin pools LVM volume groups and LVM logical volumes
v0.2.3
- Added internal cache for performance improvement
- Added health and readiness checks to controller
- Improved resource display in cli
- Now LVM volume groups are deleted when corresponding k8s resource is deleted, not when annotation is added
- Added LVM volume group size specification in percentages
- Added AllocationLimit support in LVM volume group
- Added support for contiguous volumes in sds-local-volume
v0.2.1
- Added multipath devices support
v0.2.0
- Added LVMLogicalVolumeWatcher CRDs
- Added more test cases
- Added AreSizesEqualWithinDelta function
- Fixed resize for thinPools
- Added tests to LvmLogicalVolumeWatcher controller
- Fixed naming in LVMLogicalVolume
- Added node affinity
- Enhanced LVMLogicalVolume handling with logging, size display, and event processing
- Statically linked nsenter, lsblk and lvm utils
- Fixed serial discovery by switching to dynamic lsblk
- Rewrote bin-copier script in Golang
- Moved lsblk and its libraries inside the agent image
- Added age field
- Implemented stderr filtering for LVM commands
- Added bench-tests for LVMLogicalVolume controller
- Changed size type from string to quantity
- Added parallel reconciliation to lvm_logical_volume_watcher and VG size validation to lvm_volume_group_watcher