Differences

This shows you the differences between two versions of the page.

Link to this comparison view

idp:laboratoare:03 [2021/03/18 06:32]
radu.ciobanu [Arhitectura Docker Swarm]
idp:laboratoare:03 [2023/04/10 20:40] (current)
radu.ciobanu
Line 1: Line 1:
-===== Laboratorul 03 - Docker Swarm =====+===== Laboratorul 03 - Persistență în Docker Swarm și Kong =====
  
-==== Introducere ====+<note tip>​Exemplele din acest laborator se găsesc pe [[https://​gitlab.com/​mobylab-idp/​laborator3|repository-ul materiei]].</​note>​
  
-În acest laborator, vom face tranziția de la Docker Compose la Docker Swarm, **//​orchestratorul de servicii//​** oferit de Docker. Acesta are rolul de a gestiona servicii de Docker pe una sau mai multe mașini într-o rețea (într-un cluster) de mașini fizice și/sau virtuale. Spre deosebire de Docker Compose, care rulează containere pe o singură gazdă, Docker Swarm rulează //​**servicii**//​ între mai multe gazde. La fel ca și Compose, ​Docker Swarm folosește fișiere de configurare YAML.+==== Persistență în Docker Swarm ====
  
-==== Arhitectura ​Docker Swarm ====+În contextul ​Docker Swarm, nu mai există o singură gazdă, ci multiple noduri conectate în rețea. Acest lucru face ca folosirea volumelor locale să nu fie recomandată,​ deoarce orchestrarea unui task pe un nod care nu are volumul cerut de container va rezulta în respingerea acelui task.
  
-Docker Swarm se bazează pe algoritmul distribuit [[https://​raft.github.io|Raft]],​ cu ajutorul căruia se menține consistentă starea internă ​întregului clusterÎn plus, traficul dintre nodurile din Swarm este criptat de către Raft. În imaginea de mai jos (preluată din [[https://​docs.docker.com/​engine/​swarm/​how-swarm-mode-works/​nodes/​|documentația oficială]]),​ se poate observa arhitectura unui cluster Docker Swarm.+Există două posibilități principale de rezolvare ​acestei problemePrima variantă presupune constrângerea unor servicii astfel încât să ruleze doar pe noduri manager, astfel:
  
-{{:idp:laboratoare:swarm-diagram.png?600|}}+<code yaml> 
 +services: 
 +    example: 
 +        deploy: 
 +            placement:​ 
 +                constraints:​ [node.role == manager] 
 +</​code>​
  
-Mașinile gazdă care fac parte dintr-un Swarm se numesc **//​noduri//​** și pot avea două roluri: +Această practică este utilă doar atunci când există un singur nod manager și astfel suntem siguri că taskurile ale căror containere au nevoie de volumele definite ​în configurație vor rula doar pe managerul unde exista volumele.
-  * manager ​- rol administrativ ​și funcțional;​ menține consistența clusterului,​ lansează în execuție servicii, expune endpoint-uri de rețea +
-  * worker - rol funcțional;​ execută serviciile.+
  
-Dintre toate nodurile ​manager, ​un singur nod este **//​leader//​**care are rolul de a crea task-uri și de a face loggingTask-urile sunt distribuite apoi nodurilor manager.+În cazul în care există mai multe noduri ​manager ​și dorimde exemplusă rulăm o bază de date într-un serviciu, dacă aceasta va fi orchestrată să ruleze pe alt nod față ​de cel pe care a fost prima oară orchestrată,​ nu va mai avea acces la volumul unde stocat date inițialÎn acest caz, va crea un volum nou pe noul nod, ajungându-se astfel la inconsistență.
  
-<note important>​Întotdeauna trebuie ​să existe ​un nod leader.</​note>​+Cea de-a doua variantă pentru a rezolva problema descrisă mai sus este configurarea volumelor astfel încât ​să folosească ​un sistem de stocare extern (cum ar fi NFS, GlusterFS, Samba, Amazon S3, etc.).
  
-<​note ​tip>Deoarece toleranța este de (N - 1) / 2 noduri manager picateeste indicat ​să avem un număr impar de noduri ​și un număr impar de manageri. ​Docker ​recomanda 35 sau 7 manageri.</​note>​+<​note ​important>Din păcateinfrastructura de Play with Docker nu permite realizarea unui demo practic care să ilustreze folosirea volumelor cu stocare externă, având limitări la nivel de comunicație inter-mașini. Totuși, dacă aveți acces la un cluster ​de mașini ​Docker, ​vă recomandăm să încercați să vă configurați o stivă de servicii care folosește volume cu stocare externă.</​note>​
  
-==== Crearea unui Docker Swarm ====+=== NFS ===
  
-Odată ce avem un cluster ​de mașini pe care rulează Docker, ​ne putem inițializa un Docker Swarm. Astfelputem rula următoarea comandă pe nodul care va fi leader ​(opțiunea //**--advertise-addr**// este necesară atunci când nodul are mai multe interfețe de rețea și trebuie specificat ​pe care din ele se face advertising):​+Cea mai facilă metodă de a adăuga stocare externă în Docker ​este prin intermediul NFS (Network File System). Pentru aceastaeste în primul rând nevoie de existența unui server NFS, care poate fi rulat fie nativ (pe una din mașinile din cluster-ul Docker sau undeva în exterior), fie prin intermediul unui container Docker. Există multiple soluții de rulare a unui server NFS folosind Docker, însă noi vă recomandăm [[https://​hub.docker.com/​r/itsthenetwork/nfs-server-alpine/|această soluție populară]] bazată ​pe Alpine Linux.
  
-<code bash> +Soluția de mai sus reprezintă un container care rulează în mod privilegiat,​ având acces la resursele gazdeiÎnainte să rulați containerul,​ trebuie să vă creați un director ce va fi partajat în rețea prin intermediul NFS.
-$ docker swarm init --advertise-addr 192.168.99.100+
  
-Swarm initialized:​ current node (qtyx0t5z275wp46wibcznx8g5) is now a manager. +<note important>​Directorul partajat trebuie să nu fie de tipul OverlayFS.</note>
-To add a worker to this swarm, run the following command: +
-    docker swarm join --token SWMTKN-1-4hd41nyin8kn1wx4bscnnt3e98xtlvyxw578qwxijw65jp1a3q-32rl6525xriofd5xmv0c1k5vj 192.168.99.100:​2377 +
-To add a manager to this swarm, run '​docker swarm join-token manager'​ and follow the instructions. +
-</code>+
  
-<note tip>Așa cum se poate observa, ​comanda ​de mai sus generează alte două comenzi ​pe care le putem folosi pentru a introduce alte noduri în cluster, atât ca worker, cât și ca manager.</​note>​+<note tip>Pentru a vedea sistemul de fișiere, se poate executa ​comanda ​''​%%df -Th%%''​ (pe Linux).</​note>​
  
-Putem verifica dacă swarm-ul fost creat cu succes dând comanda de mai jos pe mașina leader (unde avem două noduri numite //​**node1**// ​și //​**node2**//,​ primul din ele fiind leader, iar al doilea worker):+Dupa ce s-a creat directorul ce va reține datele partajate în rețea, se execută ​comanda de mai jos pentru pornirea serverului de NFS și exportul directorului partajat:
  
 <code bash> <code bash>
-$ docker ​node ls+$ docker ​run -d --name nfs --privileged -v /​cale/​director/​partajat:/​nfsshare \ 
 +      -e SHARED_DIRECTORY=/​nfsshare itsthenetwork/​nfs-server-alpine:​latest 
 +</​code>​
  
-ID                            HOSTNAME ​           STATUS ​             AVAILABILITY ​       MANAGER STATUS +În comanda de mai sus, directorul pe care dorim să-l partajăm se află la calea //**/​cale/​director/​partajat**//,​ fiind mapat pe serverul NFS la calea //​**/​nfsshare**//​. Odată ce serverul NFS a fost pornit, se pot crea volume peste NFS în mai multe moduri. O variantă este crearea de volume prin intermediul API-ului din linia de comandă. Astfel, dacă se dorește crearea unui volum numit //​**mynfsvol**//,​ care apoi poate fi atașat la alte containere sau servicii, se poate executa următoarea comandă: 
-qtyx0t5z275wp46wibcznx8g5 ​  node1               ​Ready ​              ​Active ​             Leader + 
-0xbb9al1kuvn0jcapxiqni29z ​    ​node2 ​              ​Ready ​              ​Active ​     +<code bash> 
 +$ docker volume create --driver local --opt type=nfs --opt o=nfsvers=3,​addr=192.168.99.1,​rw \ 
 +      ​--opt device=:/​nfsshare mynfsvol
 </​code>​ </​code>​
  
-==== Servicii ​și stive de servicii Docker ====+În comanda de mai sus, IP-ul serverului NFS este 192.168.99.1 ​și se folosește versiunea 3 de NFS. Se poate inspecta volumul nou-creat pentru a se observa caracteristicile sale:
  
-Atunci când vorbim de deployment-ul unei aplicații în Docker Swarm, trecem de la noțiune de container la noțiunea de serviciu. Un serviciu Docker reprezintă o colecție de task-uri (unul sau mai multe)iar un task reprezintă un container. Așadarun serviciu este format din unul sau mai multe containere identice. Serviciul controlează ciclul de viață al containerelorîncercând întotdeauna să mențină starea containerelor oferite în configurație. Cu alte cuvinte, un serviciu reprezintă un set de containere cu //**orchestrare**//.+<code bash> 
 +$ docker volume inspect mynfsvol 
 +
 +    { 
 +        "​CreatedAt":​ "2021-03-31T17:​26:​11Z"​, 
 +        "​Driver":​ "​local"​, 
 +        "​Labels":​ {}, 
 +        "​Mountpoint":​ "/mnt/sda1/var/lib/​docker/​volumes/​mynfsvol/​_data",​ 
 +        "​Name":​ "​mynfsvol",​ 
 +        "​Options":​ { 
 +            "​device":​ ":/​nfsshare",​ 
 +            "​o":​ "​nfsvers=3,​addr=192.168.99.1,​rw",​ 
 +            "​type":​ "​nfs"​ 
 +        }, 
 +        "​Scope":​ "​local"​ 
 +    } 
 +
 +</​code>​
  
-Mai departe, o stivă de servicii reprezintă mai multe astfel de servicii grupate în același spațiu de nume. Putem vizualiza o stivă de servicii ​ca fiind o aplicație Docker formată ​din mai multe servicii. Cel mai facil mod de a defini o stivă de servicii este prin intermediul unui fișier Docker Composeașa cum am văzut în [[idp:laboratoare:​02|laboratorul 2]]. Comportamentul serviciilor dintr-o stivă este similar cu cel al containerelor din Docker Compose, doar că politica de denumire este diferită.+Un astfel de volum extern poate fi dat ca parametru la pornirea unui container ​din linia de comandă, astfel:
  
-<note tip>Orice entitate creată într-o stivă (serviciu, volum, rețea, secret) va fi prefixată de **//NUME-STIVA_//**.</note>+<code bash> 
 +$ docker run -v mynfsvol:/test -it alpine 
 +</code>
  
-Docker Swarm are acces la o colecție nouă de opțiuni în cadrul fișierului YML de Composece vor fi trecute în proprietatea [[https://docs.docker.com/compose/compose-file/​compose-file-v3/#​deploy|deploy]] a unui serviciuImaginea de mai jos prezintă ​un fragment ​de fișier Docker Compose ​unde se exemplifică o parte din aceste opțiuni noi:+În comanda ​de mai susse mapează volumul NFS la calea //**/test**// din interiorul containeruluiAcest lucru se poate face simultan pe mai multe containere de pe mașini diferite, toate având aceeași mapare și deci acces la aceleași fișiere. 
 + 
 +Putem folosi ​un volum creat în linia de comandă chiar într-un ​fișier ​de Docker Compose, fie la rularea locală, fie la rularea folosind Docker Swarm. Pentru acest lucru, este nevoie de câteva modificări în configurația volumelor ​din cadrul fișierelor YAML. Ca exemplu, presupunem că avem un serviciu de bază de date care are nevoie de volume pentru scriptul de configurație și pentru persistența datelor (pe modelul temelor de casă din laboratoarele precedente):
  
 <code yaml> <code yaml>
-[...] 
 services: services:
-  web+    db
-    image: ​myimage +        image: ​postgres:12 
-    deploy+        ​volumes
-      ​replicas4 +            - db-data-nfs:/​var/​lib/​postgresql/​data 
-      ​resources+            - db-config-nfs:/​docker-entrypoint-initdb.
-        ​limits: + 
-          cpus: "0.2" +volumes
-          ​memory50M +    ​db-data-nfs
-      ​restart_policy+        ​externaltrue 
-        ​conditionon-failure +    db-config-nfs: 
-[...]+        ​external:​ true
 </​code>​ </​code>​
  
-În fragmentul de fișier YAML de mai sus, se rulează un serviciu numit //**web**// care are patru copii. Astfel, vor exista patru containere diferite care rulează imaginea ​//**myimage**//, oricare din ele putând răspunde la cereri pentru serviciul //​**web**//, ​în funcție de încărcare. De asemeneafiecare instanță este limitată la 20% CPU (pe toate core-urile) ​și 50 MB de RAM. Nu în ultimul rândun container al serviciului //**web**// se restartează imediat ce întâlnește o eroare (scopul final fiind cala orice moment de timpsă existe 4 copii ale containerului în rețea).+În exemplul ​de mai sus, se presupune că volumele ​//**db-data-nfs**// și //**db-config-nfs**// au fost create în prealabil folosind comenzile prezentate anterior. Este totuși posibil să se creeze volumele direct ​în fișierul Docker Composeașa cum s-a prezentat ​și în laboratoarele precedente. În acest cazvolumele nu vor mai fi declarate ca fiind externeci trebuie configurate pentru a funcționa peste NFSastfel:
  
-=== Rețele Swarm ==+<code yaml> 
 +volumes: 
 +    db-data-nfs:​ 
 +        driver: local 
 +        driver_opts:​ 
 +           type: nfs 
 +           o: "​nfsvers=3,addr=192.168.99.1,​nolock,​soft,​rw"​ 
 +           ​device:​ :/​database/​data 
 +    db-config-nfs:​ 
 +        driver: local 
 +        driver_opts:​ 
 +           type: nfs 
 +           o: "​nfsvers=3,addr=192.168.99.1,​nolock,​soft,​rw"​ 
 +           ​device:​ :/​database/​config 
 +</​code>​
  
-Spre deosebire ​de Docker clasic ​și Composerețelele create ​în Swarm nu mai sunt de tip bridge, ci de tip **//overlay//**. O rețea de tip overlay este o rețea care se întinde peste toate nodurile dintr-un swarm. Din acest motiv, porturile publice expuse vor fi unice per rețea. Așadar, nu pot fi expuse două porturi 3000 din două servicii diferite care se conectează la aceeași rețea overlay.+În exemplul ​de mai sus, s-a folosit același IP pentru serverul NFS (192.168.99.1)iar directoarele //​**/​database/​data**//​ și //​**/​database/​config**//​ trebuie să existe //**în interiorul**//​ directorului partajat ​de gazda containerului ​de server NFS (//**/cale/director/partajat**// din exemplul de pornire a serverului NFS).
  
-<note tip>​Docker Swarm realizează balansare ​încărcării la nivelul rețelei.</​note>​+O altă modalitate de adăuga persistență folosind NFS ar fi montarea directoarelor de NFS pe toate nodurile (sau pe toți managerii) din cluster, și apoi utilizarea de bind mounts pentru a mapa căile de NFS montate local în interiorul serviciilor Docker.
  
-Un serviciu la care s-a făcut deploy pe un anumit port totdeauna va avea acel port rezervat, indiferent pe ce nod rulează de fapt containerul sau containerele sale. Diagrama de mai jos (preluată din [[https://​docs.docker.com/​engine/​swarm/​ingress/​|documentația oficială]]) prezintă o situație în care avem un serviciu numit //​**my-web**//​ publicat pe portul 8080 într-un swarm cu trei noduri. Se poate observa că, dacă ne conectăm pe portul 8080 de pe oricare adresă IP de nod din swarm, vom fi redirecționați către un container care rulează serviciul specific portului extern 8080, indiferent de nodul pe care rulează.+<​hidden>​== Docker Machine NFS ==
  
-{{:idp:laboratoare:​network.png?600|}}+În cazul se folosește Docker Machine pentru gestiunea unui cluster de mașini virtuale, trebuie avut în vedere că aceste mașini vor avea [[http://​www.tinycorelinux.net|Tiny Core Linux]] ca sistem de operare, care folosește propriul package manager (numite //​**tce**//​) care descarcă pachete pre-compilate din repository-urile proprii. Din acest motiv, o modalitate mai facilă de a lucra cu NFS în Docker Machine este folosirea utilitarului [[https://github.com/​adlogix/​docker-machine-nfs|Docker Machine NFS]]. Acesta permite montarea de directoare NFS în noduri Docker Machine prin comenzi de forma următoare:
  
-=== Secrete Swarm ===+<code bash> 
 +$ docker-machine-nfs myvm1 --shared-folder=/​database/​config --shared-folder=/​database/​data -f 
 +</​code>​ 
 +</​hidden>​
  
-Secretele din Swarm trebuie create înainte ​de fi rulată configurațiaPutem folosi ​următoarea comandă:+=== GlusterFS === 
 + 
 +[[https://​www.gluster.org|GlusterFS]] este un sistem ​de fișiere de rețea open-source,​ utilizat pentru stocare în cloud sau streaming mediaPentru a putea folosi ​volume peste GlusterFS, este necesară instalarea și configurarea sa pe fiecare nod din cluster. În continuare, sunt prezentate comenzile necesare instalării pe un sistem bazat pe Ubuntu:
  
 <code bash> <code bash>
-docker secret create mysecret file.txt+apt-get install software-properties-common -y 
 +</​code>​
  
-fm49ig0i8x9pdq0xxa8wdchoy+<code bash> 
 +$ add-apt-repository ppa:​gluster/​glusterfs-3.12
 </​code>​ </​code>​
- 
-Putem lista secretele existente astfel: 
  
 <code bash> <code bash>
-docker secret ls+apt-get update 
 +</​code>​
  
-ID                          NAME       ​DRIVER ​   CREATED ​        ​UPDATED +<code bash> 
-fm49ig0i8x9pdq0xxa8wdchoy ​  ​mysecret ​            3 seconds ago   3 seconds ago+$ apt install glusterfs-server -y
 </​code>​ </​code>​
  
-Secretele din Swarm sunt criptate în Raft și deci este recomandat să fie folosite în producție.+Odată instalat, GlusterFS se pornește cu următoarele comenzi:
  
-=== Diferențe între Docker Swarm și Docker Compose ===+<code bash> 
 +$ systemctl start glusterd 
 +</​code>​
  
-Exista câteva diferențe între Swarm și Compose la nivelul fișierelor declarative YAML: +<code bash> 
-  * deoarece Swarm rulează servicii în rețea, nu poate exista cuvântul-cheie **//​build//​**;​ serviciile trebuie obligatoriu să fie rulate pe baza unor imagini deja existente într-un registru +$ systemctl enable glusterd 
-  * stivele de servicii nu accepta fișiere **//.env//** (spre deosebire de Docker Compose) +</code>
-  * Docker Compose rulează containere în mod single-host,​ pe când Docker Swarm orchestrează servicii în mod multi-host. +
- +
-=== Pornirea unei stive de servicii în Docker Swarm ===+
  
-Odată ce swarm-ul Docker a fost creat și inițializatcomanda prin care se face deployment la o stivă de servicii este următoarea ​(unde configurația se găsește în fișierul //​**my_stack.yml**//​iar numele stivei va fi //​**lab3**//​):+În continuarenodul leader al clusterului (care va fi, cel mai probabil, nodul coordonator GlusterFS) va trebui să execute ​următoarea ​comandă pentru fiecare din celălalte noduri din clusterpentru a conecta nodurile pentru sistemul de fișiere:
  
 <code bash> <code bash>
-docker stack deploy -c my_stack.yml lab3+gluster peer probe <​HOSTNAME_NOD>​
 </​code>​ </​code>​
  
-<note important>​Dacă folosim un registru diferit de Docker (precum [[https://​docs.gitlab.com/​ee/​user/​packages/​container_registry/​|GitLab Container Registry]]),​ este nevoie să fim autentificați și să adăugăm opțiunea **//​-–with-registry-auth//​** atunci când lansăm o stivă de servicii.</​note>​+Conectarea nodurilor se poate verifica prin următoarea comandă dată pe manager:
  
-Odată ce stivă de servicii a fost pornită, putem să îi vedem statusul prin următoarea comandă:+<code bash> 
 +$ gluster pool list 
 +</​code>​ 
 + 
 +Următorul pas presupune crearea unui volum partajat pe întreg clusterul, printr-comandă executată pe manager. În exemplul ​de mai jos, se presupune că avem un manager (cu hostname-ul //​**docker-manager**//​) și doi workeri (//​**docker-worker1**//​ și //​**docker-worker2**//​). Toate trei nodurile vor avea un volum partajat (numit //​**mysharedvol**//​) la calea //​**/​gluster/​mysharedvol**//​deși nu este obligatoriu ​să fie aceeași cale la toate nodurile.
  
 <code bash> <code bash>
-$ docker ​stack ps lab3                                                                                                      ​+gluster volume create mysharedvol replica 3 docker-manager:/​gluster/​mysharedvol \ 
 +      docker-worker1:/​gluster/​mysharedvol docker-worker2:/​gluster/​mysharedvol force 
 +</​code>​
  
-ID             ​NAME ​                  ​IMAGE ​                                  ​NODE ​     DESIRED STATE    CURRENT STATE           ​ERROR ​              ​PORTS +În continuare, managerul trebuie să pornească volumul, astfel
-cuktma92gm62 ​  ​lab3_adminer.1 ​        ​adminer:latest ​                         myvm2     ​Running ​         Running 9 minutes ago                        + 
-njak2qzaobtt ​  ​lab3_db.1 ​             postgres:​12 ​                            ​myvm1 ​    ​Running ​         Running 8 minutes ago                        +<code bash> 
-m811buil7e63 ​  ​lab3_io-service.1 ​     mobylab/​idp-laborator3-io:​latest ​       myvm1     ​Running ​         Running 9 minutes ago                        +$ gluster volume start mysharedvol
-jnfw37e34kz3 ​  ​lab3_books-service.1 ​  ​mobylab/​idp-laborator3-books:​latest ​    ​myvm1 ​    ​Running ​         Running 9 minutes ago                        +
-pzlzkgsxxc00 ​  ​lab3_gateway.1 ​        ​mobylab/​idp-laborator3-gateway:​latest ​  ​myvm2 ​    ​Running ​         Running 9 minutes ago                        +
-kpaahb931rbq ​  ​lab3_io-service.2 ​     mobylab/​idp-laborator3-io:​latest ​       myvm1     ​Running ​         Running 9 minutes ago                        +
-num87yijgxrg ​  ​lab3_books-service.2 ​  ​mobylab/​idp-laborator3-books:​latest ​    ​myvm2 ​    ​Running ​         Running 9 minutes ago                        +
-d9m63k9h7ium ​  ​lab3_gateway.2 ​        ​mobylab/​idp-laborator3-gateway:​latest ​  ​myvm1 ​    ​Running ​         Running 9 minutes ago                        +
-lkmy60wpy0gv ​  ​lab3_io-service.3 ​     mobylab/​idp-laborator3-io:​latest ​       myvm2     ​Running ​         Running 9 minutes ago                        +
-fy21iizn0reb ​  ​lab3_gateway.3 ​        ​mobylab/​idp-laborator3-gateway:​latest ​  ​myvm2 ​    ​Running ​         Running 9 minutes ago                       +
 </​code>​ </​code>​
  
-De asemeneaputem vedea lista de stive pornite ​astfel:+Ultimul pas se referă la montarea volumului, astfel ​încât să se poate accesa și după un restart sau în alte situații. Comenzile de mai jos trebuie executate pe toate nodurile din cluster:
  
 <code bash> <code bash>
-docker stack ls                                                                                                           +echo '​localhost:/​mysharedvol /mnt glusterfs defaults,​_netdev,​backupvolfile-server=localhost 0 0' >> /​etc/​fstab 
 +</​code>​
  
-NAME      SERVICES ​     ORCHESTRATOR +<code bash> 
-lab3      5             Swarm+$ mount.glusterfs localhost:/​mysharedvol /mnt
 </​code>​ </​code>​
- 
-Putem vedea lista de servicii (din toate stivele pornite) astfel: 
  
 <code bash> <code bash>
-$ docker ​service ls                                                                                                         +chown -R root:docker ​/mnt 
 +</​code>​
  
-ID               ​NAME ​                ​MODE ​          ​REPLICAS ​              ​IMAGE ​                                 PORTS +În acest moment, în directorul //**/mnt**// se va găsi mapat, pe fiecare nod din cluster, volumul partajat de GlusterFS. Similar cu NFS, acesta va putea fi folosit în fișiere Docker Compose ca un bind mount pentru a asigura persistență distribuită în aplicațiile noastre, astfel
-dekzzyais8g7 ​    ​lab3_adminer ​        ​replicated ​    1/1                    adminer:​latest ​                        *:​8080->​8080/tcp + 
-74y84hvq4irn ​    ​lab3_books-service ​  ​replicated ​    2/2 (max 1 per node)   ​mobylab/idp-laborator3-books:latest ​     +<code yaml> 
-ns9mxet1rkx5 ​    ​lab3_db ​             replicated ​    ​1/​1 ​                   postgres:12                              +services
-dh3sv3q74fy6 ​    ​lab3_gateway ​        ​replicated ​    3/3 (max 2 per node)   ​mobylab/idp-laborator3-gateway:latest ​ *:3000->80/tcp +    db: 
-ru0rd7g2ypu8 ​    ​lab3_io-service ​     replicated ​    3/3 (max 2 per node)   ​mobylab/idp-laborator3-io:latest+        volumes: 
 +            - /mnt/db-config:/docker-entrypoint-initdb.d
 +            - /mnt/db-data:/​var/​lib/​postgresql/​data
 </​code>​ </​code>​
-==== Deployment-ul unui cluster Docker ==== 
  
-În cadrul laboratoarelor de IDP, avem două variante principale cu ajutorul cărora putem să ne creăm un cluster Docker format din mai multe mașini: [[https://​docs.docker.com/​machine/​|Docker Machine]] sau [[https://​labs.play-with-docker.com|Play with Docker]].+=== SSHFS ===
  
-=== Docker ​Machine ===+O altă variantă de a realiza persistență corectă într-un ​Docker ​Swarm este prin crearea de volume folosind alt driver de volum decât cel implicit (care le creează local). Un astfel de exemplu este driver-ul de SSHFS, numit [[https://​hub.docker.com/​r/​vieux/​sshfs|vieux/​sshfs]]. SSHFS este un client de sistem de fișiere folosit pentru a monta și interacționa cu directoare și fișiere aflate pe un server, prin intermediul unei conexiuni SSH.
  
-Docker Machine este un utilitar care permite rularea Docker Engine pe gazde virtuale (atât local, cât și în cloud, la provideri precum AWS, Azure sau DigitalOcean),​ precum și gestiunea facilă ​acestora din terminal. Pe Windows și macOS, Docker Machine face parte din instalarea ​de Dockerdar pe Linux trebuie date explicit comenzile următoare:+Pentru ​putea folos driver-ul ​de SSHFSacesta trebuie instalat ​pe toate gazdele Docker:
  
 <code bash> <code bash>
-curl -L https://​github.com/​docker/​machine/​releases/​download/​v0.12.2/​docker-machine-`uname ​-s`-`uname -m` >/tmp/​docker-machine+$ docker ​plugin install ​--grant-all-permissions vieux/sshfs
 </​code>​ </​code>​
 +
 +Odată ce driver-ul a fost instalat, putem crea un volum peste SSFHS astfel:
  
 <code bash> <code bash>
-chmod +x /tmp/docker-machine+docker volume create --driver vieux/sshfs -o sshcmd=remoteuser@remotenode:​/home/​remoteuser \ 
 +      ​-o password=remotepassword sshvolume
 </​code>​ </​code>​
 +
 +Astfel, se creează local un volum peste SSH, aflat pe serverul //​**remotenode**//​. La server, conectarea se face cu numele de utilizator //​**remoteuser**//​ și parola //​**remotepassword**//​ (dacă există chei partajate configurate între client și server, nu mai este necesară parola). Volumul astfel creat poate fi folosit ca orice alt volum, iar tot ce se scrie în el va fi persistat la server.
 +
 +Volumul peste SSHFS se poate crea direct la rularea unui container, astfel:
  
 <code bash> <code bash>
-cp /tmp/docker-machine ​/usr/local/bin/docker-machine+$ docker ​run -d --volume-driver vieux/sshfs \ 
 +    --mount src=sshvolume,​target=/myvol,​volume-opt=sshcmd=remoteuser@remotenode:​/home/remoteuser,​volume-opt=password=remotepassword \ 
 +    alpine
 </​code>​ </​code>​
  
-În Docker Machine, putem folosi drivere pentru a crea noduri virtuale configurate pentru a rula Docker. Exista drivere pentru a crea noduri direct în cloud, dar șdrivere pentru a crea mașini virtuale pe gazda localăÎn exemplul ​de mai jos, se creează un nod virtual local folosind driverul pentru VirtualBox:+<note tip> 
 +Putețtesta SSHFS în [[https://​training.play-with-docker.com/​docker-volume-sshfs/​|acest sandbox]] ​de Play with Docker. 
 +</​note>​
  
-<​code>​ +==== Kong API Gateway ====
-$ docker-machine create --driver virtualbox myvm1+
  
-Running pre-create checks..+În cadrul scheletului de cod este implementat un API Gateway minimal sub forma de server de NodeJSAcesta are următoarele funcționalități:​ 
-Creating machine... +  * expune rute din aplicație 
-(myvm1) Copying /home/radu/.docker/​machine/​cache/​boot2docker.iso to /​home/​radu/​.docker/​machine/​machines/​myvm1/​boot2docker.iso... +  * funcționează ca un punct central de acces în sistem.
-(myvm1) Creating VirtualBox VM... +
-(myvm1) Creating SSH key... +
-(myvm1) Starting the VM... +
-(myvm1) Check network to re-create if needed... +
-(myvm1) Waiting for an IP... +
-Waiting for machine to be running, this may take a few minutes... +
-Detecting operating system of created instance... +
-Waiting for SSH to be available... +
-Detecting the provisioner... +
-Provisioning with boot2docker... +
-Copying certs to the local machine directory... +
-Copying certs to the remote machine... +
-Setting Docker configuration on the remote daemon... +
-Checking connection to Docker... +
-Docker is up and running! +
-To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env myvm1 +
-</​code>​+
  
-Putem verifica rularea corectă a comenzilor ​și alte informații utile despre starea nodurilor virtuale astfel:+Cu toate acestea, implementarea programatică a unui API Gateway necesită timp și, de multe ori, munca depusă implică scriere repetitivă de cod.
  
-<​code>​ +[[https://konghq.com/|Kong]] este unul dintre liderii din domeniul Cloud în materie de soluții de API Gateway declarativeKong este nativ Docker, este bazat pe Nginx si nu necesită scriere de cod, ci doar furnizarea unei configurații (sau configurarea on-the-fly prin cereri HTTP).
-$ docker-machine ls +
-NAME    ACTIVE ​  ​DRIVER ​      ​STATE ​    ​URL ​                        ​SWARM ​  ​DOCKER ​       ERRORS +
-myvm1   ​- ​       virtualbox ​  ​Running ​  tcp://192.168.99.100:​2376 ​          ​v17.09.0-ce ​   +
-</​code>​+
  
-Prin comanda //​**docker-machine ssh**//, putem trimite comenzi prin SSH către un nod virtual ​Docker ​pe care îl specificăm prin numeașa cum se poate observa mai jos.+Kong funcționează ca un serviciu de Docker ​și interceptează traficul venit, în funcție de regulile menționate, și apoi îl redirectează către alte servicii.
  
-<​code>​ +În plus, Kong oferă o gamă variată de **plugins** ce aduc funcționalități extra precum ​//rate limiting//, //​compression//,​ //​logging//,​ etc.
-$ docker-machine ssh myvm1 "ls -la" +
-</code>+
  
-În mod similar, există și comanda //​**docker-machine scp**//:+=== Arhitectura implementată ===
  
-<​code>​ +Arhitectura este identică cu cea a exercițiului din laboratorul precedent, însă, în loc de API Gateway programatic,​ vom folosi Kong. 
-$ docker-machine scp file.txt myvm1:. +În plus, vom expune și serviciul Adminer tot prin intermediul Kong.
-</​code>​+
  
-De asemenea, există și comenzi pentru oprirea, respectiv ștergerea, nodurilor virtuale create.+{{:​cc:​laboratoare:​schema_lab.png?600|}}
  
-<​code>​ +Comportamentul dorit va fi ca, în urma apelului **IP_PUBLIC/api/​books**,​ să interacționăm cu serviciul Books (POST/GET) și, în urma apelului **IP_PUBLIC/​adminer**,​ să interacționăm cu serviciul Adminer.
-$ docker-machine stop myvm1 +
-</code>+
  
-<​code>​ +=== Implementare Kong ==
-$ docker-machine rm myvm1 +
-</​code>​+
  
-=== Play with Docker ===+Kong poate fi rulat atât în modul **DB-on**, cât și în modul **DB-less**. Noi vom folosi abordarea **DB-less**,​ furnizând o configurație bazată pe un fișier **.yml**. În modul **DB-on**, Kong mai folosește o bază de date și configurația se face pe bază de cereri POST către API-ul intern de configurare.
  
-Play with Docker este un mediu online ​de învățare Docker ce oferă mașini virtuale pe o durată de 4 ore.+== Fișierul ​de configurație ==
  
-{{:idp:​laboratoare:​playwithdocker.png?900}}+<code yaml> 
 +_format_version"2.1"
  
-==== Comenzi utile ====+services: 
 +  - name: books-service 
 +    url: http://​labkong_books-service/​api 
 +    routes: 
 +      - name: books-service-route 
 +        paths:  
 +          - /​api/​books 
 +           
 +  - name: db-adminer 
 +    url: http://​labkong_adminer:​8080 
 +    routes: 
 +      - name: adminer-service 
 +        paths: 
 +          - /adminer
  
-=== Interacțiune servicii ===+consumers:​ 
 +  - username: lab-student
  
-<note tip>​Aceste comenzi pot fi rulate doar de pe noduri manager.</​note>​+plugins: 
 +  - name: key-auth 
 +    service: books-service
  
-<code bash> +keyauth_credentials:​ 
-$ docker service create ​--name <​NUME_SERVICIU>​ <​IMAGINE_DOCKER>​ # creează un serviciu pornind de la o imagine +  consumer: lab-student 
-$ docker service ls                                             # afișează toate serviciile din sistem +    key: mobylab 
-$ docker service inspect <​NUME_SERVICIU> ​                       # afișează informații despre un serviciu +    ​hide_credentials:​ true
-$ docker service logs –f <​NUME_SERVICIU> ​                       # afișează log-urile unui serviciu +
-$ docker service ps <​NUME_SERVICIU> ​                            # afișează task-urile (și statusurile lor) pentru un serviciu +
-$ docker service update --replicas <N> <​NUME_SERVICIU> ​         # actualizează serviciul, replicând containerele de N ori +
-$ docker service rm <​NUME_SERVICIU> ​                            # șterge un serviciu+
 </​code>​ </​code>​
  
-=== Interacțiune cluster ===+  * **services** - reprezintă ce servicii se vor conecta la Kong pentru interceptare și forwarding de trafic 
 +  * **consumers** - reprezintă ce opțiuni se pot seta fiecărui serviciu, în funcție de plugin (este opțional și se folosește doar în contextul pluginurilor)
  
-<note tip>Aceste comenzi pot fi rulate doar de pe noduri manager.</​note>​+<note tip>Fiecare serviciu trebuie să aibă obligatoriu definite următoarele:​ //name//, //url//, //routes//.</​note>​
  
-<code bash> +  * **services -name** - numele serviciului ​din punct de vedere al configurării rezultate, trebuie să fie unic 
-# docker node ls # afișează nodurile ​din cluster +  * **services ​-> url** //calea// de comunicare **cu serviciul de Docker**; în cazul nostru, reprezintă ruta **din interioriul** serviciilor de Docker ​unde se vor forwarda cererile HTTP
-# docker node promote <​NUME_NOD> ​           # promovează nodul din worker în manager +
-# docker node demote <​NUME_NOD> ​            # retrogradează nodul din manager în worker +
-# docker swarm init [--advertise-addr <IP>] # creează un cluster ​Docker +
-# docker swarm join --token <​TOKEN>​ <​IP> ​   # se alătură unui cluster Docker +
-</​code>​+
  
-=== Docker Machine ===+<note tip>​Observați că în URL se precizează NUME-STIVA_NUME_SERVICIU_DOCKER în loc de IP.</​note>​
  
-<code bash+  * **services -routes** - rutele pe care se va mapa traficul din exterior 
-# docker-machine create [--driver <DRIVER>] <​NUME>​ # creează o mașină virtuală Docker +  * **services ​-> routes ​-> name** ​numele rutei din punct de vedere al configurării rezultate, trebuie să fie unic 
-# docker-machine start <​NUME> ​                     # pornește o mașină virtuală Docker +  * **services ​-> routes ​-> path** ​//calea// de comunicare **din exterior**, care se va mapa pe ruta furnizată în URL
-# docker-machine stop <NUME                      # oprește o mașină virtuală Docker +
-# docker-machine rm <NUME                        # șterge o mașină virtuală Docker +
-# docker-machine ssh <​NUME> ​                       # se conectează prin SSH la o mașină virtuală Docker +
-# docker-machine scp <​FISIER>​ <​NUME>:<​DESTINATIE> ​ # copiază un fișier ​pe o mașină virtuală Docker +
-</​code>​+
  
-==== Exerciții ====+<note tip>​Pluginurile sunt opționale, însă am vrut să demonstrăm utilizarea unui plugin de autorizare pe bază de cheie de API trimisă în header. Deoarece pluginul este activat doar pe serviciul Books, numai calea **/​api/​books** este securizată.</​note>​
  
-=== Descriere aplicație ===+== Includerea în stiva de servicii Docker ​==
  
-Pentru exercițiile din acest laboratorvom lucra cu o variantă extinsă a aplicației bibliotecă din [[idp:​laboratoare:​02|laboratorul 2]]. Astfel, codul (care se găsește pe [[https://​gitlab.com/​mobylab-idp/​laborator3|repository-ul materiei]]) este format din trei mici microservicii scrise ​în NodeJS ​și un script ​de inițializare pentru o bază de date PostgreSQL. Cele trei microservicii sunt: +Ca oricare alt serviciu de DockerKong se adaugă în fișierul de configurație al stivei.
-  * //​**ApiGateway**//​ - mediază accesul dinspre lumea exterioara și redirecționează cererile HTTP către serviciul de cărți +
-  * //​**Books**//​ - se ocupă de partea de „business logic” ce ține de cărți și apelează serviciul IO pentru date +
-  * //**IO**// - gestionează datele sistemului și realizează comunicația cu baza de date.+
  
-=== Scop exerciții ===+<code yaml> 
 +services: 
 +  kong: 
 +    image: kong:​latest 
 +    volumes: 
 +      - ./​kong:/​usr/​local/​kong/​declarative # injectarea fișierului de configurare la calea specificată 
 +    environment:​ 
 +      KONG_DATABASE:​ '​off'​ # obligatoriu,​ dacă se vrea modul DB-less 
 +      KONG_DECLARATIVE_CONFIG:​ /​usr/​local/​kong/​declarative/​kong.yml # trebuie specificat unde anume se va găsi fișierul de configurare 
 +      KONG_PROXY_ACCESS_LOG:​ /​dev/​stdout 
 +      KONG_ADMIN_ACCESS_LOG:​ /​dev/​stdout 
 +      KONG_PROXY_ERROR_LOG:​ /​dev/​stderr 
 +      KONG_ADMIN_ERROR_LOG:​ /​dev/​stderr 
 +      KONG_ADMIN_LISTEN:​ 0.0.0.0:​8001,​ 0.0.0.0:​8444 ssl 
 +    ports: 
 +      - 8000:8000 # expunerea porturilor 
 +      - 8443:8443 
 +    deploy: 
 +      placement:​ 
 +        constraints:​ [node.role ​== manager] # constrângerea de rulare doar pe manager, pentru a nu exista conflict la nivel de volume 
 +    networks: 
 +      - internal 
 +</​code>​
  
-Scopul exercițiilor este ca, plecând de la codul propus, ​să realizați o stivă de servicii ​care să funcționeze corectFuncționalitatea este reprezentată de trei acțiuni: +<note tip>Aveți grija să conectați toate serviciile pe care le vreți expuse în Kong în aceeași rețea cu elObservațîn cadrul configurației de mai sus, am folosit rețeaua //​internal//​. Atât serviciul Books cât și Adminer vor trebui să fie în rețeaua //​internal//​.</​note>​
-  * adăugarea unei rți în bibliotecă +
-  * vizualizarea informațiilor despre toate cărțile din bibliotecă +
-  * vizualizarea detaliilor unei cărți.+
  
-Pe scurt, va trebui să scrieți unul sau mai multe fișier Docker Compose ​pe care să le folosițpentru ​rula configurația sub forma unei stive de servicii Docker Swarm.+<note tip>Kong ascultă pe porturile 8000 ș8443. Pentru ​expune în public 80 și 443, este nevoie ​de mapare explicită.</​note>​
  
-Stiva creată va fi formată din 5 servicii: +=== Comportament așteptat ===
-  * //​**gateway**//​ - puteți să creați imaginea pe baza surselor din repository, sau puteți folosi imaginea //​**mobylab/​idp-laborator3-gateway**//​ +
-  * //​**books-service**//​ - puteți să creați imaginea pe baza surselor din repository, sau puteți folosi imaginea //​**mobylab/​idp-laborator3-books**//​ +
-  * //​**io-service**//​ - puteți să creați imaginea pe baza surselor din repository, sau puteți folosi imaginea //​**mobylab/​idp-laborator3-io**//​ +
-  * //**db**// - folosiți imaginea //​**postgres:​12**//​ +
-  * //​**adminer**//​ - folosiți imaginea //​**adminer**//​.+
  
-=== Variabile ​de mediu ===+Dacă totul a decurs bine, apelarea rutei **IP_PUBLIC_PLAY_WITH_DOCKER/​adminer** va rezulta în panoul ​de administrare a bazei de date, iar cererile din Postman pe ruta **IP_PUBLIC_PLAY_WITH_DOCKER/​api/​books** vor eșua în cazul în care nu există o cheie API în header, sau să funcționeze dacă se pune cheia **mobylab** în header.
  
-Variabilele de mediu ce vor trebui puse in fișierul Docker Compose sunt următoarele: +{{:cc:laboratoare:apikey_lab6.png?600|}}
-  * serviciul //​**gateway**//​: +
-    * BOOKS_SERVICE_API_ROUTEbooks-service/​api +
-    * NODE_ENV: development +
-  * serviciul //​**books-service**//:​ +
-    * IO_SERVICE_API_ROUTE:​ io-service/​api +
-    * NODE_ENV: development +
-  * serviciul //​**io-service**//:​ +
-    * PGUSER: admin +
-    * PGPASSWORD: admin +
-    * PGHOST: db +
-    * PGPORT: 5432 +
-    * PGDATABASE: books +
-    * NODE_ENV: development +
-  * serviciul //​**db**//:​ +
-    * POSTGRES_DB:​ books +
-    * POSTGRES_USER:​ admin +
-    * POSTGRES_PASSWORD:​ admin. +
-  +
-=== Rețele ===+
  
-Pentru a izola accesul serviciilor asupra clusterului,​ sunt necesare mai multe rețele, astfel:+=== Extindere Kong ===
  
-  * serviciul //​**gateway**//​ va comunica doar cu serviciul //​**books-service**//​ +Bineînțeles,​ exemplul arătat în cadrul acestui laborator este unul simplu. Kong se poate folosi pentru mult mai multe lucruri utile în lucrul ​cu servicii distribuite ​și microservicii,​ precum ​//rate limiting////distributed logging////IP restriction//, //3rd party authorization////CORS//, etc.
-  * serviciul //​**books-service**//​ va comunica atât cu serviciul de //​**gateway**//,​ cât și cu //**io-service**// +
-  * serviciul ​//**io-service**// va comunica atât cu serviciul ​//**books-service**//, cât și cu serviciul ​//**db**// +
-  * serviciul ​//**db**// va comunica atât cu serviciul //​**io-service**//, cât și cu //​**adminer**//​.+
  
-=== Volume ​și bind mounts ===+Esențial, Kong se folosește ca un punct central de acces în sistem, care se introduce nativ în ecosistemul Docker. În plus, este indicat să dedicațcât mai multe funcționalități care au legătură cu traficul Web către API Gateway, pentru a nu îngreuna business logic-ul din interiorul serviciilor. ​
  
-Configurația de volume și bind mounts este la fel ca cea de la exercițiile din [[idp:​laboratoare:​02|laboratorul 2]]. Astfelserviciul de bază de date are nevoie de un volum pentru persistență și de un bind mount pentru a se injecta scriptul de inițializare.+În continuaresa va ilustra aplicarea următoarelor pluginuri:
  
-=== Porturi publice ===+  - [[https://​docs.konghq.com/​hub/​kong-inc/​rate-limiting/​|Rate Limiting]] - limitarea numărului de cereri pe anumite rute 
 +  - [[https://​docs.konghq.com/​hub/​kong-inc/​jwt/​|JWT]] - autorizarea serviciilor pe baza unui JWT 
 +  - [[https://​docs.konghq.com/​hub/​kong-inc/​cors/​|CORS]] - adaugărea politicilor CORS pe anumite servicii 
 +  - [[https://​docs.konghq.com/​hub/​kong-inc/​bot-detection/​|Bot Detection]] - protecția împotriva boților web 
 +  - [[https://​docs.konghq.com/​hub/​kong-inc/​prometheus/​|Prometheus Logging]] - suport pentru extragerea logurilor utilizând Prometheus.
  
-Singurele servicii accesibile din exterior vor fi //​**gateway**//​ și //​**adminer**//​. Pentru //​**gateway**//,​ trebuie expus portul intern 80, peste care se mapează alt port (de exemplu, 3000), iar pentru //​**adminer**//​ trebuie expus portul intern 8080 (peste care se poate de asemenea mapa alt port extern, dar nu obligatoriu).+<code yaml> 
 +_format_version:​ "2.1"
  
-=== Rute HTTP ===+services: 
 +  - name: books-service 
 +    url: http://​books-service/​api 
 +    routes: 
 +      - name: books-service-route 
 +        paths:  
 +          - /​api/​books 
 +           
 +  - name: db-adminer 
 +    url: http://​adminer:​8080 
 +    routes: 
 +      - name: adminer-service 
 +        paths: 
 +          - /adminer
  
-Dacă reușiți să rulați configurația,​ puteți să o testați folosind cURL sau Postman pe următoarele rute:+consumers: 
 +  - username: lab-student 
 +     
 +plugins: 
 +  - name: rate-limiting 
 +    config:  
 +      minute: 10 
 +      limit_by: ip 
 +      policy: local
  
-  ​* POST localhost:PORT_PUBLIC/​api/​books cu corpul JSON ''​%%{"​title"​"Harry Potter and the Prisoner of Azkaban",​ "​author":​ "J.K. Rowling",​ "​genre":​ "​Fantasy"​}%%''​ +  ​- name: cors 
-  * GET localhost:PORT_PUBLIC/​api/​books +    service: books-service 
-  GET localhost:​PORT_PUBLIC/​api/​books/​ID_CARTE+    config
 +      ​origins:  
 +       - "*"
  
-<note tip>​Pentru a adăuga un corp JSON unei cereri POST in Postman, selectați Body -> Raw -> JSON și scrieți JSON-ul aferent.</​note>​+  ​name: bot-detection
  
-=== Secrete ===+  - name: prometheus 
 + 
 +  - name: jwt 
 +    service: books-service 
 +    # config: 
 +    #   ​claims_to_verify:​ 
 +    #     - exp 
 +    #   ​maximum_expiration:​ 60 
 + 
 +jwt_secrets:​ 
 +  - consumer: lab-student 
 +    key: Moby Labs IDP 
 +    algorithm: HS256 
 +    secret: mobylab 
 +</​code>​
  
-Opțional, puteți adăuga secrete aplicației,​ pentru numele de utilizator și parola necesare logării în baza de date. Astfel, serviciile care vor avea nevoie de secrete sunt //​**io-service**//​ și //**db**//. În cele două servicii, va trebui să sufixați variabilele de mediu destinate numelui de utilizator și parolei cu //​**_FILE**//​ și să puneți valorile acestor variabile de mediu în funcție de documentație:​ +=== Logging ===
-  * pentru //​**io-service**//,​ la variabilele de mediu pentru numele de utilizator și parolă se pune doar **//numele secretului//​** iar NODE_ENV se setează la **//​staging//​** +
-  * pentru serviciul //**db**//, la variabilele de mediu se pune toată calea secretului (//​**/​run/​secrets/​nume-secret**//​).+
  
-=== Enunțuri ===+Fișierul //​docker-stack-kong-plugins.yml//​ integrează,​ pe lângă Kong-ul extins cu pluginuri, și Prometheus și Grafana pentru explorarea logurilor provenite din Kong.
  
-  - Scrieți un fișier Docker Compose care sa folosească un build local +Pentru a accesa Grafana, este nevoie să realizați următorii pași: 
-  Construiți imaginile și urcați-le ​pe Docker Hub sau orice alt registru +    intrați pe **IP:3000** 
-  Scrieți un fișier Docker Compose care să folosească imaginile din registru +    conectați-vă cu //admin// / //admin// 
-  Adăugați elemente ​de Docker Swarm la serviciile din fișierul Docker Compose (la proprietatea ​//**deploy**//) și rulați stiva de servicii într-un cluster (folosind Play with Docker sau Docker Machine) +    setați sursa de date // http://​prometheus:​9090 ​// 
-  Modificați fișierul Docker Compose ca să utilizați secrete externe pentru numele ​de utilizator și parolă în containerele de IO și bază de date.+    importați [[https://​grafana.com/​grafana/​dashboards/​7424|dashboardul]] oferit ​de Kong.
idp/laboratoare/03.1616041977.txt.gz · Last modified: 2021/03/18 06:32 by radu.ciobanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0