MinIO Operator — это аддон для Kubernetes, который упрощает развертывание и управление S3-совместимыми хранилищами на базе MinIO. Он позволяет создавать распределенные кластеры хранения через CRD, управлять пользователями, бакетами и конфигурацией через Kubernetes-манифесты.
Установка в ПУ
Для работы аддона необходимо, чтобы в кластере был установлен аддон CSI-driver.
Для установки MinIO Operator, в панели управления кластером, перейдите во вкладку «Дополнения». Найдите «MinIO Operator» в списке и нажмите на него.
В открывшемся окне можно при необходимости изменить параметры установки. Описание параметров доступно в официальной документации. Воспользоваться аддоном можно не меняя настроек по умолчанию.
Для устанвоки аддона нажмите на кнопку «Установить».
Дождитесь завершения установки. Для проверки, что установка завершена корректно, выполните команду:
kubectl get all -n operator
У запущеннух подов должен быть статус Running
.
Пример использования
В качестве примера развернем кластер MinIO из одного узла. Данные будут храниться на сетевом диске, а доступ к кластеру будет организован через Nginx Ingress с настроенным HTTPS.
В продакшн-среде рекомендуется использовать не менее 4-х узлов для обеспечения отказоустойчивость.
Предварительные требования
В кластере должны быть установлены аддоны:
- Nginx Ingress
- CSI-driver
- cert-manager
- MinIO Operator
Все аддоны установлены с параметрами по умолчанию.
Для доступа к консоли и S3 API мы будем использовать два поддомена:
-
minio-console.timeweb-example.cloud
— для доступа к панели управления; -
s3.timeweb-example.cloud
— для доступа к S3 API.
Перейдем к созданию кластера. Сначала опишем создание неймспейса в файле namespace.yaml
:
apiVersion: v1
kind: Namespace
metadata:
name: minio-tenant
Теперь опишем тенант в файле tenant.yaml
:
apiVersion: minio.min.io/v2
kind: Tenant
metadata:
name: myminio
namespace: minio-tenant
spec:
configuration:
name: storage-configuration
users:
- name: storage-user
image: quay.io/minio/minio:RELEASE.2025-04-08T15-41-24Z
requestAutoCert: false
mountPath: /export
podManagementPolicy: Parallel
pools:
- name: pool-0
servers: 1
volumesPerServer: 1
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: nvme.network-drives.csi.timeweb.cloud
Здесь:
pools
— определяет пул серверов (узлов) для MinIO:
-
servers: 1
— количество серверов в пуле. -
volumesPerServer: 1
— количество томов, подключаемых к каждому серверу; -
volumeClaimTemplate
— шаблон для создания PVC. Указываем: -
accessModes: ReadWriteOnce
— том может быть смонтирован только одним подом на одном узле; -
storage: 2Gi
— размер тома; -
storageClassName: nvme.network-drives.csi.timeweb.cloud
— класс хранилища, соответствующий NVMe-дискам, предоставляемым CSI-драйвером.
Обязательный параметр spec.configuration.name
, в котором мы передаем имя секрета. Параметр используется для создания root-пользователя.
В секции spec.users
указывается список пользователей, для каждого из которых должен быть создан секрет с access
и secret key
. Имя секрета передается в поле name
.
Опишем секрет storage-configuration.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: storage-configuration
namespace: minio-tenant
type: Opaque
stringData:
config.env: |-
export MINIO_ROOT_USER="minio"
export MINIO_ROOT_PASSWORD="minio123"
export MINIO_BROWSER="on"
И storage-user.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: storage-user
namespace: minio-tenant
type: Opaque
data:
CONSOLE_ACCESS_KEY: Y29uc29sZQ== # console
CONSOLE_SECRET_KEY: Y29uc29sZTEyMw== # console123
Обратите внимание, что CONSOLE_ACCESS_KEY
и CONSOLE_SECRET_KEY
передаются закодированные в base64. Например:
echo -n "console" | base64 # Y29uc29sZQ==
echo -n "console123" | base64 # Y29uc29sZTEyMw==
Применим все манифесты:
kubectl apply -f namespace.yaml
kubectl apply -f storage-configuration.yaml
kubectl apply -f storage-user.yaml
kubectl apply -f tenant.yaml
Проверьте, что все манифесты успешно применились и все сервисы корректно запустились:
kubectl get all -n minio-tenant
Вы должны будете увидеть примерно такой вывод:
NAME READY STATUS RESTARTS AGE
pod/myminio-pool-0-0 2/2 Running 0 113m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/minio ClusterIP 10.97.190.5 <none> 80/TCP 113m
service/myminio-console ClusterIP 10.96.97.1 <none> 9090/TCP 113m
service/myminio-hl ClusterIP None <none> 9000/TCP 113m
NAME READY AGE
statefulset.apps/myminio-pool-0 1/1 113m
Теперь перейдем к настройке Nginx Ingress. Создадим файл ingress.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myminio-ingress
namespace: minio-tenant
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
rules:
- host: minio-console.timeweb-example.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myminio-console
port:
number: 9090
- host: s3.timeweb-example.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio
port:
number: 80
tls:
- hosts:
- minio-console.timeweb-example.cloud
secretName: minio-console-tls
- hosts:
- s3.timeweb-example.cloud
secretName: s3-tls
Не забудьте заменить домены s3.timeweb-example.cloud
и minio-console.timeweb-example.cloud
.
Для выпуска сертификатов создадим cluster-issuer.yaml
:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: example@timeweb.cloud
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
Поменяйте example@timeweb.cloud
на вашу почту — она будет использоваться Let's Encrypt.
Опишем балансировщик нагрузки в файле lb.yaml
:
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
Примените все манифесты:
kubectl apply -f ingress.yaml
kubectl apply -f cluster-issuer.yaml
kubectl apply -f lb.yaml
Дождитесь завершения создания балансировщика нагрузки в панели управления и укажите для доменов в качестве A-записи IP-адрес балансировщика.
Проверьте, что ingress запущен, а сертификаты выпущены:
kubectl get ingress -n minio-tenant
kubectl get certificates -n minio-tenant
Теперь можно перейти к панели управления MinIO. Перейдите по домену MinIO-консоли, в нашем примере — это minio-console.timeweb-example.cloud
. Вы увидите страницу авторизации.
Для авторизации используйте данные, указанные в секретах storage-user.yaml
или storage-configuration.yaml
, например, логин console
и пароль console123
.
Перейдите в раздел «Buckets», чтобы создать бакет.
Перейдите в раздел «Access Keys», чтобы создать данные для подключения — например, с помощью S3cmd. Простой конфиг для подключения будет выглядеть так:
[default]
access_key = [Access Key]
secret_key = [Secret Key]
host_base = s3.timeweb-example.cloud
host_bucket = s3.timeweb-example.cloud
use_https = True