Статья подготовлена для студентов курса «Администратор Linux» в образовательном проекте OTUS.
Предлагаем вашему вниманию проектную работу одного из студентов OTUS, выполненную им в рамках обучения на курсе «Администратор Linux». Это высокодоступная кластерная файловая система, интегрированная с кластером СУБД, централизованной системой телеметрии, аудита и авторизации.
1. Описание стенда
Для развёртывания всех компонент системы использовался Vagrant, с помощью которого разворачивался стенд, состоящий из 7 виртуальных машин:
— 1 виртуальная машина — центральный сервер телеметрии, аудита и авторизации;
— 6 виртуальных машин — кластерная файловая система, кластер СУБД.
Для экономии ресурсов совместили 3 узла кластера СУБД с узлами кластерной файловой системы. Для развёртывания всех компонент системы использовался Ansible.
Названия виртуальных машин:
• ns.otus.test (ns) — центральный сервер телеметрии, аудита и авторизации;
• master01.otus.test (master01) — узел кластерной ФС, узел кластера СУБД;
• master02.otus.test (master02) — узел кластерной ФС, узел кластера СУБД;
• master03.otus.test (master03) — узел кластерной ФС, узел кластера СУБД;
• node01.otus.test (node01) — узел кластерной ФС;
• node02.otus.test (node04) — узел кластерной ФС;
• node03.otus.test (node03) — узел кластерной ФС.
1.1 Центральный сервер телеметрии, аудита и авторизации
Для устойчивой работы всех компонент стенда была развёрнута первая виртуальная машина, на которую установили следующие сервисы:
• DNS — локальный сервер разрешения имён;
• NTP — локальный сервер точного времени;
• Kerberos — локальный сервер авторизации;
• Prometheus — центральный сервер сбора телеметрии;
• Grafana — сервер визуализации телеметрии;
• Netdata — центральный сервер сбора и визуализации телеметрии в реальном времени;
• Lizardfs-cgi — сервер отображения состояния кластерной файловой системы;
• Lizardfs-client — клиент для подключения к кластерной файловой системе;
• Haproxy — балансировщик нагрузки на кластер СУБД;
• Etcd — key-value база данных для кластера СУБД;
• Auditd — центральный сервер для сбора событий аудита всех компонент системы;
• Nginx — web-сервер, работающий в режиме reverse-proxy;
• Autofs — сервиc автомонтирования сетевых ресурсов.
DNS, NTP, Kerberos и Etcd использовались для интеграции сервисов и их компонент.
1.2 Узлы файловой кластерной системы и кластера СУБД
На всех узлах кластера были развёрнуты следующие вспомогательные сервисы:
• NTP — клиент синхронизации с локальным NTP-сервером;
• Kerberos — kerberos-клиент;
• Auditd — клиент auditd;
• Netdata — клиент сбора телеметрии.
На узлах master01-master03 развернули роли:
• LizardFS Uraft Master Node — lizardfs-mfsmaster, lizardfs-uraft;
• PostgreSQL 11 — сервер PostgreSQL 11;
• TimescaleDB — расширение для PostgreSQL, позволяющее использовать постгрес как TimeseriesDB;
• Patroni — создание кластера PostgreSQL.
На узлах node01-node03 развернули роли:
• LizardFS Node — lizardfs-chunkserver, lizardfs-metalogger;
• LVM — управление томами LVM2.
1.3 Использование стенда
После клонирования репозитория в папке с проектом (otus-homework/project) выполнили vagrant up. После развёртывания стенда стали доступны следующие ресурсы (наружу проброшен порт 8080):
• мониторинг ресурсов узлов кластера в реальном времени — http://localhost:8080/netdata/;
• мониторинг ресурсов узлов кластера http://localhost:8080/prometheus/;
• визуализация телеметрии http://localhost:8080/grafana/:
— необходимо выполнить вход (логин/пароль: admin/admin);
— необходимо добавить источник данных (datasource):
- Name: PostgreSQL;
- Host: ns;
- Database: postgres;
- User/Password: postgres/postgres;
- SSL Mode: disable;
- Version: 10;
- TimescaleDB: checked;
— необходимо выполнить импорт тестового Dasboard sample-netdata-dashboard;
• мониторинг состояния кластера СУБД http://localhost:8080/haproxy/:
— необходимо выполнить вход (логин/пароль: someuser/password);
• мониторинг состояния кластерной файловой системы http://localhost:8080/lizardfs/mfs.cgi?masterport=9421&masterhost=master§ions=CS.
Попадаем в ВМ ns-стенда и выполняем kinit (пароль — vagrant):
$ vagrant ssh ns
$ echo "vagrant" | kinit
$ sudo aureport -x --summary
Далее можно заходить на все ноды кластера без ввода пароля.
2. Компоненты стенда
Общая схема стенда с разделением ролей:
2.1 Высокодоступная кластерная файловая система
Для проекта была выбрана кластерная файловая система LizardFS. Это распределённая, масштабируемая, отказоустойчивая и высокодоступная файловая система. Она позволяет объединять дисковое пространство, расположенное на многих серверах, в единое пространство имён, которое видно в Unix-подобных системах и системах Windows так же, как и в других файловых системах. LizardFS обеспечивает безопасность файлов, сохраняя все данные во многих репликах на доступных серверах. Её также можно использовать для создания доступного хранилища, поскольку она работает без каких-либо проблем на обычном оборудовании.
Отказы дисков и серверов обрабатываются прозрачно, без простоев и потери данных. Если требования к хранилищу растут, можно масштабировать существующую установку LizardFS, просто добавляя новые серверы — в любое время, без простоев. Система автоматически перемещает данные на вновь добавленные серверы, потому что она постоянно заботится о балансировке использования диска на всех подключённых узлах. Удаление серверов так же просто, как добавление нового.
Уникальные функции:
• поддержка многих центров обработки данных и типов носителей,
• быстрые снимки,
• механизмы QoS,
• квоты,
• ...
LizardFS хранит метаданные (например, имена файлов, метки времени изменения, деревья каталогов) и фактические данные отдельно. Метаданные хранятся на серверах метаданных, а данные хранятся на компьютерах, называемых серверами чанков.
Типичная установка состоит из:
• Как минимум двух серверов метаданных, которые работают в режиме master-slave для восстановления после сбоев. Их роль также заключается в управлении всей установкой, поэтому активный сервер метаданных часто называют главным сервером. Роль других серверов метаданных состоит в том, чтобы просто синхронизировать их с активными главными серверами, поэтому их часто называют теневыми главными серверами. Любой теневой мастер-сервер в любое время готов взять на себя роль активного мастер-сервера.
• Сhunkservers, серверов хранения данных. Каждый файл делится на блоки, называемые чанками (каждый размером до 64 Мб), которые хранятся на серверах чанков. Предлагаемая конфигурация сервера чанков — это машина с большим дисковым пространством, доступным в конфигурации JBOD или RAID в зависимости от требований. Процессор и оперативная память не очень важны. У вас могут быть всего 2 чанк-сервера (минимум, чтобы ваши данные были устойчивы к любым сбоям диска) или до сотен из них. Типичный чанксервер имеет 8, 12, 16 или даже более жёстких дисков. Каждый файл может распространяться на серверы чанков в определённом режиме репликации: standard, xor или ec.
• Клиентов, которые используют данные, хранящиеся в LizardFS. Эти машины используют монтирование LizardFS для доступа к файлам при установке и обработке их так же, как файлы на локальных жёстких дисках. Файлы, хранящиеся в LizardFS, могут быть просмотрены и одновременно доступны как можно большему числу клиентов.
Режим репликации каталога или даже файла может быть определён индивидуально:
• Standard. Режим предназначен для явного определения количества копий фрагментов данных, которые вы хотите сохранить в кластере и на определенной группе узлов. В сочетании с «пользовательскими целями» (goals) это удобно для гео-репликации.
• Xor. Похож на механизм репликации, известный в RAID5.
• Ec — erasure coding. Похож на механизм репликации, известный в RAID6.
Отдельный инструмент для обеспечения высокой доступности — LizardFS Uraft, стал доступен OpenSource-сообществу в июле 2018 года. Компонент предназначен для организации высокодоступного кластера файловой системы.
Схема развёртывания кластерной ФС:
• устанавливаем мастер-сервера (ноды master01-master03);
• устанавливаем компонент высокой доступности uraft (ноды master01-master03);
• запускаем uraft, который запускает мастер-сервера на каждой из мастер-нод;
• проводятся выборы, где определяется главный мастер-сервер;
• ноде, на которой определен главный мастер-сервер; назначается плавающий ip;
• остальные мастер-ноды устанавливаются в режим shadow;
• устанавливаем и запускаем чанк сервера (ноды node01-node03), которые соединяются с мастер-сервером.
В нашем примере на ВМ master01-master03 развёрнуты компоненты lizardfs-mfsmaster, lizardfs-uraft. Для обеспечения высокой доступности используется технология floating ip. При остановке главного мастер-сервера происходят выборы, выбирается новый ведущий мастер, которому назначается плавающий ip.
На ВМ node01-node03 развёрнуты компоненты lizardfs-chunkserver, lizardfs-metalogger, к каждой ноде подключен диск, который смонтирован в систему. В конфигурации сервера чанков он определён, как доступный для работы внутри кластерной файловой системы.
На ВМ ns установлен компонент lizardfs-client, lizardfs-admin, lizardfs-cgiserv, с помощью которых монтируется, управляется и мониторится кластерная файловая система. Также установлен сервис autofs для автоматического монтирования ФС в /data/lizard.
Пример монтирования ФС:
Проверка статусов мастер-серверов:
Вывод команды:
Мониторинг состояния файловой системы:
2.2 Кластер СУБД
Схема кластера:
Кластер высокой доступности Postgres. Развёртывание кластера идентично выполненной работе в ДЗ 29.
Разворачиваемые компоненты:
• PostgreSQL 11;
• Patroni;
• TimescaleDB. Однако есть дополнения в виде установки двух расширений для использования Postgres в качестве Timeseries DB (об этом ниже).
Устанавливаются расширения TimescaleDB и pg_prometheus. Первое позволяет сохранять в БД временные ряды, используя при этом партиционирование таблиц, второе позволяет взаимодействовать с системой мониторинга Prometheus. Pg_prometheus пришлось собрать вручную (см. архив pg_prometheus.tar.gz) и написать скрипт инсталляции внутрь Postgres.
Подключение к кластеру (логин/пароль: postgres/postgres):
2.3 Мониторинг
Схема мониторинга:
Мониторинг условно разделён на две части: реального времени и пассивный.
В мониторинге реального времени будем использовать Netdata. Netdata на всех ВМ отличных от центральной (ns.otus.test) настроим в режиме Stream, чтобы генерируемый поток метрик от каждого хоста пересылался центральному серверу Netdata.
Центральный сервер настроим на приём метрик и их визуализацию. Если в нашем кластере происходят аномалии, то будет возможно наблюдать параметры, критичные для системы в реальном времени. У Netdata достаточно широкая функциональность. Конечно, в курсовом проекте её невозможно охватить в полном объеме.
Пассивный мониторинг необходим для спокойного анализа причин возникновения проблем, которые привели к негативным последствиям. Для сбора метрик будем использовать возможность Netdata отдавать метрики в формате Prometheus. На ns.otus.test установим и настроим Prometheus, в prometheus.yml определим endpoints для сбора метрик со всех нод стенда. Вместе с Prometheus установим prometheus-postgresql-adapter — службу, с помощью которой метрики будут записываться в базу данных. Как настроить для этого БД, описано выше.
Схема работы коллектора метрик:
Рrometheus postgresql adapter также можно настроить на работу в режиме высокой доступности. Внутри БД создаётся несколько таблиц (см. структуру таблиц, документация), куда попадают данные мониторинга.
Итого, схема работы пассивного мониторинга: Netdata -> Prometheus -> prometheus-postgresql-adapter -> PostgesSQL+TimescaleDB+pg_prometheus -> Grafana.
На ns.otus.test установим Grafana, создадим для неё демонстрационный dashboard, где будем отображать метрики, получая их с помощью SQL-запросов из БД.
Пример SQL-запроса:
Выберем все значения метрики netdata_system_active_processes_processes_average в интервале 10 минут от текущего значения времени c дискретностью 1 минута (time_bucket — функция timescaleDB), для хоста ns сгруппируем и отсортируем полученные значения.
Готовый пример тестового dashboard.
2.4 Аудит
Аудит системных событий настроен по мотивам ДЗ 14. Все ноды пересылают события аудита на ns.otus.test, список правил аудита генерируется с помощью шаблона.
Общий краткий отчёт о событиях в кластере:
3. Развёртывание инфраструктуры в облаке
3.1 Доступ к Яндекс.Облаку
На локальной машине необходимо установить Yandex.Cloud CLI и выполнить начальные настройки:
В процессе инициализации cli инструмента будут запрошены доступы Яндекс.Облака. Будет создан файл ~/.config/yandex-cloud/config.yaml с данными для доступа к облаку.
3.2 Создание AWS S3 совместимого бакета и сервисного аккаунта
В веб-консоли аккаунта Яндекс.Облака создаём объектное хранилище с именем otus-infra, внутри хранилища создаём папку state. К сожалению, cli-инструментов для этих операции на сегодняшний момент нет.
3.3 Пользователь otus-user, ssh-ключ
На облачную виртуальную машину будем заходить под пользователем otus-user. Сгенерируем для него ssh-ключи:
3.4 Использование стартового скрипта
Скрипт start.sh создаёт первую машину в облаке, с которой будет разворачиваться инфрастукртура проекта. При создании ВМ устанавливаются необходимые инструменты для дальнейшей работы, генерируется файл metadata.yml. Так же внутрь новой ВМ в домашний каталог otus-user клонируется репозиторий инфраструктуры проекта.
Публичная часть ключа otus-user должна быть включена в метаданные создаваемой ВМ.
Metadata — данные, которые будут применены скриптами cloud-init при старте ВМ в Яндекс.Облаке.
После старта ВМ необходимо зайти в нее по SSH и выполнить дальнейшую настройку:
3.5 Настройка первой виртуальной машины в облаке
3.5.1 Доступ к Яндекс.Облаку
Установим Yandex Cloud CLI:
С локальной машины из ~/.config/yandex-cloud/config.yaml возьмём конфигурацию cli (токен для доступа к Облаку) и перенесём на виртуальную в такой же файл и по такому же пути. Как альтернатива — можно выполнить команду yc init, получить токен и т. д.
3.5.2 Настройка и инициализация Terraform, импорт ранее созданных ресурсов
Убедимся, что в бакете отсутствует старый стейт Terraform. Если он есть, то его необходимо удалить для дальнейшей корректной работы при создании новой инфраструктуры.
В директории с кодом инфраструктуры проекта ~/otus-infra необходимо выполнить инициализацию Terraform.
Для работы Terraform с Яндекс.Облаком необходим провайдер. Провайдер устанавливается автоматически при инициализации в директории с проектом, но для этого необходимы учетные данные из ~/.config/yandex-cloud/config.yaml.
На этапе создания первой ВМ был сгенерирован новый ssh-ключ для доступа к новосоздаваемым ресурсам ~/.ssh/otus-user.pub. Этот ключ необходимо добавить в файл, содержащий метаданные виртуальных машин.
Инициализация Terraform выполняется с параметрами, так как мы создаем бэкенд, лежащий в объектном хранилище. Команда инициализации выглядит так:
Необходимо создать сервисного пользователя, назначить ему права на каталог, в котором должна быть развёрнута инфраструктура и находиться уже созданный бакет, а также получить для него ключи доступа.
Вывод команд будет следующим, здесь нам интересны два ключа key_id, secret и service_account_id, которые необходимо зафиксировать в безопасном месте:
Из-за особенностей реализации Яндекс.Облака между назначением прав пользователю на каталог и работой с ним должно пройти примерно 60 секунд.
В терминологии Terraform мы создаём backend для хранения Terraform state, который необходим, если предполагается совместное использование этого инструмента.
На этапе создания стартовой ВМ мы создали виртуальную сеть (my-network) и в ней подсеть (my-subnet). Эти же ресурсы мы описали с помощью терраформ. Заметим, что терраформ ничего не знает о том, что эти ресурсы уже созданы. Поэтому перед развертыванием полной инфраструктуры проекта необходимо выполнить импорт описанных и уже созданных ресурсов:
После этого шага всё готово к развёртыванию полной инфраструктуры проекта.
Для выполнения всех вышеперечисленных операций написан скрипт init.sh, его необходимо выполнить в директории с проектом ~/otus-infra. Скрипт генерирует файлы ~/otus-infra/providers.tf и ~/otus-infra/boostrap/metadata.yml с нужными значениями, создаёт сервисного пользователя и инициализирует Terraform с нужными бэкендом, импортирует уже созданные ресурсы.
В скрипте в переменную CATALOG необходимо подставить имя каталога в облаке, в котором будет происходить развёртывание инфраструктуры (в новосозданном аккаунте обычно это каталог default).
3.5.3 Развёртывание инфраструктуры проекта
Для создания инфраструктуры:
Проверяем:
Дальнейшие шаги состоят в запуске ansible playbooks с нужными ролями для установки кластера LizardFS.
Вот и всё. Подробности реализации и исходный код проекта смотрите в репозитории автора. Там же вы найдёте массу полезных ссылок.