nav-img
Evolution

Введение

Описание

vhostd — это сервис для операционных систем GNU/Linux, который предоставляет виртуальным машинам QEMU доступ к блочным хранилищам Cloud SDS с использованием протокола vhost-user-blk.

Объединение потоков данных от разных виртуальных машин в рамках одного сервиса позволяет снизить нагрузку на вычислительные узлы (гипервизоры) и значительно уменьшить количество подключений к кластеру Cloud SDS, что улучшает общую производительность для всех клиентов. На рисунке ниже показано сравнение схем подключения виртуальных машин к кластеру.

Схема взаимодействия вычислительных узлов по технологиям vhost и sbd с кластером SDS.

В левой части рисунка процессы виртуальных машин VM-1, VM-2 и VM-3 подключаются к сервису vhostd, который обрабатывает IO-запросы в рамках одного процесса. В правой части каждая виртуальная машина самостоятельно подключается к кластеру.

Затраты на межпроцессное взаимодействие (IPC) между процессами виртуальных машин и сервисом vhostd минимизированы благодаря технологии vhost-user. Процесс виртуальной машины соединяется с сервисом vhostd через unix-domain сокет. Через этот канал передаются управляющие команды (control plane) протокола vhost-user. Важная особенность unix-domain сокетов — возможность обмена файловыми дескрипторами между процессами. Это позволяет организовать общую память (memory sharing) между процессами виртуальных машин и сервисом vhostd.

Технология паравиртуализированных устройств virtio (подробнее) предоставляет общие механизмы для разработки различных типов IO-устройств. Драйверы стандартных устройств virtio, таких как сетевые интерфейсы (virtio-net), блочные устройства (virtio-blk) и другие, реализованы для всех современных операционных систем:

После установления соединения по протоколу vhost-user между процессом виртуальной машины и сервисом vhostd, процесс виртуальной машины предоставляет сервису доступ к памяти драйвера virtio-устройства внутри гостевой ОС. Драйвер устройства в ядре гостевой ОС формирует IO-запросы в соответствии с протоколом virtio и размещает их в общей памяти. Сервис vhostd отслеживает изменения в общей памяти либо в режиме активного опроса (busy polling), либо с использованием прерываний (eventfd). После получения запроса сервис vhostd обрабатывает его и записывает результат обработки в общую память, уведомляя процесс виртуальной машины о завершении операции. Драйвер устройства в ядре гостевой ОС получает результат выполнения операции из общей памяти и продолжает работу. Поскольку передача IO-запросов происходит через общую память без участия ОС гипервизора или других ресурсоемких механизмов IPC, производительность этой технологии сопоставима с другими схемами, использующими паравиртуализированные устройства. Описанная схема взаимодействия показана ниже.

Схема взаимодействия QEMU и сервера vhostd.

Интерфейсы

На рисунке 3 представлена принципиальная схема взаимодействия сервиса vhostd с внешними компонентами. Сервис состоит из одного приложения и набора конфигурационных файлов, которые поставляются в виде единого пакета storage-vhostd. Управление сервисом осуществляется по бинарному протоколу Seastar-RPC, реализованному в приложении storage, которое распространяется в пакете storage-common. Доступ к управлению сервисом ограничен интерфейсом localhost (127.0.0.1) и использует TCP-порт 60100 по умолчанию. Текущая версия протокола управления сервисом vhostd не включает механизмы авторизации и аутентификации пользователей, так как сервис предназначен для работы внутри защищенного периметра и не имеет внешних подключений. В отличие от других подкоманд приложения storage, операции подкоманды storage vhost не требуют файла auth.yml. Однако для корректной работы подкоманды storage vhost необходим актуальный файл mds_list.yml с описанием кластера Cloud SDS.

Сервис подключается к кластеру Cloud SDS через сеть, используя информацию о серверах метаданных из файла /etc/storage/mds_list.yml по умолчанию. Если во время работы сервиса происходит изменение структуры кластера, сервис пытается обновить этот файл в соответствии с текущей конфигурацией. Обновление выполняется атомарно: создается временный файл в той же директории, в него записываются изменения, после чего происходит переименование временного файла в оригинальный. Если по какой-либо причине (например, из-за недостатка прав) заменить оригинальный файл не удается, в директории остается временный файл с именем вида "$NAME.$HEX.tmp", где:

  • $NAME — имя оригинального файла,

  • $HEX — случайное 64-битное число в шестнадцатеричной записи.

Постоянные настройки сервиса хранятся в файлах /etc/storage/vhostd/seastar.conf и /etc/storage/vhostd/vhost.conf. Первый файл содержит настройки реактора/ядра приложения, второй — настройки сервиса vhostd. Описание доступных параметров и их значений приведено в следующем разделе.

Файл со списком подключенных дисков находится в /etc/storage/vhostd/attachments.yml. Команды на создание и удаление подключений от приложения storage приводят к полной перезаписи этого файла. В остальных случаях сервис читает файл подключений только при старте, а затем записывает в него обновления. Запись также выполняется атомарно с использованием временного файла. Сервис может запускаться даже при отсутствии файла подключений на файловой системе. В этом случае сервис считает, что подключенных дисков нет. Подробное описание формата файла и его содержимого приведено в следующем разделе.

Процессы виртуальных машин подключаются к сервису через файлы unix-domain сокетов. Каждое подключение диска создает уникальный сокет в директории /var/lib/storage/. Имя сокета генерируется случайным образом или может быть задано пользователем. Заданные имена проверяются на уникальность — сервис не позволяет создавать несколько подключений с одинаковыми именами. Каждый созданный сокет принимает только одно соединение. Если к сокету уже подключен процесс виртуальной машины и соединение не закрыто, новые подключения к этому сокету не принимаются. Начиная с версии сервиса 1.2.43, при отключении диска соответствующий сокет удаляется с файловой системы.

Внимание

Поскольку unix-domain сокеты в ОС на базе ядра GNU/Linux представлены как файлы, к ним применяются те же правила доступа, что и к обычным файлам. Если пользователь, запускающий сервис, не имеет прав на чтение и запись в сокет, попытка подключения завершается ошибкой. Права доступа к создаваемым сокетам можно настраивать.

Принципиальная схема взаимодействия сервиса vhostd.

Блок-схемы работы сервиса

На рисунке 4 представлена общая высокоуровневая схема работы сервиса vhostd. Из схемы видно, что чтение конфигурационных файлов происходит только при старте приложения, поэтому информация обо всех кластерах, с которыми будет работать сервис, должна быть доступна при запуске. Сервис работает в терминах шардов — независимых потоков выполнения. Каждый шард работает автономно и обслуживает только 1/N часть подключенных дисков, где N — общее количество шардов. Для обеспечения высокой производительности и гарантии отсутствия блокировок при выделении памяти сервис использует собственный аллокатор памяти на основе арен. Каждый шард получает равную долю памяти M/N, где M — заданный верхний предел памяти для всего сервиса. Каждый шард имеет список назначенных ему задач. В любой момент времени шард синхронно выполняет одну задачу или ожидает поступления новых задач. Если шарду назначено несколько задач, он выполняет их последовательно, переключаясь между ними при выполнении IO-операций, что позволяет минимизировать простои процессора.

При старте сервис равномерно распределяет все известные на момент запуска подключения по шардам. Если несколько подключений ссылаются на один и тот же диск, все эти подключения назначаются одному шарду и рассматриваются как единый объект.

При получении команды на подключение диска сервис назначает его шарду с наименьшим количеством уникальных подключенных дисков. Если несколько шардов имеют одинаковое количество подключений, предпочтение отдается шарду с меньшим идентификатором (ID). Например, если шарды с ID=0 и ID=1 имеют одинаковое количество подключений, новый диск будет назначен шарду с ID=0.

При получении команды на удаление подключения команда передается всем шардам. Если у шарда нет такого подключения, он игнорирует команду. Если подключение существует, шард проверяет, что в данный момент к нему не подключена виртуальная машина, и в этом случае удаляет подключение. Если виртуальная машина использует подключение, команда возвращает ошибку «attachment currently in use».

Из-за особенностей протокола vhost-user при миграции виртуальных машин между гипервизорами фактическое обращение к серверам MDS и захват диска происходят только после первого IO-запроса от виртуальной машины. До этого момента сервис использует только информацию о диске без его захвата. Это позволяет освободить диск на исходном гипервизоре до его захвата на целевом.

При запросе списка подключений сервис опрашивает все шарды о текущих подключениях, агрегирует результаты и возвращает их клиенту.

Внимание

Поскольку порядок добавления подключений заранее неизвестен, они распределяются по шардам по мере поступления. Однако при перезапуске сервиса без удаления подключений они могут быть распределены по другим шардам, что необходимо учитывать при анализе журналов.

Блок-схема работы сервиса vhostd.