Как Docker Swarm реализует разделение томов?

Docker Swarm может управлять двумя типами хранения: объемом и связью. Хотя привязка не предлагается Docker Documentation, поскольку она создает привязку между локальным каталогом (в каждом ройном узле) к задаче, реализация метода томов не упоминается, поэтому я не понимаю, как разделяемые тома между задачами.

Как Docker Swarm разделяет объемы между узлами? Где хранятся тома (на менеджере? И если есть более одного управляющего?)?

Нет проблем между узлами, если они запускаются на разных машинах в разных сетях? Создает ли он VPN?

Ответ 1

То, о чем вы спрашиваете, - общий вопрос. Данные тома и особенности того, что может сделать этот том, управляются драйвером тома. Так же, как вы можете использовать разные сетевые драйверы, такие как overlay, bridge или host, вы можете использовать разные драйверы томов.

Docker и Swarm поставляются со стандартным local драйвером из коробки. У него нет никакой осведомленности о Роме, и он просто создаст новые тома для ваших данных на том узле, на котором запланированы ваши служебные задачи. Обычно это не то, что вы хотите.

Вам нужен плагин сторонних драйверов, который известен Swarm, и гарантирует, что том, который вы создали для задачи службы, доступен на нужном узле в нужное время. Варианты включают использование "Docker for AWS/Azure" и включенный драйвер CloudStor, или популярное решение REX-Ray с открытым исходным кодом.

Есть много сторонних драйверов томов, которые вы можете найти в Docker Store.

Ответ 2

Сам режим Swarm ничем не отличается от томов, он запускает любую команду монтирования тома, которую вы предоставляете на узле, где работает контейнер. Если ваше хранилище томов является локальным для этого узла, ваши данные будут сохранены локально на этом узле. Нет встроенных функций для автоматического перемещения данных между узлами.

Есть некоторые программные решения для распределенных хранилищ, такие как GlusterFS, а у Docker есть один Infinit, который еще не является GA, а разработка на этом заняла место интеграции Kubernetes в EE.

Типичным результатом является либо управление репликацией хранилища в вашем приложении (например, etcd и другие алгоритмы на основе платформы), либо вы выполняете настройки на внешней системе хранения (надеюсь, с ее собственной HA). Для монтирования внешней системы хранения есть две опции: блок или файл. Блочное хранилище (например, EBS) обычно имеет более высокую производительность, но ограничивается только установкой на одном узле. Для этого вам обычно понадобится драйвер плагина сторонних томов, чтобы предоставить вашему докеревому узлу доступ к этому блочному хранилищу. Файловое хранилище (например, EFS) имеет более низкую производительность, но более переносимо и может быть одновременно смонтировано на нескольких узлах, что полезно для реплицируемой службы.

Наиболее распространенным файловым сетевым хранилищем является NFS (это тот же протокол, который используется EFS). И вы можете установить это без каких-либо сторонних плагинов. К сожалению, так называемый локальный драйвер плагина тома, к которому поставляется докер, дает вам возможность передать любые значения, которые вы хотите использовать команде mount с параметрами драйвера, и без параметров, по умолчанию они сохраняют тома в каталоге docker/var/lib/Докер/тома. С помощью параметров вы можете передать ему параметры NFS, и он даже выполнит поиск DNS по имени узла NFS (что-то, чего у вас нет с NFS, как правило). Здесь приведен пример различных способов монтирования файловой системы NFS с использованием локального драйвера тома:

  # 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"
  ...

Ответ 3

Мое решение для AWS EFS, которое работает:

  1. Создайте EFS (не забудьте открыть порт NFS 2049 в группе безопасности)
  2. Установите пакет nfs-common:

    sudo apt-get install -y nfs-common

  3. Проверьте, работает ли ваш efs:

    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
    touch efs-test-point/1.txt
    sudo umount efs-test-point/
    ls -la 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

    ls -la efs-test-point/

    файл 1.txt должен существовать

  4. Настроить файл docker-compose.yml:

    services:
      sidekiq:
        volumes:
          - uploads_tmp_efs:/home/application/public/uploads/tmp
      ...
    volumes:
      uploads_tmp_efs:
        driver: local
        driver_opts:
          type: nfs
          o: addr=[YOUR_EFS_DNS],nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2
          device: [YOUR_EFS_DNS]:/

Ответ 4

После поиска в документации и обсуждениях докеров я смог найти следующую информацию по этой проблеме:

  • связать монтаж каталога-хозяина в контейнере (docker run -v/some/host/dir/: /container/path/) использует файлы, которые присутствуют на хосте. Если каталог-хозяин не существует, на хосте и в контейнере создается новый пустой каталог (он будет изменяться в будущем, и вместо этого будет показана ошибка)
  • используя "безымянный" том (docker run -v/container/path) создаст новый том и скопирует содержимое /container/path в этот том
  • используя "именованный" том (docker run -v somename: /container/path) создаст новый том с именем "somename" или использует существующий том "somename" и будет использовать файлы, которые присутствуют внутри этого тома. Если объем вновь создан, он будет пустым.

Источник: Обсуждение Github

Причиной всего этого является:

Это не ошибка, она действовала так, потому что она должна это делать. Для анонимного тома докер знает, что тома полностью контролируются сами по себе, поэтому докер может делать все, что он считает правильным (вот копирование файлов на изображение в том). Но именованный том предназначен для плагина тома, поэтому докер не знает, что он должен делать, и ничего не делает.

Источник: Связанная дискуссия о Github

Поэтому вам нужно использовать драйвер тома, который поддерживает то, что действительно можно найти в магазине докеров