04 10 2017

Jak wiemy Docker dorobił się jak na razie 2 natywnych mechanizmów HA – Swarm klasyczny (do wersji 1.11) i Swarm wbudowany (od 1.12). Obydwa działają bardzo sprawnie i potrafią po awarii jednego z węzłów uruchomić kontenery na innym żyjącym węźle. Jeśli kontenery reprezentowały usługi tymczasowe, takie jak np. mikroserwisy, lub stanowiły ogniwa łączące inne komponenty, to zazwyczaj ich tzw. „dane” ograniczają się do tego co zawierają ich Dockerfile. Obydwa Swarmy, stary i nowy, poradzą sobie z ich ponownym uruchomieniem i jeśli kontenery faktycznie były stateless, to użytkownik nie zauważy zbyt długiej przerwy w działaniu usługi. Wszystko ładnie się uruchomi i będzie dalej działać jak gdyby nigdy nic.

 

Problem pojawia się gdy działający kontener posiadał w środku jakieś ważne dane. Najgorzej gdy przy uruchamianiu nie użyto opcji „-v” – wtedy po awarii hardware dane z kontenera są bezpowrotnie utracone. Jeśli przy uruchamianiu zmapowano volumen z hosta wtedy jest jakaś szansa że nasze dane są gdzieś w backupach hosta. Pytanie tylko jak często ten backup był wykonywany oraz czy admin backupu przez przypadek „nie pominął” zamapowanego katalogu/filesystemu. Niestety nawet jeśli mamy trochę szczęścia i nasze dane są do odzyskania to nadal mamy problem. Opcja z długotrwałym oraz co gorsze ręcznym restore to nie jest przecież HA. Nasi użytkownicy na pewno zauważą że nasza usługa zaliczyła awarię. Co więcej – pewna część danych na pewno ucieknie – a już na pewno te zapisy które były realizowane po ostatnim backupie.

Dla przypomnienia krótka podstawowa teoria o dockerowym mapowaniu wolumenów:

Wersja z podaniem volumenu

HARDWARE# docker run -ti -v /dane –name=ubuntu02 ubuntu:14.04
root@4789861ae201:/# ls -l /dane
total 0
root@4789861ae201:/# touch /dane/PLIK
root@4789861ae201:/# exit

kontener umiera ale na hoście dane nadal są w /var/lib/docker/volumes/ID_KONTENERA :

HARDWARE # ls -l
/var/lib/docker/volumes/e48a58edc4c47f6fea5bec4b80cfb00bf7ceb9d16872401469d7e475941a864c/_data/
-rw-r–r–. 1 root root 0 Sep  9 11:34 PLIK

Po awarii da się jakoś pozbierać to do kupy pod warunkiem że gdzieś mamy w backupach nasze dane.

Wersja jeszcze lepsza – podanie gdzie na nasz HARDWARE mają trafiać dane z katalogu kontenera

HARDWARE # docker run -ti -v /katalog:/dane –name=ubuntu03 ubuntu:14.04
root@d9b31b8dadd9:/# ls -l /dane
total 0
root@d9b31b8dadd9:/# touch /dane/PLIK
root@d9b31b8dadd9:/# exit
exit

kontener umiera ale na hoście dane nadal są w folderze „/katalog” :

HARDWARE # ls -l /katalog/
-rw-r–r–. 1 root root 0 Sep  9 11:41 PLIK


Patrząc na powyższe idealnym byłoby rozwiązanie podające swarmowi na tacy wszystkie ważne dane na każdym jego węźle (czyli w powyższym przykładzie fajnie jakby na każdym węźle był folder „/katalog”). W sumie jeszcze lepiej by było gdyby te dane nie były montowane na każdym węźle swarma (bo i po co) ale tylko tam gdzie jest to potrzebne. I żeby swarm się nie musiał tym bezpośrednio zajmować tylko wysyłał rozkaz do jakiegoś mechanizmu który za niego to załatwi. I najlepiej żeby gadał RESTem (skoro wszystko w dockerze gada RESTem). No i ważne żeby było w miarę wydajnie i zarządzalnie. Oczywiście – jasne – można by to zrobić NFSem, koniec artykułu.

Na powyższe wyzwanie środowisko dockera odpowiedziało całą batalią storage-driverów. Co więcej – w temat zaangażowali się nawet wielcy gracze (SolidFire od Netappa , rex-ray od EMC) ale również mniejsi (np. Convoy od Ranchera czy Flocker z Clusterhq).

Moją uwagę zwrócił rex-ray ponieważ z racji pochodzenia znakomicie integruje się z EMC scale-io – twórcy drajwera czyli grupa EMC-code to część programistów z EMC. A scale-io to już świat niemal równy z legendarnym i kultowym CEPH… a skoro CEPH to już nie ma żartów, proszę zapiąć pasy. Zresztą EMC twierdzi że scaleio jest groźnym konkurentem dla CEPHa w kontekście wydajności, pozycjonowanie zatem mają idealne. Jako przyjemny dodatek – rexray integruje się też z virtualboxem, co jest bardzo fajnym podejściem. Zwykły użytkownik chciałby przecież najpierw potestować sobie rozwiązanie w domowym labie zanim wrzuci drajwer na te 500+ maszyn w DC.

Na początek trochę o samym scale-io – wycięte wprost z dokumentacji czym to w ogóle jest:

Scaleio1

W olbrzymim skrócie – scaleio to taka storagowa „spółdzielnia”. Każdy może przystąpić do niej ale fajnie jakby jako wpisowe wniósł do spółdzielni dysk minimum 100GB, co oczywiście da się obejść. Do wspólnego worka można zatem powrzucać wszystkie stare serwery – byle miały jakieś dyski. Dyski te wspólnie stworzą wielką pulę wolnego miejsca, im więcej serwerów tym lepiej. Serwer wnoszący jako wpisowe swój dysk to Scaleio Data Server (SDS). Komponent SDS zatem instaluje się na każdej maszynie która chce/musi oddać trochę swojego storage dla spółdzielni. Z drugiej strony są „biorcy storage” – czyli klienci spółdzielni – tzw. Scaleio Data Clients (SDC). Komponent SDC instaluje się zatem na każdej maszynie która chciałaby korzystać z dobrodziejstwa naszej wielkiej puli wolnego miejsca. Całość komunikacji między siecią SDS a siecią SDC odbywa się mechanizmami scaleio i robiona jest oczywiście po TCP/IP. Zarządzanie spółdzielnią spoczywa w rękach 3 managerów (MDM) Główny to master, zastępca to slave i ten trzeci który nie zarządza ale bierze udział w wyborze managera głównego, tzw. tie-breaker.

Idealnym modelem implementacji scaleio jest olbrzymia sieć serwerów gdzie na każdym pracuje po kilka SDS + kilka SDC. Dodatkowo na 3 (lub nawet 5) z nich jest MDM. Poniższy rysunek znalazłem w dokumentacji i świetnie obrazuje podręcznikowe wdrożenie scale-io:

Scaleio2

Powyższe to już raczej duża instalacja. Ale że węzły SDS i SDC można zawsze dodać potem, mój LAB opiera się na 3 serwerach. Na każdym z nich jest 1 SDS, 1 SDC i 1 MDM. Oto zatem uproszczony schemat:

Scaleio3

Scale-io instaluje się bardzo prosto specjalnym webowym narzędziem (IM) który zaciąga odpowiednie paczki i instaluje je na wszystkich komponentach. Dokumentacja jest dobra a instalacja nie przysparza większych problemów. Wspierane jest centos/rhel  i ubuntu (odradzam). Efekt końcowy w IM jawi się następująco:

Scaleio4

Jak widać mamy 3 maszyny – na każdej SDS+SDC oraz MDM.

Po zakończonej instalacji można odpalić pierwsze komendy i utworzyć sobie pierwsze urządzenia i wolumeny (poleceniem do wszystkiego – czyli scli):

Krok 1 – zalogowanie do MDM-master

[root@centos04 ~]# scli –login –username admin –password XXXXXX

Krok 2 – dodanie do wspólnego worka dysków minimum 100GB na każdej z maszyn (na moich 3 maszynach to wykrojone na szybko dodatkowe małe dyski /dev/sdb) :

[root@centos04 ~]# scli –add_sds_device –sds_ip 192.168.56.105 –protection_domain_name default –storage_pool_name default –device_path /dev/sdb

Successfully added device /dev/sdb to SDS. New device ID: 0589894700020000

[root@centos04 ~]# scli –add_sds_device –sds_ip 192.168.56.106 –protection_domain_name default –storage_pool_name default –device_path /dev/sdb

Successfully added device /dev/sdb to SDS. New device ID: 0589894800010000

[root@centos04 ~]# scli –add_sds_device –sds_ip 192.168.56.107 –protection_domain_name default –storage_pool_name default –device_path /dev/sdb

Successfully added device /dev/sdb to SDS. New device ID: 0589894900000000

Krok 3 – utworzenie pierwszego wolumenu:

[root@centos04 ~]# scli –add_volume –protection_domain_name default –storage_pool_name default –size_gb 10 –volume_name scale_vol_01

Warning: Rounding up the volume size to 16 GB

Successfully created volume of size 16 GB. Object ID 1148690400000000

Krok 4 – finalny – zamapowanie wolumenu do jednego z SDC:

[root@centos04 ~]# scli –map_volume_to_sdc –volume_name scale_vol_01 –sdc_ip 192.168.56.106

Successfully mapped volume scale_vol_01 to SDC 192.168.56.106

Po tych czynnościach otrzymujemy efekt końcowy – na maszynie 192.168.56.106 pojawiło się nowe urządzenie blokowe (scaleio nazywa je /dev/scinia,b,c itd.) :

[root@centos04 tmp]# ls -l /dev/scinia
brw-rw—-. 1 root disk 252, 0 Sep  9 04:46 /dev/scinia

Oczywiście miejmy świadomość że jest to emulacja i że to urządzenie jest niby blokowe ale tak naprawdę przyszło do nas na maszynę mechanizmami TCP/IP poprzez mechanizmy scale-io.

Bardzo przydatnym (i w miarę ładnym) narzędziem jest graficzne GUI które instaluje się jako osobną paczkę (gdziekolwiek – byle miało połączenie z MDM’ami) – jest to GUI X-owe a więc trzeba jakiś desktop manager sobie niestety zainstalować. Po wywołaniu GUI (via /opt/emc/scaleio/gui/run.sh) otrzymujemy aplikację:

Scaleio5

Dashboard pokazuje kondycję całego systemu. Zielona część kółka po lewej to miejsce zajęte (nasz wolumen ma 16 GB ale scale-io robi redundancję 2N stąd 32 GB), niebieska część to spare capacity a szara to miejsce do wykorzystania. A że moje 3 maszyny wniosły do puli dyski po ok. 109 GB każda to mamy w całości 325 GB. W systemie mamy oczywiście 3 x SDS, 3 x SDC i 1 Volumen (który jest w stanie „mapped” gdyż parę poleceń wcześniej zamapowaliśmy go do hosta 192.168.56.106).

Oprócz tego możemy obejrzeć wolumeny:

Scaleio6

Lista SDC:

Scaleio7

A najlepsza jest zakładka „BACKEND” gdzie mamy wszystko kawę na ławę:

Scaleio8

No dobra , scaleio tworzy nam urządzenia, zarządza wspólną przestrzenią, ma ładne GUI itd. Teraz trzeba by to jakoś zintegrować z dockerem. I właśnie do tego służy rex-ray.

Jak widać na poniższym wycinku z dokumentacji metod sterowania scale-io jest kilka – pierwszy i drugi mamy przećwiczony, trzeci dotyczy jakiejś zmurszałej technologii (he he) , czwarty jest do cindera, a oczywiście ten ostatni (REST) interesuje nas najbardziej.

Scaleio9

Rest Gateway instaluje się z automatu razem z webowym installation managerem (IM), tyle że ma nieco inny URL gdyż zamiast:

https://IP_MASZYNY_Z_IM/maintain.jsp

jest:

https:// IP_MASZYNY_Z_IM /api

Już za chwilę będziemy się dobierać do tegoż REST Gatewaya z poziomu dockera ale najpierw słowo o rex-ray. Otóż jest to projekt open source kierowany przez grupę zapaleńców z EMC-code. Oto strona projektu na githubie:

https://github.com/emccode/rexray

Czym jest rexray? Najlepiej zacytować chyba z githubowej strony projektu:

„REX-Ray provides a vendor agnostic storage orchestration engine. The primary design goal is to provide persistent storage forDocker containers as well as Mesos frameworks and tasks.”

A tu nagłówek z dokumentacji:

„REX-Ray is a storage orchestration tool that provides a set of common commands for managing multiple storage platforms. Built on top of the libStorage framework, REX-Ray enables persistent storage for container runtimes such as Docker and Mesos.”

Ogólnie chłopaki z emc-code naprawdę dają radę i jak się przejrzy ich repozytoria to produkują kilkadziesiąt różnych fajnych lub bardzo fajnych platform:

https://github.com/emccode

Dodatkowo należy podkreślić że poświęcają swój czas również na ułatwiacze dla potencjalnego klienta, gdyż większość swoich zabawek udostępniają via vagrant (tak aby sobie jednym poleceniem postawić całe środowisko i potestować). Przykładowo polecam poniższe repozytorium:

https://github.com/emccode/vagrant/tree/master/scaleio

Wystarczy mieć virtualboxa i vagranta a następnie zrobić git clone a potem vagrant up i mamy po dłuższej chwili wszystko na swoim laptopie. W wyniku tego stawiane są z automatu 3 centosy, na nich klaster scaleio wraz z driverem rex-ray a na końcu docker. Oczywiście jak to w automatach – wtedy nie wiemy zupełnie co się stało na naszych systemach i jak to wszystko działa jedno z drugim J

Dlatego jednak polecam metodę krok po kroku czyli stawianie ręczne, ewentualnie można zdoktoryzować się z zawartości Vagrantfile’a żeby obejrzeć jak emc-code to robią i potem co najwyżej powtórzyć ręcznie ich instalacje.

Wracając do rex-ray – instalacja jest realizowana poprzez curla:

curl -sSL https://dl.bintray.com/emccode/rexray/install | sh –

w wyniku tego w systemie pojawia się usługa rex-raya, trzeba tylko dorobić dla niej konfigurację. Konfiguracja jest w YAMLu, jeśli nie chce nam się jej tworzyć ręcznie to na stronie jest generator :

http://rexrayconfig.emccode.com

Tzn jeszcze pod koniec sierpnia był ale potem w wyniku merge DELL z EMC pojawił się pod innym adresem:

http://rexrayconfig.codedellemc.com/

Inne adresy URL podane w tym artykule też mogły przemigrować na tę nową domenę.

Oto mój konfig rexraya, jest on na wszystkich 3 maszynach taki sam:

[root@centos04 tmp]# cat /etc/rexray/config.yml

rexray:
  logLevel: error
libstorage:
  logging:
    level: error
    service: scaleio
scaleio:
  insecure: true
  thinOrThick: ThinProvisioned
  endpoint: https://192.168.56.100/api
  password: XXXXXX
  userName: admin
  protectionDomainName: default
  storagePoolName: default
  apiVersion: 2.0

Przed sprawdzeniem czy rexray rozmawia ze scaleio-rest-gatewayem należy przetestować połączenie scaleio-rest-gateway’a do scaleio-MDM – najlepiej curlem:

curl –insecure –user admin:XXXX https://adres-scaleio-rest-gatewaya/api/login

„YWRtaW46MNTI0NTpmMjU2M2Q1OGEwNzZmMTk0NWRiNjBlMTdhNTYyNw”

Jak nam się wygeneruje ten długi token to dobrze, jak nie – to znaczy że coś poszło nie tak i trzeba poczytać issues na githubie. Krok z curlem to w sumie finalny test całości środowiska – czy wszystkie komponenty gadają ze sobą, czy się widzą, czy wszystko działa, czy nie ma błędów itd.

Curl należy wykonać z każdego węzła na którym będzie docker – czyli z każdego węzła gdzie jest rexray (a zatem z każdego SDC).

Mechanizm działania polega na komunikacji serwisu rexray ze scale-io-rest-gateway’em. Następnie tenże rest-gateway rozmawia z jednym z MDM jakie ma na liście. MDM oczywiście steruje pracą klastra scaleio (czyli grupą N x SDC i N x SDS). Rest Gateway potrafi pracować w HA.

Po poprawnej weryfikacji curlem należy zweryfikować działanie samego rexray – na razie bez dockera. Sprawdzamy na każdym węźle czy rexray łączy się z rest-gatewyem i czy zobaczy konfigurację scale-io:

[root@cent03 tmp]# rexray volume
– attachments:
– instanceID:
id: d9ce935400000001
driver: scaleio
volumeID: „1148690400000000”
availabilityZone: default
name: scale_vol_01
size: 16
id: „1148690400000000”
type: default

[root@cent04 ~]# rexray volume
– attachments:
– instanceID:
id: d9ce935400000001
driver: scaleio
volumeID: „1148690400000000”
availabilityZone: default
name: scale_vol_01
size: 16
id: „1148690400000000”
type: default

[root@cent05 ~]# rexray volume
– attachments:
– instanceID:
id: d9ce935400000001
driver: scaleio
volumeID: „1148690400000000”
availabilityZone: default
name: scale_vol_01
size: 16
id: „1148690400000000”
type: default

Volumen był jeden (scale_vol_01) – widać go na każdym węźle, weryfikacja się udała.

Skoro można sterować klastrem scale-io za pomocą rexray to sprawdźmy czy da się założyć wolumen:

[root@cent05 ~]# rexray volume create –size=16 –volumename=”scale_vol_02″ –availabilityzone=”default”
availabilityZone: default
name: scale_vol_02
size: 16
id: 1148de3100000001
type: default

Sprawdźmy czy go widać:

[root@cent05 ~]# rexray volume
– attachments:
– instanceID:
id: d9ce935400000001
driver: scaleio
volumeID: „1148690400000000”
availabilityZone: default
name: scale_vol_01
size: 16
id: „1148690400000000”
type: default
– availabilityZone: default
name: scale_vol_02
size: 16
id: 1148de3100000001
type: default

Jak widać udało się rexrayem stworzyć kolejny wolumen – w GUI też już go widać:

Scaleio10

Co ciekawe nasze 2 wolumeny są widoczne z poziomu wszystkich dockerów na 3 węzłach:

Scaleio11

Docker jak widać rozmawia z serwisem rexray, co więcej – gdy wyłączy się usługę rexray, docker zaczyna mieć problemy z obsługą wolumenów:

[root@cent03 ~]# docker volume ls

list rexray: Post http://%2Frun%2Fdocker%2Fplugins%2Frexray.sock/VolumeDriver.List: dial unix /run/docker/plugins/rexray.sock: connect: connection refused

Oczywiście docker nadal potrafi zarządzać lokalnymi zwykłymi wolumenami:

[root@cent03 ~]# docker volume create –name=test01
test01
[root@cent03 ~]# docker volume ls
DRIVER              VOLUME NAME
rexray              scale_vol_01
rexray              scale_vol_02
local               test01

Oczywiście takich zwykłych wolumenów nie widać na pozostałych hostach:

Scaleio12

Stwórzmy zatem teraz kolejny wolumen ale już rexrayem licząc na to że pojawi się on w całym klastrze scale-io:

Scaleio13

Jak widać na każdym węźle docker pokazuje obecność tego wolumenu, pojawił się także w scale-io-GUI:

Scaleio14

Wolumen został zamapowany – oczywiście tylko do tego węzła gdzie uruchomiliśmy kontener (centos03 – 192.168.56.105)

Scaleio15

Co zatem tu zaszło? Wydaliśmy dla przypomnienia polecenie:

docker run -tdi -v docker_vol_01:/dane  –volume-driver=rexray ubuntu:14.04

A zatem przy tworzeniu kontenera silnik dockera połączył się z serwisem rexray i zlecił mu utworzenie wolumenu. Serwis rexray połączył się z scale-io-rest-gatewayem który zlecił resztę prac do warstwy MDM. MDM oczywiście utworzył wszystko w warstwie SDC i SDS. W SDC pojawiło się urządzenie blokowe (/dev/sciniX) które teraz służy jako storage dla wolumenu nowo powołanego kontenera.

To może dla podsumowania jeszcze jedna próba – tym razem na węźle gdzie jeszcze nie ma żadnych urządzeń blokowych SDC.

Scaleio16

Takim węzłem jest jak widać maszyna 192.168.56.107 – co prawda ma SDC ale nie ma jeszcze żadnych zamapowanych wolumenów (co widać w GUI jako 0 w kolumnie Mapped Volumes).

Scaleio17

Pojawiło się nowe blokowe urządzenie /dev/scinia.

Rexray jako tako po sobie sprząta (co w świecie dockera wcale nie jest takie oczywiste) – jak widać usuwa urządzenie blokowe z SDC:

Scaleio18

Niestety ale z defaultu nie usuwa wolumenów w samym scale-io – jedynie odmapowuje je od węzłów:

Scaleio19

Czas na swarma i swarm-service który wykorzysta całą funkcjonalność jaką do tej pory omawialiśmy. Zacznijmy od porządków – usuwamy wszystko co do tej pory było tworzone aby mieć czyste systemy. W wyniku tego na żadnym node nie ma wolumenów. W międzyczasie tworzymy też 3 węzłowy klaster swarma:

Scaleio20

Tworzymy usługę (w swarm tzw. „service”) ze specjalną opcją do wolumenów (w service nie ma przełącznika „-v”) – czyli „–mount” (z całą batalią dodatkowych opcji ad punkty montowania, nazwa wolumenu i wskazanie drivera raxray):

[root@cent03 ~]# docker service create –replicas 1 –name service_1 \
–mount type=volume,source=service_1_vol,target=/data,volume-driver=rexray \
ubuntu:14.04 tail -f /dev/null
4m1i3uj6pkrpngl165sxnxokm

[root@cent03 ~]# docker service ls
ID            NAME       REPLICAS  IMAGE         COMMAND
4m1i3uj6pkrp  service_1  0/1       ubuntu:14.04  tail -f /dev/null

[root@cent03 ~]# docker service ps service_1
ID                         NAME         IMAGE         NODE    DESIRED STATE  CURRENT STATE          ERROR
1qnqbt5zg1x6sy7wlbkes9pbd  service_1.1  ubuntu:14.04  cent04  Running        Running 1 minute ago

Utworzył się volumen:

[root@cent03 ~]# docker volume ls
DRIVER              VOLUME NAME
rexray              service_1_vol

 

Widoczny również na pozostałych węzłach:

[root@cent03 ~]# ssh 192.168.56.107 „hostname; docker volume ls”
cent05
DRIVER              VOLUME NAME
rexray              service_1_vol

[root@cent03 ~]# ssh 192.168.56.106 „hostname; docker volume ls”
cent04
DRIVER              VOLUME NAME
rexray              service_1_vol

Service posiada liczbę replik = 1 , więc reprezentowany jest przez 1 kontener – w naszym przypadku trafił on na maszynę cent04:

[root@cent03 ~]# docker service ps service_1
ID                         NAME         IMAGE         NODE    DESIRED STATE  CURRENT STATE          ERROR
1qnqbt5zg1x6sy7wlbkes9pbd  service_1.1  ubuntu:14.04  cent04  Running        Running 5 minutes ago

I oczywiście tylko na tej maszynie pojawiło się urządzenie /dev/sciniX (w tym wypadku X=a):

Scaleio21

Po wywołaniu awarii otrzymujemy :

[root@cent04 ~]# service  docker stop
[root@cent04 ~]# ls -l /dev/scini*
crw-r–r–. 1 root root 248, 0 Sep 16 10:31 /dev/scini

Swarm zmigrował usługę na inny węzeł

[root@cent03 ~]# docker service ps service_1
ID                         NAME             IMAGE         NODE    DESIRED STATE  CURRENT STATE               ERROR
6xtmldgw1k9fsqgwgarwu8d01  service_1.1      ubuntu:14.04  cent05  Running        Running about a minute ago
ebj93548ugs7213i2pmhf2n9l   \_ service_1.1  ubuntu:14.04  cent04  Shutdown       Running 2 minutes ago


na którym to węźle oczywiście utworzyło się urządzenie /dev/scinia:

Scaleio22

Stwórzmy zatem jakiś plik w kontenerze i wywołajmy kolejną awarię, a następnie sprawdźmy czy dane ocalały:

Scaleio23

Co stało się powyżej? Sprawdziliśmy istnienie urządzenia /dev/scinia na węźle cent05, wywołaliśmy awarię (via service docker stop), sprawdziliśmy że urządzenie blokowe nagle znikło. Usługa (kontener) została przemigrowana na ostatni żyjący węzeł (cent03) i na nim pojawiło się urządzenie blokowe /dev/scinia . Po zalogowaniu do kontenera okazało się że całą awarię przeżyły nasze dane (czyli PLIK_000). Czyli HA pełną gębą! No prawie…

Na chwilę obecną infrastruktura niestety nie przechodzi testu na awarię hosta.

Zróbmy teraz test całej farmy swarmowej. Na wejściu będą stały ingresowe swarmload-balancery które będą rozmawiały z produkcyjnym kontenerem – niezależnie na którym węźle ten kontener będzie pracował. Podczas symulacji awarii kontener będzie migrował między węzłami ale dane „biznesowe” będzie serwował wciąż te same – end-user nie odczuje różnicy. Dane statyczne (czyli te „biznesowo-ważne”) się nie zmienią (storage pod spodem je przemigruje – jedynie co się zmieni to identyfikator web-serwera (w naszym labie będzie to hostname kontenera)

Najpierw jednak przygotujmy sobie wolumen rexrayowy (nazwijmy go vol_dane) z „danymi biznesowymi” w środku. Potem zrobimy z niego katalog mapowany do każdego kontenera.

Na początku odpalamy w tym celu obraz z ubuntu i w środku tworzymy nasze dane

[root@cent03 tmp]# docker run -ti -v vol_dane:/data  –volume-driver=rexray ubuntu:14.04

root@07619eca55e0:/# cd /data/
root@07619eca55e0:/data# echo „WAZNE i KRYTYCZNE DANE” > plik
root@07619eca55e0:/data# exit

Weryfikujemy czy kolejny kontener z ubuntu widzi dane

[root@cent03 ~]# docker run -ti -v vol_dane:/data  –volume-driver=rexray ubuntu:14.04

root@a2e0a2ea2332:/# cat /data/plik
WAZNE i KRYTYCZNE DANE

root@a2e0a2ea2332:/# exit

Oczywiście wolumen pojawił się na każdym węźle (widoczny z poziomu rexray) :

[root@cent03 ~]# rexray volume ls
– availabilityZone: default
name: vol_dane
size: 16
id: 11497a7100000000
type: default

—

[root@cent05 ~]#  rexray volume ls
– availabilityZone: default
name: vol_dane
size: 16
id: 11497a7100000000
type: default

—

[root@cent04 ~]#  rexray volume ls
– availabilityZone: default
name: vol_dane
size: 16
id: 11497a7100000000
type: default

Sprawdźmy na wszelki wypadek czy dane są widoczne na innym węźle

[root@cent05 ~]# docker run -ti -v vol_dane:/data  –volume-driver=rexray ubuntu:14.04

root@a83136dbbb5b:/# cat /data/plik
WAZNE i KRYTYCZNE DANE

root@a83136dbbb5b:/# exit

 

Jak widać wszytko gra. Wróćmy zatem do naszego web-serwera który ma realizować całą usługę

Musi to być image serwujący po www jakieś „ważne biznesowe dane” które będą migrowane swarmem między węzłami. Oprócz widocznych via www danych biznesowych będzie również widać hostname kontenera który je serwuje. Trzeba zatem stworzyć kontenery które mają zamapowany wolumen z scaleio oraz oprócz jego zawartości pokazują również swój hostname

Oto Dockerfile:

FROM ubuntu:14.04

RUN apt-get -y update && apt-get install -y apache2

CMD apachectl start && hostname > /var/www/html/index.html && cat /data/plik >> /var/www/html/index.html  ; tail -f /dev/null

Budujemy obraz (i np. kopiujemy go na każdy węzeł swarma lub jeśli ktoś ma czas stawiamy private-repo):

[root@cent03 tmp]# docker build -t test_apache .

uruchamiamy kontener z apache mapując wolumen tak aby jego zawartość trafiła do katalogu gdzie apache ma index.html

[root@cent03 tmp]# docker run -tdi -v vol_dane:/data  –volume-driver=rexray test_apache

Sprawdzamy czy faktycznie kontener wrzucił do index.html swój hostname i nasze „biznesowe dane”

[root@cent03 tmp]# docker exec -ti 8e4dfdcc74ef bash
root@8e4dfdcc74ef:/# hostname
8e4dfdcc74ef
root@8e4dfdcc74ef:/# cat /var/www/html/index.html
8e4dfdcc74ef
WAZNE i KRYTYCZNE DANE

Jest ok :)

Co tu zaszło ? Odpalony kontener z apache zamapował sobie nasz wolumen jako /data i zaraz po wrzuceniu do index.html swojego hostname skopiował także (tak jak jest zlecone w Dockerfile) zwartość pliku „plik” do tegoż index.html

Udało się stworzyć mechanizm który uruchamia kolejne kontenery z zachowaniem danych w środku. Oczywiście to zwykłe dockery, migrować po awarii się nie będą. A zatem trzeba przejść na konfigurację w swarmie. Celem jest stworzenie serwisu który zmapuje nasz scaleio-raxray’owy wolumen i zacznie serwować jego dane.

[root@cent03 tmp]# docker service create –replicas 1 –name www –publish 8088:80 –mount type=volume,source=vol_dane,target=/data,volume-driver=rexray test_apache
57j6dtlrp38avacl6kac4fhxp

[root@cent03 ~]# docker service ls
ID            NAME  REPLICAS  IMAGE        COMMAND
b4fag0y6brsj  www   1/1       test_apache

[root@cent03 ~]# docker service ps www
ID                         NAME   IMAGE        NODE    DESIRED STATE  CURRENT STATE          ERROR
b7tq1p3a0ch056v96wr3qvrqq  www.1  test_apache  cent05  Running        Running 2 minutes ago

[root@cent03 ~]#

Na węźle cent05 faktycznie uruchomił się kontener:

[root@cent05 tmp]# docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS               NAMES
88839d1ef279        test_apache:latest   „/bin/sh -c ‚apachect”   3 minutes ago       Up 3 minutes                            www.1.b7tq1p3a0ch056v96wr3qvrqq

Jak wiadomo z teorii na każdym węźle swarm otworzył port 8088 i można przez ten port sięgać po dane:

[root@cent04 tmp]# curl 127.0.0.1:8088
88839d1ef279
WAZNE i KRYTYCZNE DANE

[root@cent04 tmp]#

[root@cent05 tmp]# curl 127.0.0.1:8088
88839d1ef279
WAZNE i KRYTYCZNE DANE

[root@cent05 tmp]#

Serwuje je jednakowoż jeden kontener – ten z węzła cent05 (jego hostname to 88839d1ef279). Czas wyłączyć węzeł cent05 (via „service docker stop”). Po chwili widzimy że swarm przerzucił usługę na węzeł cent04:

[root@cent03 ~]# docker  service  ps www
ID                         NAME       IMAGE        NODE    DESIRED STATE  CURRENT STATE           ERROR
70fxd74x6ckryl3x71yr8x6og  www.1      test_apache  cent04  Running        Starting 1 seconds ago
b7tq1p3a0ch056v96wr3qvrqq   \_ www.1  test_apache  cent05  Shutdown       Running 5 minutes ago

Gdy sprawdzimy curlem (obojętnie z którego węzła byle nie z tego który zaliczył „awarię”) zawartość www otrzymujemy:

[root@cent04 tmp]# curl 127.0.0.1:8088
1c843995943c
WAZNE i KRYTYCZNE DANE

Jak widać hostname kontenera serwującego dane się zmienił ale nasze dane biznesowe zostały przerzucone na inną maszynę. Oczywiście rexray i scale-io przemapowały wolumen z danymi na węzeł który teraz świadczy usługę (ip końcówka 106):

Scaleio24

Podsumowanie

Jak do tej pory docker dorobił się całkiem sprawnych i nowoczesnych mechanizmów dla load-balancingu, service-discovery czy networkingu. Jeśli chodzi o storage niestety bardzo dużo jeszcze brakuje. Jednak jeśli zastosujemy driver rex-ray który pod spodem wysteruje farmą SDS i SDC scale-io jesteśmy w stanie osiągnąć w miarę kuloodporny i pancerny landscape. Pozostaje moim zdaniem jednak zaczekać co powie docker w którejś z przyszłych wersji silnika. Myślę, że pojawienie się natywnego drivera do storage-HA to tylko kwestia czasu.

 
Sławomir Wolak, Kierownik Zespołu Utrzymania Serwerów i Systemów Operacji, Raiffeisen Polbank