Привет! В этой статье рассмотрим разворачивание dev кластера min.io в контейнерах (docker-compose) с tls, site-replication, nginx и заденем немного tiering. Также настроим мониторинг нашего кластера в prometheus+grafana.
Статья представляет собой пошаговое руководство для разворачивания кластерного minio в контейнерах от bitnami. Также рядом развернем однонодный minio. Объединим эти 2 minio с помощью site-replication. Создадим тестового пользователя, тестовый policy, тестовый бакет и попробуем с ним работать.
Подготовка
Начнем с клонирования репозитория https://github.com/yubazh/minio-compose
git clone git@github.com:yubazh/minio-compose.git
Для использования TLS нам необходимо сгенерировать сертификаты. Сертификаты можно сгенерировать с помощью скрипта generate_ssl_cert.ssh, который лежит в директории certsgen. Скрипт использует openssl. Перед запуском сертификата, необходимо поместить свой ip-адрес в файл certsgen/server-ext.cnf
вместо адреса 192.168.0.199. Также стоит обратить внимание, что сертификат будет выписан на *.local. Доменные имена minio{1..4}.local будут использовать для взаимодействия нод minio между собой.
cat certsgen/server-ext.cnf
subjectAltName=DNS:*.local,IP:0.0.0.0,IP:127.0.0.1,IP:192.168.0.199
Посмотрим на сам скрипт:
# удаляем существующие сертификаты
rm *.pem
# генерируем certificate authority с ключом
# 1. Generate CA's private key and self-signed certificate
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=XX/ST=XXX/L=XXXX/O=XXXXX/OU=XXXXXX/CN=*.local/emailAddress=mail@gmail.com"
echo "CA's self-signed certificate"
openssl x509 -in ca-cert.pem -noout -text
# генерируем сертификат с ключом
# 2. Generate web server's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -keyout server-key.pem -out server-req.pem -subj "/C=XX/ST=XXX/L=XXXX/O=XXXXX/OU=XXXXXX/CN=*.local/emailAddress=mail@gmail.com" -nodes
# 3. Use CA's private key to sign web server's CSR and get back the signed certificate
openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 60 -extfile server-ext.cnf
echo "Server's signed certificate"
openssl x509 -in server-cert.pem -noout -text
echo "Command to verify Server and CA certificates"
openssl verify -CAfile ca-cert.pem server-cert.pem
# удаляем директорию certs, в которую мы положим вновь созданные сертификаты для minio
echo "Deleting certs dir"
rm -rf ../certs
# создаем заново директорию ../certs и помещаем туда необходимые сертификаты
echo "Creating certs dirs"
mkdir -p ../certs/CAs
cp ca-cert.pem ../certs/ca.crt
cp ca-cert.pem ../certs/CAs/ca.crt
cp server-cert.pem ../certs/public.crt
cp server-key.pem ../certs/private.key
chmod +r ../certs/private.key
# удаляем существующие директории для хранения данных самого minio
echo "Deleting minio dirs"
rm -rf ../minio*
# создаем новые директории для хранения данных minio
echo "Creating minio dirs"
mkdir ../minio1
mkdir ../minio2
mkdir ../minio3
mkdir ../minio4
mkdir ../miniosolo
sudo chown -R 1001:1001 ../minio*
Если коротко, то мы удаляем все ранее созданные сертификаты в диреткории certsgen, удаляем директорию ../certs (в которую сложим новые сертификаты и прокинем в контейнеры), удаляем старые директории для хранения персистентных данных minio и создадим новые с необходимыми правами. Запустим скрипт:
cd certsgen
./generate_ssl_cert.ssh
Если все ок, то мы увидим вывод наших сертификатов, а также сообщения об удалении старых директорий и создании новых.
Основной кластер min.io
Теперь разберем основной compose и развернем кластер.
Для разворачивания будем использовать контейнеры minio от bitnami (https://github.com/bitnami/containers/tree/main/bitnami/minio). В docker-compose мы зададим админский пароль, хостнеймы контейнеров, настроим "кластерность", https, постоянное хранилище, healthcheck, а также nginx, который будет выступать в виде прокси перед нашим кластером.
Отдельно стоит отметить, что в документации указано, что минимальное количество нод в кластере minio - 4. Также, указано что в продакшн среде необходимо использовать минимум 4 диска на каждой ноде. Это вся связано с внутренним устройством minio, и тем как он разбивает всё на объекты и хранит данные объекты в дальнейшем. На сайте minio есть удобный калькулятор для продакшн решений: https://min.io/product/erasure-code-calculator.
Также отмечу, что в документации указано, использовать на дисках для хранения "data" файловую систему xfs.
Разберем более детально файл docker-compose.yaml, а именно первый контейнер minio (остальные 3 совершенно идентичны) и контейнер с nginx:
cat docker-compose.yaml
version: '3.7'
services:
# first cluster
minio1:
# рестарт в случае падения - всегда
restart: always
# указываем использование образа bitnami minio с тегом 2024.7.26
image: bitnami/minio:2024.7.26
# отдельно указываем название контейнера
container_name: minio1
# указываем hostname по которому к нему можно будет обращаться внутри docker network
hostname: minio1.local
# блок с переменными, которые будут загружаться в minio
environment:
# указываем админский логин и пароль
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=MBVfbuu2NDS3Aw
# указываем использование distributed mode (кластера)
- MINIO_DISTRIBUTED_MODE_ENABLED=yes
# указываем из каких нод будет состоять кластер.
# в нашем случае это будут контейнеры, обращаемся к ним по хостнеймам
- MINIO_DISTRIBUTED_NODES=minio1.local,minio2.local,minio3.local,minio4.local
# данную переменную подсмотрел где-то на стаковерфлоу, фиксит некоторые падения
- MINIO_SKIP_CLIENT=yes
# указываем явное использование https
- MINIO_SCHEME=https
# указывает порт, по которому можем попасть на web-ui
- MINIO_CONSOLE_PORT_NUMBER=9001
# следующие 2 переменные следует добавлять при использовании nginx перед кластером
# первая переменная указывает адрес всего кластер
- MINIO_SERVER_URL=https://minio.local
# вторая указываем конкретное расположение web-ui
- MINIO_BROWSER_REDIRECT_URL=https://minio.local/minio/ui
# обе эти переменные решают вопрос взаимодействия и переадресации между нодами minio и nginx
volumes:
# указываем директорию для хранения данных. монтируем в /bitnami/minio/data
# обратите внимание что в разных контейнерах (разных сборщиков) разное место монтирования
- ./minio1:/bitnami/minio/data
# монтируем директорию с сертификатами, для взаимодействия по https
- ./certs:/certs
healthcheck:
# производим очень простой healthcheck
test: [ "CMD", "curl", "-k", "https://localhost:9000/minio/health/live" ]
interval: 30s
timeout: 20s
retries: 3
...
...
...
minio:
# контейнер с nginx. указываем используемый образ
image: nginx:1.19.2-alpine
# указываем имя контейнера
container_name: minio
# указываем hostname, по которому сможем взаимодействовать с контейнером внутри docker сети
hostname: minio.local
volumes:
# монтируем конфиг nginx
- ./nginx.conf:/etc/nginx/nginx.conf:ro
# монтируем сертификаты, для взаимодействия с нодами по https
- ./certs:/certs
ports:
# выбрасываем порт 443, причем только в nginx. так как соединения будет принимать только nginx
- "443:443"
Остальные 3 контейнера minio имеют идентичные настройки. Только порядковые номера в названии, хостнейме и директории для монтирования отличаются.
Рассмотрим файл конфигурации nginx.conf. Он в общем виде представлен в документации minio (https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html). Нам его необходимо лишь немного подправить. Обратите внимание на раздел upstream:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# include /etc/nginx/conf.d/*.conf;
upstream minio_s3 {
least_conn;
server minio1.local:9000;
server minio2.local:9000;
server minio3.local:9000;
server minio4.local:9000;
}
upstream minio_console {
least_conn;
server minio1.local:9001;
server minio2.local:9001;
server minio3.local:9001;
server minio4.local:9001;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name minio.local;
# Allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# Disable buffering
proxy_buffering off;
proxy_request_buffering off;
ssl_certificate /certs/public.crt;
ssl_certificate_key /certs/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_verify_client off;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass https://minio_s3; # This uses the upstream directive definition to load balance
}
location /minio/ui/ {
rewrite ^/minio/ui/(.*) /$1 break;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
# This is necessary to pass the correct IP to be hashed
real_ip_header X-Real-IP;
proxy_connect_timeout 300;
# To support websockets in MinIO versions released after January 2023
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
# Uncomment the following line to set the Origin request to an empty string
# proxy_set_header Origin '';
chunked_transfer_encoding off;
proxy_pass https://minio_console; # This uses the upstream directive definition to load balance
}
}
}
Посмотрим на директорию certs. Мы увидим, что в нее поместили сертификат public.crt, который по факту является файлом certsgen/server-cert.pem (т.е. грубо говоря сертификат сервера). Также ключ от упомянутого выше сертификата - private.key, который является файлом certsgen/server-key.pem. И положили исходный самоподписанный ca-cert.pem, переименовав в ca.crt. Также создали директорию certs/CAs и в нее скопировали ca.crt. Директорию CAs необходимо для minio, так как по дефолту он в ней ищет необходимый ему ca.crt. (https://min.io/docs/minio/linux/operations/network-encryption.html) Все сертификаты пробрасываются в контейнеры с minio.
Запустим кластерную версию:
docker compose -f docker-compose.yaml up -d
Подождем минуту пока все запустится и пройдет healthcheck'и. Сделаем
docker ps -a
И мы должны увидеть, что все наши контейнеры поднялись:
![docker ps docker ps](https://habrastorage.org/getpro/habr/upload_files/c83/b38/f84/c83b38f84738cb2b73d30c6d7ef6efd6.png)
Заходим в webui
Теперь добавим наш ca.crt в браузер и попробуем зайти в webui.
Я использую firefox, поэтому опишу как добавить сертификат в firefox: Переходим в settings => в строке поиска вводим "cert" => нажимаем на кнопку "View Certificates" =>
![View Certificates View Certificates](https://habrastorage.org/getpro/habr/upload_files/459/d57/5ee/459d575eea62b4ade8fcd33c219b0b52.png)
В появившемся окне выбираем крайнюю правую вкладку "Authorities" => далее снизу "Import" => теперь выбираем наш ca.crt из certs/ca.crt => проставляем необходимые галки => жмем "OK" => еще раз "OK".
Также, добавим у себя локально запись в /etc/hosts:
cat /etc/hosts
...
127.0.0.1 minio.local
Теперь открываем браузер и переходим на https://127.0.0.1/minio/ui/login и вводим логин и пароль, которые мы указали в docker-compose.yaml в переменных MINIO_ROOT_USER и MINIO_ROOT_PASSWORD. Обратите внимание на замочек возле нашего адреса, он должен быть без восклицательного знака, что будет свидетельствовать о защищенности подключения.
![TLS TLS](https://habrastorage.org/getpro/habr/upload_files/bb6/455/04d/bb645504d36da780a3114e094747c249.png)
После успешного логина, мы попадем в web интерфейс minio. Можем убедиться что все хорошо, выбрав в левой части экрана пункты: monitoring => metrics. Мы увидим сводную информацию по кластеру:
![Встроенный мониторинг Встроенный мониторинг](https://habrastorage.org/getpro/habr/upload_files/395/dbe/4b9/395dbe4b954350b1bae6fe519bbf68ba.png)
Создание policy
Теперь создадим policy. Перейдем в "policies" => create policy. Введем testpolicy в строку с названием, и добавим свой блок Statemenet.
"Statement": [
{
"Action": [
"s3:PutBucketPolicy",
"s3:GetBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:ListAllMyBuckets",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::testbucket"
],
"Sid": ""
},
{
"Action": [
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:GetObject",
"s3:ListMultipartUploadParts",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::testbucket/*"
],
"Sid": ""
}
]
Этот полиси дает полный контроль над бакетом с названием testbucket. Жмем "Save"
![testpolicy testpolicy](https://habrastorage.org/getpro/habr/upload_files/126/adf/fdd/126adffdd8a94f46d23ff18c6dd9112d.png)
Создание user'a
Теперь создадим пользователя. Перейдем в Identify => Users => Create User. Введем в поле Name: testuser. В поле password: testpassword. Также чуть ниже, среди существующих политик, выберем созданную нами ранее testpolicy. Жмем Save.
![User User](https://habrastorage.org/getpro/habr/upload_files/841/d46/ec4/841d46ec41b37bfa9aaf24239ac515dc.png)
Создание bucket'a
Ну и создадим тестовый бакет. Переходим в Buckets => Create Bucket. В Name вносим testbucket и обязательно вклю1чаем версионирование. Нам оно понадобится при включении site replication в дальнейшем. Жмем create bucket.
![testbucket testbucket](https://habrastorage.org/getpro/habr/upload_files/c3f/60a/d66/c3f60ad66a19fecc62b626130e2a0d65.png)
s3cmd
Попробуем повзаимодействовать с бакетом из операционной системы. Устанавливаем утилиту s3cmd
sudo apt install -y s3cmd
Настраиваем ее, создам файл ~/.s3cfg
. Приведу пример моего конфига:
# Setup endpoint
# указываем наш сервер
host_base = 127.0.0.1
host_bucket = 127.0.0.1
# оставляем по дефолту
bucket_location = us-east-1
# указываем что используем https
use_https = True
# указываем логин и пароль нашего тестового пользователя
# Setup access keys
access_key = testuser
secret_key = testpassword
# Enable S3 v4 signature APIs
# при выполнении большого количества тестов,
# у меня возникла необходимость подключить указанную ниже директиву
# однако при выполнении дефолтных действий она не нужна
# поэтому я ее закоментил, но оставил на всякий случай
# signature_v2 = False
Теперь нам необходимо установить сертификат в нашу операционную систему (у меня ubuntu)
sudo cp certs/ca.crt /usr/local/share/ca-certificates/ca-minio.crt
sudo update-ca-certificates
Произведем тест. Попробуем получить список бакетов в нашем s3:
![s3cmd ls s3cmd ls](https://habrastorage.org/getpro/habr/upload_files/3db/185/eb8/3db185eb809c873981b47302b79e6a61.png)
Видим, что отражается наш testbucket. В случае, если вместо успеха, вы получаете сообщение, говорящее о проблемах с сертификатом, то можете подложить его к утилите s3cmd вручную при помощи аргумента ca-certs:
s3cmd --ca-certs ./certs/ca.crt ls s3://
Получим тот же вывод:
![](https://habrastorage.org/getpro/habr/upload_files/bea/a9b/a91/beaa9ba915432cf35db08c9bdab143a9.png)
Положим наш файл nginx.conf в бакет и проверим его в web-ui:
![](https://habrastorage.org/getpro/habr/upload_files/f18/d5b/75e/f18d5b75e1ee63facdcf203287142cbf.png)
Переходим в webui, object browser и открываем testbucket. Файл на месте:
![testbucket testbucket](https://habrastorage.org/getpro/habr/upload_files/9c7/0fe/eac/9c70feeacd3dcd2e31e0bf5bf1e60fe4.png)
Отдельный minio
Для организации site-replication или tiering нам понадобиться второй minio. Однако необходимо в кластерном решении у нас нет, поэтому развернем отдельностоящий minio из одного контейнера.
Рассмотрим docker-compose.yaml. Остановлюс только на отличиях от кластерного варианта:
cat docker-compose-solo.yaml
version: '3.7'
services:
# minio solo
miniosolo:
restart: always
image: bitnami/minio:2024.7.26
container_name: miniosolo
hostname: miniosolo.local
# в данном случае мы обязательно выбрасываем порты, по которым будем
# взаимодействовать с нашим minio
# 9001 - webuil 9000 - api
ports:
- '9000:9000'
- '9001:9001'
environment:
# также указываем login & password
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=2eG1~B/j{70d
- MINIO_SKIP_CLIENT=yes
# указываем использование https
- MINIO_SCHEME=https
# указываем порт для web-ui
- MINIO_CONSOLE_PORT_NUMBER=9001
extra_hosts:
# вносим в /etc/hosts данного контейнера связку minio.local c 192.168.0.199
- "minio.local:192.168.0.199"
volumes:
- ./miniosolo:/bitnami/minio/data
- ./certs:/certs
healthcheck:
test: [ "CMD", "curl", "-k", "https://localhost:9000/minio/health/live" ]
interval: 30s
timeout: 20s
retries: 3
Разворачиваем minio и проверяем контейнер:
docker compose -f docker-compose-solo.yaml up -d
docker ps
Убеждаемся, что контейнер поднялся. После этого заходим в webui: https://127.0.0.1:9001/login (обратите внимание, данный минио доступен по конкретным портам. для webui - 9001).
и логинимся, используя переменные из docker-compose-solo.yaml. Удостоверяемся секьюрности коннекта (тот же замочек рядом с адресом). А также удостоверяемся, что это совершенно другой minio. У него только одна нода в metrics. А также нет пользователей, политик и бакетов.
![](https://habrastorage.org/getpro/habr/upload_files/927/c5e/7ad/927c5e7adf9290f4468a266ec9a11381.png)
Site Replication
Настроим репликацию между этими кластерами
Переходим в webui основого кластера на вкладку site replication в самом низу панели администрирования. Жмем Add Sites и заполняем все поля. В данный момент воспользуемся админской учеткой, однако для этих целей лучше создать отдельную учетную запись:
![Site Replication Site Replication](https://habrastorage.org/getpro/habr/upload_files/753/2fd/3fb/7532fd3fb18bc54b000d5b6d9939f531.png)
Здесь нам понадобятся ранее внесенные записи в /etc/hosts. К первому (main) кластеру мы обратимся по minio.local. А ко второму кластеру по внешнему ip-адресу (192.168.0.199 - мы его прописали в самом начале, при создании сертификата). Жмем Save и получаем:
![](https://habrastorage.org/getpro/habr/upload_files/e27/321/b94/e27321b9401ff28df4248f58f02a9f32.png)
Можем перейти на вкладку Replication Status и убедиться, в том, что все сущности перенесены. Также можем перейти в webui stand-alone minio (https://127.0.0.1:9001/) и посмотреть содержимое его бакеты:
![](https://habrastorage.org/getpro/habr/upload_files/cc4/a78/ad9/cc4a78ad977201cb753e819ecdbf3663.png)
Видим что бакет создан, а вот количество objects = 0. Проверим через утилиту s3cmd. Изменим s3cfg, указав использовать stand-alone minio (добавим только порт, остальное оставим таким же):
cat ~/.s3cfg
# Setup endpoint
host_base = 127.0.0.1
host_bucket = 127.0.0.1
bucket_location = us-east-1
use_https = True
# Setup access keys
access_key = testuser
secret_key = testpassword
# Enable S3 v4 signature APIs
#signature_v2 = False
Попытаемся загрузить файл nginx.conf:
![](https://habrastorage.org/getpro/habr/upload_files/f99/9fe/d54/f999fed546d252ab46be051749e8566e.png)
Видим, что все прошло успешно. Насколько я понял, это "фича" отображения. Теперь в web-ui видим, что объект - 1.
Tiering
Особо сильно останавливаться не будем на этом пункте. Опишу только основные собственные выводы. Minio не умеет делить диски на ssd и hdd. Он их просто собирает все в одну кучу. Причем, насколько указано в документации - по принципу самого слабого звена. Т.е. если диски разных размеров, то по факту использоваться будет только емкость в диске, соответствующая самому маленькому по объему диску.
Ну и так как minio не умеет делить диски на ssd и hdd, то он и не может создавать bucket'ы только на каких-то конкретных дисках. Т.е. бакет размазывается в общем, а не на конкретных дисках. Из этого следует, что для использования tiering, вам необходимый рядом стоящие кластеры, или арендованные бакеты, которые развернут на соответствующих дисках. Т.е. например свой кластер на ssd в виде горячего хранилище. И арендованный s3 бакет где-то еще в виде холодного хранилища.
Для настройки tiering'a есть соответствующий раздел слева на панели: tiering. После подключения бакета в этом разделе, мы можем его использовать в уже конкретном нашем бакете: buckets => testbucket => lifecycle => add lifecycle rule. Т.е. по факту tiering в minio = lifecycle management.
В правилах мы устанавливаем какие конкретно файлы в какой tiering-bucket выгрузятся после какого именно периода времени. Т.е. например, мы можем хранить в нашем бакете файлы только 1 месяц. После этого, они все выгружаются на удаленный бакет. Причем они остаются доступны из нашего основого бакета. Также отмечу, что движения файлов обратно - нет. Если файлы выгрузились в tiering bucket - то настройки чтобы их поместить обратно в горячее хранилище нет (по крайней мере я не нашел).
Стоит отдельно отметить. При настройке site replication + tiering нам необходимо настраивать каждому кластеру свой tiering отдельно. В документации отдельно указано, что tiering не реплецируемая сущность.
По данному разделу приветствуются комменты. Не сказать, что в документации эта часть расписана предельно понятно. Здесь ответы на вопросы можно получить только после поднятия кластера и самостоятельных тестов.
Minio client
Для настройки мониторинга нам понадобится утилита minio client. Установим ее по инструкции из оф документации: https://min.io/docs/minio/linux/reference/minio-mc.html
После установки, добавим наш main кластер в minio client:
# в случае если у вас уже установлена утилита midnight commander,
# то обратитесь к mc например через ~/minio-binaries/mc
~/minio-binaries/mc alias set mainminio https://127.0.0.1 minioadmin MBVfbuu2NDS3Aw
Увидим сообщение об успехе:
![](https://habrastorage.org/getpro/habr/upload_files/853/45c/062/85345c06204991336b2d6d0fa0e33a3e.png)
Проверим и получим краткую информацию о кластере:
![minio client minio client](https://habrastorage.org/getpro/habr/upload_files/28a/9c6/d7e/28a9c6d7edeafd36abf4ed35d1ee4042.png)
Monitoring
Как мы видели ранее, в web интерфейса минио уже есть раздел monitoring, в котором можно посмотреть некоторую информацию о кластере. Однако мы развернем prometheus, настроим scrapeconfig и отрисуем собранные метрики в grafana.
Для начала сгенерируем токен для сбора метрик:
~/minio-binaries/mc admin prometheus generate mainminio
Получим следующее:
![](https://habrastorage.org/getpro/habr/upload_files/1ed/602/cf1/1ed602cf19ebe2cf345066381c6a5538.png)
Нам необходимо скопировать bearer_token и заменить его в файле prometheus/prometheus.yml
в двух местах (строки 7 и 16):
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 15s
scrape_configs:
- job_name: minio-job-server
bearer_token: #####ВОТ_ЗДЕСЬ######
metrics_path: /minio/v2/metrics/cluster
scheme: https
tls_config:
ca_file: /certs/ca.crt
#insecure_skip_verify: true
static_configs:
- targets: [minio.local]
- job_name: minio-job-bucket
bearer_token: #####И_ВОТ_ЗДЕСЬ######
metrics_path: /minio/v2/metrics/bucket
scheme: https
tls_config:
ca_file: /certs/ca.crt
#insecure_skip_verify: true
static_configs:
- targets: [minio.local]
В данном скрейпконфиге мы указываем прометеусу, что нужно собирать метрики с minio.local, перейдя по https://minio.local/minio/v2/metrics/cluster и https://minio.local/minio/v2/metrics/bucket. Также указываем какой ca.crt использовать при сборе метрик (/certs/ca.crt - директорию certs мы прокинем в prometheus).
Посмотрим docker-compose-monitoring.yaml:
version: "3.5"
services:
prometheus:
image: prom/prometheus:v2.51.2
container_name: prometheus
# указываем прометеусу что нужно подхватить в качестве конфиг-файла наш,
# который лежит в /etc/prometheus/prometheus.yml
# это конфиг, который мы правили немного выше
command:
- '--config.file=/etc/prometheus/prometheus.yml'
# "выбрасываем" порт 9090
ports:
- 9090:9090
volumes:
# монтируем директорию prometheus с нашим конфигом
- ./prometheus:/etc/prometheus
# для хранения данных используем volume
# мне не нужно хранить данные в директории с кластером minio
# поэтому будем класть их в volume
- prom_data:/prometheus
# прокидываем директорию certs с нашими сертификатами
- ./certs:/certs
healthcheck:
test: wget --no-verbose --tries=1 --spider localhost:9090 || exit 1
interval: 5s
timeout: 10s
retries: 3
start_period: 5s
grafana:
image: grafana/grafana:10.4.2
container_name: grafana
ports:
# порт, по которому мы будем ходить в grafana
- 3000:3000
environment:
# указываем логин и пароль от админа
# AUTH
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
# указываем возможность просматривать дашборды без аутентификации
- GF_AUTH_ANONYMOUS_ENABLED=true
volumes:
# монтируем директорию provisioning, в которой настройки по
# добавлению datasources и dashboards
- ./grafana/provisioning:/etc/grafana/provisioning
# монтируем директорию c json наших дашбордов
- ./grafana/dashboards:/var/lib/grafana/dashboards
depends_on:
# перед разворачиванием графаны, дожидаемся готовности prometheus
- prometheus
healthcheck:
test: curl --fail localhost:3000
interval: 5s
timeout: 10s
retries: 3
start_period: 10s
# раздел описания томов (volume)
volumes:
prom_data:
Поднимаем мониторинг:
docker compose -f docker-compose-monitoring.yaml up -d
Через docker ps убеждаемся что оба контейнера healthy. Даем еще некоторое время подняться графане и заходим на http://127.0.0.1:3000. Выбираем слева вверху меню (три горизонтальные черты) и переходим в dashboards.
![Minio Dashboard Minio Dashboard](https://habrastorage.org/getpro/habr/upload_files/a15/22a/840/a1522a84005698e03f90ea5b9502b433.png)
Minio dashboard выдает информацию по кластеру в общем.
Minio Bucket Dashboard выводит информацию конкретно по бакетам:
![](https://habrastorage.org/getpro/habr/upload_files/e3a/85d/39b/e3a85d39bc531339c2af0531fb3569e9.png)
Обратите внимание, что прометеусу нужно некоторое время, чтобы собрать хоть какие-то метрики. Также, если видите что пустыми только часть полей - то видимо именно эти метрики еще пусты. Например так может случится если бакетов еще нет совсем, тогда и дашборд с бакетами будет выводить "no data". Или например если обращений к api еще не было, то и S3 Api Request тоже будет пуст.
Разделение на виртуальные машины
Если вы хотите развернуть свой кластер минио на разных машинах, а не на одной, то compose можно немного трансформировать. Рассмотрим отдельно компоуз первого контейнера. Обратите внимание, что в данном случае мы пробрасываем порты 9000 и 9001 для связи с контейнером из вне. А также жестко закрепляем в /etc/hosts (раздел extra_hosts) адреса всех наших виртуальных машин с контейнерами
version: '3.7'
services:
minio1:
restart: always
image: bitnami/minio:2024.7.26
container_name: minio1.local
hostname: minio1.local
ports:
- '9000:9000'
- '9001:9001'
environment:
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=MBVfbuu2NDS3Aw
- MINIO_DISTRIBUTED_MODE_ENABLED=yes
- MINIO_DISTRIBUTED_NODES=minio1.local,minio2.local,minio3.local,minio4.local
- MINIO_SKIP_CLIENT=yes
- MINIO_SCHEME=https
- MINIO_CONSOLE_PORT_NUMBER=9001
- MINIO_SERVER_URL=https://minio.local
- MINIO_BROWSER_REDIRECT_URL=https://minio.local/minio/ui
extra_hosts:
- "minio1.local:192.168.0.55"
- "minio2.local:192.168.0.56"
- "minio3.local:192.168.0.57"
- "minio4.local:192.168.0.58"
- "minio.local:192.168.0.59"
volumes:
- /mnt/minio1:/bitnami/minio/data
- ./certs:/certs
healthcheck:
test: [ "CMD", "curl", "-k", "https://localhost:9000/minio/health/live" ]
interval: 30s
timeout: 20s
retries: 3
# раздел с разворачиванием node exporter
node_exporter:
image: prom/node-exporter:v1.8.2
container_name: node_exporter
command:
- '--path.rootfs=/host'
network_mode: host
pid: host
restart: unless-stopped
volumes:
- '/:/host:ro,rslave'
Листинг nginx:
version: '3.7'
services:
nginx:
image: nginx:1.19.2-alpine
hostname: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/certs
extra_hosts:
- "minio1.local:192.168.0.55"
- "minio2.local:192.168.0.56"
- "minio3.local:192.168.0.57"
- "minio4.local:192.168.0.58"
- "minio.local:192.168.0.59"
ports:
- "443:443"
node_exporter:
image: prom/node-exporter:v1.8.2
container_name: node_exporter
command:
- '--path.rootfs=/host'
network_mode: host
pid: host
restart: unless-stopped
volumes:
- '/:/host:ro,rslave'
А также посмотрим на nginx.conf. В файле конфигурации nginx, нас интересует прежде всего раздел upstream, там мы перечисляем наши ноды:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# include /etc/nginx/conf.d/*.conf;
upstream minio_s3 {
least_conn;
server minio1.local:9000;
server minio2.local:9000;
server minio3.local:9000;
server minio4.local:9000;
}
upstream minio_console {
least_conn;
server minio1.local:9001;
server minio2.local:9001;
server minio3.local:9001;
server minio4.local:9001;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name minio.local;
# Allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# Disable buffering
proxy_buffering off;
proxy_request_buffering off;
ssl_certificate /certs/public.crt;
ssl_certificate_key /certs/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_verify_client off;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass https://minio_s3; # This uses the upstream directive definition to load balance
}
location /minio/ui/ {
rewrite ^/minio/ui/(.*) /$1 break;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
# This is necessary to pass the correct IP to be hashed
real_ip_header X-Real-IP;
proxy_connect_timeout 300;
# To support websockets in MinIO versions released after January 2023
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
# Uncomment the following line to set the Origin request to an empty string
# proxy_set_header Origin '';
chunked_transfer_encoding off;
proxy_pass https://minio_console; # This uses the upstream directive definition to load balance
}
}
}
Заключение
На просторах интернета готовых компоузов не нашел, поэтому решил выложить свои. Надеюсь, кому-то поможет в работе.
Комментарии (7)
trabl
06.08.2024 05:44+1Для dev решений single node вполне достаточно, а если уж хочется отказоустойчивости то лучше конечно использовать multinode multidrive, то есть минимум 4 ноды по 4 диска с EC:4. Какой смысл в использовании по сути multinode singledrive в docker-compose?
yubazh Автор
06.08.2024 05:44смысл в том, что это dev кластер, с которым мы будем производить различные эксперименты. выдан шаблон, который можно уже дальше вертеть как угодно. в том числе и добавить по 4 диска. в статье указан этот момент из документации (про необходимость использования минимум 4 серверов по минимум 4 диска)
vasyakrg
06.08.2024 05:44+1На просторах интернета готовых компоузов не нашел
https://github.com/vasyakrg/minio
Вот когда-то я копипастил, как вы, сейчас так не делаю.
UnusualLetter
06.08.2024 05:44+2В статье не увидел, спрашиваю в комментах — почему используется не образ minio, а некий bitnami/minio, который к minio не имеет отношения?
yubazh Автор
06.08.2024 05:44с инфой о bitnami можно ознакомиться вот тут: https://bitnami.com/
использую bitnami вместо дефолтного образа minio, потому что bitnami предлагает уже преднастроенный образ. можно переменными настроить разворачивание, что несомненно удобно. использую как в k8s, так и в docker-compose образы различных приложений от битнами. есть внятная документация и примеры использования: https://github.com/bitnami/containers/tree/main/bitnami/minio.
vasyakrg
Так вынесите все повторяющиеся элементы в якорь и цепляйте к изнеменяемому. Композ, как и любой ямл это понимает и любит. Зачем плодить копипаст?
Посоветовал бы юзать rclone. Он быстрее, умеет как в много потоков, так и в много ядер, приятный --progress и много с чем другим, кроме миньки умеет, а значит не надо плодить бинари у себя на компе.
yubazh Автор
спасибо за rclone, надо попробовать.
по повторяющимся элементам - в своих тестах (да и в конце статьи есть данная инфа) крутил компоузы по всякому, в том числе по разным виртуальным машинам. поэтому просто оставил так для удобства.