Стадия жизненного цикла модуля: General Availability
Очистка томов при удалении
Возможность очистки томов доступна только в коммерческих редакциях Deckhouse.
При удалении файлов операционная система не удаляет содержимое физически, а лишь помечает соответствующие блоки как «свободные». Если новый том получает физические блоки, ранее использовавшиеся другим томом, в них могут остаться данные предыдущего пользователя.
Пример сценария утечки данных
- Пользователь №1 разместил файлы в томе, запрошенном из StorageClass 1 на узле 1 (в режиме «Block» или «Filesystem»).
- Пользователь №1 удалил файлы и том.
- Физические блоки, которые занимал том, становятся «свободными», но не затертыми.
- Пользователь №2 запросил новый том из StorageClass 1 на узле 1 в режиме «Block».
- Существует риск, что часть или все блоки, ранее занимаемые пользователем №1, будут снова выделены пользователю №2.
- В этом случае пользователь №2 может восстановить данные пользователя №1.
Thick-тома
Для предотвращения утечек данных через thick-тома предусмотрен параметр volumeCleanup, который позволяет выбрать метод очистки тома перед удалением PersistentVolume (PV).
Возможные значения:
-
параметр не задан — дополнительные действия при удалении тома не выполняются. Данные могут остаться доступными следующему пользователю;
-
RandomFillSinglePass— том перезаписывается случайными данными один раз перед удалением. Не рекомендуется для твердотельных накопителей, так как уменьшает ресурс накопителя; -
RandomFillThreePass— том перезаписывается случайными данными три раза перед удалением. Не рекомендуется для твердотельных накопителей, так как уменьшает ресурс накопителя; -
Discard— все блоки тома отмечаются как свободные с использованием системного вызоваdiscardперед удалением. Используйте эту опцию только для твердотельных накопителей.
Большинство современных твердотельных накопителей гарантирует, что помеченный discard блок при чтении не вернет предыдущие данные. Это делает опцию Discard самым эффективным способом предотвращения утечек при использовании твердотельных накопителей.
Однако очистка ячейки — относительно долгая операция, поэтому выполняется устройством в фоне. К тому же многие диски не могут очищать индивидуальные ячейки, а только группы — страницы. Из-за этого не все накопители гарантируют немедленную недоступность освобожденных данных. К тому же не все накопители, гарантирующие это, держат обещание.
Не используйте устройство, если оно не гарантирует Deterministic TRIM (DRAT), Deterministic Read Zero after TRIM (RZAT) и не является проверенным.
Thin-тома
При освобождении блока thin-тома через discard гостевой операционной системы эта команда пересылается на устройство. В случае использования жесткого диска или отсутствия поддержки discard со стороны твердотельного накопителя данные могут остаться на thin pool до нового использования такого блока.
Пользователям предоставляется доступ только к thin-томам, а не к самому thin pool. Они могут получить только том из пула. Для thin-томов производится зануление блока thin pool при новом использовании, что предотвращает утечки между клиентами. Это гарантируется настройкой thin_pool_zero=1 в LVM.
Миграция данных между PVC
Используйте следующий скрипт для переноса данных из одного PVC в другой:
-
Скопируйте скрипт в файл
migrate.shна любом master-узле. -
Используйте скрипт с параметрами:
migrate.sh NAMESPACE SOURCE_PVC_NAME DESTINATION_PVC_NAME
#!/bin/bash
ns=$1
src=$2
dst=$3
if [[ -z $3 ]]; then
echo "You must give as args: namespace source_pvc_name destination_pvc_name"
exit 1
fi
echo "Creating job yaml"
cat > migrate-job.yaml << EOF
apiVersion: batch/v1
kind: Job
metadata:
name: migrate-pv-$src
namespace: $ns
spec:
template:
spec:
containers:
- name: migrate
image: debian
command: [ "/bin/bash", "-c" ]
args:
-
apt-get update && apt-get install -y rsync &&
ls -lah /src_vol /dst_vol &&
df -h &&
rsync -avPS --delete /src_vol/ /dst_vol/ &&
ls -lah /dst_vol/ &&
du -shxc /src_vol/ /dst_vol/
volumeMounts:
- mountPath: /src_vol
name: src
readOnly: true
- mountPath: /dst_vol
name: dst
restartPolicy: Never
volumes:
- name: src
persistentVolumeClaim:
claimName: $src
- name: dst
persistentVolumeClaim:
claimName: $dst
backoffLimit: 1
EOF
kubectl create -f migrate-job.yaml
kubectl -n $ns get jobs -o wide
kubectl_completed_check=0
echo "Waiting for data migration to be completed"
while [[ $kubectl_completed_check -eq 0 ]]; do
kubectl -n $ns get pods | grep migrate-pv-$src
sleep 5
kubectl_completed_check=`kubectl -n $ns get pods | grep migrate-pv-$src | grep "Completed" | wc -l`
done
echo "Data migration completed"
Создание снимков томов
Возможность работы со снимками томов доступна только в коммерческих редакциях Deckhouse Kubernetes Platform и только при использовании LVM-thin томов.
Для работы со снимками томов требуется подключенный модуль snapshot-controller.
Подробную информацию о снимках см. в документации Kubernetes.
Для того чтобы создать снимок тома, выполните следующие действия:
-
Включите модуль
snapshot-controller:d8 s module enable snapshot-controller -
Для того чтобы создать снимок тома, выполните следующую команду с необходимыми параметрами:
d8 k apply -f -<<EOF apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshot metadata: name: my-snapshot namespace: <namespace-name> # Имя пространства имен, где находится PVC spec: volumeSnapshotClassName: sds-local-volume-snapshot-class source: persistentVolumeClaimName: <pvc-name> # Имя PVC, для которого создается снимок EOFВнимание: класс
sds-local-volume-snapshot-classсоздается автоматически. ПараметрdeletionPolicyустановлен вDelete, поэтомуVolumeSnapshotContentудаляется при удалении связанногоVolumeSnapshot. -
Проверьте статус снимка:
d8 k get volumesnapshotКоманда выводит список всех снимков и их текущий статус.
Назначение StorageClass по умолчанию
Добавьте аннотацию storageclass.kubernetes.io/is-default-class: "true" в соответствующий ресурс StorageClass:
d8 k annotate storageclasses.storage.k8s.io <storageClassName> storageclass.kubernetes.io/is-default-class=true
Выбор узлов для работы модуля
Модуль использует узлы, которые имеют метки, указанные в поле nodeSelector в настройках модуля. Сделать это можно следующим образом:
-
Для отображения настроек модуля выполните команду:
d8 k edit mc sds-local-volumeПример вывода:
apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: sds-local-volume spec: enabled: true settings: dataNodes: nodeSelector: my-custom-label-key: my-custom-label-value status: message: "" version: "1" -
Выполните команду для просмотра меток в поле
nodeSelector:d8 k get mc sds-local-volume -o=jsonpath={.spec.settings.dataNodes.nodeSelector}Пример вывода:
nodeSelector: my-custom-label-key: my-custom-label-value -
Модуль выбирает узлы, которые имеют все указанные метки. Измените поле
nodeSelector, чтобы изменить список узлов.Внимание: в поле
nodeSelectorможно указать любое количество меток. Все указанные метки должны присутствовать на узле. Модуль запускает подcsi-nodeтолько на узлах, которые имеют все указанные метки. -
После добавления меток проверьте, что поды
csi-nodeзапущены на узлах:d8 k -n d8-sds-local-volume get pod -owide
Вывод узла из-под управления модуля
Чтобы вывести узел из-под управления модуля, снимите метки, указанные в поле nodeSelector в настройках модуля. Для этого:
-
Выполните команду для просмотра меток в
nodeSelector:d8 k get mc sds-local-volume -o=jsonpath={.spec.settings.dataNodes.nodeSelector}Пример вывода:
nodeSelector: my-custom-label-key: my-custom-label-value -
Снимите указанные метки с узла:
d8 k label node %node-name% %label-from-selector%-Внимание: для снятия метки добавьте знак минуса после ключа метки вместо значения.
-
Проверьте, что pod
csi-nodeудален с узла:d8 k -n d8-sds-local-volume get po -owide
Если под csi-node остался на узле после снятия меток:
-
Проверьте, что метки действительно сняты с узла:
d8 k get node <node-name> --show-labels -
Убедитесь, что на узле нет ресурсов LVMVolumeGroup, которые используются в ресурсах LocalStorageClass. Подробнее см. Проверка зависимых ресурсов LVMVolumeGroup на узле.
Обратите внимание, что на ресурсах LVMVolumeGroup и LocalStorageClass, из-за которых не удается вывести узел из-под управления модуля, будет отображена метка storage.deckhouse.io/sds-local-volume-candidate-for-eviction.
На самом узле будет присутствовать метка storage.deckhouse.io/sds-local-volume-need-manual-eviction.
Создание thin-хранилища
-
Получите список доступных ресурсов BlockDevice в кластере:
d8 k get bdПример вывода:
NAME NODE CONSUMABLE SIZE PATH dev-ef4fb06b63d2c05fb6ee83008b55e486aa1161aa worker-0 false 100Gi /dev/nvme1n1 dev-7e4df1ddf2a1b05a79f9481cdf56d29891a9f9d0 worker-1 false 100Gi /dev/nvme1n1 dev-53d904f18b912187ac82de29af06a34d9ae23199 worker-2 false 100Gi /dev/nvme1n1 -
Создайте ресурс LVMVolumeGroup для узла
worker-0:d8 k apply -f - <<EOF apiVersion: storage.deckhouse.io/v1alpha1 kind: LVMVolumeGroup metadata: name: "vg-2-on-worker-0" spec: type: Local local: nodeName: "worker-0" blockDeviceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: In values: - dev-ef4fb06b63d2c05fb6ee83008b55e486aa1161aa actualVGNameOnTheNode: "vg-2" thinPools: - name: thindata size: 100Gi EOF -
Дождитесь перехода ресурса LVMVolumeGroup в состояние
Ready:d8 k get lvg vg-2-on-worker-0 -wПосле перехода в состояние
Readyна узлеworker-0из блочного устройства/dev/nvme1n1создана группа томов LVM с именемvg-2и thin pool с именемthindata. -
Создайте ресурс LVMVolumeGroup для узла
worker-1:d8 k apply -f - <<EOF apiVersion: storage.deckhouse.io/v1alpha1 kind: LVMVolumeGroup metadata: name: "vg-2-on-worker-1" spec: type: Local local: nodeName: "worker-1" blockDeviceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: In values: - dev-7e4df1ddf2a1b05a79f9481cdf56d29891a9f9d0 actualVGNameOnTheNode: "vg-2" thinPools: - name: thindata size: 100Gi EOF -
Дождитесь перехода ресурса LVMVolumeGroup в состояние
Ready:d8 k get lvg vg-2-on-worker-1 -wПосле перехода в состояние
Readyна узлеworker-1из блочного устройства/dev/nvme1n1создана группа томов LVM с именемvg-2и thin pool с именемthindata. -
Создайте ресурс LVMVolumeGroup для узла
worker-2:d8 k apply -f - <<EOF apiVersion: storage.deckhouse.io/v1alpha1 kind: LVMVolumeGroup metadata: name: "vg-2-on-worker-2" spec: type: Local local: nodeName: "worker-2" blockDeviceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: In values: - dev-53d904f18b912187ac82de29af06a34d9ae23199 actualVGNameOnTheNode: "vg-2" thinPools: - name: thindata size: 100Gi EOF -
Дождитесь перехода ресурса LVMVolumeGroup в состояние
Ready:d8 k get lvg vg-2-on-worker-2 -wПосле перехода в состояние
Readyна узлеworker-2из блочного устройства/dev/nvme1n1создана группа томов LVM с именемvg-2и thin pool с именемthindata. -
Создайте ресурс LocalStorageClass:
d8 k apply -f -<<EOF apiVersion: storage.deckhouse.io/v1alpha1 kind: LocalStorageClass metadata: name: local-storage-class spec: lvm: lvmVolumeGroups: - name: vg-2-on-worker-0 thin: poolName: thindata - name: vg-2-on-worker-1 thin: poolName: thindata - name: vg-2-on-worker-2 thin: poolName: thindata type: Thin reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer EOF -
Дождитесь перехода ресурса LocalStorageClass в состояние
Created:d8 k get lsc local-storage-class -w -
Проверьте, что создан соответствующий StorageClass:
d8 k get sc local-storage-class
Теперь можно создавать PVC, указывая StorageClass с именем local-storage-class.
Проверка зависимых ресурсов LVMVolumeGroup на узле
Выполните следующие шаги:
-
Отобразите ресурсы LocalStorageClass:
d8 k get lsc -
Проверьте список используемых ресурсов LVMVolumeGroup в каждом LocalStorageClass.
Отобразите содержимое всех ресурсов LocalStorageClass:
d8 k get lsc -oyamlИли отобразите содержимое конкретного ресурса:
d8 k get lsc <lsc-name> -oyamlПример ресурса LocalStorageClass:
apiVersion: v1 items: - apiVersion: storage.deckhouse.io/v1alpha1 kind: LocalStorageClass metadata: finalizers: - storage.deckhouse.io/local-storage-class-controller name: test-sc spec: fsType: ext4 lvm: lvmVolumeGroups: - name: test-vg type: Thick reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer status: phase: Created kind: ListВ поле
spec.lvm.lvmVolumeGroupsуказаны используемые ресурсы LVMVolumeGroup. -
Отобразите список ресурсов LVMVolumeGroup:
d8 k get lvgПример вывода:
NAME THINPOOLS CONFIGURATION APPLIED PHASE NODE SIZE ALLOCATED SIZE VG AGE vg0-on-astra-1-8 0/0 True Ready astra-1-8 5116Mi 0 vg0 180d vg0-on-master-0 0/0 True Ready p-master-0 5116Mi 0 vg0 182d vg0-on-redos-murom 0/0 True Ready redos-murom 5116Mi 0 vg0 32d vg0-on-worker-1 0/0 True Ready p-worker-1 5116Mi 0 vg0 225d vg0-on-worker-2 0/0 True Ready p-worker-2 5116Mi 0 vg0 225d vg1-on-redos-murom 1/1 True Ready redos-murom 3068Mi 3008Mi vg1 32d vg1-on-worker-1 1/1 True Ready p-worker-1 3068Mi 3068Mi vg1 190d vg1-on-worker-2 1/1 True Ready p-worker-2 3068Mi 3068Mi vg1 190d -
Проверьте, что на узле нет ресурсов LVMVolumeGroup, которые используются в ресурсах LocalStorageClass.
Перед выводом узла из-под управления модуля удалите зависимые ресурсы вручную, чтобы не потерять контроль над созданными томами.