MinIO: Yüksek Performanslı ve Ölçeklenebilir Nesne Depolama Çözümü

Burak Uğur
6 min readDec 24, 2023

--

MinIO; bir nesne depolama aracıdır. Amazon Web Services içerisindeki S3 hizmeti benzer işleri görmektedir. S3 bulut hizmeti olduğu için veri gizliliği ve maliyet gibi sebeplerden dolayı MinIO kulllanılabilmektedir.

Nesne Depolama Aracı Nedir?

Nesne depolama kavramı standart Unix dosya sistemine benzer, ancak dizinler ve dosyalar yerine Buckets ve Objects kullanılır.

Bucket tıpkı dizinler gibi bir hiyerarşiye yerleştirilebilir ve nesneler yalnızca bir bayt koleksiyonu olarak düşünülebilir. Bu koleksiyonlar isteğe bağlı bayt dizileri veya resimler, PDF’ler ve daha fazlası gibi normal dosyalar olabilir.

MinIO çoğu popüler mimaride local bir uygulama olarak çalışabilir ve ayrıca Docker veya Kubernetes kullanılarak konteynerli bir uygulama olarak da dağıtılabilir. Docker ortamında çalışırken veri kaybına yol açmamak için Volume oluşturmayı unutmayınız.

Kullanım Alanları:

1. Bulut Depolama: MinIO’nun Amazon S3 uyumluluğu, bulut tabanlı depolama projeleri için ideal bir çözüm sunar. Mevcut S3 entegrasyonlarıyla uyumlu olması, bulut altyapılarında kullanımını kolaylaştırır.

2. Büyük Veri Depolama: Dağıtık yapısı, büyük veri setleri ile çalışan işletmelerin depolama ihtiyaçlarına cevap verir. Ölçeklenebilir yapısı, depolama kapasitesini ve performansı ihtiyaca göre artırma esnekliği sunar.

3. Veri Arşivleme: Düşük maliyetli nesne depolama çözümleri arayan şirketler için MinIO, veri arşivleme ihtiyaçlarını karşılamak üzere uygun bir seçenektir.

HDFS dosyalarınızı arşivlemek istediğinizde çok yardımcı olacaktır.

Ölçeklenebilirlik:

  1. Dağıtık Mimarisi: Minio, veriyi çeşitli düğümlere dağıtarak ölçeklenebilir bir mimari sunar. Bu, daha fazla depolama kapasitesi eklemeyi ve yükü denglemeyi mümkün kılar.
  2. Paralel İşleme: Minio, veri okuma ve yazma işlemlerini paralel olarak gerçekleştirerek performansı artırır. Bu özellik, büyük dosyalar veya çok sayıda dosya içeren işlemleri hızlandırabilir.
  3. Yüksek Performans: Minio’nun tasarımı, düşük gecikme süreleri ve yüksek transfer hızlarına odaklanarak yüksek performans sağlar. Bu, ölçeklenebilir bir sistemde verimli çalışmayı destekler.
  4. Elasticsearch ve Kafka Entegrasyonu: Minio, Elasticsearch ve Apache Kafka gibi popüler araçlarla entegre olabilir. Bu entegrasyonlar, çeşitli sistemlerle uyumlu bir şekilde çalışabilme yeteneğini artırır.

MinIO Örnek Kullanım

A. Kurulum

Bu örneğimizde Faker kütüphanesini kullanarak sahte uçuş kayıtları oluşturuyoruz. Daha sonra bunu JSONolarak döndüren bir rest endpoint yazıyoruz. Oluşturulan JSON dosyasını MinIO Python API kullanarak sunucuya aktarımını sağlıyoruz.

Uygulamayı başlatmak için docker-compose.yml dosyasını kullanın.

version: '3'

services:
minio:
image: minio/minio
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_storage:/data
environment:
MINIO_ROOT_USER: root
MINIO_ROOT_PASSWORD: rootroot
MINIO_DEFAULT_BUCKETS: TestBucket

command: server --console-address ":9001" /data

volumes:
minio_storage: {}

Python ortamının yapılandırılması için requirements.txt dosyasında gerekli olan kütüphaneleri kurun.

pip install -r requriements.txt

B. Sahte Veri Üretmek

Senaryomuzda örnek bir uçuş biletleme sisteminden gelen kişi ve uçuşa ait bilgileri kaynaktan dinliyoruz. Bunun için bir REST API geliştirdik.

Geliştirmemizi sınıf yapısını kullanıyoruz. İlerleyen projelerde de kullanacağımız özellikler olabilir.

import random
from faker import Faker
fake = Faker()


class FakeFlightPerson:
def __init__(self, orderID, name, address, birthday, email, segment, chanellname, citycode, countrycode, airlinecode, reservationid, origin, destination, amount, ticketprice):
self.orderID = orderID
self.name = name
self.address = address
self.birthday = birthday
self.email = email
self.segment = segment
self.chanellname = chanellname
self.citycode = citycode
self.countrycode = countrycode
self.airlinecode = airlinecode
self.reservationid = reservationid
self.origin = origin
self.destination = destination
self.amount = amount
self.ticketprice = ticketprice



def CreateFakeFlightPerson():
chanellNameList = ['XTatil',
'Obilet',
'Fixbilet',
'Enuygun',
'Skycanner',
'bilet.com',
'Tatilsepeti',
'None']
AirlineList = [
"Aegean Airlines",
"Aer Lingus",
"Aeroflot",
"Aerolineas Argentinas",
"Aeromexico",
"Air Arabia",
"Air Astana",
"Air Austral",
"Air Baltic",
"Air Belgium",
"Air Canada",
"Air Caraibes",
"Air China",
"Air Corsica",
"Air Dolomiti",
"Air Europa",
"Air France",
"Air India",
"Air India Express",
"Air Macau",
"Air Malta",
"Air Mauritius",
"Air Namibia",
"Air New Zealand",
"Air North",
"Air Seoul",
"Air Serbia",
"Air Tahiti Nui",
"Air Transat",
"Air Vanuatu",
"AirAsia",
"AirAsia X",
"Aircalin",
"Alaska Airlines",
"Alitalia",
"Allegiant",
"American Airlines",
"ANA",
"Asiana",
"Austrian",
"Avianca",
"Azerbaijan Hava Yollary",
"Azores Airlines",
"Azul",
"Bamboo Airways",
"Bangkok Airways",
"British Airways",
"Brussels Airlines",
"Caribbean Airlines",
"Cathay Dragon",
"Cathay Pacific",
"Cayman Airways",
"CEBU Pacific Air",
"China Airlines",
"China Eastern",
"China Southern",
"Condor",
"Copa Airlines",
"Croatia Airlines",
"Czech Airlines",
"Delta",
"easyJet",
"Edelweiss Air",
"Egyptair",
"Emirates",
"Ethiopian Airlines",
"Etihad",
"Eurowings",
"EVA Air",
"Fiji Airways",
"Finnair",
"flydubai",
"FlyOne",
"French bee",
"Frontier",
"Garuda Indonesia",
"Gol",
"Gulf Air",
"Hainan Airlines",
"Hawaiian Airlines",
"Helvetic Airways",
"HK Express",
"Hong Kong Airlines",
"Iberia",
"Icelandair",
"IndiGo Airlines",
"InterJet",
"Japan Airlines",
"Jeju Air",
"Jet2",
"JetBlue",
"Jetstar",
"Jin Air",
"Kenya Airways",
"KLM",
"Korean Air",
"Kulula",
"La Compagnie",
"LATAM",
"Lion Airlines",
"LOT Polish Airlines",
"Lufthansa",
"Luxair",
"Malaysia Airlines",
"Mango",
"Middle East Airlines",
"Nok Air",
"Nordwind Airlines",
"Norwegian Air International",
"Norwegian Air Shuttle",
"Norwegian Air Sweden",
"Norwegian Air UK",
"Oman Air",
"Pakistan International Airlines",
"Peach",
"Pegasus Airlines",
"Philippine Airlines",
"Porter",
"Qantas",
"Qatar Airways",
"Regional Express",
"Rossiya - Russian Airlines",
"Royal Air Maroc",
"Royal Brunei",
"Royal Jordanian",
"RwandAir",
"Ryanair",
"S7 Airlines",
"SAS",
"Saudia",
"Scoot Airlines",
"Shanghai Airlines",
"Silkair",
"Silver",
"Singapore Airlines",
"Skylanes",
"South African Airways",
"Southwest",
"SpiceJet",
"Spirit",
"Spring Airlines",
"Spring Japan",
"SriLankan Airlines",
"Sun Country",
"Sunclass Airlines",
"Sunwing",
"SWISS",
"Swoop",
"TAAG",
"TACA",
"TAP Portugal",
"THAI",
"tigerair Australia",
"Transavia Airlines",
"TUI UK",
"TUIfly",
"Tunis Air",
"Turkish Airlines",
"Ukraine International",
"United",
"Ural Airlines",
"UTair Aviation",
"Uzbekistan Airways",
"Vietnam Airlines",
"Virgin Atlantic",
"Virgin Australia",
"Vistara",
"Viva Aerobus",
"Volaris",
"Volotea",
"Vueling Airlines",
"WestJet",
"Wizzair",
"Xiamen Airlines"
]

person = FakeFlightPerson(
orderID=fake.passport_number(),
name=fake.name(),
address=fake.address(),
birthday=fake.date_of_birth(),
email=fake.ascii_email(),
segment=random.choice(['Economy', 'Premium Economy', 'Business', 'First', 'Suit']),
chanellname=random.choice(chanellNameList),
citycode=fake.city(),
countrycode=fake.country_code(),
airlinecode=random.choice(AirlineList),
reservationid=fake.random.randint(0, 999999999),
origin=''.join([fake.city(), fake.country_code()]),
destination=''.join([fake.city(), fake.country_code()]),
amount=fake.random.randint(0, 200),
ticketprice=fake.random.randint(0, 1000),
)

result = {'orderID': person.orderID,
'name': person.name,
'address': person.address,
'birthday': person.birthday,
'email': person.email,
'segment': person.segment,
'chanellname': person.chanellname,
'citycode': person.citycode,
'countrycode': person.countrycode,
'airlinecode': person.airlinecode,
'reservationid': person.reservationid,
'origin': person.origin,
'destination': person.destination,
'amount': person.amount,
'ticketprice': person.ticketprice
}
return result

Ürettiğimiz veri JSON tipinde dönmektedir.

FAST API kütüphanesi yardımı ile REST endpoint oluşturarak her GET isteği sonrasında veriyi üreterek sonuç döndürmesine uygun hale getiriyoruz.

C. MinIO Kurulum ve Client

MinIO object storage olduğu için JSON tipindeki verileri dosyaya yazarak bunları anlık olarak MinIO sunucusuna göndereceğiz.

Bunun için gerkeli olan AWS hizmetlerine erişimde de kullandığımız boto3 kütüphanesini kullanacağız. Bunun için öncelikle endpointe GET isteği atarak veriyi dosya yapısına kaydetmemiz gerekmektedir.

personData = requests.get("http://127.0.0.1:8000/FlightPerson").text
#print(personData)

# write file
with open(str(FILENAME), 'w') as f:
json.dump(personData, f)

# Send file to minIO server
createBucket(BUCKETNAME)
uploadFile(BUCKETNAME, FILENAME)

create ve upload fonksiyonları boto3 kullanarak geliştirdik.

import boto3

# Set up MinIO client
# Help => https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html
localStorage = boto3.client('s3',
endpoint_url='http://localhost:9000',
aws_access_key_id='*********',
aws_secret_access_key='**********')


def createBucket(BUCKETNAME,localStorage=localStorage):
localStorage.create_bucket(Bucket=BUCKETNAME)

def UploadContent(OBJECTDIR, BUCKETNAME, OBJECTNAME ,localStorage=localStorage):
localStorage.upload_file(OBJECTDIR, BUCKETNAME, OBJECTNAME)

def checkBucketName(BUCKETNAME,localStorage=localStorage):
try:
status = localStorage.head_bucket(Bucket=BUCKETNAME)['ResponseMetadata']['HTTPStatusCode']
if(status == 200):
return True
else:
return False
except:
return False

Burada verileri gönderdiğimiz bucket ve object isimlerini fonksiyon parametresi olarak almaktayız.

Veri transfer işlemini ise, insertData.py dosyasında olduğu gibi modülleri çağırarak gerçekleştiriyoruz.

import MinIOClient.minioClient as mc
import requests
from datetime import datetime
import os
import json

# define file & bucket name with datetime
FILENAME = "".join([datetime.now().strftime("%m_%d_%Y_%H_%M_%S") + ".json"])
BUCKETNAME = "".join([datetime.now().strftime("%m-%Y")])


def createBucket(BUCKETNAME, mc=mc):
#check bucket available
if mc.checkBucketName(BUCKETNAME) == False:
mc.createBucket(BUCKETNAME)
else:
pass

def uploadFile(BUCKETNAME, FILENAME, mc=mc):
mc.UploadContent( str(os.getcwd() +'/'+ FILENAME), BUCKETNAME, FILENAME)
os.remove(str(os.getcwd() +'/'+ FILENAME))



personData = requests.get("http://127.0.0.1:8000/FlightPerson").text

with open(str(FILENAME), 'w') as f:
json.dump(personData, f)

createBucket(BUCKETNAME)
uploadFile(BUCKETNAME, FILENAME)

MINIO Web Arayüzü

MinIO web arayüzü başlangıçta bu şekilde gözükmektedir. Sol tarafta bucket ve uygulama özellikleri görülmektedir. LDAP entegrasyonu, kullanıcı izin ve yönetimi, webhook ekleme, Log yönetimi, dosya sıkıştırma gibi bir çok özellik buradan kontrol edilmektedir.

Bucket sekmesinden oluşturduğumuz bucketları ve detaylarını görebilmekteyiz. Geliştirdiğimiz uygulamada ay-yıl olmak üzere bucket oluşturduk.

Üretilen JSON dosyaları ise ilgili ayın bucket’i altında depolanmaktadır.

SONUÇ

Minio’nun kullanımı, genellikle büyük ölçekli veri depolama ve dağıtım gereksinimlerine sahip organizasyonlar için avantajlıdır. Ayrıca, açık kaynak olması, kullanıcıların ihtiyaçlarına uygun olarak özelleştirebilme ve uyum sağlama esnekliği sunar. Proje kodlarına aşağıdan ulaşabilirsiniz.

Diğer Okumalar

https://www.baeldung.com/minio

--

--