Objektová storage

Vyťukejte v prohlížeči www.cloudsvet.cz. Co se stane? Browser kontaktuje tuto URL (a zajistí si informace o všem pod tím, tedy z DNS sežene IP, z ARP zjistí cílovou MAC nebo MAC výchozí brány) a co dostane? Přistane mu proud bitů, kterým bude HTML soubor a ten browser interpretuje. Pokud si na našem webu dáte stáhnout PDF ze sekce Dokumenty, pošle web server do prohlížeče jiný proud reprezentující PDF soubor (a metadata, která informují právě o tom, co je to za typ souboru). Nebo to bude obrázek a ten se vám začne vykreslovat tak, jak k vám bity přichází. Možná to bude podcast nebo video, které začnete poslouchat a neřešíte, že ještě nedorazil poslední bit ze závěrečných titulků. Možná to nebudou data přímo pro browser, ale půjde o RESTful API (webové programovací rozhraní) využívané mobilní aplikací na vašem telefonu nebo se takto propojí vaše ERP s ERP dodavatelů. Takhle funguje web a HTTP.

Objektová storage je vlastně web - jak nahrávání tak čtení je stejné, jako pohyb po webu. Každý nahraný objekt zahrnuje metadata (popis o co jde apod.) a URL, kde ho najdete. K jeho získání nepotřebujete žádný nízkoúrovňový protokol - neřešíte iSCSI, nastavení FC adaptéru, stačí IP konektivita, která funguje vždy stejně - z Ethernetu, WiFi, 3G nebo LTE. Nemusíte znát žádný protokol - FTP, NFS, SMB, SCSI - stačí HTTP, které umí nejen vaše servery a počítače, ale i telefon, televize, lednička a vaše auto. To je obrovská síla objektové storage.

Tento typ ukládání dat za sebou nemá dlouhou historii, existující trhy, které by bylo třeba bránit, patenty, zákazníky a jejich proinvestované prostředky. To je jeho velká výhoda - přímo ve svých pricipech má decentralizované distribuované řešení, je tedy nativně scale-out. To je především díky eventuálně konzistentnímu řešení (nemusí na rozdíl třeba od souborových systémů dodržovat POSIX).

Objektová storage obvykle funguje tak, že vezmete jednoduché nody (server s lokálními disky) a nahrajete tam chytrý software. Řešení obsahuje směrovací mechanismus, který udržuje přehled o tom, kde se který objekt fyzicky nachází - tedy má mapování URL (což je jednoznačný identifikátor objektu) na fyzické server a konkrétní disk, kde objekt je (objekt se uloží celý na disk a většinou i na několik dalších pro redundanci). Směrovač je schopen identifikovat odumřelé nody a požadavky uživatelů směrovat na ty, co fungují. Další komponentou je out-of-band kontroler a také nějaký proces, který udržuje přehled integrity. Tak například vytvoříte pravidlo, že jistý typ dat bude uložen minimálně na třech nodech, které jsou rozprostřené přes minimálně dvě zóny dostupnosti (o komplexnějších politikách později). Pokud dojde k roztržení clusteru, havárii nodu nebo odpodanutí celé zóny, zajistí mechanismus potřebnou "doreplikaci" tak, aby bylo všem politikám učiněno zadost. Všechny uvedené části, které by se daly označit za řídící, fungují na principu scale-out clusteru. S každým nodem tak zvyšujete jak celkovou kapacitu, tak celkový výkon a to plynule a za provozu (už žádné situace, kdy vám dojdou pozice pro disky v poli nebo kdy musíte vyhodit stávající kontroler a nahradit silnějším).

Některé objektové storage replikují objekty na nastavený počet kopií průběžně, tedy s eventuální konzistencí (AP systém dle CAP teorému) - Swift typicky vrací odpověď o úspěšném zápisu v okamžiku, kdy zapíše polovinu předepsaných kopií (většinou se nastavují 3 kopie v algoritmu „co nejméně podobné“, tedy ne na stejném serveru, ale ideálně v jiných zónách dostupnosti. V poslední době se pracuje i na erasure coding (místo kopie celých replik rozsekání na dílky a kontrolní součty - lepší využití místa za cenu trochu horšího výkonu).

Co je OpenStack Swift

Před rokem 2010 vytvořil public cloud poskytovatel Rackspace svůj vlastní object storage systém jako reakci na Amazon S3. V roce 2010 americká NASA uvolnila do open source svůj kód pro nadstavbu nad virtualizací a Rackspace udělal pro tento společný projekt totéž se svou object storage. Vznikl tak OpenStack a projekty Nova a Swift (a takhle ve dvou projektech to celé začalo). Swift je tedy plně otevřený s Apache2 licencí a je nasaditelný jak samostatně, tak jako součást OpenStack distribuce. Přináší tak naprostou otevřenost, žádný vendor lock-in a možnost nasazení na komoditním železe.

Swift je objektová storage, obvykle namíchaná jako AP systém v rámci CAP teorému. O tom proč je tento typ storage tak zajímavý jsem psal v článku na cloudsvet.cz. Nabízí tedy masivní škálovatelnost ve výkonu i kapacitě a řadu zajímavých funkcí.

V rámci samotného OpenStack je Swift používán třeba k ukládání image (Glance modulem) nebo záloh volumů (Cinder modul). Výhodou toho také je, že různé instalátory OpenStack umí rychle a snadno instalovat i Swift nody, takže se svou object storage můžete pracovat velmi cloudovým způsobem. Typické využití v dalších systémech je ukládání multimédií (audio, video, záznamy z kamer), snímků ve vysokém rozlišení (zdravotnictví, průmysl, umění), při renderingu a modelování, k zálohování a diskovým obrazům nebo pro cloudové ukládání fotek a dokumentů. To všechno můžete mít nejen jako službu od veřejného poskytovatele, ale Swift si jednoduše postavíte interně u sebe - bezpečně, spolehlivě a bez závazků.

Přestavme si nejzajímavější funkce:

  • Samozřejmě přirozené vlastnosti scale-out object storage - velká horizontální škálovatelnost, použití komoditního hardware, vstup a výstup HTTP protokolem atd.

  • Erasure-coding (v nejnovější verzi Kilo) umožňuje místo ukládání celých objektů na nodu a jejich replikaci k několika dalším využít rozsekání velkého objektu na dílky, ty rozprostřít po nodech a přidat k nim kontrolní součty. Za cenu snížení výkonu a zvýšení latence lze snížit cenu za úložný prostor (srovnání obou metod se budeme věnovat v samostatném článku)

  • Řízení přístupu k vašim objektům (kdo smí?)

  • Streamované vkládání, tedy schopnost vkládat objekt aniž by byla dopředu známa jeho délka

  • Verzování zápisů, takže URL vede vždy na nejnovější verzi, ale systém drží a umožní získat ty předchozí

  • Přímý upload z klienta přes HTTP POST, tedy webová aplikace dovoluje prohlížeči vzít lokální soubor a poslat přímo do object storage, nemusí se jít přes web server

  • Časově omezené URL (dočasné odkazy)

  • Časově omezené objekty (sami se odmažou)

  • Velmi flexibilní storage politiky - dá se například podle uživatele nebo typu dat preferovat SSD, omezit fyzikální umístění dat na určitý region nebo naopak vynutit celoplanetární repliku

Jak se data ukládají

Připomeňme si, že adresa objektu je ve formátu „země, město, ulice“, tedy /account/container/object. Když Swift požádáte o objekt na nějaké adrese, ten musí vědět na kterém nodu a kterém disku ho najít. Klasický centralizovaný file systém by se s problémem vypořádal tak, že by si držel tabulku se seznamem souborů, metadaty a informací o jeho fyzickém umístění na disku. Scale-out distribuovaná object storage by ale s takovým přístupem měla problém.

Ve swift existuje seznam prostorů, kontejnerů a objektů a Swift ho svými procesy udržuje, nicméně ten nijak nesouvisí s vlastním umísťováním objektů a jejich nalezením - jde jednoduše o seznamy, kde uživatel nejde název svých objektů a jejich URL. K nalezení objektu dojde až po zadání této URL. Jak na to?

Udržovat stavový seznam objektů a jejich umístění špatně škáluje, proto se používá HASH funkce. Jde o matematickou operaci, která z libovolného vstupu vytvoří jeho otisk o stále stejné velikosti. Používá se dnes prakticky všude - kryptografie, ukládání dat, integrita, certifikáty - typickými zástupci jsou třeba MD5 nebo SHA. Vezmete tedy URL ve formátu /account/container/object a udělate nad tímto řetězcem HASH, které vede na nějaké číslo (je docela velké). Protože počet disků bude určitě menší mohli bychom použít modulo operaci a převést ho třeba na číslici 0-7 pro našich 8 disků a podle toho víme, kam máme zapsat (a kde najít) náš objekt. Čas vyhledávání by byl velmi rychlý a nepotřebujeme složitou stavovou tabulku. Nicméně změna počtu disků by znamenala použít modulo na jiný počet - v ten okamžik prakticky veškerá dosavadní umístění budou špatně a museli bychom celý cluster přeskládat, což je extrémně náročné. Navíc přidávání disků tímto způsobem způsobí, že jejich kompetence ve smyslu velikosti výseče budou nevyrovnané. Chce to nějaké vylepšení.

Tím je použití Consistent Hash Ring. Představte si možné výsledky HASH jako kolečko s číslicemi (HASH vrací výsledek ve stejném rozmezí bez ohledu na délku vstupu, takže kolečko bude stále stejně veliké). Zanaste vaše disky/nody na toto kolečko jako body. Disk bude "vlastnit" všechny objekty, jejichž hash je v rozmezí daném bodem disku na kružnici a vším po směru hodinových ručiček až do bodu, kde sedí další disk. V čem je to lepší, než obyčejné modulo? Když přidáte disk, ovlivníte pouze bezprostředního souseda - usurpujete si nárok na část jeho dat, protože jejich domovem jste teď vy. Všichni ostatní měnit nemusí.

Už je to lepší, ale přidání disku vytvoří stres pro jednoho souseda, což také není ideální. Swift tedy funguje ještě o něco chytřeji. Celá kružnice se rozseká na relativně velký počet výsečí, třeba 32K. Tyto se přidělí diskům, každý tedy vlastní výsečí hned několik a to napříč celým kolečkem. Nově přidaný disk si tak převezme některé výseče a rovnoměrně vycucne po kousíčkách dat z ostatních disků. Připomínám, že tato výseč (partition) je jen rozsah možných výsledků HASH.

Pojďme teď kroužků použít víc. Swift tak vytvoří jeden kroužek pro informace o záznamech o accountech (prostorech). Také jeden o kontejnerech a dále pro každou storage policy.

Jak se výseče rozdělí mezi disky v rámci různých storage policy? A jak se budou držet repliky? Každý prstenec obsahuje dvě základní tabulky - tou první je seznam všech nodů a tou druhou tabulka přidělených partition k jednotlivým diskům a replikám. Představte si jednoduchou tabulku, jejíž sloupce jsou čísla partition a řádky repliky (typicky tak bude mít tabulka 3 řádky). Obsahem je mapování partition na fyzické umístění. Při rozdělování výsečí mezi fyzické disky se berou v úvahu dva faktory. Tím prvním je "váha" disku, tedy administrátorem nastavitelné preference disku (například v reflexi na jeho velikost či rychlost). Druhou je pravidlo maximální diverzity. Pakliže jedna výseč má mít tři repliky, pro jejich fyzické umístění se zvolí co nejodlišnější disk - v jiné zóně nebo alespoň v jiném serveru.

Úvod do object store s použitím GUI

Pojďme si nejprve vyzkoušet nejzákladnější funkce s využitím GUI. Důležité zde je říct, že pokud byste chtěli použít Swift pro vší vlastní verzi něčeho jako je Box, DropBox, OneDrive apod. tak Swift v takovém scénáři bude plnit funkci backend systému. GUI není zaměřeno na běžné desktopové uživatele, nenabízí synchronizaci souborů s desktopem - to mohou dělat nadstavby jako je CTERA či SME, které si popíšeme později.

Jděte do sekce objektové storage v Helion OpenStack GUI.

Založme si nový kontejner, který můžete považovat za něco jako složku nebo disk.

Pojmenujte ho a vytvořte.

Klikněte na název kontejneru a v pravo můžete vytvářet pseudo-adresáře (defacto do URL objektu zakódovat jakoby cestu) a také uploadovat nový objekt - a přesně to teď udělejme.

Uploadujte nějaký objekt, třeba soubor či obrázek (pro šetření zdrojů z labu vezměte prosím něco rozumně velkého).

Objekt máte nahraný a můžete si ho třeba rovnou stáhnout.

Takhle jednoduché to základu je. Pro pokročilé funkce ale už musíme do příkazové řádky (či API) nebo bychom použili některou z front-end nadstaveb.

Použití CLI

Vyzkoušejme si příkazovou řádku pro Swift (úvod do problematiky najdete v části OpenStack CLI tohoto lab guide).

Načtěte komunikační parametry.

   tomas@labserver:~$ source stack

Vytvoříme nový kontejner

    tomas@labserver:~$ openstack container create novyKontejner

    +---------------------------------------+---------------+------------------------------------+

    | account                               | container     | x-trans-id                         |

    +---------------------------------------+---------------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | novyKontejner | txc5ddd9d9b77d42beb29f7-00576cd821 |

    +---------------------------------------+---------------+------------------------------------+

Vypíšeme si svoje kontejnery.

    tomas@labserver:~$ openstack container list

    +---------------+

    | Name          |

    +---------------+

    | mujProstor    |

    | novyKontejner |

    | zalohy        |

    +---------------+

Vytvořme nový soubor a uploadněme jako objekt.

    tomas@labserver:~$ echo "Muj text" > mujsoubor.txt

    tomas@labserver:~$ openstack object create novyKontejner mujsoubor.txt

    +---------------+---------------+----------------------------------+

    | object        | container     | etag                             |

    +---------------+---------------+----------------------------------+

    | mujsoubor.txt | novyKontejner | b56b9d21d9b5a09869ae2c45ab74e178 |

    +---------------+---------------+----------------------------------+

Vypišme obsah kontejneru

    tomas@labserver:~$ openstack object list novyKontejner

    +---------------+

    | Name          |

    +---------------+

    | mujsoubor.txt |

    +---------------+

Smažeme objekt i kontejner

    tomas@labserver:~$ openstack object delete novyKontejner mujsoubor.txt

    tomas@labserver:~$ openstack container delete novyKontejner

    tomas@labserver:~$ openstack container list

    +------------+

    | Name       |

    +------------+

    | mujProstor |

    | zalohy     |

    +------------+

Držení předchozích verzí objektů

První pokročilá funkce, kterou si vyzkoušíme, je schopnost Swiftu držet všechny předchozí verze objektu. Funguje to tak, že vytvoříme jeden kontejner pro archivaci starších verzí a také jiný kontejner, z kterého budou starší verze propadávat do archivu. Výsledkem bude, že v kontejneru budeme mít vždy nejposlednější verze objektu, ale můžeme se přímo podívat do archivu na ty předchozí. Pokud v kontejneru objekt smažeme a při tom existuje jeho starší verze, Swift automaticky na jeho místo dosadí nejnovější předchozí verzi.

Vytvořme dva kontejnery - archiv a aktualni (můžete použít i GUI).

    tomas@labserver:~$ openstack container create archiv

    +---------------------------------------+-----------+------------------------------------+

    | account                               | container | x-trans-id                         |

    +---------------------------------------+-----------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | archiv    | tx1519bec562c2454d922f7-00576cdca9 |

    +---------------------------------------+-----------+------------------------------------+

    tomas@labserver:~$ openstack container create aktualni

    +---------------------------------------+-----------+------------------------------------+

    | account                               | container | x-trans-id                         |

    +---------------------------------------+-----------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | aktualni  | txe500d883fa1b4c99ab32b-00576cdcad |

    +---------------------------------------+-----------+------------------------------------+

V dalším kroku potřebujeme zapnout funkci držení verzí. K tomu zatím neexistuje GUI ani příkaz v rámci sjednoceného openstack CLI, takže použijeme příkaz z klienta specifického pro Swift, kterým pošleme kontejneru nastavení hlavičky. Tím zapneme verzování. U kontejneru aktualni tedy nastavujeme, že starší verze objektů se mají ukládat do kontejneru archiv.

    tomas@labserver:~$ swift post aktualni -H 'X-Versions-Location: archiv'

    tomas@labserver:~$ swift stat aktualni

                     Account: AUTH_d2811986367044f9a5d9efa180e746cd

                   Container: aktualni

                     Objects: 0

                       Bytes: 0

                    Read ACL:

                   Write ACL:

                     Sync To:

                    Sync Key:

               Accept-Ranges: bytes

            X-Storage-Policy: General

                 X-Timestamp: 1466752173.47233

                  X-Trans-Id: txed227be13d4c4554a137f-00576cdd4c

                Content-Type: text/plain; charset=utf-8

         X-Versions-Location: archiv

Teď už si to můžeme vyzkoušet. Vytvořte v kontejeru aktualni nový objekt z našeho textového souboru.

    tomas@labserver:~$ openstack object create aktualni mujsoubor.txt

    +---------------+-----------+----------------------------------+

    | object        | container | etag                             |

    +---------------+-----------+----------------------------------+

    | mujsoubor.txt | aktualni  | b56b9d21d9b5a09869ae2c45ab74e178 |

    +---------------+-----------+----------------------------------+

Přidejme do souboru lokálně řádek a uploadujme novou verzi

    tomas@labserver:~$ echo "dalsi radek" >> mujsoubor.txt

    tomas@labserver:~$ cat mujsoubor.txt

    Muj text

    dalsi radek

    tomas@labserver:~$ openstack object create aktualni mujsoubor.txt

    +---------------+-----------+----------------------------------+

    | object        | container | etag                             |

    +---------------+-----------+----------------------------------+

    | mujsoubor.txt | aktualni  | 96ad90095dad7b3b2529a05b4e3a2529 |

    +---------------+-----------+----------------------------------+

Swift aktualizoval objekt, ale jeho starší verzi najdete s časovou značkou v kontejneru archiv.

    tomas@labserver:~$ openstack object list archiv

    +-----------------------------------+

    | Name                              |

    +-----------------------------------+

    | 00dmujsoubor.txt/1466753035.71726 |

    +-----------------------------------+

Udělejme ještě jednu verzi.

    tomas@labserver:~$ echo "jeste jeden radek" >> mujsoubor.txt

    tomas@labserver:~$ openstack object create aktualni mujsoubor.txt

    +---------------+-----------+----------------------------------+

    | object        | container | etag                             |

    +---------------+-----------+----------------------------------+

    | mujsoubor.txt | aktualni  | 1d84480e95d3e31222e8d0e4a1f2da72 |

    +---------------+-----------+----------------------------------+

V archivu už máme dvě předchozí verze.

    tomas@labserver:~$ openstack object list archiv

    +-----------------------------------+

    | Name                              |

    +-----------------------------------+

    | 00dmujsoubor.txt/1466753035.71726 |

    | 00dmujsoubor.txt/1466753077.92799 |

    +-----------------------------------+

Teď pojďme smazat objekt z kontejneru aktualni. Co se stane? Z archivu se do kontejneru aktualni přesune jeho historická (ale nejmladší) verze.

    tomas@labserver:~$ openstack object delete aktualni mujsoubor.txt

    tomas@labserver:~$ openstack object list aktualni

    +---------------+

    | Name          |

    +---------------+

    | mujsoubor.txt |

    +---------------+

    tomas@labserver:~$ openstack object list archiv

    +-----------------------------------+

    | Name                              |

    +-----------------------------------+

    | 00dmujsoubor.txt/1466753035.71726 |

    +-----------------------------------+

Máme hotovo - verzování nám funguje. Jak vidíte všechno se nastavuje na úrovni kontejnerů, takže se můžete takto chovat pouze k vybraným datům.

Omezení platnosti objektu

Swift umožňuje u objektu nastavit časově omezenou platnost a ten se ve stanovené datum a čas stane nepřístupným. Můžete tak zabránit k přístupu k dokumentům, které už v daný okamžik nebudou aktuální (standardy, výkresy). Ve Swift implementaci může rovněž běžet čistící proces, který takto vypršené objekty fyzicky smaže a šetří tak místo v objektové storage. Často firmy dávají data na FTP nebo NFS server se záměrem dočasnosti, ale pak se na to zapomene a zbytečná data pak trvale zabírají místo. Pokud dopředu víte, že objekt má časové mezení, Swift vám jeho vypršení ohlídá sám.

Funguje to nastavením hodnot v metadatech a to jak při nahravání objektu přes API nebo modifikací metadat již nahraného objektu. Vyzkoušíme si to. Použitý atribut v metadatech se jmenuje X-Delete-At a obsahuje datum a čas v Unix formátu (tedy počet vteřin od 1.1.1970). Abychom nemuseli složitě počítat, použijeme variantu X-Delete-After, kam zapíšeme počet sekund, po které má být objekt platný.

    tomas@labserver:~$ openstack container create docasne

    +---------------------------------------+-----------+------------------------------------+

    | account                               | container | x-trans-id                         |

    +---------------------------------------+-----------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | docasne   | tx49a44bbb66d140f1b29f0-00576d08db |

    +---------------------------------------+-----------+------------------------------------+

    tomas@labserver:~$ openstack object create docasne mujsoubor.txt

    +---------------+-----------+----------------------------------+

    | object        | container | etag                             |

    +---------------+-----------+----------------------------------+

    | mujsoubor.txt | docasne   | 1d84480e95d3e31222e8d0e4a1f2da72 |

    +---------------+-----------+----------------------------------+

Máme tedy kontejner a objekt. Pojďme teď u něj nastavit expiraci 120 vteřin.

    tomas@labserver:~$ swift post docasne mujsoubor.txt -H 'X-Delete-After: 60'

Zkuste objekt stáhnou - půjde to.

    tomas@labserver:~$ openstack object save docasne mujsoubor.txt

Počkejte dvě minuty a zkuste to znovu. Objekt už není nalezen, není dostupný.

    tomas@labserver:~$ openstack object save docasne mujsoubor.txt

    Not Found (HTTP 404)

Pokud si ale teď necháte vypsat obsah kontejneru, možná tam ještě chvilku bude. Nikdo už se k němu nedostane, ale fyzicky ještě není smazaný. Jedná se tedy o nedostupný, ale ještě nesmazaný objekt. Swift v pravidelných intervalech (obvykle kolem pěti minut) prochází svoje nody a neplatné objekty fyzicky odstraňuje.

    tomas@labserver:~$ openstack object list docasne

    +---------------+

    | Name          |

    +---------------+

    | mujsoubor.txt |

    +---------------+

Zkuste to později - už bude pryč.

    tomas@labserver:~$ openstack object list docasne

Dočasné veřejné URL

Swift kotejner můžete označit jako Private nebo Public. Může ovšem být situace, kdy obsah kontejneru nechcete volně přístupný všem, ale současně vznikne potřeba někomu dát velmi rychle a jednoduše možnost objekt stáhnout, možná i modifikovat. Například máte soubor ve Swiftu a na email je moc velký. Swift umožňuje vygenerovat dočasnou URL, pod kterou si lze objekt vyzvednout a můžete s přesností na vteřiny nastavit její platnost. Tato URL nebude vyžadovat žádné přihlášení, ale po vypršení času už nebude fungovat (na samotný objekt to pro přihlášené uživatele samozřejmě nemá vliv). Tato funkce nemá nativní grafickou nadstavbu (je ovšem velmi jednoduché si ji vytvořit a integrovat do nějakého z vašich systémů), použijeme CLI.

Nejprve musíte ke svému účtu přiřadit náhodný řetězec, který se bude používat při kryptografickém generování URL (v praxi použijte něco sofistikovanější, než mojeheslo).

   tomas@labserver:~$ openstack object store account set --property Temp-URL-Key=mojeheslo

Vytvořte kontejner a uploadujte objekt.

    tomas@labserver:~$ openstack container create dalsiKontejner

    +---------------------------------------+----------------+------------------------------------+

    | account                               | container      | x-trans-id                         |

    +---------------------------------------+----------------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | dalsiKontejner | tx608b9e30e36145a9b802b-00576d78dc |

    +---------------------------------------+----------------+------------------------------------+

    tomas@labserver:~$ openstack object create dalsiKontejner mujsoubor.txt

    +---------------+----------------+----------------------------------+

    | object        | container      | etag                             |

    +---------------+----------------+----------------------------------+

    | mujsoubor.txt | dalsiKontejner | 1d84480e95d3e31222e8d0e4a1f2da72 |

    +---------------+----------------+----------------------------------+

Teď vygenerujeme URL. Říkáme, zda bude pouze pro čtení (GET) nebo povolíme modifikaci objektu (PUT). Možnost PUT se často využívá v kombinaci s funkcí uploadování z webového formuláře (bezpečný způsob, jak můžete ve webové aplikaci nechat někoho uploadovat objekt do privátního kontejneru - webová aplikace vygeneruje tempurl, na kterou formulář objekt přímo pošle - uživatel tak neukládá skrz webový server samotný, což by ho zatěžovalo, ale přímo do object store). Dále říkáme počet vteřin, po které bude dočasná URL platná (přepínačem --absolute můžete také definovat cílové datum a čas v UNIX formátu). Pak specifikujete adresu k objektu (to je váš account/kontejner/objekt).

    tomas@labserver:~$ swift tempurl GET 240 /v1/AUTH_d2811986367044f9a5d9efa180e746cd/dalsiKontejner/mujsoubor.txt mojeheslo

    /v1/AUTH_d2811986367044f9a5d9efa180e746cd/dalsiKontejner/mujsoubor.txt?temp_url_sig=8bf48b3ab698b21f73ad6b2ef91ad591a5e96672&temp_url_expires=1466792528

Na svém počítači vyzkoušejte, že jste schopni si stáhnout objekt z dočasné URL (adresa je 16.21.188.203:8080 následovaná výše uvedenou cestou.

    http://16.21.188.203:8080/v1/AUTH_d2811986367044f9a5d9efa180e746cd/dalsiKontejner/mujsoubor.txt?temp_url_sig=8bf48b3ab698b21f73ad6b2ef91ad591a5e96672&temp_url_expires=1466792528

Po nějaké době to zkuste znovu - URL už vypršela.

Řízení přístupu aneb od kolegů po veřejnost

Zatím jsme vytvářeli kontejnery, které byly dostupné pouze uživatelům našeho tenantu (tedy kromě vygenerování dočasné URL). OpenStack Swift ale disponuje možností vytvářet přístupová pravidla (ACL) jak pro čtení, tak pro zápis. Ve výchozím stavu nebudou žádná (tedy ke kontejneru mohou jen uživatelé tenantu).

    tomas@labserver:~$ swift stat dalsiKontejner

             Account: AUTH_d2811986367044f9a5d9efa180e746cd

           Container: dalsiKontejner

             Objects: 1

               Bytes: 39

            Read ACL:

           Write ACL:

             Sync To:

            Sync Key:

       Accept-Ranges: bytes

    X-Storage-Policy: General

         X-Timestamp: 1466792156.28434

          X-Trans-Id: txf99886584f2b42fca2d17-00576d7acc

        Content-Type: text/plain; charset=utf-8

Můžete povolit přístup jinému tenantu (v takovém případě zadáváte jména tenantů oddělená čárkou) nebo jen konkrétním osobám nějakých tenantů (pak zadáváte tenant:jméno a pokud je takových záznamů víc, oddělujete je čárkou). Můžete také vytvořit kontejner, který je volně přístupný ke čtení odkudkoli bez jakéhokoli ověření (váš object store pak může třeba přímo servírovat obrázky na web přímo bez „průtoku“ web serverem a tak podobně). Pro volný přístup se používá řetězec .r:*,.rlistings.

Povolte tomuto kontejneru veřejný přístup.

    tomas@labserver:~$ swift post dalsiKontejner -r '.r:*,.rlistings'

    tomas@labserver:~$ swift stat dalsiKontejner

             Account: AUTH_d2811986367044f9a5d9efa180e746cd

           Container: dalsiKontejner

             Objects: 1

               Bytes: 39

            Read ACL: .r:*,.rlistings

           Write ACL:

             Sync To:

            Sync Key:

       Accept-Ranges: bytes

          X-Trans-Id: tx509daa6af87a4ff4b6468-00576d7b07

    X-Storage-Policy: General

         X-Timestamp: 1466792156.28434

        Content-Type: text/plain; charset=utf-8

Ze svého počítače si nechte vypsat obsah kontejneru zcela bez přihlášení na adrese

    http://16.21.188.203:8080/v1/AUTH_d2811986367044f9a5d9efa180e746cd/dalsiKontejner/mujsoubor.txt

Funguje - můžete zadat přímo URL vašeho objektu (tedy přidat mujsoubor.txt na konec předchozí).

Swift jako statický web

OpenStack Swift může sloužit také jako primitivní statický web. Výhodou je, že nemusíte nic moc řešit a máte jednoduchý webový přístup k objektům některého z kontejnerů a využít tak všech výhod object storage (tzn. vysoce redundantní řešení, data efektivně distribuovaná přes mnoho nodů/disků, možnost inteligentní replikace napříč planetou, programovatelný přístup z aplikací přes jednoduché API apod.).

Vytvořme si ještě další kontejner, uploadujme do něj nějaký objekt a zpřístupněme kontejner všem.

    tomas@labserver:~$ openstack container create staticweb

    +---------------------------------------+-----------+------------------------------------+

    | account                               | container | x-trans-id                         |

    +---------------------------------------+-----------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | staticweb | txa45c90a9f5b24e63b14ab-00576d7d3b |

    +---------------------------------------+-----------+------------------------------------+

    tomas@labserver:~$ openstack object create staticweb mujsoubor.txt

    +---------------+-----------+----------------------------------+

    | object        | container | etag                             |

    +---------------+-----------+----------------------------------+

    | mujsoubor.txt | staticweb | 1d84480e95d3e31222e8d0e4a1f2da72 |

    +---------------+-----------+----------------------------------+

    tomas@labserver:~$ swift post staticweb -r '.r:*,.rlistings'

Podobně jako v předchozí kapitolce se prohlížečem svého počítač připojte na URL kontejneru (IP adresa vašeho OpenStack Swift a jeho portu, potom v1 a pak account a jméno kontejneru), tedy v mém případě

    http://16.21.188.203:8080/v1/AUTH_d2811986367044f9a5d9efa180e746cd/staticweb/

Co uvidíme? Výpis našich objektů, ale pouze jako text.

Pojďme teď říci Swiftu, že pro tento kontejner má fungovat jako mini-web-server a na hlavní URL zobrazit HTML se seznamem všech objektů, tentokrát ale ve formě odkazů, takže si jednoduše můžete stáhnout (nebo přečíst, pokud jde o HTML objekty, poslechnout pokud jde o MP3 objekty apod.).

    tomas@labserver:~$ openstack container set --property 'Web-Listings=true' staticweb

Refreshujte stránku v prohlížeči.

Graficky si můžeme stránku upravit použitím CSS. Vytvořme tedy jednoduchý CSS soubor, uploadujme ho do kontejneru a nastavme Swift tak, že jej použije jako kaskádový styl.

    tomas@labserver:~$ echo "body {background-color: lightblue;}" > styl.css



    tomas@labserver:~$ openstack object create staticweb styl.css

    +----------+-----------+----------------------------------+

    | object   | container | etag                             |

    +----------+-----------+----------------------------------+

    | styl.css | staticweb | dc63ed634268ac2e4c5aa19338aa3069 |

    +----------+-----------+----------------------------------+



    tomas@labserver:~$ openstack container set --property 'Web-Listings-CSS=styl.css' staticweb

Znovu obnovte stránku.

Místo výpisu obsahu můžete take zobrazit nějaký výchozí HTML soubor. Vytvořme jej, uploadněme a řekněme to Swiftu.

    tomas@labserver:~$ echo "<H1>Muj staticky web</H1>" > index.html

    tomas@labserver:~$ openstack object create staticweb index.html

    +------------+-----------+----------------------------------+

    | object     | container | etag                             |

    +------------+-----------+----------------------------------+

    | index.html | staticweb | 542a2a044483c3b834bd25a28d9768de |

    +------------+-----------+----------------------------------+

    tomas@labserver:~$ openstack container set --property 'Web-Index=index.html' staticweb

Vnořování objektů do stránek na jiném web serveru

Vaše webová aplikace může přímo referencovat objekty ve Swiftu. Jednou z možností například je vytvořit si kontejner typu public, takže jeho dokumenty jsou běžně dostupné. Pokud by šlo o download nějakých souborů “na kliknutí” (něco ve smyslu “diskový obraz si stáhnete ZDE”), nemusíte podnikat nic dalšího, bude to fungovat. Pakliže by ovšem šlo o nějaké objekty vnořené do stránky (obrázek, video), browser může ukazovat varování o cross-origin. V rámci Swift můžete kontejneru nastavit CORS, což je standardizované HTML řešení, jak korektně cross-origin řešit. Nastavení se provádí na úrovni kontejneru, kde zadáte stránku, která může přistupovat (mimochod lze použít i wildcard a povolit všechny).

    tomas@labserver:~$ openstack container set --property Access-Control-Allow-Origin=http://mojesite.demo dalsiKontejner

Následujícím způsobem si můžeme z CURL otestovat práva při simulaci správného a špatného origin.

    tomas@labserver:~$ curl -k -i -X OPTIONS -H "Origin: http://mojesite.demo" -H "Access-Control-Request-Method: GET" http://16.21.188.203:8080/v1/AUTH_d2811986367044f9a5d9efa180e746cd/dalsiKontejner/mujsoubor.txt

    HTTP/1.1 200 OK

    access-control-allow-origin: http://mojesite.demo

    access-control-allow-methods: HEAD, GET, PUT, POST, COPY, OPTIONS, DELETE

    Allow: HEAD, GET, PUT, POST, COPY, OPTIONS, DELETE

    Content-Length: 0

    X-Trans-Id: txe383bb8681d44cdc9af68-00576d7ebe

    Date: Fri, 24 Jun 2016 18:41:02 GMT

    tomas@labserver:~$ curl -k -i -X OPTIONS -H "Origin: http://jinasite.demo" -H "Access-Control-Request-Method: GET" http://16.21.188.203:8080/v1/AUTH_d2811986367044f9a5d9efa180e746cd/dalsiKontejner/mujsoubor.txt

    HTTP/1.1 401 Unauthorized

    Content-Length: 131

    Content-Type: text/html; charset=UTF-8

    Allow: HEAD, GET, PUT, POST, COPY, OPTIONS, DELETE

    WWW-Authenticate: Keystone uri='http://helion-cp1-vip-KEY-API-mgmt:5000'

    X-Trans-Id: txd2164a2f83494b4a9eb08-00576d7efb

    Date: Fri, 24 Jun 2016 18:42:03 GMT



    <html><h1>Unauthorized</h1><p>This server could not verify that you are authorized to access the document you requested.</p></html>

Takto tedy nemusíte ukládat velké soubory (typicky obrázky ve vysokém rozlišení, soubory, videa) prostředky vašeho webového serveru, ale odkážete se přímo na vaší instalaci Swift se všemi výhodami, které přináší – vysokou míru spolehlivosti díky replikaci, regionální politiky (replikace napříč planetou a upřednostnění blízkých nodů s objektem), přehled, multitenancy a velkou škálovatelnost.

Swift podporuje i možnost přímého uploadování objektů z webového formuláře klienta. Pakliže tedy máte webovou aplikaci, implementace nevyžaduje, že klientský browser nejprve uploaduje soubor na váš web server, který pak provede upload do Swift (což ovšem ale samozřejmě možné a může to mít i nějaké výhody). Místo toho lze povolit přímý kontakt Swift s klientem z HTML formuláře (tedy data neprotečou přes webový server a šetří jeho výkon). Zabezpečeno je to trochu podobně jako u TempURL, tedy definujete parametry (tentokrát zahrnují třeba i maximální velikost objektu) a ty potom zašifrujete – tímto způsobem nelze řešení zneužít k neoprávněnému odesílání dat mimo vaší webovou aplikaci. Víc informací najdete v dokumentaci (http://docs.openstack.org/developer/swift/api/form_post_middleware.html)

Hromadné operace

OpenStack Swift umožňuje programátorům zefektivnit některé operace při uploadování a mazání objektů. První z funkcí je možnost uploadovat archiv ve formátu tar, gz bebo bz2 s tím, že Swift si archiv sám rozbalí a jeho soubory uloží v požadovaném kontejneru. Dále je k dispozici API, které v jednou požadavku na smazání objektu umožňuje jich uvést až 10 000, což má pozitivní vliv na výkon v případě nutnosti smazat velké množství objektů najednou.

Protože je tato funkce aktuálně zaměřena na vývojáře používající API, nebudeme ji v našem labu zkoušet (nicméně funguje dobře, na detaily se kliedně zeptejte nebo prostudujte dokumentaci).

Velké soubory

Swift je ve výchozím stavu omezen na maximální velikost objektu 5GB. Hlavním cílem je zabránit nerovnoměrnému rozložení dat v systému. Hodnotu můžete zvětšit, ale Swift má možnost rozdělení vetších objektů na menší kousky. Funguje to tak, že při uploadování si soubor rozdělíte na bloky o velikosti do 5GB, ale soubor uložíte tak, že využijete funkce Static Large Objects. Ta umožní, že v jednom kontejneru máte segmenty, ale v jiném je virtuální reprezentace celého objektu. Při jeho stahování tedy nemusí uživatelé dělat nic dalšího, jednoduše stahují (ukládání tedy může vyžadovat nějakou péči, alse stahování ne.

Klasické administrátorské GUI toto neumožňuje, nicméně existují tři příjemné možnosti:

  • Použijete API například v situaci, kdy objekt je vytvářen jinou aplikací (pro programátory je to velmi snadné) a ne přímo uživatelem (ten ho případně pouze stahuje, což nevyžaduje nic dalšího)

  • Použijete nadstavbové GUI, které to udělá za vás (uvidíte v další části labu)

  • Použijte klasické Swift CLI, které to umožňuje

Právě CLI si teď vyzkoušíme, ale abychom šetřili zdroje v labu, uděláme segmenty podstatně menší.

Vytvořte soubor o velikosti 5 MB.

    tomas@labserver:~$ dd if=/dev/zero of=vetsisoubor  bs=5M  count=1

    1+0 records in

    1+0 records out

    5242880 bytes (5.2 MB) copied, 0.0128545 s, 408 MB/s

Uploadujte do kontejneru s využitím klasického Swift CLI klienta a specifikujte použití segmentace (SLO) a velikost segment dejte na 1 MB.

    tomas@labserver:~$ swift upload mujKontejner vetsisoubor --use-slo --segment-size 1048576

    vetsisoubor segment 0

    vetsisoubor segment 1

    vetsisoubor segment 2

    vetsisoubor segment 3

    vetsisoubor segment 4

    vetsisoubor

Zkuste si object stáhnout - z CLI nebo GUI, nic zvláštního to po vás chtít nebude.

    tomas@labserver:~$ openstack object save mujKontejner vetsisoubor

Podívejme na seznam kontejnerů - najdete něco nového?

    tomas@labserver:~$ openstack container list

    +-----------------------+

    | Name                  |

    +-----------------------+

    | aktualni              |

    | archiv                |

    | dalsiKontejner        |

    | docasne               |

    | mujKontejner          |

    | mujKontejner_segments |

    | mujProstor            |

    | staticweb             |

    | zalohy                |

    +-----------------------+

Byl vytvořen kontejner se segmenty pro mujKontejner (výchozí jméno je možné při uploadování zvolit jiné). Podívejme co obsahuje ten originální a ten se segmenty.

    tomas@labserver:~$ openstack object list mujKontejner

    +-------------+

    | Name        |

    +-------------+

    | vetsisoubor |

    +-------------+

    tomas@labserver:~$ openstack object list mujKontejner_segments

    +------------------------------------------------------------+

    | Name                                                       |

    +------------------------------------------------------------+

    | vetsisoubor/slo/1466793808.487653/5242880/1048576/00000000 |

    | vetsisoubor/slo/1466793808.487653/5242880/1048576/00000001 |

    | vetsisoubor/slo/1466793808.487653/5242880/1048576/00000002 |

    | vetsisoubor/slo/1466793808.487653/5242880/1048576/00000003 |

    | vetsisoubor/slo/1466793808.487653/5242880/1048576/00000004 |

    +------------------------------------------------------------+

Kvóty na počet objektů nebo velikost

Swift podporuje nastavení kvóty pro každý kontejner zvlášť co do počtu objektů nebo celkové velikosti kontejneru. Toto nastavení smí provádět pouze uživatel v roli Swift administrátora a omezit tak možnosti jiným členům tenantu, kteří nemají taková práva. Velmi užitečné je to zejména v případě veřejných kontejnerů například s uploadem přes webový formulář ve vaší aplikaci nebo pro ochranu před nepovedenou aplikací, která by nějakou chybou zabrala veškerý prostor. Vyzkoušejme si to.

Vytořte nový kontejner.

    tomas@labserver:~$ openstack container create omezeni

    +---------------------------------------+-----------+------------------------------------+

    | account                               | container | x-trans-id                         |

    +---------------------------------------+-----------+------------------------------------+

    | AUTH_d2811986367044f9a5d9efa180e746cd | omezeni   | tx2d905a82b7e548c980d1e-00576d80c3 |

    +---------------------------------------+-----------+------------------------------------+

Nastavte kvótu na počet objektů (nebo Quota-Bytes na velikost kontejneru).

    tomas@labserver:~$ openstack container set --property Quota-Count=2 omezeni

Vytvořte si tři soubory

    tomas@labserver:~$ touch soubor1

    tomas@labserver:~$ touch soubor2

    tomas@labserver:~$ touch soubor3

Uploadujte první dva.

    tomas@labserver:~$ openstack object create omezeni soubor1

    +---------+-----------+----------------------------------+

    | object  | container | etag                             |

    +---------+-----------+----------------------------------+

    | soubor1 | omezeni   | d41d8cd98f00b204e9800998ecf8427e |

    +---------+-----------+----------------------------------+

    tomas@labserver:~$ openstack object create omezeni soubor2

    +---------+-----------+----------------------------------+

    | object  | container | etag                             |

    +---------+-----------+----------------------------------+

    | soubor2 | omezeni   | d41d8cd98f00b204e9800998ecf8427e |

    +---------+-----------+----------------------------------+

Teď bude nutné na chvilku počkat (typicky 60 vteřin). Swift je masivně škálovatelný, má obrovskou kapacitu a může se rozprostřít přes celou planetu. Z toho důvodu stojí na eventuální konzistenci (na rozdíl třeba od souborových systémů). Pokud byste uploadovali třetí objekt rychle, pravděpodobně se to podaří - informace o spotřebě se v clusteru replikuje nějakou dobu. Po chvilce zkuste nahrát třetí objekt.

    tomas@labserver:~$ openstack object create omezeni soubor3

    Request Entity Too Large (HTTP 413)

Pro běžné účely je takové chování dostatečné - odměnou za toleranci je pro vás masivní celoplanetární škálovatelnost současně s lokální dostupností, nízkou latencí a velkým výkonem. Tam, kde je nutné striktně dodržovat podobná pravidla doporučuji použít nějakou nadstavbu, která vynucení (a s ním spojené distribuvané zámečky nebo centralizaci přístupů) provede o úroveň víš.

Klienstké GUI s open source CyberDuck

V rámci labu si můžete vyzkoušet nainstalovat klienta na váš počítač (a to dokonce s podporou češtiny). Jde o open source řešení podporující přístup do OpenStack Swift. Stáhněte si na https://cyberduck.io/

V našem labu je instalace OpenStack bez použíti TLS šifrování a běžně dostupné profily CyberDuck po instalaci vyžadují HTTPS (což je pro produkci více než rozumné). Abyste mohli vyzkoušet řešení s HTTP stáhněte si nový profil na adrese https://trac.cyberduck.io/wiki/help/en/howto/openstack v části Connect without SSL.

Vytvořte profil.

Po zadání tenantu (v labu má stejný název jako vaše přihlašovací jméno) se vám načtou vaše kontejnery.

Pokud máte u svého účtu nastaven TempURL klíč (viz příslušná kapitola) můžete například generovat dočasné URL pro přístup bez přihlášení.

Dále můžete synchronizovat adresář na vašem počítači, stahovat a uploadovat objekty (a to včetně podpory libovolných velikostí) a to velmi spolehlivě (s možností navázání spojení v případě přerušení). Dá se také omezit rychlost stahování.

Komerční nadstavby

Na trhu existují komerčně dostupné systémy pro enterprise sdílení souborů a jejich synchronizaci, které podporují OpenStack Swift jako svůj backend. Mezi ně patří:

  • Storage Made Simple (mám vyzkoušeno, vřele doporučuji, funguji i vypadá perfektně)

  • CTERA (společně s SME jsou to as dvě nejlepší řešení na trhu)

  • Owncloud

Využití Swift ve vašich aplikacích a webech

Jak jsme viděli, Swift používá jednoduché RESTful API, s kterým se velmi dobře pracuje. Z libovolného programovacího jazyka je pak můžete volat přes jejich HTTP knihovny. Pokud to chcete ještě o něco jednoduší, existují knihovny (SDK) pro programovací jazyky: