Стадия жизненного цикла модуля: Experimental
У модуля есть требования для установки
Модуль sds-object находится в стадии Experimental. Experimental-модули не включены по умолчанию. Перед включением установите allowExperimentalModules: true в ModuleConfig deckhouse. Сейчас работают только профили System и Lightweight (Garage).
Включение модуля
d8 k apply -f - <<EOF
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: sds-object
spec:
enabled: true
version: 1
EOFСоздание кластера
Кластер Lightweight на PVC поверх существующего StorageClass:
apiVersion: storage.deckhouse.io/v1alpha1
kind: ObjectStore
metadata:
name: shared
spec:
type: Lightweight
storage:
sizePerNode: 50Gi
class: localpath
redundancy: StandardКластер System для нужд платформы (Garage на control-plane узлах, hostPath; storage.class игнорируется):
apiVersion: storage.deckhouse.io/v1alpha1
kind: ObjectStore
metadata:
name: system
spec:
type: SystemОтслеживание готовности:
d8 k get objectstore
# NAME TYPE PHASE ENDPOINT READY AGE
# shared Lightweight Ready http://shared-garage.d8-sds-object.svc...:3900 True 3mСистемное хранилище в одной реплике
Встроенный кластер system (поставляется модулем, см. systemBucket) по умолчанию работает в трёх репликах Garage и ребалансирует их по control-plane узлам. На небольших и непродуктивных инсталляциях его можно свести к одной реплике:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: sds-object
spec:
enabled: true
version: 1
settings:
systemBucket:
singleReplica: trueЕдинственная реплика размещается на одном control-plane узле и никогда не переезжает между мастерами: её данные лежат на локальном томе этого узла, а дореплицироваться не с чего — второй копии нет. Пока узел недоступен или выведен, системное хранилище недоступно: данные на его диске остаются целыми, но контроллер реплику не перенесёт.
Включение и выключение singleReplica пересоздаёт системное объектное хранилище и уничтожает всё, что в нём хранилось. Garage не умеет менять фактор репликации на живом кластере, поэтому контроллер удаляет data plane (StatefulSet, тома, идентичности нод) и поднимает его пустым на новых каталогах. Бакеты создаются заново, ключи доступа перевыпускаются автоматически; объекты — нет. Сохраните содержимое бакета system до переключения параметра.
Каталоги с данными предыдущих реплик остаются на control-plane узлах в /var/lib/deckhouse/sds-object/garage/system и могут быть удалены вручную, когда перестанут быть нужны.
Ход пересоздания виден в статусе кластера — сначала сообщение о сносе data plane, затем Ready с одной репликой:
d8 k get objectstore system -o jsonpath='{.status.phase}{"\n"}{.status.conditions[?(@.type=="BackendReady")].message}{"\n"}'
d8 k get pods -n d8-sds-object -l storage.deckhouse.io/object-store=systemОбъявление Shared-бакета
Bucket — cluster-scoped-ресурс: администратор объявляет бакет в объектном хранилище, учётных данных он не содержит. Это Shared-бакет, предназначенный для потребления из нескольких namespace через заявки с проверкой политики:
apiVersion: storage.deckhouse.io/v1alpha1
kind: Bucket
metadata:
name: app-data
spec:
objectStoreRef: shared
# bucketName по умолчанию равен metadata.name
accessPolicy: Private
reclaimPolicy: Retaind8 k get bucket app-data
# NAME OBJECTSTORE BUCKET PHASE READY AGE
# app-data shared app-data Ready True 30sРазрешение namespace привязывать бакет
Привязка Shared-бакета работает по принципу deny-by-default: namespace может заявить его, только если существует совпадающая BucketClaimPolicy для этого бакета. Namespace выбираются точными именами names и/или RE2-паттернами patterns.
BucketClaimPolicy — namespaced-ресурс, и учитывается он только в namespace-владельце бакета: доступ раздаёт тот, кому бакет принадлежит. Для бакета, объявленного администратором, владелец — namespace модуля d8-sds-object; для бакета, созданного greenfield-заявкой, — namespace этой заявки. Политика, созданная в любом другом namespace, отклоняется вебхуком: иначе потребитель мог бы выдать доступ сам себе.
apiVersion: storage.deckhouse.io/v1alpha1
kind: BucketClaimPolicy
metadata:
name: app-data-teams
# Бакет app-data объявлен администратором, поэтому им владеет namespace модуля.
namespace: d8-sds-object
spec:
bucketRef: app-data
allowedNamespaces:
names:
- my-app
patterns:
- "team-.*"Владелец greenfield-бакета может так же поделиться им с другими namespace — создав политику в своём namespace и указав в bucketRef имя бакета из status.boundBucketName своей заявки.
Заявка на бакет
Каждый потребляющий namespace создаёт BucketClaim. Чтобы привязать Shared-бакет выше (brownfield), задайте existingBucketName. Чтобы вместо этого создать новый приватный бакет (greenfield), опустите existingBucketName и задайте objectStoreRef — для greenfield-заявок политика не требуется.
apiVersion: storage.deckhouse.io/v1alpha1
kind: BucketClaim
metadata:
name: app-data
namespace: my-app
spec:
existingBucketName: app-data # brownfield: привязать Shared-бакет (гейтится политикой)
# --- или, для нового приватного бакета, уберите existingBucketName и используйте: ---
# objectStoreRef: shared
# accessPolicy: Private
# reclaimPolicy: Retaind8 k -n my-app get bucketclaim app-data
# NAME BUCKET PHASE READY AGE
# app-data app-data Ready True 20sЗапрос учётных данных
Каждый workload создаёт BucketAccess, ссылающийся на BucketClaim в состоянии Bound в своём namespace. Контроллер генерирует отдельную пару access key / secret key с доступом к привязанному бакету и пишет Secret (по умолчанию <access>-s3-credentials) в том же namespace:
apiVersion: storage.deckhouse.io/v1alpha1
kind: BucketAccess
metadata:
name: app-data
namespace: my-app
spec:
bucketClaimName: app-data
permission: ReadWrite # или ReadOnlyd8 k -n my-app get bucketaccess app-data
# NAME CLAIM PHASE SECRET READY AGE
# app-data app-data Ready app-data-s3-credentials True 20sИспользование учётных данных
Secret содержит стандартные переменные подключения к S3, готовые к монтированию через envFrom:
| Ключ | Описание |
|---|---|
S3_ENDPOINT |
Внутрикластерный URL S3-эндпойнта |
S3_REGION |
Регион S3 |
S3_BUCKET |
Имя бакета |
AWS_ACCESS_KEY_ID |
Ключ доступа |
AWS_SECRET_ACCESS_KEY |
Секретный ключ |
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-app
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- secretRef:
name: app-data-s3-credentialsРотация учётных данных
Чтобы сменить access key у BucketAccess, установите или измените аннотацию storage.deckhouse.io/rotate. Контроллер выпустит новую пару ключей, обновит Secret и отзовёт предыдущий ключ:
d8 k -n my-app annotate bucketaccess app-data \
storage.deckhouse.io/rotate="$(date +%s)" --overwriteПолитика высвобождения
- Бакет
reclaimPolicy: Retain(по умолчанию) — при удаленииBucketбакет и объекты сохраняются;Delete— удаляются. - Удаление
BucketAccessвсегда отзывает его ключ доступа и удаляет егоSecret(данные бакета не затрагиваются). - Кластер
reclaimPolicy: Retain(по умолчанию) — при удаленииObjectStoreданные сохраняются (дляHeavy— пулы Ceph RGW; для профилей на PVC — сами PVC).Delete— данные уничтожаются.
Профиль Heavy
Профиль Heavy разворачивает Ceph RADOS Gateway поверх существующего кластера sds-elastic и выбирается через spec.elasticClusterRef:
apiVersion: storage.deckhouse.io/v1alpha1
kind: ObjectStore
metadata:
name: heavy
spec:
type: Heavy
elasticClusterRef: mainПрофиль Heavy разворачивает data plane Ceph RGW (Rook CephObjectStore на указанном кластере sds-elastic). Бакеты и доступ работают так же, как у остальных профилей: Bucket создаёт владельца-бакета Rook CephObjectStoreUser и сам бакет, а каждый BucketAccess получает собственного CephObjectStoreUser, которому доступ к бакету выдаётся через bucket policy.