# MinIO — стандарт объектного хранилища S3 в кластере MinIO — S3-совместимое объектное хранилище. Предоставляет S3 API (порт 9000) и веб-интерфейс Console (порт 9001). Запускается как standalone StatefulSet на worker-ноде, использует отдельный StorageClass `longhorn-minio` с политикой Retain. --- ## Содержание 1. [Архитектура](#1-архитектура) 2. [Предварительные условия](#2-предварительные-условия) 3. [Развёртывание](#3-развёртывание) 4. [StorageClass longhorn-minio](#4-storageclass-longhorn-minio) 5. [Traefik: порты 10005 и 10006](#5-traefik-порты-10005-и-10006) 6. [Пользователи и политики](#6-пользователи-и-политики) 7. [Бакеты и lifecycle](#7-бакеты-и-lifecycle) 8. [Интеграция с Loki](#8-интеграция-с-loki) 9. [Масштабирование](#9-масштабирование) 10. [Диагностика](#10-диагностика) --- ## 1. Архитектура ``` k8s-worker-01 (10.203.0.96) │ ├── MinIO Pod (StatefulSet, 1 replica, namespace: minio) │ ├── порт 9000 — S3 API (aws s3, boto3, mc, s3cmd) │ └── порт 9001 — Console UI (браузер) │ ├── PVC 1 TiB → StorageClass longhorn-minio │ └── Longhorn volume → longhorn-disk1 (/mnt/longhorn-disk1, ~4 TiB) │ └── Traefik DaemonSet ├── :10005 → minio:9000 (S3 API, внешний доступ) └── :10006 → minio-console:9001 (Console UI, внешний доступ) ``` ### Адреса | Адрес | Назначение | |---|---| | `http://10.203.0.96:10005` | S3 API (внешний, через Traefik) | | `http://10.203.0.96:10006` | Console UI (внешний, через Traefik) | | `http://minio.minio.svc.cluster.local:9000` | S3 API (внутри кластера) | | `http://minio-console.minio.svc.cluster.local:9001` | Console (внутри кластера) | --- ## 2. Предварительные условия - Longhorn установлен и работает (`setup_longhorn.yml` выполнен) - Traefik установлен (`setup_traefik.yml` выполнен; записи `minio-api` и `minio-console` добавлены в `traefik_port_map`) - Secret `minio-root-credentials` создан вручную в namespace `minio`: ```bash kubectl create namespace minio kubectl create secret generic minio-root-credentials \ --from-literal=rootUser=minioadmin \ --from-literal=rootPassword='СИЛЬНЫЙ_ПАРОЛЬ_МИНИМУМ_8_СИМВОЛОВ' \ -n minio ``` > Пароль — минимум 8 символов. MinIO не примет короткий пароль и не запустится. --- ## 3. Развёртывание ```bash # Запуск через CI/CD (рекомендуется) # GitLab → CI/CD → Pipelines → setup:minio → Run manually # Запуск локально ansible-playbook -i inventory/prod playbooks/setup_minio.yml # После установки Traefik нужно перезапустить setup_traefik.yml, # если записи minio-api и minio-console ещё не применены ansible-playbook -i inventory/prod playbooks/setup_traefik.yml ``` ### Проверка после развёртывания ```bash # Статус пода kubectl get pod -n minio # Логи kubectl logs -n minio -l app=minio --tail=50 # Проброс порта для локальной проверки kubectl port-forward -n minio svc/minio 9000:9000 & # Проверка S3 API через mc (MinIO Client) mc alias set local http://localhost:9000 minioadmin ПАРОЛЬ mc ls local mc admin info local ``` --- ## 4. StorageClass longhorn-minio Отдельный StorageClass с двумя ключевыми отличиями от дефолтного `longhorn`: | Параметр | `longhorn` (default) | `longhorn-minio` | |---|---|---| | `reclaimPolicy` | `Delete` | **`Retain`** | | `numberOfReplicas` | `1` | `1` | | `dataLocality` | `disabled` | `best-effort` | **Retain** — при удалении PVC или namespace `minio` данные на диске **не уничтожаются**. Для восстановления: пересоздать PVC с тем же `volumeName`, указав имя существующего Longhorn volume. ### (Опционально) Изоляция MinIO на disk1 через тег Если нужно зафиксировать MinIO именно на `longhorn-disk1`, добавить тег через Longhorn API: ```bash kubectl -n longhorn-system patch node.longhorn.io k8s-worker-01 --type=json -p='[ {"op":"add","path":"/spec/disks/longhorn-disk1/tags","value":["minio"]} ]' ``` Затем раскомментировать `diskSelector: "minio"` в `roles/minio/templates/storageclass.yml.j2` и перезапустить `setup_minio.yml`. Без тега Longhorn выбирает любой из доступных дисков — это тоже корректно. --- ## 5. Traefik: порты 10005 и 10006 Записи в `inventory/prod/group_vars/traefik.yml`: ```yaml - name: minio-api port: 10005 backend: namespace: minio service: minio port: 9000 scheme: http basicauth: enabled: false # MinIO использует AWS Signature v4 - name: minio-console port: 10006 backend: namespace: minio service: minio-console port: 9001 scheme: http basicauth: enabled: false # Console защищён собственным логином ``` > BasicAuth от Traefik несовместим с MinIO Console — браузер не может пройти двойную аутентификацию. Console имеет свой логин. После изменения `traefik_port_map` перезапустить `setup_traefik.yml`. --- ## 6. Пользователи и политики Не используйте root-учётные данные в приложениях. Для каждого сервиса — отдельный пользователь с ограниченной политикой. ### Создание пользователей через mc ```bash # Настройка alias (через Traefik) mc alias set prod http://10.203.0.96:10005 minioadmin ПАРОЛЬ # Пользователь для Loki (только бакет loki-chunks) mc admin user add prod loki ПАРОЛЬ_LOKI mc admin policy create prod loki-policy /dev/stdin <<'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:*"], "Resource": [ "arn:aws:s3:::loki-chunks", "arn:aws:s3:::loki-chunks/*" ] } ] } EOF mc admin policy attach prod loki-policy --user loki # Пользователь для бэкапов (только запись в backups) mc admin user add prod backup ПАРОЛЬ_BACKUP mc admin policy create prod backup-policy /dev/stdin <<'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::backups", "arn:aws:s3:::backups/*" ] } ] } EOF mc admin policy attach prod backup-policy --user backup ``` --- ## 7. Бакеты и lifecycle Бакеты создаются автоматически при старте MinIO через `values.buckets`. Дефолтный список: `loki-chunks`, `backups`, `artifacts`. Изменить список — через переменную `minio_buckets` в `defaults/main.yml` или `group_vars`. ### Lifecycle: автоудаление старых объектов ```bash # Удалять объекты в backups старше 30 дней mc ilm rule add --expire-days 30 prod/backups # Включить версионирование бакета mc version enable prod/backups # Посмотреть все версии объекта mc ls --versions prod/backups/db-dump.sql.gz ``` --- ## 8. Интеграция с Loki При переходе Loki на distributed-режим MinIO становится S3 backend. Внутрикластерный endpoint: ```yaml # В loki-values.yml (distributed режим) loki: storage: type: s3 s3: endpoint: http://minio.minio.svc.cluster.local:9000 region: us-east-1 # MinIO игнорирует region, но поле обязательно bucketnames: loki-chunks access_key_id: loki secret_access_key: "ПАРОЛЬ_LOKI" insecure: true # http, не https s3forcepathstyle: true # обязательно для MinIO ``` Secret для Loki в namespace monitoring: ```bash kubectl create secret generic loki-minio-secret \ --from-literal=AWS_ACCESS_KEY_ID=loki \ --from-literal=AWS_SECRET_ACCESS_KEY='ПАРОЛЬ_LOKI' \ -n monitoring ``` --- ## 9. Масштабирование ### Расширение PVC без остановки MinIO Longhorn поддерживает online-расширение PVC: ```bash kubectl patch pvc minio -n minio \ -p '{"spec":{"resources":{"requests":{"storage":"2Ti"}}}}' # MinIO увидит новое пространство автоматически mc admin info prod ``` ### Переход на SNMD (4 диска на 1 ноде) При добавлении ещё 2 дисков к worker-ноде (итого 4 диска): ```yaml # minio-values.yml — SNMD (mode: distributed для 1 ноды с 4 дисками) mode: distributed replicas: 1 drivesPerNode: 4 persistence: storageClass: longhorn-minio size: 1Ti # 4 × 1 TiB raw → ~2 TiB usable (EC:2) ``` ### Миграция standalone → distributed MinIO **не поддерживает** in-place миграцию. Процедура: ``` 1. Запустить distributed MinIO рядом (namespace minio-dist) 2. mc mirror prod prod-dist --preserve --watch 3. Дождаться синхронизации (mc du для сверки объёмов) 4. Переключить Traefik (изменить service в traefik_port_map) 5. Обновить endpoint в Loki, бэкапах и других клиентах 6. Через 24–48 ч удалить standalone namespace и PVC ``` --- ## 10. Диагностика ```bash # Статус пода и PVC kubectl get pod,pvc -n minio # Логи MinIO kubectl logs -n minio -l app=minio --tail=100 # Проверка S3 API напрямую kubectl port-forward -n minio svc/minio 9000:9000 & mc alias set local http://localhost:9000 minioadmin ПАРОЛЬ mc admin info local # Проверка через Traefik curl -I http://10.203.0.96:10005/minio/health/live # StorageClass kubectl get storageclass longhorn-minio -o yaml # Longhorn volume для MinIO kubectl get pvc -n minio kubectl -n longhorn-system get volume # Console недоступна (redirect на неверный URL) # → проверить MINIO_BROWSER_REDIRECT_URL в values kubectl get pod -n minio -o yaml | grep MINIO_BROWSER_REDIRECT_URL ``` ### Типичные ошибки | Симптом | Причина | Решение | |---|---|---| | Pod в состоянии `Pending` | PVC не создан (StorageClass не найден) | Проверить `kubectl get sc`, перезапустить `setup_minio.yml` | | `Access Denied` при входе | Неверные данные в Secret | Пересоздать `minio-root-credentials` | | Console → 401 после логина | Неверный `MINIO_BROWSER_REDIRECT_URL` | Исправить URL в values, перезапустить `setup_minio.yml` | | Traefik → 404 на порту 10005/10006 | IngressRoute не применён | Перезапустить `setup_traefik.yml` | | PVC завис в `Released` после удаления | reclaimPolicy: Retain (ожидаемо) | Удалить PV вручную или привязать к новому PVC |