Minio Object Storage

Minio Object Storage kann für die Speicherung von unstrukturierten Daten eingesetzt werden. Angela Stempfel berichtet von ihren ersten Erfahrungen mit Minio.

Eine der Anforderungen für ein aktuelles Kundenprojekt war, einen Object Storage zu verwenden, um grössere Dateien abzulegen. Im Rahmen eines Proof of Concepts habe ich den Minio Object Storage integriert und erste Erfahrungen damit gesammelt.

Folgende Kriterien sollten abgedeckt werden:

  • Die S3 REST API sollte unterstützt werden
  • Die Lösung soll sowohl in der Cloud wie auch on-premises in Docker betrieben werden können
  • Eine horizontale Skalierung muss möglich sein
  • Die Lösung soll eine «gesunde» Community aufweisen

Was ist Minio?

Minio ist ein Object Storage auf Open Source Basis, der zur Speicherung von unstrukturierten Daten wie Fotos, Videos, Logfiles, Backups und Container- /VM Images eingesetzt werden kann. Es wird eine Dateigrösse bis 5 TB unterstützt. Die Daten werden in Buckets abgelegt und so logisch organisiert. Buckets sind mit Verzeichnissen vergleichbar.

Minio unterstützt das Amazon S3 API. Dieses API ist der de facto Standard für Object Storage.

Des Weiteren gibt es von Minio ein Java-SDK, das ich für meinen POC benutzt habe.

Folgende Funktionalitäten möchte ich kurz vorstellen:

  1. Starten eines Minio Servers
  2. Ablegen von Daten
  3. Holen von Daten
  4. Buckets erstellen
  5. Mandantenfähigkeit

1. Minio Docker start

Minio kann ganz einfach in einem Docker Container gestartet werden:

docker run -p 9000:9000 --name minio-poc \
  -v /mnt/data:/data \
  -v /mnt/config:/root/.minio \
  minio/minio server /data

Achtung: Ein persistentes Volume wird benötigt, um die Konfiguration und die Applikationsdaten zu speichern.

Minio Custom Access and Secret Keys

Die per default generierten Zugangsdaten (Access & Secret Key) können beim Starten des Containers wie folgt überschrieben werden:

docker run -p 9000:9000 --name minio-poc \
  -e "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE" \
  -e "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
  -v /mnt/data:/data \
  -v /mnt/config:/root/.minio \
  minio/minio server /data

Nach dem Start ist Minio unter dem obigen Port verfügbar:

2./3. Speichern und Zugriff auf Daten

Um das Minio Java SDK zu benutzen, können die Dependencies via Maven integriert werden:

Danach hat man mit dem Minio-Client Zugriff auf den Object Storage. In meinem POC habe ich die Konfiguration und das Initialisieren des Clients ausgelagert:

@Component
public class MinioConfiguration {

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.accessKey}")
    private String accessKey;

    @Value("${minio.secretKey}")
    private String secretKey;

    private MinioClient minioClient;

    @PostConstruct
    public void initMinioClient() throws InvalidPortException, InvalidEndpointException {
        minioClient = new MinioClient(endpoint, accessKey, secretKey);
    }

    /**
     * Gets a Minio client
     *
     * @return an authenticated Amazon S3 client
     */
    @Bean
    public MinioClient getMinioClient() {
        return minioClient;
    }

Der Upload eines Files kann nun mit der Methode „putObject“ gestartet werden. Die Methode benötigt folgende Argumente:

  • Bucket-Name, das heisst, in welches Bucket man das File uploaden möchte
  • eindeutige Referenz auf das File
  • die hochzuladende Datei
 public void putObject(String bucketName, String objectStorageReference, byte[] imageBuffer) {
        try {
            // Check if the bucket already exists.
            createBucket(bucketName);

            // Upload the file to the bucket with putObject
            minioClient.putObject(bucketName, objectStorageReference, new ByteArrayInputStream(imageBuffer), imageBuffer.length, "application/octet-stream");

        } catch (MinioException | NoSuchAlgorithmException | XmlPullParserException | InvalidKeyException | IOException e) {
            throw new ObjectStorageException(e);
        }
    }

Der Download eines Files mit der Methode ‚getObject‘ funktioniert folgendermassen:

     public InputStream getObject(String bucketName, String objectStorageReference) {
         try {
             return minioClient.getObject(bucketName, objectStorageReference);
 
         } catch (MinioException | NoSuchAlgorithmException | XmlPullParserException | InvalidKeyException | IOException e) {
             throw new ObjectStorageException(e);
         }

4. Buckets erstellen

Auch für die Buckets stellt das API entsprechende Methoden zur Verfügung:

protected void createBucket(String bucketName) throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException, RegionConflictException {
        boolean isExist = minioClient.bucketExists(bucketName);
        if (isExist) {
            log.debug("Bucket {} already exists on Minio Server", bucketName);
        } else {
            log.debug("Bucket {} doesn't exist yet, creating it", bucketName);
            // Make a new bucket called asiatrip to hold a zip file of photos.
            minioClient.makeBucket(bucketName);
        }
    }

* `bucketExists` überprüft, ob das entsprechende Bucket bereits existiert
* `makeBucket` erstellt ein neues Bucket

Die komplette JAVA-API Referenz befindet sich hier: Komplettes Java-API

5. Mandantentfähigkeit

Minio unterstützt die Mandantenfähigkeit mit verschiedenen Konfigurationen:

1 Host mit einem Drive und mehreren Minio-Instanzen

1 Host mit mehreren Drives

Mehrere Hosts und mehrere Drives

Da in unserer Applikation jedoch Mandanten direkt im Web-GUI erstellt werden können, sind die oben genannten Konfigurationen keine Option. Es gibt für uns 2 Varianten, mit denen wir die Mandantenfähigkeit unterstützen können:

Variante 1: Minio unterstützt das Erstellen von Benutzern nach Server-Startup. Es soll künftig nach Server-Startup pro Mandant ein Benutzer erstellt werden. Dieser soll dann nur auf die Buckets Zugriff erhalten, welche vom Mandant erstellt wurden.

Variante 2: Wir starten aus der Applikation einen Docker Container, sobald ein Mandant erstellt wird.

FAZIT

Minio unterstützt natürlich noch viele weitere Funktionen, wie zum Beispiel:

  • Setzen von Policies auf Buckets
  • Resume eines Uploads
  • Löschen von Files
  • Verschlüsseln von Files

Diese habe ich aber im Rahmen des POC (noch) nicht angeschaut.

Alles in allem fand ich das Integrieren der Object Storage sehr einfach und übersichtlich. Die Dokumentation ist sehr gut und ausführlich, so dass alle Informationen schnell gefunden werden.

Der einzig negative Punkt ist, dass das Java SDK noch nicht alle von Minio angebotenen Funktionen unterstützt.

In einem zweiten Schritt möchte ich den Minio Storage über das S3 REST API einbinden, so dass eine Austauschbarkeit des Object Stores gewährleistet ist. Wie das genau aussehen wird, lest ihr in meinem nächsten Blogpost…

 

Kommentare sind geschlossen.