Cloud Storage: Minio Test

Bewertung (nach oben gezogen, da das Wesentliche)
Minio ist grundsätzlich, wie der Name erahnen lässt, sehr minimalistisch gehalten. Dadurch ist die Konfiguration und Inbetriebnahme sehr einfach. Um schnell einen Objektspeicher für ein Testsystem zur Verfügung zu stellen ist es bestens geeignet.

Minio unterstützt jedoch keine User Accounts, ACLs, o.ä. In diesem Fall müssen mehrere Silos nebeneinander konfiguriert werden.. Diese Konfiguration muss von Hand erfolgen – einzelne Disks werden quasi einzelnen Kunden zugewiesen, oder mehrere Kunden werden auf bestimmte Disks gelegt. Diese Art der Konfiguration führt schnell zu einer sehr unübersichtlichen Systemlandschaft, speziell wenn das System hochskaliert wird.

Minio unterstützt folglich auch keine Quotas – denn es gibt ja immer nur einen User für den einzelnen Silo/das gesamte Storage. Um zu verhindern, dass ein Kunde den gesamten Plattenplatz mehrer Kunden konsumiert, müssten bspw. per LVM einzelne Volumes angelegt und/oder mit Quotas versehen werden, was einen zusätzlichen unüberschaubaren Konfigurationsaufwand nach sie ziehen würde.

Die Performance des SDS ist sehr nieder. Die (vermutete) Ursache liegt zwar nicht im eigentlichen SDS sondern im Docker SDN, aber da es keinen einfachen Workaround gibt, muss sie als gegeben angenommen werden. Ferner bedeutet dies, dass Minio sehr schnell an einer „natürlichen Grenze“ anschlägt, die hinsichtlich Performance keine weitere Skalierung des SDS erlaubt. Die Speichertiefe könnte vermutlich noch sehr viel weiter skaliert werden.

Ggfs. könnte ermittelt werden, ab wie vielen Nodes kein Performancezuwachs mehr entsteht.

Allerdings muss festgehalten werden, dass selbst wenn man einen Docker Schwarm mit eingebettetem SDS pro Kunde erzeugen würde, bereits ein einzelnes HiRes Transcoding die gemessenen Bandbreiten überschreitet oder sehr knapp am Limit operiert, zumal die Lesegeschwindigkeit nur unwesentlich höher ist als die Schreibgeschwindigkeit. Mehr als 5 dieser Transcodings parallel pro Kunde wären daher auf dem Speicher nicht möglich – und das auch nur unter der Voraussetzung, dass der Kunde parallel keine Operationen durchführt (Upload/Download).

Minio ist somit aus infrastruktureller Sicht für den Einsatz in produktiven Mediensystemen ungeeignet.

Hinweis: Servernamen etc. existieren in dieser Form zum Zeitpunkt der Veröffentlichung bereits nicht mehr, daher habe ich mir nicht die Mühe gemacht sie zu ändern

Hintergrund
Minio ist ein SDS basierend auf Docker Swarm.
Die einzelnen Nodes werden getagged damit immer die gleiche Minio Instanz auf dem gleichen Host hochfährt.
Auf der Platte des Hosts gibt es ein persistentes Volume, das in die Minio Instanz eingebunden wird. Da dieses Volume auf einem bestimmten Host liegt und dort auch nicht weg/von dort ohne weiteres verschoben werden kann, und eine andere Instanz mit den Daten nichts anfangen kann/darf/will, muss diese 1zu1 Beziehung existieren.
Als Hosts kommen s0002-s0011 zum Einsatz.
In Summe stehen damit am Ende 10 x 1Gbit/s Uplink und ca. 8TB Brutto auf 20 SSDs zur Verfügung.
Die Host werden manuell neu installiert und mit einer LVM Volume Group versehen um den gesamten Speicherplatz von sdb und den freien Speichplatz von sda in einem Volume zusammenzubinden. Dieses wird unter /mnt/minio eingehängt.
In fdisk /dev/sda und danach /dev/sdb den Partitiontype auf 8e setzen.
Formatierung mit ext4.
s0002-s0004 werden Schwarm Manager, der Rest wird als Worker eingebunden.
Sämtlicher Traffic soll über das externe Interface gehen um Ergebnisse zu erhalten, die auf CloudVMs übertragbar sind.
In der UFW werden die Maschinen untereinander freigeschaltet.
Listing:

pvcreate /dev/sda4
pvcreate /dev/sdb1
pvs
mkdir -p /mnt/minio
vgcreate vg0 /dev/sda4 /dev/sdb1
lvcreate -n minio -l100%VG vg0
mkfs.ext4 /dev/vg0/minio
echo "/dev/vg0/minio /mnt/minio ext4 defaults 0 0">>/etc/fstab
mount -a
mkfs.ext4 /dev/vg0/minio
apt update && apt upgrade -y
apt install ufw apt-transport-https ca-certificates curl software-properties-common -y
ufw allow from 93.95.133.130
ufw allow from 78.94.178.52
ufw allow from 94.130.207.66
ufw allow from 94.130.207.67
ufw allow from 94.130.207.68
ufw allow from 94.130.207.70
ufw allow from 94.130.207.71
ufw allow from 94.130.207.72
ufw allow from 94.130.207.73
ufw allow from 94.130.207.74
ufw allow from 94.130.207.75
ufw allow from 94.130.207.76
ufw enable
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-get install docker-ce -y
reboot # Mit dem apt upgrade oben kam ein neuer Kernel
docker swarm init --advertise-addr 94.130.207.70 # Rückgabe auf Workers ausführen
docker swarm join-token manager # Rückgabe auf anderen MGRs ausführen
docker node list
docker node update --label-add minio1=true s0002
docker node update --label-add minio2=true s0003
docker node update --label-add minio3=true s0004
docker node update --label-add minio4=true s0005
docker node update --label-add minio5=true s0006
docker node update --label-add minio6=true s0007
docker node update --label-add minio7=true s0008
docker node update --label-add minio8=true s0009
docker node update --label-add minio9=true s0010
docker node update --label-add minio10=true s0011

Docker Secrets zum Zugriff auf das Storage erstellen:

echo "test-user" | docker secret create access key -
echo "passwd" | docker secret create secret_key -

 

Compose File:

version: '3.1'

services:
  minio1:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio1
    volumes:
      - minio1-data:/storage
    ports:
      - "9001:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio1==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio2:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio2
    volumes:
      - minio2-data:/storage
    ports:
      - "9002:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio2==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio3:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio3
    volumes:
      - minio3-data:/storage
    ports:
      - "9003:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio3==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio4:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio4
    volumes:
      - minio4-data:/storage
    ports:
      - "9004:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio4==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio5:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio5
    volumes:
      - minio5-data:/storage
    ports:
      - "9005:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio5==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio6:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio6
    volumes:
      - minio6-data:/storage
    ports:
      - "9006:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio6==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio7:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio7
    volumes:
      - minio7-data:/storage
    ports:
      - "9007:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio7==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio8:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio8
    volumes:
      - minio8-data:/storage
    ports:
      - "9008:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio8==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio9:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio9
    volumes:
      - minio9-data:/storage
    ports:
      - "9009:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio9==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

  minio10:
    image: minio/minio:RELEASE.2018-12-13T02-04-19Z
    hostname: minio10
    volumes:
      - minio10-data:/storage
    ports:
      - "9010:9000"
    networks:
      - minio_distributed
    deploy:
      restart_policy:
        delay: 10s
        max_attempts: 10
        window: 60s
      placement:
        constraints:
          - node.labels.minio10==true
    command: server http://minio1/storage http://minio2/storage http://minio3/storage http://minio4/storage http://minio5/storage http://minio6/storage http://minio7/storage http://minio8/storage http://minio9/storage http://minio10/storage
    secrets:
      - secret_key
      - access_key

volumes:
  minio1-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio2-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio3-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio4-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio5-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio6-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio7-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio8-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio9-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

  minio10-data:
    driver_opts:
      device: /mnt/minio
      type: none
      o: bind

networks:
  minio_distributed:
    driver: overlay

secrets:
  secret_key:
    external: true
  access_key:
    external: true

Rollout

docker stack deploy --compose-file=./minio-deloy.yml minio-stack

 

Clients
Über die Minio WebUI (http://s0002.ntrm.de:9001) wird ein Bucket Transcode erstellt.
Es werden 10 CloudVMs bei Hetzner hochgefahren und das Minio Storage via Goofys eingebunden.
Jede VM wird auf einen Endpunkt des SDS Clusters geschaltet (10 Endpunkte – 10 Clients).

mkdir -p /mnt/goofys
wget https://github.com/kahing/goofys/releases/download/v0.19.0/goofys
chmod a+x goofys
mv goofys /usr/bin
mkdir -p ~/.aws
echo "[default]">>~/.aws/credentials
echo "test-user">>~/.aws/credentials
echo "passwd">>~/.aws/credentials
goofys --endpoint http://s0002.ntrm.de:9001 transcode /mnt/goofys/

Test
Auf Grund des beschränkten Speicherplatzes auf den Cloud VMs wurde zunächst dd genutzt um Traffic zu erzeugen. Es wurden zwei verschiedene Blocksizes (8 und 1MB) genutzt, die Messwerte unterscheiden sich aber nicht. Als Input wurde /dev/zero gewählt, da dieses Device schneller als /dev/random ist.
Es wurden 80GB große Files geschrieben:

dd if=/dev/zero of=/mnt/goofys/transcode/test1.file bs=8M count=10k status=progress

Nach anfänglich hoher Performance von über 80MB/s in der ersten Minute, fiel die Geschwindigkeit und pendelte sich reproduzierbar bei ca. 22MB/s ein.
Wenn nur ein einzelner Client aktiv ist, können knapp über 30MB/s erreicht werden.

Mit iftop wurde auf dem s0002 der Fluss des Traffics beobachtet. Minio verteilt an einem Node auflaufenden Traffic im Hintergrund auf verschiedene weitere Nodes.

Um dd als Ursache für die überschaubare Performance des SDS auszuschliessen, wurden 12GB große Files auf den Clients erzeugt und diese mit rsync und cp auf das SDS kopiert.
Die Werte blieben dabei weitestgehend gleich, wichen aber nie signifikant ab.
Da rsync nach erfolgreichem Transfer nochmals eine Prüfung des entfernten Files auf Unversehrtheit durchführt, konnte auch die kombinierte Schreib-/Lesegeschwindigkeit ermittelt werden. Diese lag bei einem einzelnen Client kombiniert (erst schreiben, dann nochmal vom Storage lesen) bei ca. 18MB/s. Da die Schreibgeschwindigkeit bei 30MB/s lag, kann daraus gefolgert werden, dass die Lesegeschwindigkeit nochmal niedriger liegt.

Vermutung: Die Limitierung in der Performance wird durch das Docker SDN verursacht. Es konnte docker-interner Traffic von ges. 800Mbit/s beodachtet werden. Dieser Wert deckt sich mit dem auch bei K8s beobachteten max. SDN Durchsatz. Durch Puffer-Effekte und weil Minio bei der Replikation auf Raid5 ähnliche Mechanismen setzt, wird die Bandbreite sehr effizient genutzt, wodurch letztendlich auf den gesamten Cluster bezogen in Summe 1,6GBit/s erreicht werden.

Auf Grund der schlechten Performance ist das SDS für unsere Zwecke ungeeignet, auf Failover bzw. Ausfalltests und Skalierung wurde daher verzichtet.

Related Post