Changes

Docker volume orchestration

8,726 bytes added, 20:16, 17 February 2019
Swarm service
Az úgynevezett volume orkesztráció kulcsfontosságú a konténeres cluster építésben. Orchestration alatt azt érjük, hogy a több VM-en futó, sok konténerből álló cluster-en az egyes konténerek (amiket "random" telepít fel a swarm valamelyik szabad kapacitású VM-re) hogyan férnek hozzá a futásukhoz szükséges perzisztens tárolóhoz, ahol a konfigurációs állományuk van. Pl. a Portainer-nek hozzá kell férnie egy olyan perzisztens tárolóhoz, ahol az adatbázisát, beállításait tárolni tudja. Ha a Portainer-t swarm service-ként telepítjük fel, akkor nem tudjuk előre megmondani, hogy a swarm melyik node-ra fogja feltelepíteni. Bárhova is telepíti föl, ott rendelkezésre kell álljon a neki szükséges perzisztens állomány. Két fő csapásirány közül választhatunk:
===Network file share on the Mount VMfileshare to container===Valamilyen network file system-et mount-unk minden egyes VM-re, ami részt vesz a cluster-ben. (pl NFS vagy Samba). Aztán a VM-en létrejött megosztásnak a tetejére NFS vagy Samba megosztásra mount-oljuk a konténer megfelelő egyik mappáját'''bind moun'''t-al. Ezzel több baj is van, ez produckicós környezetben csak nagyon kis cluster-en működőképes. # Egy bizonyos cluster méret felett nem igazán lehet ugyan azt a network megosztást (pl NFS) minden egyes VM-re mount-olni (sávszélesség, sebesség, erőforrás igény) # Mivel a swarm "random" módon telepíti fel a konténereket, a VM-ek és nem is lesz szükség egyáltalán a megosztásra, feleslegesen foglalja majd ez az erőforrást. Tehát ez így nagyon favágó ajánlott módszer. (Mivel nem tudjuk hol lesz tegyük oda mindenhova) 
===docker volume plugin===
Használhatunk úgynevezett '''docker volume plugin'''-eket, amik lehetőév teszik, hogy on-demand alapon közvetlen a konténerre mount-oljuk föl a network fájlrendszer megfelelő megosztását(Pl Netshare vagy REX-ray) vagy a VM-re mount-olt network megosztást használhassuk volume-ként a konténer számára transzparnes módon (Pl Convoy ) . Nagyon sokféle volume plugin elérhető a docker-hez, amikkel NFS, AWS, Azure és még sok más network fájlrendszert tudunk közvetlen a konténerbe bekötni. A volume plugin használatakor pont úgy kell megadni a volume-ot mint ha az a lokális VM-en lenne. A plugin elfedi előlünk a network filesystem-hez való csatlakozás komplexitását.
Mikor egy volume-ot megadunk akár a '''docker run''', akár a '''docker service create''' parancsban, akkor igazából mindig megadjuk a volume driver típusát a '''volume-driver''' paraméterben. Ha külön nem definiáljuk, akkor a '''local''' driver-t fogja használni, amivel a volume a lokális VM-en fog létrejönni. Ha nem a lokális driver-t akarjuk használni, akkor két dolgunk van.
# Fel kell telepíteni a kiválasztott volume plugin-t.
# A service definiálásakor a mount parancsban meg kell adni a '''volume-driver ''' paraméterrel a használni kívánt driver nevét.
Mivel Lista az elérhető hivatalosan támogatott plugin-ekről: https://docs.docker.com/engine/extend/legacy_plugins/ <br>Bizonyos pluginek benne fent vannak a docker hub-on, így a '''docker plugin install''' paranccsal automatikusan telepíthetőek.   ===Volume plugin vs storage driver===A '''docker volume plugin'''-eket nem szabad összekeverni a megosztás '''storage driver''' témakörrel (https://docs.docker.com/storage/storagedriver/#copying-makes-containers-efficient). A '''storage driver'''-ek a konténer tetején található vékony írható réteget kezelik, míg a volume plugin-ek a konténerbe felcsatolt volume-ok kezeléséért felelősek.  A konténerek felső vékony írható rétege nem perzisztens, az csak azon arra való, hogy a VMkonténer futása közben módosított image fájlokat tárolja vagy az esetlegesen létrehozott új fájlokat, amik benne sem voltak az image-en jön létreban. Mikor a konténer hozzá akar férni vagy módosítani akar egy fájlt, akkor a '''storage driver''' megpróbálja azt megkeresni a konténert felépítő (nem írható) image rétegekben fentről lefelé. Azt hogy ezt pontosan milyen algoritmussal csinálja, ahol tényleg szükség és hogy milyen hatásfokkal az a storage driver-től függ.  Ez a vékony írható réteg csak "gyenge" írási terhelésre van kitalálva, ez semmi képen sem arra, hogy egy adatbázis kezelő ott tárolja az egyetlen járható út nagyobb clusteradatbázis fájlokat. Erős írási terhelésre kifejezetten a docker volume-okat kell használni tipikusan valamelyik volume plugin-al együtt.   Elérhető storage diver-ek esetében: '''aufs, devicemapper, overlay2, vfs'''<br>Az alapértelmezett az overlay2.<br><br>
=NFS mount on the VM=
Az itt leírtaknak még semmi köze a docker volume plugin-ekhez. Itt annyit mutatok be, hogy lehet minden egyes VM-re felcsatolni ugyanazt az NFS megosztást. Ez egy jó kiindulási alap. A guest VM-ekre felcsatolt NFS megosztásokat kétféle képen használhatják a konténerek:
* Tovább mount-oljuk a konténer belsejébe b'''ind mount'''-al a megosztást (csak tesztelési célra, kis méretű cluster-ekre)
* A megfelelő docker volume diver plugin-el volume-okat hozunk létre az NFS megosztáson a konténer számára transzparens módon. (Convoy plugin)
 
 
A következőkben KVM/qemu VM-en futó boot2docker Lunux-ra fogunk felcsatolni egy NFS megosztást. A példában a Portainer service számára fogunk létrehozni egy megosztást, ahol a /data mappáját perzisztens módon tudja tárolni, amiben a beállítások és felhasználó adatok vannak.
 
==NFS szerver telepítése==
 
Elsőként a host gépen (vagy bárhol máshol, amit elérnek majd a VM-ek) hozzunk létre egy NFS megosztást.
<pre>
# dnf install -y nfs-utils
# systemctl enable nfs
# systemctl restart nfs
</pre>
A host gép tűzfalán az alábbi portokat kell kinyitni:
* '''2049''' - udp + tcp
* '''111''' - udp + tcp
Ha a GUI tűzfal szerkesztőben csak a Permanent beállítások közé vesszük fel, akkor újra kell indítani a tűzfalat vagy a gépet. Ha a Runtime-ba is felvesszük, akkor azonnal érvényre jut. (A 'No route to host' tipikusan tűzfal hibára vall)
 
 
 
A NFS szerver konfigurációs fájlja a '''/etc/exports''' . Ebbe egy sort kell csak belerakjunk:
<pre>
/home/adam/docker/portainer/data/ 192.168.42.0/255.255.255.0(rw,sync,no_root_squash,no_subtree_check)
</pre>
Vagyis, hogy a /home/adam/docker/portainer/data/ mappának a megosztását megengedjük a 192.168.42. -ás alhálózaton
 
 
Töltsük újra a NFS fájlt:
<pre>
# exportfs -ra
</pre>
 
 
Majd nézzük meg, a showmount paranccsal hogy a szerverünk valóban kiajánlja e a fenit mappát:
<pre>
# showmount -e 192.168.42.1
Export list for 192.168.42.1:
/home/adam/Projects/DockerCourse/portainer/data 192.168.42.0/255.255.255.0
</pre>
 
 
==NFS kliens beállítása==
Az összes node-on mount-olni kell az előbb létrehozott NFS megosztást, amiben a Portainer a perzisztens adatait fogja tárolni. Ehhez be kell lépni SSH-val egyenként az összes node-kora és ott futtatni kell a megfelelő '''mount''' parancsot.
 
{{note|KVM driver által telepített '''boot2docker''' Linux-okon csak a '''/var/lib/boot2docker''' mappa tartalma boot perzisztens, minden máshol történt módosítást ki fog dobni újraindításkor}}
 
===Kézi mount===
A boot2docker-ben az NFS mount-nak speciális szerkezete van, leírás itt: https://gist.github.com/leeor/e70419fd7f656ca4bff3<br>
Mivel a boot2docker-ben csak a '''/var/lib/boot2docker/''' tartalma boot perzisztens, ezen a mappán belül hozzuk létre a portainer számára azt a mappát ahova az NFS megosztást fel fogjuk csatolni.
<pre>
sudo mkdir /var/lib/boot2docker/portainerdata
sudo /usr/local/etc/init.d/nfs-client start
sudo mount 192.168.42.1:/home/adam/docker/portainer/data/ /var/lib/boot2docker/portainerdata -o rw,async,noatime,rsize=32768,wsize=32768,proto=tcp
</pre>
A második parancs elindítja az NFS klienst a mount előtt.
(normál esetben a mount így nézne ki: ''mount -t nfs source target'')
 
 
Ha ez működik, akkor az utolsó két sort írjuk be a '''/var/lib/boot2docker/profile''' fájlba, ami a docker user-hez tartozó profile-ja, hogy boot perzisztensé tegyük a mount-ot. Fontos, hogy a profile fájlt csak akkor tudjuk írni, ha előtte 777 jogot adunk rá még akkor is ha sudo-t használunk. Ki érti ezt?!
 
 
===Automatizált mount script-el===
 
'''mountNFS.sh'''
<source lang="sh">
#!/bin/bash
 
# Usage: ./mountNFS.sh machine-name
 
machineName=$1
 
PORTA_HOST_DIR='/home/adam/docker/portainer/data'
PORTA_GUEST_DIR='/var/lib/boot2docker/portainerdata'
PORTA_MOUNT_OPT='-o rw,async,noatime,rsize=32768,wsize=32768,proto=tcp'
 
#Mount NFS for this session
docker-machine ssh $machineName sudo mkdir /var/lib/boot2docker/portainerdata
docker-machine ssh $machineName sudo /usr/local/etc/init.d/nfs-client start
docker-machine ssh $machineName sudo mount 192.168.42.1:$PORTA_DATA_DIR $PORTA_GUEST_DIR $PORTA_MOUNT_OPT
 
#Make the NFS mount boot persistent
docker-machine ssh $machineName sudo chmod 777 /var/lib/boot2docker/profile
docker-machine ssh $machineName "echo 'sudo /usr/local/etc/init.d/nfs-client start'"
docker-machine ssh $machineName "echo 'sudo mount 192.168.42.1:$PORTA_DATA_DIR $PORTA_GUEST_DIR $PORTA_MOUNT_OPT' >> /var/lib/boot2docker/profile"
 
</source>
 
==Portainer telepítése==
A portainer-t swarm service-ként fogjuk telepíteni. Ki fogjuk kötni hogy csak manager node-ra telepítheti a swarm, tehát biztos, hogy az előbb létrehozott mg0, mg1 és mg2 valamelyikén fog landolni. Fontos, hogy megadjuk, hogy csak egy példány jöhessen belőle létre. Két fontos mount-ot kell beállítani:
# '''/data''': ezt a guest VM /var/lib/boot2docker/portainerdata mappájába fogjuk felcsatolni, ahova az NFS megosztás mount-olva van.
# '''/var/run/docker.sock''': ezt a guest VM docker socket-jére kell rákötni, hogy a portainer hozzáférjen a docker/swarm adatokhoz és tudja is módosítani azokat.
 
<pre>
eval $(docker-machine env mg0)
 
docker service create \
--name portainer \
--publish 9000:9000 \
--replicas=1 \
--constraint 'node.role == manager' \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=bind,src=/var/lib/boot2docker/portainerdata,dst=/data \
portainer/portainer -H unix:///var/run/docker.sock
</pre>
{{note|A '''/var/lib/boot2docker/portainerdata''' VM mappába mount-oltuk a távol NFS megosztás '''/home/adam/docker/portainer/data''' mappáját, és erre mount-oltuk rá a swarm service-ben a portainer '''/data''' mappáját}}
<br>
=Netshare=
 
==Bemutatás==
http://netshare.containx.io/
:[[File:ClipCapIt-180830-002410.PNG]]
Mount A Netshare docker plugin-el háromféle network fájlrendszert mount-olhatunk közvetlen a docker konténerekbe. Ezek: * NFS v3/4, * AWS EFS or * CIFS
A Netshare a legegyszerűbb az itt bemutatott megoldások közül. Nem kell telepíteni, nem rendelkezik parancssoros interfésszel sem.  Támogat több docker cluster eszközt is: Mesos/Marathon and és Docker Swarm
==Installálás a boot2docker VM-en==
nfs.sock
</pre>
 
 
==Docker standalone==
 
<pre>
# docker run -i -t --name ubuntu --volume-driver=nfs -v 192.168.42.1/home/adam/Projects/DockerCourse/persistentstore/portainer/data/:/data ubuntu /bin/bash
</pre>
 ===Volume létrehozása===<pre># docker volume create -d nfs --name portainerdata -o share=192.168.42.1:/home/adam/Projects/DockerCourse/persistentstore/portainer/dataportainerdata</pre> <pre># docker volume lsDRIVER VOLUME NAMEnfs portainerdata</pre> Majd mount-oljuk föl az új nevesített volume-ot: <pre># docker run -i -t --name ubuntu --volume-driver=nfs -v portainerdata:/data ubuntu /bin/bashroot@5e82828c7a37:/#</pre>
==Swarm service==
--constraint 'node.role == manager' \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=volume,volume-driver=nfs,src=192.168.42.1/home/adam/Projects/DockerCourse/persistentstore/portainer/data/,dst=/data,volume-driver=nfs \
portainer/portainer -H unix:///var/run/docker.sock
</pre>
docker-machine ssh $machineName "sudo tar -xvzf docker-volume-netshare_0.35_linux_amd64.tar.gz"
docker-machine ssh $machineName "sudo mv docker-volume-netshare_0.35_linux_amd64 /var/lib/boot2docker/"
docker-machine ssh $machineName "sudo mv chmod 777 /var/lib/boot2docker/docker-volume-netshare_0.35_linux_amd64 /var/lib/boot2docker/netshare"docker-machine ssh $machineName "sudo chmod 777 /var/lib/boot2docker/netshare/"
#Start NFS during system start up
docker-machine ssh $machineName "sudo chmod 777 /var/lib/boot2docker/profile"
docker-machine ssh $machineName "sudo echo 'cd /var/lib/boot2docker/netsharedocker-volume-netshare_0.35_linux_amd64' >> /var/lib/boot2docker/profile"
docker-machine ssh $machineName "sudo echo 'sudo nohup ./docker-volume-netshare nfs -v 3 &' >> /var/lib/boot2docker/profile"
#Restart the sytem for the modifications to take effect
#docker-machine restart $machineName
virsh shutdown $machineName
sleep 20s
virsh start $machineName
</source>
{{note|Fontos, hogy '''shutdown'''-al állítsuk le a VM-et, ne '''destroy'''-al (force off), mert akkor nem fogja tudni a boot2docker elmenteni a változtatásokat, és a netshare installációnk el fog veszni.}}
Sajnos a '''docker-machine ssh machine command''' paranccsal nem lehet valamiért elindítani a '''netshare'''-t. Tehát ez a formula nem működik:
installNetshare.sh futtatása az összes node-on.
<source lang=sh>
for machine in $(docker-machine ls -q); do
./installNetshare.sh $machine
done
</source>
 
 
Ellenőrizzük, hogy minden node-on elindult e a plugin:
<pre>
# docker-machine ssh mg0 ps -ef | grep netshare
1793 root ./docker-volume-netshare nfs -v 3
1833 root ./docker-volume-netshare nfs -v 3
</pre>
<br>
=Convoy=
https://github.com/rancher/convoy
 
A Convoy 4 féle volume kezelést támogat:
* Device Mapper
* NFS
* Amazon EBS
* Digital Ocean
 
 
Az NFS kezelése eltér a Netshare plugin-nál látottaktól, ugyanis nem közvetlen a konténerbe csatolja fel megosztást. A guest VM-en létre fel kell csatolni egy NFS megosztást, ahol a Convoy a volume-okat fogja tárolni a konténer számára transzparens módon.
=REX-Ray=