31 KiB
MinIO в Kubernetes: объектное хранилище 1 ТБ с веб-интерфейсом
Кластер: Rocky Linux 9 · Kubernetes 1.33 · Flannel CNI
Текущая топология: k8s-manager-01 (10.203.0.92) · k8s-master-01 (10.203.0.97) · k8s-worker-01 (10.203.0.96)
Дата исследования: 2026-05-28
Проверено на кластере: 2026-05-28 (kubectl + Longhorn API)
Содержание
- Обзор и назначение
- Режимы развёртывания
- Планирование хранилища 1 ТБ
- Helm-развёртывание (standalone)
- MinIO Console: веб-интерфейс
- Интеграция с Traefik
- Безопасность: пользователи и политики
- Интеграция с Loki (S3 backend)
- Ansible-роль и плейбук
- Масштабирование до distributed-режима
- Итоги и рекомендации
1. Обзор и назначение
MinIO — S3-совместимое объектное хранилище. Работает в Kubernetes как StatefulSet или Deployment, предоставляет:
- S3 API (порт 9000) — совместим с любым клиентом AWS SDK, boto3, mc, s3cmd
- MinIO Console (порт 9001) — встроенный веб-интерфейс: браузер объектов, управление пользователями, мониторинг
Сценарии использования в текущем кластере
| Сценарий | Описание |
|---|---|
| Loki S3 backend | Хранилище chunks/index при переходе на distributed Loki |
| Бэкапы баз данных | S3-target для pg_dump, mysqldump, Velero |
| Артефакты CI/CD | GitLab Runner cache, артефакты сборки |
| Файловое хранилище | Статика, медиафайлы приложений |
| Резервные копии etcd | Автоматические снэпшоты control plane |
2. Режимы развёртывания
Текущее состояние кластера (проверено)
Longhorn-диски на k8s-worker-01:
longhorn-disk1 /mnt/longhorn-disk1 ~4.09 TiB (свободно ~4.06 TiB) allowScheduling=true
longhorn-disk2 /mnt/longhorn-disk2 ~4.09 TiB (свободно ~4.06 TiB) allowScheduling=true
k8s-master-01: диск из Longhorn удалён — нода без дисков, в планировании не участвует ✓
StorageClass longhorn (default):
numberOfReplicas: 1 ✓
allowVolumeExpansion: true
createDefaultDiskLabeledNodes: true
Traefik hostPort (занято): 10001 (k8s-dashboard), 10002 (longhorn-ui)
Traefik hostPort (свободно): 10003+ → MinIO: 10005 (API), 10006 (Console)
Standalone (текущий кластер — 1 worker)
┌─────────────────────────────────────────────────────────────┐
│ k8s-worker-01 (10.203.0.96) │
│ │
│ [MinIO Pod — StatefulSet 1 replica] │
│ ├── порт 9000 (S3 API) │
│ └── порт 9001 (Console UI) │
│ ↓ │
│ [PVC 1 TiB → StorageClass longhorn-minio] │
│ [Longhorn → longhorn-disk1 (/mnt/longhorn-disk1, 4 TiB)] │
└─────────────────────────────────────────────────────────────┘
↓ ClusterIP
┌─────────────────────┐
│ Traefik │
│ 10005 → API :9000 │
│ 10006 → UI :9001 │
└─────────────────────┘
Ограничения standalone: нет erasure coding. Потеря диска = потеря данных. Приемлемо при наличии Longhorn-снэпшотов по расписанию.
SNMD — Single Node Multi-Drive (будущее)
Worker уже имеет два диска (~4 TiB каждый). MinIO поддерживает SNMD начиная с 4 дисков. При добавлении ещё двух дисков к worker-ноде можно перейти на SNMD без новых нод:
MinIO SNMD, 4 диска по ~1 TiB (из доступных 4 TiB на каждом диске):
- usable storage ≈ 2 TiB (EC:2 — паритет 50%)
- допустимая потеря: 2 из 4 дисков
Distributed (4+ нод)
При добавлении worker-нод: 1 под MinIO на ноду, PVC через Longhorn на каждой. Требует минимум 4 пода (4 ноды) для полноценного erasure coding.
Для текущего кластера (1 worker, 2 диска) — только standalone.
3. Планирование хранилища 1 ТБ
Реальная конфигурация дисков (проверено)
На k8s-worker-01 уже настроены два Longhorn-диска:
| Диск | Путь | Всего | Свободно | Статус |
|---|---|---|---|---|
longhorn-disk1 |
/mnt/longhorn-disk1 |
~4.09 TiB | ~4.06 TiB | Ready, Schedulable |
longhorn-disk2 |
/mnt/longhorn-disk2 |
~4.09 TiB | ~4.06 TiB | Ready, Schedulable |
Оба диска полностью свободны. PVC 1 TiB займёт ~25% одного диска, оставляя ~3 TiB в резерве на том же диске.
Выделенный StorageClass для MinIO
Дефолтный longhorn (numberOfReplicas: 1) технически подойдёт, но для MinIO рекомендуется отдельный StorageClass по двум причинам:
- reclaimPolicy: Retain — при случайном удалении namespace или PVC данные на диске не уничтожаются (дефолтный Longhorn использует
Delete) - diskSelector — позволяет зафиксировать MinIO на
longhorn-disk1, оставивlonghorn-disk2для других workload (Loki, бэкапы и т.д.)
# применить через роль minio/tasks/storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-minio
provisioner: driver.longhorn.io
reclaimPolicy: Retain # данные остаются при удалении PVC
allowVolumeExpansion: true
parameters:
numberOfReplicas: "1"
dataLocality: "best-effort"
diskSelector: "minio" # тег только на longhorn-disk1
fsType: "ext4"
dataEngine: "v1"
Disk-тег для изоляции MinIO на disk1 (опционально)
Если нужно зафиксировать MinIO именно на longhorn-disk1 (рекомендуется при нескольких workload):
kubectl -n longhorn-system patch node.longhorn.io k8s-worker-01 --type=json -p='[
{"op":"add","path":"/spec/disks/longhorn-disk1/tags","value":["minio"]}
]'
Без тега Longhorn выберет любой из двух дисков (disk1 или disk2) — это тоже корректно, просто менее предсказуемо.
Репликация на уровне Longhorn
Сейчас: numberOfReplicas: 1 — без репликации. При добавлении второго worker с Longhorn-дисками поднять до 2 — Longhorn начнёт реплицировать PVC MinIO между нодами без остановки пода.
Важно: репликация Longhorn защищает от потери ноды, но не заменяет MinIO distributed mode. Longhorn реплицирует блочное устройство целиком, erasure coding MinIO работает на уровне объектов.
Расчёт полезной ёмкости
Физический диск (longhorn-disk1) — ~4.09 TiB. MinIO получает PVC 1 TiB — остаток диска доступен для других PVC.
| Параметр | Значение |
|---|---|
| Физический диск | ~4.09 TiB (longhorn-disk1) |
| PVC для MinIO | 1 TiB |
| Overhead Longhorn + ext4 | ~2% |
| Overhead MinIO (метаданные) | ~1% |
| Доступно для объектов | ~990 Gi |
| Рекомендуемый порог заполнения | 80% → ~790 Gi |
| Остаток на диске для других PVC | ~3.09 TiB |
MinIO по умолчанию отказывается принимать данные при заполнении > 95% (настраивается через MINIO_STORAGE_CLASS_STANDARD).
4. Helm-развёртывание (standalone)
Helm chart
Используется официальный chart minio/minio (не bitnami — он добавляет лишние зависимости).
helm repo add minio https://charts.min.io/
helm repo update
minio-values.yml
# roles/minio/files/minio-values.yml
## Режим: standalone
mode: standalone
## Образ
image:
repository: quay.io/minio/minio
tag: RELEASE.2025-04-22T22-12-26Z # фиксированная версия
pullPolicy: IfNotPresent
## Корневые учётные данные (переопределяются через Secret)
existingSecret: minio-root-credentials
## Хранилище
persistence:
enabled: true
storageClass: longhorn-minio # выделенный SC: numberOfReplicas=1, только worker-диски
accessMode: ReadWriteOnce
size: 1Ti
## Ресурсы пода
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1000m
## Привязка к worker-ноде (не запускать на control plane)
nodeSelector:
node-role.kubernetes.io/control-plane: "" # исключить
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: DoesNotExist
## Сервисы
service:
type: ClusterIP
port: 9000
consoleService:
type: ClusterIP
port: 9001
## Buckets создаются автоматически при старте
buckets:
- name: loki-chunks
policy: none
purge: false
- name: backups
policy: none
purge: false
- name: artifacts
policy: none
purge: false
## Пользователи (пароли — через Secret, задаются ниже)
users:
- accessKey: loki
existingSecret: minio-user-loki
existingSecretKey: secretKey
policy: readwrite
- accessKey: backup
existingSecret: minio-user-backup
existingSecretKey: secretKey
policy: readwrite
## Политики для бакетов
policies:
- name: loki-policy
statements:
- resources:
- "arn:aws:s3:::loki-chunks"
- "arn:aws:s3:::loki-chunks/*"
actions:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:ListBucket"
## Метрики (если Prometheus есть)
metrics:
serviceMonitor:
enabled: false # включить когда появится Prometheus
## MinIO Console — веб-интерфейс
consoleIngress:
enabled: false # используем Traefik напрямую через ClusterIP
## Окружение MinIO
environment:
MINIO_BROWSER_REDIRECT_URL: "http://10.203.0.96:10006" # URL Console через Traefik
MINIO_STORAGE_CLASS_STANDARD: "EC:0" # standalone: без erasure coding
MINIO_UPDATE: "off" # отключить автообновление
Secret с корневыми учётными данными
kubectl create secret generic minio-root-credentials \
--from-literal=rootUser=minioadmin \
--from-literal=rootPassword='СИЛЬНЫЙ_ПАРОЛЬ_МИНИМУМ_8_СИМВОЛОВ' \
-n minio
Установка
kubectl create namespace minio
helm upgrade --install minio minio/minio \
--namespace minio \
--version 5.4.0 \
--values roles/minio/files/minio-values.yml \
--wait
Проверка
# Статус пода
kubectl get pod -n minio
# Логи
kubectl logs -n minio -l app=minio
# Проброс порта для быстрой проверки
kubectl port-forward -n minio svc/minio 9000:9000 &
kubectl port-forward -n minio svc/minio-console 9001:9001 &
# Проверка S3 API через mc (MinIO Client)
mc alias set local http://localhost:9000 minioadmin ПАРОЛЬ
mc ls local
mc admin info local
5. MinIO Console: веб-интерфейс
MinIO Console — встроенный React-интерфейс, запускается в том же поде на порту 9001. Отдельная установка не нужна начиная с MinIO RELEASE.2021-07-08.
Возможности Console
| Раздел | Функции |
|---|---|
| Object Browser | Навигация по бакетам, загрузка/скачивание файлов, просмотр метаданных |
| Buckets | Создание бакетов, версионирование, lifecycle policies, replication |
| Identity → Users | Создание пользователей, назначение политик |
| Identity → Groups | Группировка пользователей |
| Identity → Policies | Редактор IAM-политик (JSON) |
| Monitoring | Дашборд загрузки, IOPS, throughput в реальном времени |
| Logs | Потоковый просмотр логов MinIO в браузере |
| Audit | Журнал операций (включается через MINIO_AUDIT_WEBHOOK_*) |
Настройка адреса Console
MinIO Console проверяет MINIO_BROWSER_REDIRECT_URL при формировании redirect после логина. Без правильного значения Console вернёт 401 или redirect на неверный URL.
# В minio-values.yml — уже задано выше
environment:
MINIO_BROWSER_REDIRECT_URL: "http://10.203.0.96:10006"
6. Интеграция с Traefik
Два порта в traefik_port_map:
10005— MinIO S3 API (для клиентов, boto3, mc)10006— MinIO Console (веб-интерфейс)
Добавить в inventory/prod/group_vars/traefik.yml
traefik_port_map:
# ... существующие записи ...
- name: minio-api
description: "MinIO S3 API"
port: 10005
backend:
namespace: minio
service: minio
port: 9000
scheme: http
basicauth:
enabled: false # MinIO использует собственную аутентификацию (AWS Signature v4)
- name: minio-console
description: "MinIO Console (Web UI)"
port: 10006
backend:
namespace: minio
service: minio-console
port: 9001
scheme: http
basicauth:
enabled: false # MinIO Console имеет собственный логин
Важно: BasicAuth от Traefik + MinIO Console не совместимы — браузер не может пройти двойную аутентификацию. MinIO Console защищён своим логином, этого достаточно.
После добавления запустить setup_traefik.yml.
Адреса после развёртывания
| Сервис | URL | Назначение |
|---|---|---|
| MinIO S3 API | http://10.203.0.96:10005 |
Внешний доступ клиентов |
| MinIO Console | http://10.203.0.96:10006 |
Веб-интерфейс администратора |
| MinIO API (внутри кластера) | http://minio.minio.svc.cluster.local:9000 |
Для подов кластера |
| MinIO Console (внутри кластера) | http://minio-console.minio.svc.cluster.local:9001 |
— |
Настройка mc (MinIO Client) для внешнего доступа
# На manager-ноде или локально
mc alias set prod http://10.203.0.96:10005 minioadmin ПАРОЛЬ
# Проверка
mc ls prod
mc admin info prod
mc du prod/loki-chunks
7. Безопасность: пользователи и политики
Принцип минимальных привилегий
Не используйте root-учётные данные в приложениях. Для каждого сервиса — отдельный пользователь с ограниченной политикой.
Создание пользователей через mc
# Пользователь для Loki (только свой бакет)
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
Lifecycle policy: автоудаление старых объектов
# Удалять объекты в backups старше 30 дней
mc ilm rule add --expire-days 30 prod/backups
# Удалять незавершённые multipart uploads старше 7 дней
mc ilm rule add --expire-days 7 --noncurrent-expire-days 7 prod/backups
Версионирование бакетов (защита от случайного удаления)
# Включить версионирование
mc version enable prod/backups
# Посмотреть все версии объекта
mc ls --versions prod/backups/db-dump.sql.gz
8. Интеграция с Loki (S3 backend)
При переходе Loki на distributed-режим (см. PLG исследование) MinIO становится S3 backend для хранения chunks и index.
Loki values для S3 backend
# roles/logging/templates/loki-values.yml.j2 (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_minio_password }}"
insecure: true # http (не https)
s3forcepathstyle: true # обязательно для MinIO
schemaConfig:
configs:
- from: "2024-01-01"
store: tsdb
object_store: s3 # ← было filesystem
schema: v13
index:
prefix: loki_index_
period: 24h
Secret для Loki в namespace monitoring
kubectl create secret generic loki-minio-secret \
--from-literal=AWS_ACCESS_KEY_ID=loki \
--from-literal=AWS_SECRET_ACCESS_KEY='ПАРОЛЬ_LOKI' \
-n monitoring
9. Ansible-роль и плейбук
Структура роли roles/minio/
roles/minio/
├── defaults/main.yml
├── tasks/
│ ├── main.yml
│ ├── namespace.yml — создать namespace minio
│ ├── secrets.yml — создать Secrets из vault/переменных
│ ├── helm.yml — helm upgrade --install minio
│ └── mc.yml — настройка mc alias, пользователей, политик, lifecycle
├── files/
│ └── minio-values.yml
└── templates/
└── minio-values.yml.j2
defaults/main.yml
minio_namespace: minio
minio_chart_version: "5.4.0" # minio/minio chart
minio_image_tag: "RELEASE.2025-04-22T22-12-26Z"
minio_storage_class: longhorn-minio # выделенный SC, не дефолтный longhorn (numberOfReplicas=3)
minio_storage_size: 1Ti
minio_console_url: "http://10.203.0.96:10006"
minio_api_external_url: "http://10.203.0.96:10005"
# Имена Secrets (значения создаются вручную через kubectl)
minio_root_secret: minio-root-credentials
minio_buckets:
- loki-chunks
- backups
- artifacts
minio_resources_requests_memory: "512Mi"
minio_resources_limits_memory: "2Gi"
tasks/helm.yml
- name: MinIO | Add Helm repo
kubernetes.core.helm_repository:
name: minio
repo_url: https://charts.min.io/
- name: MinIO | Deploy via Helm
kubernetes.core.helm:
name: minio
chart_ref: minio/minio
chart_version: "{{ minio_chart_version }}"
release_namespace: "{{ minio_namespace }}"
create_namespace: true
values: "{{ lookup('template', 'minio-values.yml.j2') | from_yaml }}"
wait: true
wait_condition:
type: Ready
status: "True"
timeout: "10m0s"
playbooks/setup_minio.yml
---
- name: Deploy MinIO object storage
hosts: manager_nodes
become: false
roles:
- minio
.gitlab-ci.yml — новый job
setup/minio:
stage: setup
script:
- ansible-playbook -i inventory/prod playbooks/setup_minio.yml
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
resource_group: production
Переменные GitLab CI/CD (добавить)
| Переменная | Описание |
|---|---|
MINIO_ROOT_PASSWORD |
Пароль root-пользователя MinIO |
MINIO_LOKI_PASSWORD |
Пароль пользователя loki |
MINIO_BACKUP_PASSWORD |
Пароль пользователя backup |
10. Масштабирование
Этапы роста: Longhorn и MinIO вместе
Реальное текущее состояние (проверено): worker имеет 2 диска по ~4 TiB, оба пустые. Это даёт несколько путей масштабирования без добавления нод:
| Этап | Кластер | Longhorn | MinIO |
|---|---|---|---|
| Сейчас | 1 worker, 2 диска по 4 TiB | longhorn SC: numberOfReplicas: 1, master без дисков ✓ |
standalone, PVC 1 TiB на disk1 |
| +2 диска к worker | 1 worker, 4 диска | 4 PVC по 1 TiB, numberOfReplicas: 1 |
SNMD: 4 drives, EC:2, ~2 TiB usable |
| +1 worker с дисками | 2 workers | Поднять numberOfReplicas: 2 в longhorn-minio |
standalone + Longhorn-репликация между нодами |
| +3 workers (4 total) | 4 workers | numberOfReplicas: 2 |
Distributed: 4 пода, EC:2 |
Шаг 1: добавление второго worker (без пересоздания MinIO)
После добавления k8s-worker-02 в кластер:
# Убедиться что Longhorn видит новую ноду и диск
kubectl get nodes -o wide
kubectl get nodes.longhorn.io -n longhorn-system
# Обновить numberOfReplicas у StorageClass (или через Longhorn UI)
kubectl edit storageclass longhorn
# numberOfReplicas: "1" → "2"
# Обновить replicas у существующего PVC MinIO
kubectl -n longhorn-system edit volume <minio-pvc-volume-name>
# spec.numberOfReplicas: 1 → 2
# Longhorn начнёт ребалансировку в фоне, MinIO продолжает работать
Шаг 2: SNMD — 4 диска на одной ноде (реалистичный следующий шаг)
Worker уже имеет 2 диска (~4 TiB каждый). При добавлении ещё 2 дисков можно перейти на SNMD без новых нод:
# minio-values.yml — SNMD режим (4 диска на k8s-worker-01)
mode: distributed # в MinIO SNMD тоже использует mode: distributed
replicas: 1 # 1 нода
drivesPerNode: 4 # 4 PVC на под
persistence:
storageClass: longhorn-minio
size: 1Ti # 4 × 1 TiB = 4 TiB raw → ~2 TiB usable (EC:2)
При SNMD Longhorn создаёт 4 отдельных PVC (по одному на каждый логический диск MinIO). numberOfReplicas: 1 в StorageClass — MinIO EC уже обеспечивает отказоустойчивость.
Шаг 3: distributed (4+ workers)
# minio-values.yml при 4 worker-нодах
mode: distributed
replicas: 4 # 4 пода на 4 нодах
drivesPerNode: 1 # 1 Longhorn PVC на под
persistence:
storageClass: longhorn-minio
size: 1Ti # 4 × 1 TiB raw → ~2 TiB usable (EC:2)
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: minio
topologyKey: kubernetes.io/hostname
В distributed-режиме Longhorn предоставляет отдельный PVC каждому поду MinIO. Репликацию Longhorn для distributed оставить на numberOfReplicas: 1 — MinIO EC уже обеспечивает отказоустойчивость.
Миграция standalone → distributed
MinIO не поддерживает in-place миграцию. Процедура:
1. Запустить distributed MinIO рядом (namespace minio-dist)
2. mc mirror minio-standalone minio-distributed --preserve --watch
3. Дождаться синхронизации всех объектов (mc du для сверки объёмов)
4. Переключить Traefik (изменить service в IngressRoute) на новый сервис
5. Обновить endpoint в configs Loki, бэкапов и других клиентов
6. Подождать 24-48 часов, убедиться что клиенты работают корректно
7. Удалить standalone namespace и PVC
Расширение объёма без миграции (только standalone)
Longhorn поддерживает расширение PVC онлайн — без остановки MinIO:
kubectl patch pvc minio -n minio \
-p '{"spec":{"resources":{"requests":{"storage":"2Ti"}}}}'
# Longhorn расширит том; MinIO увидит новое пространство автоматически
mc admin info prod # проверить новый объём в разделе capacity
11. Итоги и рекомендации
Почему Longhorn — правильный выбор для этого кластера
Longhorn уже является стандартом хранилища в кластере. Использование его для MinIO даёт:
- Единая точка управления — диски, снэпшоты, репликация управляются через Longhorn UI, без отдельной операционной нагрузки
- Онлайн-расширение — PVC MinIO расширяется без остановки пода (
kubectl patch pvc) - Путь к отказоустойчивости — при добавлении второго worker достаточно поднять
numberOfReplicas: 2, MinIO продолжает работать без изменений - Снэпшоты как бэкап — Longhorn умеет делать снэпшоты PVC по расписанию; для MinIO standalone это основной механизм защиты данных до перехода на distributed
Порядок развёртывания
1. Применить StorageClass longhorn-minio (см. раздел 3)
(опц.) Longhorn UI → k8s-worker-01 → добавить тег "minio" на longhorn-disk1 для изоляции
2. kubectl create namespace minio
3. Создать Secret minio-root-credentials вручную
4. Запустить setup_minio.yml (Helm install)
5. Добавить minio-api и minio-console в traefik_port_map (порты 10005, 10006 — свободны)
6. Запустить setup_traefik.yml
7. Проверить Console: http://10.203.0.96:10006
8. Создать пользователей через mc (loki, backup)
9. Обновить loki-values.yml если Loki уже работает
Итоговые адреса
| Сервис | URL |
|---|---|
| MinIO Console (UI) | http://10.203.0.96:10006 |
| MinIO S3 API | http://10.203.0.96:10005 |
| MinIO API (внутри кластера) | http://minio.minio.svc.cluster.local:9000 |
Следующие шаги
- Применить StorageClass
longhorn-minio(раздел 3) - (опц.) Longhorn UI: добавить тег
minioнаlonghorn-disk1для изоляции диска - Создать Secret
minio-root-credentialsвручную - Написать роль
roles/minio/по структуре из раздела 9 - Добавить job
setup/minioв.gitlab-ci.yml - Добавить
minio-apiиminio-consoleвtraefik_port_map(порты 10005, 10006) - Добавить переменные
MINIO_ROOT_PASSWORD,MINIO_LOKI_PASSWORDв GitLab CI/CD Variables - Добавить firewalld-правило в
roles/minio/tasks/firewall.yml(порты 9000, 9001 вtrustedzone для flannel.1/cni0)