Курсы

Курсы в разработке Подготовительные курсы
Работа в компаниях Компаниям Блог +7 499 110-61-65

Мощный выпускной проект студента курса «Администратор Linux»

Linux_Deep_8.07_Site-5020-bc9e3c.png

Предлагаем вашему вниманию проектную работу одного из студентов 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&sections=CS.

Попадаем в ВМ ns-стенда и выполняем kinit (пароль — vagrant):

$ vagrant ssh ns
$ echo "vagrant" | kinit
$ sudo aureport -x --summary

Далее можно заходить на все ноды кластера без ввода пароля.

2. Компоненты стенда

Общая схема стенда с разделением ролей:

1.jpg-20219-ab129f.png

2.1 Высокодоступная кластерная файловая система

2.jpg-20219-ddfe4d.pngДля проекта была выбрана кластерная файловая система LizardFS. Это распределённая, масштабируемая, отказоустойчивая и высокодоступная файловая система. Она позволяет объединять дисковое пространство, расположенное на многих серверах, в единое пространство имён, которое видно в Unix-подобных системах и системах Windows так же, как и в других файловых системах. LizardFS обеспечивает безопасность файлов, сохраняя все данные во многих репликах на доступных серверах. Её также можно использовать для создания доступного хранилища, поскольку она работает без каких-либо проблем на обычном оборудовании.

Отказы дисков и серверов обрабатываются прозрачно, без простоев и потери данных. Если требования к хранилищу растут, можно масштабировать существующую установку LizardFS, просто добавляя новые серверы — в любое время, без простоев. Система автоматически перемещает данные на вновь добавленные серверы, потому что она постоянно заботится о балансировке использования диска на всех подключённых узлах. Удаление серверов так же просто, как добавление нового.

Уникальные функции: • поддержка многих центров обработки данных и типов носителей, • быстрые снимки, • механизмы QoS, • квоты, • ...

LizardFS хранит метаданные (например, имена файлов, метки времени изменения, деревья каталогов) и фактические данные отдельно. Метаданные хранятся на серверах метаданных, а данные хранятся на компьютерах, называемых серверами чанков.

Типичная установка состоит из:

• Как минимум двух серверов метаданных, которые работают в режиме master-slave для восстановления после сбоев. Их роль также заключается в управлении всей установкой, поэтому активный сервер метаданных часто называют главным сервером. Роль других серверов метаданных состоит в том, чтобы просто синхронизировать их с активными главными серверами, поэтому их часто называют теневыми главными серверами. Любой теневой мастер-сервер в любое время готов взять на себя роль активного мастер-сервера.

Сhunkservers, серверов хранения данных. Каждый файл делится на блоки, называемые чанками (каждый размером до 64 Мб), которые хранятся на серверах чанков. Предлагаемая конфигурация сервера чанков — это машина с большим дисковым пространством, доступным в конфигурации JBOD или RAID в зависимости от требований. Процессор и оперативная память не очень важны. У вас могут быть всего 2 чанк-сервера (минимум, чтобы ваши данные были устойчивы к любым сбоям диска) или до сотен из них. Типичный чанксервер имеет 8, 12, 16 или даже более жёстких дисков. Каждый файл может распространяться на серверы чанков в определённом режиме репликации: standard, xor или ec.

• Клиентов, которые используют данные, хранящиеся в LizardFS. Эти машины используют монтирование LizardFS для доступа к файлам при установке и обработке их так же, как файлы на локальных жёстких дисках. Файлы, хранящиеся в LizardFS, могут быть просмотрены и одновременно доступны как можно большему числу клиентов.

3.jpg-20219-b1b209.png Режим репликации каталога или даже файла может быть определён индивидуально: • 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.

Пример монтирования ФС:

$ mfsmount -o big_writes,nosuid,nodev,noatime,allow_other -o cacheexpirationtime=500 -o readaheadmaxwindowsize=4096 /mnt

Проверка статусов мастер-серверов:

$ for i in {1..3}; do telnet master0$i 9428; done

Вывод команды:

Trying 192.168.50.21...
Connected to master01.
Escape character is '^]'.
SERVER ID 0
I'M THE BOOSSSS
president=1
state=LEADER
term=586
voted_for=0
leader_id=0
data_version=1
loyalty_agreement=0
local_time=3550745
blocked_promote=0
votes=[       1|       1|       1]
heart=[    0.00|    0.00|    0.00]
recv =[       1|       1|       1]
ver  =[       1|       1|       1]
Connection closed by foreign host.
Trying 192.168.50.22...
Connected to master02.
Escape character is '^]'.
SERVER ID 1
president=0
state=FOLLOWER
term=586
voted_for=0
leader_id=0
data_version=1
loyalty_agreement=1
local_time=3567651
blocked_promote=0
Connection closed by foreign host.
Trying 192.168.50.23...
Connected to master03.
Escape character is '^]'.
SERVER ID 2
president=0
state=FOLLOWER
term=586
voted_for=-1
leader_id=0
data_version=1
loyalty_agreement=1
local_time=3551294
blocked_promote=0
Connection closed by foreign host.

Мониторинг состояния файловой системы:

4.jpg-20219-8ac402.png

2.2 Кластер СУБД

Схема кластера:

5.jpg-20219-aaabfb.pngКластер высокой доступности Postgres. Развёртывание кластера идентично выполненной работе в ДЗ 29. Разворачиваемыt компоненты: • PostgreSQL 11; • Patroni; • TimescaleDB. Однако есть дополнения в виде установки двух расширений для использования Postgres в качестве Timeseries DB (об этом ниже).

Устанавливаются расширения TimescaleDB и pg_prometheus. Первое позволяет сохранять в БД временные ряды, используя при этом партиционирование таблиц, второе позволяет взаимодействовать с системой мониторинга Prometheus. Pg_prometheus пришлось собрать вручную (см. архив pg_prometheus.tar.gz) и написать скрипт инсталляции внутрь Postgres.

Подключение к кластеру (логин/пароль: postgres/postgres):

psql -U postgres -h ns.otus.test

2.3 Мониторинг

Схема мониторинга:

6.jpg-20219-3b4937.pngМониторинг условно разделён на две части: реального времени и пассивный.

В мониторинге реального времени будем использовать Netdata. Netdata на всех ВМ отличных от центральной (ns.otus.test) настроим в режиме Stream, чтобы генерируемый поток метрик от каждого хоста пересылался центральному серверу Netdata.

Центральный сервер настроим на приём метрик и их визуализацию. Если в нашем кластере происходят аномалии, то будет возможно наблюдать параметры, критичные для системы в реальном времени. У Netdata достаточно широкая функциональность. Конечно, в курсовом проекте её невозможно охватить в полном объеме.

7.jpg-20219-86d46e.pngПассивный мониторинг необходим для спокойного анализа причин возникновения проблем, которые привели к негативным последствиям. Для сбора метрик будем использовать возможность Netdata отдавать метрики в формате Prometheus. На ns.otus.test установим и настроим Prometheus, в prometheus.yml определим endpoints для сбора метрик со всех нод стенда. Вместе с Prometheus установим prometheus-postgresql-adapter — службу, с помощью которой метрики будут записываться в базу данных. Как настроить для этого БД, описано выше.

Схема работы коллектора метрик:

8.jpg-20219-0da991.pngРrometheus postgresql adapter также можно настроить на работу в режиме высокой доступности. Внутри БД создаётся несколько таблиц (см. структуру таблиц, документация), куда попадают данные мониторинга.

Итого, схема работы пассивного мониторинга: Netdata -> Prometheus -> prometheus-postgresql-adapter -> PostgesSQL+TimescaleDB+pg_prometheus -> Grafana.

На ns.otus.test установим Grafana, создадим для неё демонстрационный dashboard, где будем отображать метрики, получая их с помощью SQL-запросов из БД.

Пример SQL-запроса:

SELECT
  time_bucket ('1m', time) AS time,
  avg(value) as load_1m
FROM
  metrics
WHERE
  time BETWEEN $__timeFrom() AND $__timeTo()
  AND name = 'netdata_users_cpu_system_percentage_average'
  AND labels @> '{"instance": "ns:19999"}'
  GROUP BY 1
  ORDER BY 1 ASC;

Выберем все значения метрики netdata_system_active_processes_processes_average в интервале 10 минут от текущего значения времени c дискретностью 1 минута (time_bucket — функция timescaleDB), для хоста ns сгруппируем и отсортируем полученные значения.

Готовый пример тестового dashboard.

9.jpg-20219-6a2258.png

2.4 Аудит

Аудит системных событий настроен по мотивам ДЗ 14. Все ноды пересылают события аудита на ns.otus.test, список правил аудита генерируется с помощью шаблона.

Общий краткий отчёт о событиях в кластере:

$ aureport

Summary Report
======================
Skipping line 37 in /etc/audit/auditd.conf: too long
Range of time in logs: 01/01/1970 03:00:00.000 - 04/30/2019 16:26:52.204
Selected time for report: 01/01/1970 03:00:00 - 04/30/2019 16:26:52.204
Number of changes in configuration: 0
Number of changes to accounts, groups, or roles: 3
Number of logins: 2
Number of failed logins: 0
Number of authentications: 4
Number of failed authentications: 0
Number of users: 2
Number of terminals: 8
Number of host names: 4
Number of executables: 20
Number of commands: 22
Number of files: 30
Number of AVC's: 0
Number of MAC events: 2
Number of failed syscalls: 18015
Number of anomaly events: 0
Number of responses to anomaly events: 0
Number of crypto events: 25
Number of integrity events: 0
Number of virt events: 0
Number of keys: 0
Number of process IDs: 14866
Number of events: 36719

3. Развёртывание инфраструктуры в облаке

3.1 Доступ к Яндекс.Облаку

На локальной машине необходимо установить Yandex.Cloud CLI и выполнить начальные настройки:

$ curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash && source "/home/otus-user/.bashrc"
$ yc init

В процессе инициализации cli инструмента будут запрошены доступы Яндекс.Облака. Будет создан файл ~/.config/yandex-cloud/config.yaml с данными для доступа к облаку.

3.2 Создание AWS S3 совместимого бакета и сервисного аккаунта

В веб-консоли аккаунта Яндекс.Облака создаём объектное хранилище с именем otus-infra, внутри хранилища создаём папку state. К сожалению, cli-инструментов для этих операции на сегодняшний момент нет.

3.3 Пользователь otus-user, ssh-ключ

На облачную виртуальную машину будем заходить под пользователем otus-user. Сгенерируем для него ssh-ключи:

$ ssh-keygen -t rsa -b 4096 -f /home/otus-user/.ssh/otus-user-key -q -N ""

3.4 Использование стартового скрипта

Скрипт start.sh создаёт первую машину в облаке, с которой будет разворачиваться инфрастукртура проекта. При создании ВМ устанавливаются необходимые инструменты для дальнейшей работы, генерируется файл metadata.yml. Так же внутрь новой ВМ в домашний каталог otus-user клонируется репозиторий инфраструктуры проекта.

Публичная часть ключа otus-user должна быть включена в метаданные создаваемой ВМ.

Metadata — данные, которые будут применены скриптами cloud-init при старте ВМ в Яндекс.Облаке.

После старта ВМ необходимо зайти в нее по SSH и выполнить дальнейшую настройку:

$ ssh -i ~/.ssh/otus-user-key otus-user@$(yc compute instance get bastion --format json | jq -r '.network_interfaces[].primary_v4_address.one_to_one_nat.address')

3.5 Настройка первой виртуальной машины в облаке

3.5.1 Доступ к Яндекс.Облаку

Установим Yandex Cloud CLI:

$ curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash && source "/home/otus-user/.bashrc"

С локальной машины из ~/.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 выполняется с параметрами, так как мы создаем бэкенд, лежащий в объектном хранилище. Команда инициализации выглядит так:

$ terraform init -backend-config="access_key=key_id" -backend-config="secret_key=secret" -backend-config="bucket=state"

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

$ yc iam service-account create --name otus-user
$ yc iam access-key create --service-account-name otus-user
$ yc resource-manager folder add-access-binding **ИМЯ_КАТАЛОГА** --role editor --subject serviceAccount:**service_account_id**

Вывод команд будет следующим, здесь нам интересны два ключа key_id, secret и service_account_id, которые необходимо зафиксировать в безопасном месте:

access_key:
 ...
 **key_id:** xxx...xxx
 **secret:** xxx....xxxxxx

Из-за особенностей реализации Яндекс.Облака между назначением прав пользователю на каталог и работой с ним должно пройти примерно 60 секунд.

В терминологии Terraform мы создаём backend для хранения Terraform state, который необходим, если предполагается совместное использование этого инструмента.

На этапе создания стартовой ВМ мы создали виртуальную сеть (my-network) и в ней подсеть (my-subnet). Эти же ресурсы мы описали с помощью терраформ. Заметим, что терраформ ничего не знает о том, что эти ресурсы уже созданы. Поэтому перед развертыванием полной инфраструктуры проекта необходимо выполнить импорт описанных и уже созданных ресурсов:

$ terraform import yandex_vpc_network.my-network network_id
$ terraform import yandex_vpc_subnet.my-subnet subnet_id

После этого шага всё готово к развёртыванию полной инфраструктуры проекта.

Для выполнения всех вышеперечисленных операций написан скрипт init.sh, его необходимо выполнить в директории с проектом ~/otus-infra. Скрипт генерирует файлы ~/otus-infra/providers.tf и ~/otus-infra/boostrap/metadata.yml с нужными значениями, создаёт сервисного пользователя и инициализирует Terraform с нужными бэкендом, импортирует уже созданные ресурсы.

В скрипте в переменную CATALOG необходимо подставить имя каталога в облаке, в котором будет происходить развёртывание инфраструктуры (в новосозданном аккаунте обычно это каталог default).

3.5.3 Развёртывание инфраструктуры проекта

Для создания инфраструктуры:

$ terraform plan
$ terraform apply

Проверяем:

$ terraform state list

10.jpg-20219-c33549.pngДальнейшие шаги состоят в запуске ansible playbooks с нужными ролями для установки кластера LizardFS.

Вот и всё. Подробности реализации и исходный код проекта смотрите в репозитории автора. Там же вы найдёте массу полезных ссылок.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться