Хостинг
VDS
Аренда серверов
Домены
Почта
SSL
Хранилище
Сайты
Обзоры
Регламенты
AI Studio
Kubernetes
Архив
Использование Piraeus Datastore в Kubernetes кластере

Piraeus Datastore — это open-source решение для управления распределённым хранилищем в Kubernetes, построенное на базе LINSTOR и DRBD. Оно предоставляет CSI-интерфейс и поддерживает динамическое создание томов, репликацию, снапшоты и резервное копирование в облачные хранилища, включая S3.

1. Подготовка кластера Kubernetes

Для начала работы вам потребуется созданный кластер по крайней мере с одним узлом и подключенным к нему дополнительным диском. В данном примере будет рассмотрен кластер с тремя узлами ищущими метку csi-type=piraeus.

Если вы не указали метки при создании группы узлов, можете добавить их внучную:

kubectl label nodes worker-1 worker-2 worker-3 csi-type=piraeus

2. Установка Piraeus Datastore

2.1 Установка через манифест

kubectl apply --server-side -f "https://github.com/piraeusdatastore/piraeus-operator/releases/latest/download/manifest.yaml"

Проверим статус подов:

kubectl get pods -n piraeus-datastore
NAME                                                  READY   STATUS    RESTARTS   AGE
piraeus-operator-controller-manager-7d786569f-v9rlp   1/1     Running   0          2m41s
piraeus-operator-gencert-86b9d78f75-spl57             1/1     Running   0          2m41s

3. Настройка LINSTOR-кластера и саттелитов

3.1 Создание секрета с парольной фразой

LINSTOR будет использовать этот секрет при создании зашифрованных томов, а так же для сохранения реквизитов доступа для сохранения резервных копий

ВАЖНО: замените значение MASTER_PASSPHRASE на надёжную фразу!

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Secret
metadata:
  name: linstor-passphrase
  namespace: piraeus-datastore
stringData:
  MASTER_PASSPHRASE: B4dd_Ex4Mple_Pa$$PHr4ze
EOF

3.2 Создание LinstorCluster

kubectl apply -f - <<EOF
apiVersion: piraeus.io/v1
kind: LinstorCluster
metadata:
  name: linstorcluster
spec:
  linstorPassphraseSecret: linstor-passphrase
  nodeAffinity:
    nodeSelectorTerms:
      - matchExpressions:
          - key: csi-type
            operator: In
            values:
              - piraeus
  highAvailabilityController:
    enabled: false
  nfsServer:
    enabled: false
  csiNode:
    enabled: true
    podTemplate:
      spec:
        containers:
        - name: linstor-csi
          volumeMounts:
          - mountPath: /var/lib/k0s/kubelet
            mountPropagation: Bidirectional
            name: publish-dir
        - args:
          - --v=5
          - --csi-address=/csi/csi.sock
          - --kubelet-registration-path=/var/lib/k0s/kubelet/plugins/linstor.csi.linbit.com/csi.sock
          - --health-port=9809
          name: csi-node-driver-registrar
        volumes:
        - hostPath:
            path: /var/lib/k0s/kubelet
          name: publish-dir
        - hostPath:
            path: /var/lib/k0s/kubelet/plugins_registry
          name: registration-dir
        - hostPath:
            path: /var/lib/k0s/kubelet/plugins/linstor.csi.linbit.com
          name: plugin-dir
EOF

3.3 Настройка LinstorSatelliteConfiguration — использование /dev/vdb

kubectl apply -f - <<'EOF'
apiVersion: piraeus.io/v1
kind: LinstorSatelliteConfiguration
metadata:
  name: storage-satellites
spec:
  podTemplate:
    spec:
      # Отключаем автоматическую загрузку DRBD-модуля (если он уже есть)
      initContainers:
        - name: drbd-module-loader
          $patch: delete
  nodeAffinity:
    nodeSelectorTerms:
      - matchExpressions:
          - key: csi-type
            operator: In
            values:
             - piraeus
  storagePools:
    - name: vg1
      lvmThinPool:
        volumeGroup: vg1
      source:
        hostDevices:
          - /dev/vdb
EOF

О типах хранилищ в LINSTOR
LINSTOR поддерживает следующие типы storage pools (определяются в LinstorSatelliteConfiguration):

Тип пула Описание Особенности
lvmPool Классический LVM Volume Group (thick) — По умолчанию использует storage pool name как имя VG
— Можно переопределить через volumeGroup: <vg-name>
— Выделение места — full/dense
lvmThinPool LVM Thin Pool (thin LVM) — По умолчанию: VG = linstor_<pool-name>, LV = <pool-name>
— Можно переопределить volumeGroup, thinPool
— Экономия места, поддержка снапшотов и быстрое создание томов
filePool Файловое хранилище (каждому тому — файл в FS) — По умолчанию: /var/lib/linstor-pools/<pool-name>
— Подходит для отладки и лёгких нагрузок
fileThinPool Тонкое (sparse) файловое хранилище — Поведение как filePool, но файлы создаются sparse (разрежённые)
— Требует поддержки sparse файлов (XFS, ext4 с опцией sparse)
zfsPool ZFS ZPool (thick zVol) — По умолчанию использует pool name как имя zpool
— Можно переопределить через zPool: <zpool-name>
zfsThinPool ZFS ZPool с sparse zVol — Поведение как zfsPool, но тома создаются sparse (reservation=0)
— Подходит для экономии места на ZFS

Дождемся заверщения запуска подов в неймспейсе piraeus-datastore и проверим статус саттелитов:

kubectl -n piraeus-datastore exec -it deployments/linstor-controller -- linstor storage-pool list

На каждом из узлов на дополнительных дисках был инициализирован LVM. Приступим к выделению PV


4. Динамическое выделение PV и создание PVC

4.1 Создание StorageClass

kubectl apply -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: piraeus-storage-lvm
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: linstor.csi.linbit.com
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
parameters:
  linstor.csi.linbit.com/storagePool: "vg1"
  linstor.csi.linbit.com/layerList: "storage"
EOF

Проверим:

kubectl get storageclass
NAME                            PROVISIONER              RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
piraeus-storage-lvm (default)   linstor.csi.linbit.com   Delete          WaitForFirstConsumer   true                   10s

4.2 Создание PVC

kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-piraeus
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: nginx-piraeus
  name: nginx-piraeus
spec:
  storageClassName: piraeus-storage-lvm
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
EOF

4.3 Создание Pod и сервиса

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  namespace: nginx-piraeus
  name: nginx-piraeus
spec:
  containers:
  - name: nginx
    image: library/nginx:1.28-alpine
    ports:
    - containerPort: 80
    volumeMounts:
      - mountPath: "/var/www/html"
        name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: nginx-piraeus
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-piraeus
  namespace: nginx-piraeus
spec:
  selector:
    app.kubernetes.io/name: nginx-piraeus
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer
EOF

4.4 Проверка созданных ресурсов

Проверим состояние PVC:

kubectl get pvc -n nginx-piraeus
NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          VOLUMEATTRIBUTESCLASS   AGE
nginx-piraeus   Bound    pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66   2Gi        RWO            piraeus-storage-lvm   <unset>                 2m18s

Проверим PV:

kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS          VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66   2Gi        RWO            Delete           Bound    nginx-piraeus/nginx-piraeus   piraeus-storage-lvm   <unset>                          80s

Уточним размещение Persistent Volume:

kubectl describe pvc -n nginx-piraeus nginx-piraeus | grep volume.kubernetes.io/selected-node:
        volume.kubernetes.io/selected-node: worker-3

Проверим состояние LV на узле, где был размещен Persistent Volume:

kubectl -n piraeus-datastore exec pods/linstor-satellite.worker-3-bdhng -- lvs
LV                                             VG  Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000 vg1 Vwi-aotz-- 2.00g vg1         4.76                                   
vg1                                            vg1 twi-aotz-- 9.97g             0.96   10.90  

Проверим Pod и Service:

kubectl get -n nginx-piraeus pods,svc
NAME                READY   STATUS    RESTARTS   AGE
pod/nginx-piraeus   1/1     Running   0          92s

NAME                    TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
service/nginx-piraeus   LoadBalancer   10.96.28.209   172.16.100.251   80:30539/TCP   92s

Проверим монтирование и файловую систему внутри контейнера:

kubectl -n nginx-piraeus exec -it pods/nginx-piraeus -- df -h /var/www/html
Filesystem                Size      Used Available Use% Mounted on
/dev/mapper/vg1-pvc--deaf559a--6e96--4a3f--801f--bc56eb165c66_00000
1.9G     24.0K      1.8G   0% /var/www/html

Проверим тип файловой системы и параметры монтирования:

kubectl -n nginx-piraeus exec -it pods/nginx-piraeus -- grep www /proc/mounts
/dev/mapper/vg1-pvc--deaf559a--6e96--4a3f--801f--bc56eb165c66_00000 /var/www/html ext4 rw,relatime,stripe=16 0 0

Как видим, Persistent Volume был успешно создан и подключен к созданному поду


5. Создание и восстановление снапшотов

Важное примечание: до создания VolumeSnapshotClass необходимо установить CRD и snapshot-контроллер, который обеспечивает поддержку снапшотов в Kubernetes:

5.1 Установка CRD и контроллера снапшотов

kubectl apply -k https://github.com/kubernetes-csi/external-snapshotter/client/config/crd
kubectl apply -k https://github.com/kubernetes-csi/external-snapshotter/deploy/kubernetes/snapshot-controller

Проверим, что контроллер запущен:

kubectl get pods -n kube-system | grep snapshot-controller
snapshot-controller-65b49c865c-vbr8l       1/1     Running   0          1m24s
snapshot-controller-65b49c865c-z5g77       1/1     Running   0          1m24s

5.2 Класс снапшотов для локального хранения (без S3)

kubectl apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: piraeus-snapshots
  namespace: piraeus-datastore
driver: linstor.csi.linbit.com
deletionPolicy: Delete
EOF

5.3 Создание снапшота

kubectl apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: nginx-piraeus
  namespace: nginx-piraeus
spec:
  volumeSnapshotClassName: piraeus-snapshots
  source:
    persistentVolumeClaimName: nginx-piraeus
EOF

Проверим:

kubectl get volumesnapshot -n nginx-piraeus
NAME            READYTOUSE   SOURCEPVC       SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS       SNAPSHOTCONTENT                                    CREATIONTIME   AGE
nginx-piraeus   true         nginx-piraeus                           2Gi           piraeus-snapshots   snapcontent-efe15b67-cbd1-4fef-ac5a-c39a215db2e9   5s             7s

kubectl -n piraeus-datastore exec pods/linstor-satellite.worker-3-bdhng -- lvs
  LV                                                                                           VG  Attr       LSize Pool Origin                                         Data%  Meta%  Move Log Cpy%Sync Convert
  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000                                               vg1 Vwi-aotz-- 2.00g vg1                                                 4.76                                   
  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000_snapshot-efe15b67-cbd1-4fef-ac5a-c39a215db2e9 vg1 Vri-a-tz-k 2.00g vg1  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000 4.76                                   
  vg1                                                                                          vg1 twi-aotz-- 9.97g                                                     0.96   10.97   

5.4 Восстановление PVC из снапшота

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-piraeus-v2
  namespace: nginx-piraeus
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  dataSource:
    apiGroup: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: nginx-piraeus
EOF

5.5 Пересоздамим под с использованием нового PVC

kubectl delete pod nginx-piraeus -n nginx-piraeus

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  namespace: nginx-piraeus
  name: nginx-piraeus
spec:
  containers:
  - name: nginx
    image: library/nginx:1.28-alpine
    ports:
    - containerPort: 80
    volumeMounts:
      - mountPath: "/var/www/html"
        name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: nginx-piraeus-v2
EOF

Проверим блочные устройства на worker-узле:

kubectl -n piraeus-datastore exec pods/linstor-satellite.worker-3-bdhng -- lvs
  LV                                                                                           VG  Attr       LSize Pool Origin                                                                                       Data%  Meta%  Move Log Cpy%Sync Convert
  pvc-25263fd1-ed50-4da7-bf8a-8685c5cb4e52_00000                                               vg1 Vwi-aotz-k 2.00g vg1  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000_snapshot-efe15b67-cbd1-4fef-ac5a-c39a215db2e9 4.76                                   
  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000                                               vg1 Vwi-a-tz-- 2.00g vg1                                                                                               4.76                                   
  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000_snapshot-efe15b67-cbd1-4fef-ac5a-c39a215db2e9 vg1 Vri-a-tz-k 2.00g vg1  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000                                               4.76                                   
  vg1                                                                                          vg1 twi-aotz-- 9.97g                                                                                                   0.96   11.07                      

5.6 Удалим созданный ранее снапшот

И снова проверим уструктуру Logical Volume

kubectl delete volumesnapshot -n nginx-piraeus nginx-piraeus
kubectl -n piraeus-datastore exec pods/linstor-satellite.worker-3-bdhng -- lvs
volumesnapshot.snapshot.storage.k8s.io "nginx-piraeus" deleted
  LV                                             VG  Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  pvc-25263fd1-ed50-4da7-bf8a-8685c5cb4e52_00000 vg1 Vwi-aotz-k 2.00g vg1         4.76                                   
  pvc-deaf559a-6e96-4a3f-801f-bc56eb165c66_00000 vg1 Vwi-a-tz-- 2.00g vg1         4.76                                   
  vg1                                            vg1 twi-aotz-- 9.97g             0.96   11.00  

6. Загрузка снапшотов в S3

6.1 Настройка доступа к S3

Создадим Secret с учетными данными и VolumeSnapshotClass для S3:

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Secret
metadata:
  name: linstor-csi-s3-access
  namespace: piraeus-datastore
immutable: true
type: linstor.csi.linbit.com/s3-credentials.v1
stringData:
  access-key: YOUR_AWS_ACCESS_KEY_ID
  secret-key: YOUR_AWS_SECRET_ACCESS_KEY
---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: piraeus-snapshots-s3
driver: linstor.csi.linbit.com
deletionPolicy: Delete
parameters:
  snap.linstor.csi.linbit.com/type: S3
  snap.linstor.csi.linbit.com/remote-name: example
  snap.linstor.csi.linbit.com/delete-local: "true"
  snap.linstor.csi.linbit.com/allow-incremental: "false"
  snap.linstor.csi.linbit.com/s3-bucket: piraeus-backups
  snap.linstor.csi.linbit.com/s3-endpoint: s3.example.com
  snap.linstor.csi.linbit.com/s3-signing-region: ru-1
  snap.linstor.csi.linbit.com/s3-use-path-style: "true"
  csi.storage.k8s.io/snapshotter-secret-name: linstor-csi-s3-access
  csi.storage.k8s.io/snapshotter-secret-namespace: piraeus-datastore
EOF

Замените имя бакета, точку подключения, и учетные данные на свои.

6.2 Создание и загрузка снапшота в S3

kubectl apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: nginx-piraeus-s3
  namespace: nginx-piraeus
spec:
  volumeSnapshotClassName: piraeus-snapshots-s3
  source:
    persistentVolumeClaimName: nginx-piraeus
EOF

Проверим статус снапшота — readyToUse: true означает успешную загрузку в S3:

kubectl get volumesnapshot -n nginx-piraeus nginx-piraeus-s3
NAME            READYTOUSE   SOURCEPVC       SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS          SNAPSHOTCONTENT                                    CREATIONTIME   AGE
nginx-piraeus   true         nginx-piraeus                           2Gi           piraeus-snapshots-s3   snapcontent-c7aa2b19-8331-47d1-a549-4c615d60bb46   3m10s          3m10s

6.3 Восстановление PVC из снапшота в S3

Используем тот же VolumeSnapshot, что и выше:

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-piraeus-from-s3
  namespace: nginx-piraeus
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  dataSource:
    apiGroup: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: nginx-piraeus-s3
EOF

Важно: если в VolumeStorageClass параметр delete-local установлен в значение true, то локальный снапшот удаляется после загрузки данных в S3 — он будет восстановлен из облака при создании PVC.


Заключение

Piraeus Datastore — это зрелое и гибкое решение для распределённого и локального хранения в Kubernetes:

  • Простая установка через манифест и Helm-чарты

  • Гибкая настройка саттелитов под любые конфигурации дисков

  • Динамическое создание PV/PVC через CSI

  • Локальные и облачные снапшоты с поддержкой загрузки в S3

Благодаря S3-интеграции вы можете не только быстро восстанавливать тома из снапшотов, но и обеспечивать длительное хранение и трансферные точки восстановления в облаке.

Нам доверяют тысячи компаний и разработчиков

22 года
Предоставляем услуги профессионального хостинга
35 000+
Клиентов доверяют нам размещение своих сайтов
99.99%
Подтвержденный uptime наших серверов хостинга
Callibri
Крылья
Tele-Club
Linline
Премьер зал
УГМК-Здоровье
Магнум
Алатырь
Туристер
Callibri
Крылья
Tele-Club
Linline
Премьер зал
УГМК-Здоровье
Магнум
Алатырь
Туристер
ВК49865