Использование драйвера хранилища BTRFS

Btrfs - это файловая система нового поколения, поддерживающая множество передовых технологий хранения данных, что делает ее подходящей для Docker. Btrfs включена в основное ядро Linux.

Драйвер хранения Docker btrfs использует многие возможности Btrfs для управления образами и контейнерами. Среди этих возможностей - операции на уровне блоков, тонкая инициализация, моментальные снимки «копия на запись» и простота администрирования. Вы можете легко объединить несколько физических блочных устройств в единую файловую систему Btrfs.

В этой статье драйвер хранения Btrfs в Docker обозначается как btrfs, а файловая система Btrfs - как Btrfs.

Примечание

Драйвер хранилища btrfs поддерживается только в Docker Engine - Community на SLES, Ubuntu или Debian.

Пререквизиты

btrfs поддерживается при выполнении следующих предварительных условий:

  • Docker Engine - Community: Для Docker Engine - Community, btrfs рекомендуется только на Ubuntu или Debian.

  • Изменение драйвера хранилища делает все уже созданные контейнеры недоступными на локальной системе. Используйте docker save для сохранения контейнеров и перенесите существующие образы в Docker Hub или частный репозиторий, чтобы впоследствии не пришлось создавать их заново.

  • btrfs требует выделенного блочного устройства хранения, например, физического диска. Это блочное устройство должно быть отформатировано для Btrfs и смонтировано в /var/lib/docker/. Ниже приведены инструкции по настройке, которые помогут вам выполнить эту процедуру. По умолчанию файловая система SLES / отформатирована в BTRFS, поэтому для SLES нет необходимости использовать отдельное блочное устройство, но вы можете сделать это по соображениям производительности.

  • Поддержка btrfs должна существовать в вашем ядре. Чтобы проверить это, выполните следующую команду:

$ grep btrfs /proc/filesystems

btrfs
  • Для управления файловыми системами BTRFS на уровне операционной системы необходима команда btrfs. Если у вас нет этой команды, установите пакет btrfsprogs (SLES) или btrfs-tools (Ubuntu).

Настройте Docker на использование драйвера хранилища btrfs

Эта процедура в основном идентична для SLES и Ubuntu.

  1. Остановка Docker.

  2. Скопируйте содержимое /var/lib/docker/ в резервное место, затем удалите содержимое /var/lib/docker/:

    $ sudo cp -au /var/lib/docker /var/lib/docker.bk
    $ sudo rm -rf /var/lib/docker/*
    
  3. Отформатируйте выделенное блочное устройство или устройства как файловую систему Btrfs. В этом примере предполагается, что вы используете два блочных устройства с именами /dev/xvdf и /dev/xvdg. Дважды проверьте имена блочных устройств, поскольку это разрушительная операция.

    $ sudo mkfs.btrfs -f /dev/xvdf /dev/xvdg
    

    Для Btrfs существует множество других возможностей, включая чередование и RAID. См. Документация по Btrfs.

  4. Монтирование новой файловой системы Btrfs в точке монтирования /var/lib/docker/. Вы можете указать любое из блочных устройств, использованных для создания файловой системы Btrfs.

    $ sudo mount -t btrfs /dev/xvdf /var/lib/docker
    

    Не забудьте сделать изменение постоянным при всех перезагрузках, добавив запись в /etc/fstab.

  5. Скопируйте содержимое /var/lib/docker.bk в /var/lib/docker/.

    $ sudo cp -au /var/lib/docker.bk/* /var/lib/docker/
    
  6. Настройте Docker на использование драйвера хранилища btrfs. Это необходимо, даже если /var/lib/docker/ теперь использует файловую систему Btrfs. Отредактируйте или создайте файл /etc/docker/daemon.json. Если это новый файл, добавьте следующее содержимое. Если это существующий файл, добавьте только ключ и значение, не забывая заканчивать строку запятой, если это не последняя строка перед завершающей фигурной скобкой (}).

    {
      "storage-driver": "btrfs"
    }
    

    См. все варианты хранения для каждого драйвера хранения в справочной документации по демону

  7. Запуск Docker. После его запуска проверьте, что в качестве драйвера хранилища используется btrfs.

    $ docker info
    
    Containers: 0
     Running: 0
     Paused: 0
     Stopped: 0
    Images: 0
    Server Version: 17.03.1-ce
    Storage Driver: btrfs
     Build Version: Btrfs v4.4
     Library Version: 101
    <...>
    
  8. Когда вы будете готовы, удалите каталог /var/lib/docker.bk.

Управление томом Btrfs

Одним из преимуществ Btrfs является простота управления файловыми системами Btrfs без необходимости размонтирования файловой системы или перезапуска Docker.

Когда места становится мало, Btrfs автоматически расширяет том чанками примерно по 1 ГБ.

Чтобы добавить блочное устройство к тому Btrfs, используйте команды btrfs device add и btrfs filesystem balance.

$ sudo btrfs device add /dev/svdh /var/lib/docker

$ sudo btrfs filesystem balance /var/lib/docker

Примечание

Хотя эти операции можно выполнять и при запущенном Docker, производительность при этом страдает. Возможно, лучше запланировать окно отключения для балансировки файловой системы Btrfs.

Как работает драйвер хранения данных btrfs?

Драйвер хранения btrfs работает иначе, чем devicemapper или другие драйверы хранения, поскольку весь ваш каталог /var/lib/docker/ хранится на томе Btrfs.

Слои образа и контейнера на диске

Информация о слоях образов и записываемых слоях контейнеров хранится в /var/lib/docker/btrfs/subvolumes/. Этот подкаталог содержит по одному каталогу для каждого слоя образа или контейнера, причём единая файловая система строится из слоя плюс все его родительские слои. Вложенные тома имеют встроенную функцию копирования при записи, а пространство для них выделяется по требованию из базового пула хранения. Они также могут быть вложенными и моментальными снимками. На диаграмме ниже показаны 4 субтома. Подтом 2» и «Подтом 3» являются вложенными, в то время как «Подтом 4» показывает свое собственное внутреннее дерево каталогов.

пример подтома

Только базовый слой образа хранится как настоящий подтом. Все остальные слои хранятся в виде моментальных снимков, которые содержат только различия, внесенные в этот слой. Можно создавать моментальные снимки моментальных снимков, как показано на рисунке ниже.

диаграмма снимков

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

данные совместного использования моментальных снимков и субтомов

Для максимальной эффективности, когда контейнеру требуется больше места, оно выделяется кусками размером примерно 1 ГБ.

Драйвер хранения Docker btrfs хранит каждый слой образа и контейнер в собственном подтоме Btrfs или моментальном снимке. Базовый слой образа хранится в виде подтома, а дочерние слои образа и контейнеры - в виде снимков. Это показано на диаграмме ниже.

Btrfs container layers

Процесс создания образов и контейнеров на хостах Docker с драйвером btrfs на высоком уровне выглядит следующим образом:

  1. Базовый слой образа хранится в Btrfs subvolume под /var/lib/docker/btrfs/subvolumes.

  2. Последующие слои образов хранятся как Btrfs снимок подтома или снимка родительского слоя, но с изменениями, внесенными этим слоем. Эти изменения хранятся на уровне блоков.

  3. Записываемый слой контейнера представляет собой снимок Btrfs конечного слоя образа с различиями, внесенными запущенным контейнером. Эти различия хранятся на уровне блоков.

Как чтение и запись контейнеров работает с btrfs?

Чтение файлов

Контейнер - это компактный снимок образа. Метаданные в снимке указывают на фактические блоки данных в пуле хранения. Это то же самое, что и в случае с субтомом. Поэтому чтение, выполняемое из моментального снимка, по сути, то же самое, что и чтение из подтома.

Запись файлов

  • Запись новых файлов: Запись нового файла в контейнер вызывает операцию allocate-on-demand для выделения нового блока данных под снимок контейнера. Затем файл записывается в это новое пространство. Операция allocate-on-demand присуща всем операциям записи в Btrfs и аналогична записи новых данных в субтома. В результате запись новых файлов в моментальный снимок контейнера выполняется на скорости, характерной для Btrfs.

  • Модификация существующих файлов: Обновление существующего файла в контейнере - это операция копирования-на-записи (redirect-on-write - терминология Btrfs). Исходные данные считываются из слоя, где файл существует в данный момент, и только измененные блоки записываются в слой контейнера, доступный для записи. Затем драйвер Btrfs обновляет метаданные файловой системы в снимке, чтобы они указывали на эти новые данные. Такое поведение влечет за собой очень незначительные накладные расходы.

  • Удаление файлов или каталогов: Если контейнер удаляет файл или каталог, существующий на нижнем уровне, Btrfs маскирует существование файла или каталога на нижнем уровне. Если контейнер создает файл, а затем удаляет его, эта операция выполняется в самой файловой системе Btrfs, и место освобождается.

При использовании Btrfs запись и обновление большого количества маленьких файлов может привести к низкой производительности.

Производительность Btrfs и Docker

Существует несколько факторов, влияющих на производительность Docker под управлением драйвера хранилища btrfs.

Примечание

Многие из этих факторов смягчаются при использовании томов Docker для тяжелых рабочих нагрузок, связанных с записью, вместо того, чтобы полагаться на хранение данных в записываемом слое контейнера. Однако в случае с Btrfs тома Docker по-прежнему страдают от этих недостатков, если только /var/lib/docker/volumes/ не не поддерживается Btrfs.

  • Кэширование страниц. Btrfs не поддерживает совместное использование кэша страниц. Это означает, что каждый процесс, обращающийся к одному и тому же файлу, копирует его в память хостов Docker. В результате драйвер btrfs может оказаться не лучшим выбором для высокоплотных сценариев использования, таких как PaaS.

  • Маленькие записи. Контейнеры, выполняющие множество мелких записей (такая модель использования соответствует тому, что происходит при запуске и остановке множества контейнеров за короткий промежуток времени), могут привести к плохому использованию чанков Btrfs. Это может преждевременно заполнить файловую систему Btrfs и привести к состоянию out-of-space на вашем хосте Docker. Используйте btrfs filesys show, чтобы внимательно следить за количеством свободного места на устройстве Btrfs.

  • Последовательная запись. Btrfs использует технику журналирования при записи на диск. Это может повлиять на производительность последовательной записи, снижая производительность до 50%.

  • Фрагментация. Фрагментация является естественным побочным продуктом файловых систем типа Btrfs. Множество мелких случайных записей может усугубить эту проблему. Фрагментация может проявляться в виде скачков процессора при использовании твердотельных накопителей или в виде трепета головок при использовании вращающихся дисков. Любая из этих проблем может снизить производительность.

Если версия ядра Linux 3.9 или выше, вы можете включить функцию autodefrag при монтировании тома Btrfs. Протестируйте эту функцию на собственных рабочих нагрузках, прежде чем внедрять ее в производство, так как некоторые тесты показали негативное влияние на производительность.

  • Производительность SSD: Btrfs содержит встроенные оптимизации для SSD-носителей. Чтобы включить эти возможности, смонтируйте файловую систему Btrfs с опцией монтирования -o ssd. Эти оптимизации включают в себя повышение производительности записи на SSD, избегая таких оптимизаций, как оптимизация поиска, которые не применимы к твердотельным носителям.

  • Часто балансируйте файловые системы Btrfs: Используйте утилиты операционной системы, такие как задание `cron для балансировки файловой системы Btrfs регулярно, в непиковые часы. Это возвращает нераспределенные блоки и помогает предотвратить излишнее заполнение файловой системы. Вы не сможете восстановить баланс полностью заполненной файловой системы Btrfs, если не добавите в нее дополнительные физические блочные устройства. См. BTRFS Wiki.

  • Используйте быстрое хранение данных: Твердотельные накопители (SSD) обеспечивают более быстрое чтение и запись, чем вращающиеся диски.

  • Используйте тома для рабочих нагрузок с высокой интенсивностью записи: Тома обеспечивают наилучшую и наиболее предсказуемую производительность при работе с большими объемами записи. Это происходит потому, что они обходят драйвер хранилища и не несут никаких потенциальных накладных расходов, возникающих при тонком выделении ресурсов и копировании при записи. У томов есть и другие преимущества, например, возможность совместного использования данных контейнерами и сохранение данных даже тогда, когда ни один из запущенных контейнеров их не использует.