W jaki sposób Docker Swarm wdraża udostępnianie woluminów?

93

Docker Swarm może zarządzać dwoma typami pamięci:

volume i bind

Chociaż bindnie jest to sugerowane przez Docker Documentation, ponieważ tworzy powiązanie między katalogiem lokalnym (na każdym węźle roju) z zadaniem, volumeimplementacja nie jest wspomniana, więc nie rozumiem, jak woluminy są współdzielone między zadaniami?

  • W jaki sposób Docker Swarm udostępnia woluminy między węzłami?
  • Gdzie są zapisywane woluminy (w menedżerze? A jeśli jest więcej niż jeden menedżer?)
  • Czy nie ma problemu między węzłami, jeśli działa na różnych komputerach w różnych sieciach?
  • Czy tworzy VPN?
alessandro308
źródło
1
Czy Swarm dzieli woluminy? Około rok temu miałem do czynienia z rojem dokerów, ale myślę, że rój NIE jest odpowiedzialny za współdzielenie woluminów między węzłami. Jeśli chcesz, aby węzły współdzieliły ten sam wolumin, musisz użyć wtyczek woluminów, takich jak azure volumedriver.
Munchkin,

Odpowiedzi:

66

To, o co pytasz, to typowe pytanie. Danymi woluminu i funkcjami tego, co może zrobić ten wolumin, zarządza sterownik woluminu. Tak jak można używać różnych sterowników sieciowych, takich jak overlay, bridgelub hostmożna stosować różne sterowniki głośności.

Docker i Swarm są dostarczane tylko ze standardowym localsterownikiem po wyjęciu z pudełka. Nie ma żadnej wiedzy o Swarm i po prostu utworzy nowe woluminy dla twoich danych w dowolnym węźle, w którym zaplanowane są zadania usługi. Zwykle tego nie chcesz.

Potrzebujesz wtyczki sterownika innej firmy, która jest świadoma roju i zapewni, że wolumin utworzony dla zadania serwisowego będzie dostępny we właściwym węźle we właściwym czasie. Opcje obejmują użycie „Docker for AWS / Azure” i dołączonego do niego sterownika CloudStor lub popularnego rozwiązania REX-Ray typu open source .

Istnieje wiele sterowników woluminów innych firm, które można znaleźć w sklepie Docker Store .

Bret Fisher
źródło
czy hadoop może działać jako taki wspólny wolumin?
stackit
55

Sam tryb roju nie robi nic innego z woluminami, uruchamia dowolne polecenie podłączenia woluminu, które podasz w węźle, w którym działa kontener. Jeśli instalacja woluminu jest lokalna w tym węźle, dane zostaną zapisane lokalnie w tym węźle. Nie ma wbudowanej funkcji automatycznego przenoszenia danych między węzłami.

Istnieje kilka rozproszonych rozwiązań pamięci masowych opartych na oprogramowaniu, takich jak GlusterFS, a Docker ma jeden o nazwie Infinit, który nie jest jeszcze GA, a jego rozwój zajął tylne miejsce w integracji Kubernetes w EE.

Typowy wynik jest taki, że musisz albo zarządzać replikacją pamięci masowej w aplikacji (np. Etcd i inne algorytmy oparte na tratwie), albo wykonywać montowania w zewnętrznym systemie pamięci masowej (miejmy nadzieję, z własnym HA). Montowanie zewnętrznego systemu pamięci masowej ma dwie opcje, oparte na blokach lub plikach. Pamięć masowa oparta na blokach (np. EBS) ma zwykle wyższą wydajność, ale jest ograniczona do montażu tylko w jednym węźle. W tym celu zazwyczaj będziesz potrzebować sterownika wtyczki woluminu innej firmy, aby zapewnić węzłowi Docker dostęp do tego bloku magazynowego. Magazyn oparty na plikach (np. EFS) ma niższą wydajność, ale jest bardziej przenośny i może być jednocześnie montowany na wielu węzłach, co jest przydatne w przypadku usługi replikowanej.

Najpopularniejszym magazynem sieciowym opartym na plikach jest NFS (jest to ten sam protokół używany przez EFS). Możesz to zamontować bez sterowników wtyczek innych firm. Niestety nazwany „lokalny” sterownik wtyczki woluminu, z którym docker jest dostarczany, daje możliwość przekazania dowolnych wartości do polecenia mount z opcjami sterownika, a bez opcji domyślnie przechowuje woluminy w katalogu docker / var / lib / docker / woluminy. Dzięki opcjom możesz przekazać mu parametry NFS, a nawet wykona wyszukiwanie DNS na nazwie hosta NFS (coś, czego normalnie nie masz w NFS). Oto przykład różnych sposobów montowania systemu plików NFS przy użyciu lokalnego sterownika woluminu:

  # create a reusable volume
  $ docker volume create --driver local \
      --opt type=nfs \
      --opt o=nfsvers=4,addr=192.168.1.1,rw \
      --opt device=:/path/to/dir \
      foo

  # or from the docker run command
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=192.168.1.1\",volume-opt=device=:/host/path \
    foo

  # or to create a service
  $ docker service create \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=192.168.1.1\",volume-opt=device=:/host/path \
    foo

  # inside a docker-compose file
  ...
  volumes:
    nfs-data:
      driver: local
      driver_opts:
        type: nfs
        o: nfsvers=4,addr=192.168.1.1,rw
        device: ":/path/to/dir"
  ...

Jeśli na końcu użyjesz przykładu pliku redagowania, zwróć uwagę, że zmiany w wolumenie (np. Aktualizacja ścieżki lub adresu serwera) nie są odzwierciedlane w istniejących nazwanych woluminach tak długo, jak istnieją. Musisz albo zmienić nazwę swojego wolumenu, albo go usunąć, aby umożliwić rójowi odtworzenie go z nowymi wartościami.

Innym częstym problemem, który widzę w większości zastosowań NFS, jest włączenie „root squash” na serwerze. Powoduje to problemy z uprawnieniami, gdy kontenery działające jako root próbują zapisywać pliki na woluminie. Masz również podobne problemy z uprawnieniami UID / GID, w których identyfikator UID / GID kontenera jest tym, który wymaga uprawnień do zapisu w woluminie, co może wymagać posiadania własności katalogu i dostosowania uprawnień na serwerze NFS.

BMitch
źródło
9

Moje rozwiązanie dla AWS EFS, które działa:

  1. Utwórz EFS (nie zapomnij otworzyć portu NFS 2049 w grupie bezpieczeństwa)
  2. Zainstaluj pakiet nfs-common:

    sudo apt-get install -y nfs-common

  3. Sprawdź, czy Twój EFS działa:

    mkdir efs-test-point
    sudo chmod go + rw efs-test-point
    sudo mount -t nfs -o nfsvers = 4.1, rsize = 1048576, wsize = 1048576, hard, timeo = 600, retrans = 2, noresvport [YOUR_EFS_DNS]: / efs-test-point
    dotknij efs-test-point / 1.txt
    sudo umount efs-test-point /
    ls -la efs-test-point /

    katalog musi być pusty

    sudo mount -t nfs -o nfsvers = 4.1, rsize = 1048576, wsize = 1048576, hard, timeo = 600, retrans = 2, noresvport [YOUR_EFS_DNS]: / efs-test-point

    ls -la efs-test-point/

    plik 1.txt musi istnieć

  4. Skonfiguruj plik docker-compose.yml:

    usługi:
      sidekiq:
        wolumeny:
          - uploads_tmp_efs: / home / application / public / uploads / tmp
      ...
    wolumeny:
      uploads_tmp_efs:
        kierowca: lokalny
        driver_opts:
          typ: nfs
          o: addr = [YOUR_EFS_DNS], nfsvers = 4.1, rsize = 1048576, wsize = 1048576, hard, timeo = 600, retrans = 2
          urządzenie: [YOUR_EFS_DNS]: /

super_p
źródło
6

Moje rozwiązanie dla naszego lokalnie hostowanego roju: każdy węzeł roboczy ma zamontowany udział nfs, dostarczany przez nasz serwer plików /mnt/docker-data. Kiedy definiuję woluminy w moich usługach tworzą pliki, ustawiam urządzenie na jakąś ścieżkę pod /mnt/docker-data, na przykład:

volumes:
  traefik-logs:
    driver: local
    driver_opts:
      o: bind
      device: /mnt/docker-data/services/traefik/logs
      type: none

Dzięki takiemu rozwiązaniu docker tworzy wolumen na każdym węźle, usługa jest wdrażana i - o dziwo - są już dane, bo to ta sama ścieżka, której używał wolumen na drugim węźle.

Jeśli przyjrzysz się bliżej systemowi plików węzłów, zobaczysz, że montowanie na moim serwerze plików jest tworzone pod /var/lib/docker/volumes, zobacz tutaj:

root@node-3:~# df -h
Dateisystem                                                                                                   Größe Benutzt Verf. Verw% Eingehängt auf
[...]
fs.mydomain.com:/srv/shares/docker-data/services/traefik/logs                                 194G    141G   53G   73% /var/lib/docker/volumes/traefik_traefik-logs/_data
tigu
źródło