MinIO es un servidor de almacenamiento de alto rendimiento compatible com Amazon S3, sus principales características son, arquitectura hyperescalable multi datacenter, alto rendimiento para servir grandes volúmenes de información, actualización fácil no disruptiva, alta disponibilidad/resistencia a fallo de discos y/o nodos, soporte para cifrado y compresión de datos.
Compilamos e instalamos Minio:
Podemos consultar la versión instalada con:
Version: 2019-09-11T19-53-16Z
Release-Tag: DEVELOPMENT.2019-09-11T19-53-16Z
Commit-ID: 3e3fbdf8e6e5e889232eb7afc0b27ac054adfda0
Editamos el script de arranque de Minio para asignarle la ACCESS_KEY y la SECRET_KEY:
#!/sbin/openrc-run
# Copyright 2016-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
description="Minio Object Storage Server"
pidfile=${pidfile:-"/run/${SVCNAME}.pid"}
export MINIO_ACCESS_KEY=XXXXXXXXXXXXXXXXXXX
export MINIO_SECRET_KEY=YYYYYYYYYYYYYYYYYYY
command="/usr/bin/minio"
command_args="${command_args:-server /var/lib/minio}"
command_background="true"
start_stop_daemon_args="--stdout /var/log/${SVCNAME}.log \
--stderr /var/log/${SVCNAME}.log"
Arrancamos el servicio y lo añadimos al arranque:
rc-update add minio default
Por defecto Minio arranca en modo mono-server exportanto el directorio /var/lib/minio, podemos comprobar que funciona correctamente accediendo a:
http://IP:9000
Para utilizar múltiples discos(min: 4 discos) tendremos que modificar el script de arranque, en este escenario se podrán perder N/2 discos sin pérdida de datos:
#!/sbin/openrc-run
# Copyright 2016-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
description="Minio Object Storage Server"
pidfile=${pidfile:-"/run/${SVCNAME}.pid"}
export MINIO_ACCESS_KEY=XXXXXXXXXXXXXXXXXXX
export MINIO_SECRET_KEY=YYYYYYYYYYYYYYYYYYY
command="/usr/bin/minio"
command_args="${command_args:-server /data1 /data2 /data3 /data4 /data5 /data6 /data7 /data8 /data9 /data10 /data11 /data12}"
command_background="true"
start_stop_daemon_args="--stdout /var/log/${SVCNAME}.log \
--stderr /var/log/${SVCNAME}.log"
Reiniciamos el servicio para que surta efecto la configuración:
Si consultamos el proceso podremos ver los parámetros con los que ha arrancado:
root 10568 0.0 0.2 2130480 91204 ? Ssl 12:13 0:00 /usr/bin/minio server /data1 /data2 /data3 /data4 /data5 /data6 /data7 /data8 /data9 /data10 /data11 /data12
Para realizar despliegues distribuidos debemos tener en cuenta los siguientes puntos:
- Mínimo de servidores: 2
- Máximo de servidores: 32
- Para que siga funcionando deben quedar N/2 discos vivos pero (N/2)+1 para crear objetos nuevos.
- Mismo número de discos en cada nodo.
- Todos los sistemas operativos deben ser el mismo SO y mismo ancho de banda.
- Los relojes deben estar sincronizados con un error máximo de 3s(net-misc/ntpclient).
- Las access_keys/secret_keys deben ser compartidas entre servidores.
- El path de los directorios utilizados como almacenamiento deben ser los mismos en todos los servers.
Asignamos las mismas credenciales en todos los servers y en los argumentos del comando indicaremos la lista de servidores minio:
#!/sbin/openrc-run
# Copyright 2016-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
description="Minio Object Storage Server"
pidfile=${pidfile:-"/run/${SVCNAME}.pid"}
export MINIO_ACCESS_KEY=XXXXXXXXXXXXXXXXXXX
export MINIO_SECRET_KEY=YYYYYYYYYYYYYYYYYYY
command="/usr/bin/minio"
command_args="${command_args:-server http://MINIOSERVER1IP/data http://MINIOSERVER2IP/data http://MINIOSERVER3IP/data http://MINIOSERVER4IP/data"
command_background="true"
start_stop_daemon_args="--stdout /var/log/${SVCNAME}.log \
--stderr /var/log/${SVCNAME}.log"
Arrancamos el servicio y lo añadimos al arranque en todos los nodos:
rc-update add minio default
Finalmente instalamos el cliente en nuestro pc, debemos tener en cuenta que tanto el cliente como los servidores deben compartir versión, en mi caso los servidores son Version: 2019-09-11T19-53-16Z por lo tanto descargamos la versión correspondiente del cliente:
chmod +x mc.RELEASE.2019-09-11T20-17-47Z
mv mc.RELEASE.2019-09-11T20-17-47Z /usr/local/bin/mc
Consultamos la versión:
Version: 2019-09-11T20:17:47Z
Release-tag: RELEASE.2019-09-11T20-17-47Z
Commit-id: 54ee3a280031adabc49a8309b74e5786cf266706
Configuramos las credenciales de nuestro minio:
export MINIO_ACCESS_KEY=XXXXXXXXXXXXXXXXXXX
export MINIO_SECRET_KEY=YYYYYYYYYYYYYYYYYYY
Añadimos los servidores:
mc config host add kr0mminio2 http://MINIOSERVER2IP:9000 XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYY
mc config host add kr0mminio3 http://MINIOSERVER3IP:9000 XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYY
mc config host add kr0mminio4 http://MINIOSERVER4IP:9000 XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYY
Consultamos los servidores:
kr0mminio
URL : http://MINIOSERVER1IP:9000
AccessKey : XXXXXXXXXXXXXXXXXXX
SecretKey : YYYYYYYYYYYYYYYYYYY
API : s3v4
Lookup : auto
kr0mminio2
URL : http://MINIOSERVER2IP:9000
AccessKey : XXXXXXXXXXXXXXXXXXX
SecretKey : YYYYYYYYYYYYYYYYYYY
API : s3v4
Lookup : auto
kr0mminio3
URL : http://MINIOSERVER3IP:9000
AccessKey : XXXXXXXXXXXXXXXXXXX
SecretKey : YYYYYYYYYYYYYYYYYYY
API : s3v4
Lookup : auto
kr0mminio4
URL : http://MINIOSERVER4IP:9000
AccessKey : XXXXXXXXXXXXXXXXXXX
SecretKey : YYYYYYYYYYYYYYYYYYY
API : s3v4
Lookup : auto
Desde la interfaz web he creado un bucket llamado kr0m donde he subido una imagen:
Consultamos el bucket desde CLI:
[2020-02-26 15:27:42 CET] 0B kr0m/
Consultamos el contenido del bucket desde CLI:
[2020-02-26 15:27:42 CET] 18KiB zabbixEscalation.jpg
NOTA: Si utilizamos discos mecánicos habilitar la compresión suele ayudar, ya que evitará el tener que leer tanto del disco.
Para habilitar la compresión debemos dumpear la configuración actual, modificarla y volverla a cargarla:
vi /tmp/myconfig
"compress": {
"enabled": true,
"extensions": [".txt",".log",".csv", ".json"],
"mime-types": ["text/csv","text/plain","application/json"]
}
Cargamos la configuración modificada:
Setting new MinIO configuration file has been successful.
Please restart your server with `mc admin service restart kr0mminio`.
Reiniciamos el proceso de minio para que aplique la configuración.
Restart command successfully sent to `kr0mminio`.
Restarted `kr0mminio` successfully.
NOTA: Hay que tener en cuenta que Minio no soporta encriptación y compresión simultáneamente ya que esto haría posible ataques de side channel como CRIME y BREACH.
Una funcionalidad interesante de Minio es la sincronización de ficheros en tiempo real:
touch work/AA
mc mirror work kr0mminio/kr0m
Si entramos a cualquier otro servidor Minio deberíamos de ver el mismo contenido:
http://IP:9000
Los permisos de acceso se gestionan mediante las políticas:
- none (no anonymous access)
- download (anonymous read-only access)
- upload (anonymous write-only access)
- public (anonymous read/write access)
Podemos ver las políticas aplicadas mediante un get:
Access permission for `kr0mminio/kr0m` is `none`
Para asignar políticas utilizaremos el comando set:
Access permission for `kr0mminio/kr0m` is set to `download`
Si volvemos a hacer el get podemos ver que la política ha cambiado:
Access permission for `kr0mminio/kr0m` is `download`
Si cambiamos un disco podemos hacer que los datos se repliquen al nuevo con el comando heal, para ello primero debemos parar el servicio en el nodo afectado:
Cambiamos el disco y arrancamos el servicio de nuevo:
Desde el cliente le ordenamos que resincronize el contenido:
◓ kr0m/zabbixEscalation.jpg
2/2 objects; 18 KiB in 1s
|--------------------------------------|
| Green | 8 | 100.0% ████████████ │
| Yellow | 0 | 0.0% |
| Red | 0 | 0.0% |
| Grey | 0 | 0.0% |
|--------------------------------------|
Para actualizar las versiones de Minio en los servidores utilizaremos el cliente:
Server `kr0mminio` already running the most recent version 2019-09-11T19-53-16Z of MinIO
Podemos ver el estado del cluster mediante el comando info:
● MINIOSERVER1IP:9000
Uptime: 1 hour
Version: 2019-09-11T19-53-16Z
Storage: Used 215 KiB, Free 2.4 TiB
Drives: 1/1 OK
CPU min avg max
current 0.11% 0.14% 0.18%
historic 0.05% 0.56% 27.37%
MEM usage
current 70 MiB
historic 70 MiB
● MINIOSERVER2IP:9000
Uptime: 1 hour
Version: 2019-09-11T19-53-16Z
Storage: Used 215 KiB, Free 2.4 TiB
Drives: 1/1 OK
CPU min avg max
current 0.18% 0.23% 0.28%
historic 0.05% 0.52% 35.29%
MEM usage
current 70 MiB
historic 70 MiB
● MINIOSERVER3IP:9000
Uptime: 1 hour
Version: 2019-09-11T19-53-16Z
Storage: Used 215 KiB, Free 2.4 TiB
Drives: 1/1 OK
CPU min avg max
current 0.33% 0.34% 0.36%
historic 0.05% 0.51% 21.96%
MEM usage
current 70 MiB
historic 70 MiB
● MINIOSERVER4IP:9000
Uptime: 1 hour
Version: 2019-09-11T19-53-16Z
Storage: Used 215 KiB, Free 2.4 TiB
Drives: 1/1 OK
CPU min avg max
current 0.14% 0.15% 0.15%
historic 0.05% 0.52% 20.05%
MEM usage
current 70 MiB
historic 70 MiB
Minio permite la exportación de métricas mediante Prometheus:
scrape_configs:
- job_name: minio-job
scrape_interval: 1m
scrape_timeout: 10s
metrics_path: /minio/prometheus/metrics
scheme: http
static_configs:
- targets:
- kr0mminio:9000
- kr0mminio2:9000
- kr0mminio3:9000
- kr0mminio4:9000
Algunas alertas interesantes serían cuando hay un disco defectuoso o cuando un disco se está quedando sin espacio:
groups:
- name: Minio
rules:
- alert: DiskOffline
expr: minio_offline_disks != 0
for: 5m
labels:
severity: critical
annotations:
summary: Disk offline
groups:
- name: Minio
rules:
- alert: StorageSpaceExhausted
expr: minio_disk_storage_free_bytes < 10737418240
labels:
severity: info
annotations:
summary: Free space threshold reached
groups:
- name: Minio
rules:
- alert: MinioNodeDown
expr: up{job="minio-job"} == 0
for: 5m
labels:
severity: critical
Mediante Prometheus podemos visualizar los datos al vuelo, pero una forma mas cómoda es mediante Grafana, para ello utilizaremos esta dashboard.
Una vez importada la dashboard veremos datos de este estilo:
NOTA: Hay versiones de minio que no exportan la métrica minio_version por lo tanto el desplegable de instancias aparecerá vacío, para solventarlo debemos editar la dashboard y en la sección de Variables -> Instancia cambiar la query a label_values(minio_total_disks,instance)
Cifrar las comunicaciones de los nodos Minio nos protegerá ante el robo de información sensible y nos permitirá detectar alteraciones del contenido.
Generamos un certificado para todos los nodos, si vamos a utilizar las direcciones ip directamente sin dominios tendremos que generar el certificado de una forma especial:
cat «-EOF
default_bits = 2048
distinguished_name = dn
x509_extensions = san
req_extensions = san
extensions = san
prompt = no
[ dn ]
countryName = ES
stateOrProvinceName = XXXX
localityName = XXXX
organizationName = Alfaexploit
[ san ]
subjectAltName = @alt_names
[ alt_names ]
IP.1 = MINIOSERVER1IP
IP.2 = MINIOSERVER2IP
IP.3 = MINIOSERVER3IP
IP.4 = MINIOSERVER4IP
EOF
)
Cada servidor servirá el certificado en base a public.crt/private.key y tendrá como CA de confianza public.crt.
scp public.crt kr0mminio:/root/.minio/certs/
scp private.key kr0mminio:/root/.minio/certs/
scp public.crt kr0mminio2:/root/.minio/certs/
scp private.key kr0mminio2:/root/.minio/certs/
scp public.crt kr0mminio3:/root/.minio/certs/
scp private.key kr0mminio3:/root/.minio/certs/
scp public.crt kr0mminio4:/root/.minio/certs/
scp private.key kr0mminio4:/root/.minio/certs/
Modificamos el script en cada uno de los nodos:
#!/sbin/openrc-run
# Copyright 2016-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
description="Minio Object Storage Server"
pidfile=${pidfile:-"/run/${SVCNAME}.pid"}
export MINIO_ACCESS_KEY=XXXXXXXXXXXXXXXXXXX
export MINIO_SECRET_KEY=YYYYYYYYYYYYYYYYYYY
command="/usr/bin/minio"
#command_args="${command_args:-server /var/lib/minio}"
command_args="${command_args:-server https://MINIOSERVER1IP/data https://MINIOSERVER2IP/data https://MINIOSERVER3IP/data https://MINIOSERVER4IP/data}"
command_background="true"
start_stop_daemon_args="--stdout /var/log/${SVCNAME}.log \
--stderr /var/log/${SVCNAME}.log"
Reiniciamos el servicio:
También le pasamos los certificados al cliente mc para que pueda conectar sin problemas:
Actualizamos la base de datos de CAs:
Habrá que reañadir los nodos en modo https al cliente:
mc config host remove kr0mminio2
mc config host remove kr0mminio3
mc config host remove kr0mminio4
mc config host add kr0mminio2 https://MINIOSERVER2IP:9000 XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYY
mc config host add kr0mminio3 https://MINIOSERVER3IP:9000 XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYY
mc config host add kr0mminio4 https://MINIOSERVER4IP:9000 XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYY
Podemos comprobar los servidores configurados mediante el comando ls:
NOTA: Si utilizamos SSL añadiremos el certificado a la configuración de Prometheus, debemos pasarle el contenido del fichero public.crt además de tener en cuenta que si hemos generado los certificados con IP habrá que meter las ips y no los nombres de dominio en la configuración de Prometheus:
scrape_configs:
- job_name: minio-job
scrape_interval: 1m
scrape_timeout: 10s
metrics_path: /minio/prometheus/metrics
scheme: https
tls_config:
ca_file: /usr/local/share/ca-certificates/minio.crt
insecure_skip_verify: false
static_configs:
- targets:
- MINIOSERVER1IP:9000
- MINIOSERVER2IP:9000
- MINIOSERVER3IP:9000
- MINIOSERVER4IP:9000
DEBUG:
La mejor manera de debugear problemas es arrancar manualmente cada uno de los nodos para ver los errores por stdout:
También podemos consultar los logs de todos los servidores desde el cliente conectando con cualquiera de los servidores: