Skip to content

Commit

Permalink
[controller] Add data wipe (#122)
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksandr Stefurishin <aleksandr.stefurishin@flant.com>
Signed-off-by: Pavel Karpov <pavel.karpov@flant.com>
Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
Signed-off-by: Anton Sergunov <anton.sergunov@flant.com>
Signed-off-by: v.oleynikov <vasily.oleynikov@flant.com>
Signed-off-by: Denis.Rebenok <denis.rebenok@flant.ru>
Co-authored-by: Aleksandr Stefurishin <aleksandr.stefurishin@flant.com>
Co-authored-by: Pavel Karpov <pavel.karpov@flant.com>
Co-authored-by: Nikolay Demchuk <nikolay.demchuk@flant.com>
Co-authored-by: Anton Sergunov <anton.sergunov@flant.com>
Co-authored-by: v.oleynikov <vasily.oleynikov@flant.com>
Co-authored-by: Denis.Rebenok <denis.rebenok@flant.ru>
  • Loading branch information
7 people authored Feb 25, 2025
1 parent 48ca0f5 commit 1778068
Show file tree
Hide file tree
Showing 18 changed files with 508 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .werf/consts.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# base images
{{- $_ := set $ "BASE_ALT" "registry.deckhouse.io/base_images/alt:p10@sha256:f105773c682498700680d7cd61a702a4315c4235aee3622757591fd510fb8b4a" }}
{{- $_ := set $ "BASE_ALT_P11" "registry.deckhouse.io/base_images/alt:p11@sha256:e47d84424485d3674240cb2f67d3a1801b37d327e6d1eb8cc8d01be8ed3b34f3" }}
{{- $_ := set $ "BASE_GOLANG_1_23" "registry.deckhouse.io/base_images/golang:1.23.5-alpine3.20@sha256:623ef3f63012bbd648021a2f097de3f411889332ba83bd98f0ac8d1288bdaa06" }}
{{- $_ := set $ "BASE_GOLANG_1_23" "registry.deckhouse.io/base_images/golang:1.23.6-alpine3.20@sha256:3058c63e0e2532881949c4186414baa24a0f9a8f9349b1853daa49be816f42e9" }}
{{- $_ := set $ "BASE_SCRATCH" "registry.deckhouse.io/base_images/scratch@sha256:653ae76965c98c8cd1c8c9ff7725316d2983986f896655b30e0f44d2f8b2dd7e" }}
{{- $_ := set $ "BASE_ALPINE" "registry.deckhouse.io/base_images/alpine:3.20.3@sha256:41628df7c9b935d248f64542634e7a843f9bc7f2252d7f878e77f7b79a947466" }}

Expand Down
1 change: 1 addition & 0 deletions api/v1alpha1/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package v1alpha1
const (
PhaseCreated = "Created"
PhasePending = "Pending"
PhaseCleaning = "Cleaning"
PhaseResizing = "Resizing"
PhaseFailed = "Failed"
PhaseNotReady = "NotReady"
Expand Down
3 changes: 2 additions & 1 deletion api/v1alpha1/lvm_logical_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ type LVMLogicalVolumeThinSpec struct {
}

type LVMLogicalVolumeThickSpec struct {
Contiguous *bool `json:"contiguous"`
Contiguous *bool `json:"contiguous,omitempty"`
VolumeCleanup *string `json:"volumeCleanup,omitempty"`
}
type LVMLogicalVolumeStatus struct {
Phase string `json:"phase"`
Expand Down
8 changes: 8 additions & 0 deletions crds/doc-ru-lvmlogicalvolume.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ spec:
contiguous:
description: |
Если true, логический том будет создан с флагом contiguous. Примечание: Этот флаг следует использовать с осторожностью, так как он может привести к невозможности создания LV, не смотря на наличие свободного пространства.
volumeCleanup:
description: |
Метод очистки тома после удаления PV.
Если параметр не задан, после удаления PV данные могут удалиться, либо остаться. Гарантий удаления или неудаления нет.
Допустимые значения:
- `RandomFillSinglePass` - том будет перезаписан случайными данными один раз перед удалением. Использовать эту опцию не рекомендуется для твердотельных накопителей, так как она уменьшает ресурс накопителя.
- `RandomFillThreePass` - том будет перезаписан случайными данными три раза перед удалением. Использовать эту опцию не рекомендуется для твердотельных накопителей, так как она уменьшает ресурс накопителя.
- `Discard` - все блоки тома будут отмечены как свободные с использованием системного вызова `discard` перед удалением. Эта опция имеет смысл только для твердотельных накопителей.
status:
description: |
Описывает состояние ресурса.
Expand Down
29 changes: 19 additions & 10 deletions crds/lvmlogicalvolume.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ spec:
- rule: |
(self.type == "Thin" && has(self.thin) && !has(self.thick)) || self.type != "Thin"
message: "Field 'thin' is required and field 'thick' is forbidden when 'type' is 'Thin'."
- rule: |
(!has(oldSelf.thick) || has(self.thick))
message: "Field 'thick' cannot be removed."
- rule: |
(!has(self.thick) || !has(self.thick.contiguous) || (has(self.thick.contiguous) && self.thick.contiguous == oldSelf.thick.contiguous))
- rule: >
(
(!has(self.thick) || !has(self.thick.contiguous)) &&
(!has(oldSelf.thick) || !has(oldSelf.thick.contiguous))
) || (
has(self.thick) && has(self.thick.contiguous) &&
has(oldSelf.thick) && has(oldSelf.thick.contiguous)
)
message: "Field 'contiguous' is immutable and cannot be added if not specified at creation."
required:
- actualLVNameOnTheNode
Expand Down Expand Up @@ -100,13 +103,9 @@ spec:
thick:
type: object
x-kubernetes-validations:
- rule: self == oldSelf
message: Value is immutable.
- rule: |
(!has(oldSelf.contiguous) || has(self.contiguous))
message: "Field 'contiguous' cannot be removed."
required:
- contiguous
properties:
contiguous:
type: boolean
Expand All @@ -115,6 +114,16 @@ spec:
message: Value is immutable.
description: |
If true, the Logical Volume will be created with the contiguous flag. Use it carefully as LV might not be created even if there is enough space in VG.
volumeCleanup:
type: string
enum: [RandomFillThreePass, RandomFillSinglePass, Discard]
description: |
The method of the volume cleanup before deletion.
If the parameter is not set, after deleting the PV, the data may be deleted or it may remain. There is no guarantee of deletion or non-deletion.
Allowed values:
- `RandomFillSinglePass`: The volume will be overwritten with random data once before deletion. This option is not recommended for solid-state drives, as it reduces the lifespan of the drive.
- `RandomFillThreePass`: The volume will be overwritten with random data three times before deletion. This option is also not recommended for solid-state drives, as it reduces the lifespan of the drive.
- `Discard`: All blocks of the volume will be marked as free using the `discard`` system call before deletion. This option is only applicable to solid-state drives.
source:
type: object
description: |
Expand Down Expand Up @@ -149,7 +158,7 @@ spec:
properties:
phase:
type: string
enum: [Created, Pending, Resizing, Failed]
enum: [Created, Pending, Cleaning, Resizing, Failed]
description: |
The current resource's phase.
reason:
Expand Down
35 changes: 35 additions & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,38 @@ To extract the `BlockDevice` resource from the `LVMVolumeGroup` resource, you ne
> **Caution!** If the deleting `LVM Volume Group` resource contains any `Logical Volume` (even if it is only the `Thin-pool` that is specified in `spec`), a user must delete all those `Logical Volumes` manually. Otherwise, the `LVMVolumeGroup` resource and its `Volume Group` will not be deleted.

> A user can forbid to delete the `LVMVolumeGroup` resource by annotate it with `storage.deckhouse.io/deletion-protection`. If the controller finds the annotation, it will not delete nether the resource or the `Volume Group` till the annotation removal.

## Protection against data leakage between volumes

When deleting files, the operating system does not physically delete the contents, but only marks the corresponding blocks as “free”. If a new volume receives physical blocks previously used by another volume, the previous user's data may remain in them.

This is possible, for example, in the following case:

- user №1 placed files in the volume requested from StorageClass 1 and on node 1 (no matter in “Block” or “Filesystem” mode);
- user №1 deleted the files and the volume;
- the physical blocks it occupied become “free” but not wiped;
- user №2 requested a new volume from StorageClass 1 and on node 1 in “Block” mode;
- there is a risk that some or all of the blocks previously occupied by user №1 will be reallocated to user №2;
- in which case user №2 has the ability to recover user №1's data.

### Thick volumes

The `volumeCleanup` parameter is provided to prevent leaks through thick volumes.
It allows to select the volume cleanup method before deleting the PV.
Allowed values:

* parameter not specified — do not perform any additional actions when deleting a volume. The data may be available to the next user;

* `RandomFillSinglePass` - the volume will be overwritten with random data once before deletion. Use of this option is not recommended for solid-state drives as it reduces the lifespan of the drive.

* `RandomFillThreePass` - the volume will be overwritten with random data three times before deletion. Use of this option is not recommended for solid-state drives as it reduces the lifespan of the drive.

* `Discard` - all blocks of the volume will be marked as free using the `discard` system call before deletion. This option is only applicable to solid-state drives.

Most modern solid-state drives ensure that a `discard` marked block will not return previous data when read. This makes the `Discard' option the most effective way to prevent leakage when using solid-state drives.
However, clearing a cell is a relatively long operation, so it is performed in the background by the device. In addition, many drives cannot clear individual cells, only groups - pages. Because of this, not all drives guarantee immediate unavailability of the freed data. In addition, not all drives that do guarantee this keep the promise.
If the device does not guarantee Deterministic TRIM (DRAT), Deterministic Read Zero after TRIM (RZAT) and is not tested, then it is not recommended.

### Thin volumes

When a thin-pool block is released via `discard` by the guest operating system, this command is forwarded to the device. If a hard disk drive is used or if there is no `discard` support from the solid-state drive, the data may remain on the thin-pool until such a block is used again. However, users are only given access to thin volumes, not the thin-pool itself. They can only retrieve a volume from the pool, and the thin volumes are nulled for the thin-pool block on new use, preventing leakage between clients. This is guaranteed by setting `thin_pool_zero=1` in LVM.
35 changes: 35 additions & 0 deletions docs/USAGE.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,38 @@ kubectl delete lvg %lvg-name%
> **Внимание!** Если удаляемый ресурс `LVMVolumeGroup` содержит `Logical Volume` (даже если это только `Thin-pool`, который указан в `spec`) пользователю необходимо самостоятельно удалить все `Logical Volume`, которые содержит удаляемая `Volume Group`. В противном случае ни ресурс, ни `Volume Group` удалены не будут.

> Пользователь может запретить удаление `LVMVolumeGroup` ресурса, повесив на ресурс специальную аннотацию `storage.deckhouse.io/deletion-protection`. При наличии данной аннотации контроллер не будет удалять ни ресурс, ни соответствующую `Volume Group` до тех пор, пока аннотация не будет снята с ресурса.

## Защита от утечек данных между томами

При удалении файлов операционная система не удаляет содержимое физически, а лишь помечает соответствующие блоки как «свободные». Если новый том получает физические блоки, ранее использовавшиеся другим томом, в них могут остаться данные предыдущего пользователя.

Это возможно, например, в таком случае:

- пользователь №1 разместил файлы в томе, запрошенном из StorageClass 1 и на узле 1 (не важно, в режиме «Block» или «Filesystem»);
- пользователь №1 удалил файлы и том;
- физические блоки, которые он занимал, становятся «свободными», но не затертыми;
- пользователь №2 запросил новый том из StorageClass 1 и на узле 1 в режиме «Block»;
- есть риск, что часть или все блоки, ранее занимаемые пользователем №1, будут снова выделены пользователю №2;
- в этом случае пользователь №2 имеет возможность восстановить данные пользователя №1.

### Thick-тома

Для предотвращения утечек через thick-тома предусмотрен параметр `volumeCleanup`.
Он позволяет выбрать метод очистки тома перед удалением PV.
Возможные значения:

* параметр не задан — не выполнять никаких дополнительных действий при удалении тома. Данные могут оказаться доступными следующему пользователю;

* `RandomFillSinglePass` — том будет перезаписан случайными данными один раз перед удалением. Использовать эту опцию не рекомендуется для твердотельных накопителей, так как она уменьшает ресурс накопителя.

* `RandomFillThreePass` — том будет перезаписан случайными данными три раза перед удалением. Использовать эту опцию не рекомендуется для твердотельных накопителей, так как она уменьшает ресурс накопителя.

* `Discard` — все блоки тома будут отмечены как свободные с использованием системного вызова `discard` перед удалением. Эта опция имеет смысл только для твердотельных накопителей.

Большинство современных твердотельных накопителей гарантирует, что помеченный `discard` блок при чтении не вернет предыдущие данные. Это делает опцию `Discard` самым эффективным способом предотвращения утечек при использовании твердотельных накопителей.
Однако очистка ячейки относительно долгая операция, поэтому выполняется устройством в фоне. К тому-же многие диски не могут очищать индивидуальные ячейки, а только группы - страницы. Из-за этого не все накопители гарантируют немедленную недоступность освобожденных данных. К тому-же не все накопители, гарантирующие это, держат обещание.
Если устройство не гарантирует Deterministic TRIM (DRAT), Deterministic Read Zero after TRIM (RZAT) и не является проверенным, то использовать его не рекомендуется.

### Thin-тома

В момент освобождения блока thin-тома через `discard` гостевой операционной системы, эта команда пересылается на устройство. В случае использования жесткого диска или отсутствии поддержки `discard` со стороны твердотельного накопителя, данные могут остаться на thin-pool до нового использования такого блока. Однако, пользователям предоставляется доступ только к thin-томам, а не к самому thin-пулу. Они могут получить только том из пула, а для thin-томов производится зануление блока thin-pool при новом использовании, что предотвращает утечки между клиентами. Это гарантируется настройкой `thin_pool_zero=1` в LVM.
1 change: 1 addition & 0 deletions images/agent/src/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func main() {
log.Info(fmt.Sprintf("[main] OS/Arch:Go OS/Arch:%s/%s ", goruntime.GOOS, goruntime.GOARCH))

log.Info(fmt.Sprintf("[main] Feature SnapshotsEnabled: %t", feature.SnapshotsEnabled()))
log.Info(fmt.Sprintf("[main] Feature VolumeCleanupEnabled: %t", feature.VolumeCleanupEnabled()))

log.Info("[main] CfgParams has been successfully created")
log.Info(fmt.Sprintf("[main] %s = %s", config.LogLevel, cfgParams.Loglevel))
Expand Down
Loading

0 comments on commit 1778068

Please sign in to comment.