Выбор дискового хранилища в облаке выглядит простой строчкой в конфигурации, пока первая ночная выгрузка не упрётся в потолок скорости или первая остановка машины не сотрёт рабочие данные. В мире AWS за выбор отвечают два разных класса хранилищ: постоянные сетевые тома EBS и временные диски instance store, физически живущие на хосте машины. Они решают противоположные задачи, стоят по-разному и ведут себя по-разному при перезагрузках и остановках. Разберём их устройство, характерные ловушки производительности и рабочие схемы сочетания, которые закрывают потребности и базы данных, и пакетной обработки.
Два класса хранилищ и их устройство на уровне железа
Том EBS это сетевое устройство: диски живут на отдельной ферме хранения, а машина общается с ними по выделенному каналу. Отсюда главное свойство: том переживает остановку и удаление машины и может переезжать между инстансами, подключаясь и отключаясь на лету. Но сетевая природа имеет цену: каждый ввод вывод проходит через канал, полоса которого ограничена типом самой машины, и даже самый быстрый том упрётся в потолок инстанса, если тот не относится к разряду с выделенной полосой под хранение. У машин с выделенной полосой под хранение сетевой ввод вывод изолирован от остального трафика, поэтому тяжёлая работа с дисками не душит ответы пользователям, а сравнение конфигураций всегда стоит вести по обоим числам сразу: возможностям тома и пропускной способностью машины.
Instance store устроен противоположно: диски физически сидят на том же хосте, что и процессор машины, и машина общается с ними напрямую, без сетевой прослойки. Скорость у такого диска выдающаяся, а плата за неё уже включена в цену инстанса. Обратная сторона расплаты записана в самом названии: хранилище привязано к жизни машины на конкретном хосте, и появление данных там следует считать временным событием.
Внутри EBS есть несколько линеек под разные профили нагрузки, и понимать разницу между ними важнее, чем выбирать между EBS и временным диском. Универсальная линейка gp3 даёт базовую полосу в три тысячи операций ввода вывода в секунду и сто двадцать пять мегабайт в секунду на любой том, а нужную полосу выше базовой можно задать отдельно, не наращивая размер. Это исправление главной боли прежней линейки gp2, где скорость росла только вместе с гигабайтами, а маленькие тома жили на кредитной модели bursts и проседали после всплеска активности, исчерпав накопленные баллы.
Для тяжёлых баз данных существует линейка с заказными операциями, где скорость выписывается явно и достигает сотен тысяч операций в секунду с выдающейся надёжностью на уровне девяти девяток сохранности. Для последовательных потоков вроде журналов и выгрузок есть линейка на магнитных дисках с высокой пропускной способностью, которая дёшево переваривает гигабайты потока, но не пригодна для случайных обращений. Наконец, холодная линейка предназначена для архивов, к которым обращаются редко, и стоит копейки.
Проблема холодных данных после восстановления из снимка
Резервные копии томов хранятся в объектном хранилище, и новый том, созданный из снимка, поднимается за секунды. Подвох в том, что при этом копируются только служебные структуры: реальные блоки подтягиваются с хранилища лениво, при первом обращении к каждому из них. Только что развёрнутый из снимка том формально готов, но первые обращения к каждому участку идут заметно медленнее, чем обычно, и нагрузочный тест на свежей копии базы покажет провалы, которых нет на прогретой машине.
Лечится это прогревом: перед боевой нагрузкой том читают целиком последовательным или случайным чтением, после чего все блоки оказываются на быстром уровне. Облачный сервис предлагает и платную опцию быстрого восстановления из снимка, когда блоки прогреваются заранее, но для большинства задач достаточно одного прохода утилиты проверки или чтения диска в фоне. Практическое правило: развёрнул копию для теста или нового узла прогрей перед нагрузкой, иначе первый отчёт о производительности будет ложью.
Временный диск на хосте и что с ним происходит при остановке
С дисками на хосте поведение зависит от того, что именно случилось с машиной. При перезагрузке, когда машина остаётся на том же хосте, данные на локальных дисках сохраняются, и многим это кажется гарантией. Но остановка с последующим запуском означает переселение на другой хост, и локальные диски нового места оказываются пустыми. То же происходит при отказе железа: хост чинят или заменяют, а содержимое локальных дисков уходит вместе с ним. Именно это расхождение между перезагрузкой и остановкой регулярно ловит тех, кто сложил на временный диск что-то ценное.
Из этого следует простая дисциплина. На локальном диске живут данные одного из двух сортов: либо кэш, который можно отстроить заново без потерь, либо промежуточные результаты задачи, которая переживёт потерю и перезапустится с начала. Ценные данные появляются на временных дисках только как транзит с быстрой выгрузкой наружу. Отдельная ловушка заключается в размерах: объём временных дисков определяется типом машины и не выбирается отдельно, поэтому желание иметь побольше быстрого места тянет за собой более дорогой тип инстанса целиком.
Как проверить реальную скорость диска на машине
Обещания в описаниях типов не заменяют измерения на конкретной машине, потому что итоговая скорость зависит и от тома, и от полосы инстанса, и от характера обращений. Стандартный инструмент для этого называется fio, и короткий прогон отвечает на главный вопрос о реальных возможностях диска:
fio --name=read-test --filename=/mnt/data/testfile \
--size=4G --rw=randread --bs=4k --iodepth=32 --runtime=60 --time_based
fio --name=write-test --filename=/mnt/data/testfile \
--size=4G --rw=randwrite --bs=4k --iodepth=32 --runtime=60 --time_based
Важно запускать проверку на файле нужного размера на реально смонтированном томе, а не на сыром устройстве с рабочими данными: запись в тестовом режиме затирает содержимое. Для сопоставления конфигураций прогон повторяют с одинаковыми параметрами, а результаты сравнивают по устойчивым значениям, а не по пиковым выбросам. Такой прогон перед переводом базы на новую конфигурацию занимает минуты и избавляет от сюрпризов после переезда. В результатах смотрят не только на среднюю скорость, но и на хвосты задержек: среднее число может быть обманчиво ровным, пока отдельные обращения ожидают в очереди в разы дольше остальных. Глубина очереди в тесте подбирается под характер приложения: база данных с редкими запросами живёт в неглубокой очереди и ценит малую задержку, потоковая обработка задирает глубину ради пропускной способности. Полезно сохранить результаты прогонов в журнале проекта: сравнение с прошлыми замерами мгновенно показывает, изменилось ли поведение хранилища после смены типа машины или тома.
Хозяйства со стажем редко выбирают между классами, они сочетают их по ролям:
- корневой том и данные приложений живут на универсальном gp3, который переживает любые переселения и легко расширяется на лету;
- базы данных размещают на gp3 с заказанной полосой или на линейке с явными операциями, а резервирование строят на снимках;
- временные таблицы, промежуточные выгрузки и кэш отдают instance store ради скорости и отсутствия отдельного счёта;
- тяжёлые последовательные потоки вроде журналов и выгрузок кладут на магнитную линейку, экономя на каждом гигабайте потока;
- машины пакетной обработки получают локальные диски как рабочую область, а результат задачи выгружают в объектное хранилище до завершения;
- критичные к отказам кластеры используют тома с одновременным подключением к нескольким машинам, где это поддерживается.
Каждая строчка этого списка описывает устоявшуюся практику, и перенос её в шаблон инфраструктуры занимает минуты. Главное правило сочетания звучит так: постоянное хранится снаружи, быстрое вычисляется на месте, и граница между ними проведена сознательно, а не случайно.
Снимки и живые операции над томами
Отдельная сила постоянных томов это снимки. Копия строится инкрементально: первый снимок переносит всё содержимое, а последующие записывают только изменившиеся блоки, поэтому регулярное резервное копирование не раздувает счёт и не останавливает работу. Из снимка поднимается копия тома в любой зоне, на основе снимка собирается образ для запуска новых машин, а перенос между регионами превращает георезервирование в пару команд. Для баз данных снимки согласовывают с моментом записи, иначе копия получится с несведёнными транзакциями, поэтому либо снимают диск в короткое окно покоя, либо используют механизм согласования на уровне самой базы.
Хранение снимков тоже поддаётся экономике: устаревшие копии удаляют по правилам хранения, оставляя, например, дневные за неделю и недельные за квартал. Автоматизация этого правила занимает несколько строк и избавляет от роста расходов со временем.
Универсальный том расширяется вживую: команду увеличения применяют к работающему диску, и никакие сервисы не останавливаются. Единственный шаг, который легко забыть, происходит внутри операционной системы: файловая система узнаёт о новом пространстве только после отдельной команды расширения, и до неё место числится, но не используется. Для большинства современных файловых систем расширение также выполняется на живом разделе.
У операций изменения есть своё ограничение: один том нельзя менять чаще, чем раз в несколько часов, поэтому серию правок стоит сводить в одну. Понижение размера невозможно в принципе, и это довод в пользу старта с консервативного минимума: вырасти всегда можно, а освободить место, отдав его обратно в счёт, не получится. Скоростные параметры, в отличие от размера, меняются свободно, и подросшая нагрузка на базу лечится заказом полосы без переезда на больший диск.
Практические схемы сочетания и разнесения по назначению
Взрослые конфигурации редко держат всё на одном диске. Системный раздел с программами, раздел данных с растущими файлами и раздел журналов с частой перезаписью имеют разные профили нагрузки и разные требования к сохранности, и разнесение их по отдельным томам даёт сразу три выгоды: пики на одном разделе не мешают другому, резервные правила настраиваются по отдельности, а расширение затрагивает только то, что реально подросло. Журналы вообще удобно выносить на дешёвую последовательную линейку: поток записи там ровный и предсказуемый.
Для машин с временными дисками работает та же логика наоборот: всё, что пересоздаётся без сожалений, стекается на локальный диск, и том постоянного хранения освобождается от мусорного трафика. Разделение по назначению стоит прописать в шаблоне запуска один раз, и каждая новая машина получает правильную раскладку автоматически, без споров о том, куда что положить, на пятой машине фермы.
На что смотреть при выборе в проекте
Первый вопрос при выборе звучит не о скорости, а о судьбе данных: что произойдёт, если машину остановят прямо сейчас. Если ответ устраивает, выбор сводится к профилю нагрузки и цене, если нет решение уже принято в пользу постоянных томов. Второй вопрос касается полосы самой машины: даже идеальный том упрётся в лимит инстанса без выделенной полосы под хранение, и этот лимит стоит проверять по спецификации типа до запуска.
Третий вопрос это рост. Универсальные тома расширяются вживую без остановки, что снимает страх недооценить объём на старте, а вот сужение тома операция невозможная, поэтому стартуют с разумного минимума и растят по факту. Четвёртый вопрос шифрование: включённое на уровне тома шифрование не требует изменений в приложении и почти не влияет на скорость, поэтому для любых данных с требованиями безопасности оно должно быть включено с первого дня, потому что задним числом том не шифруется. Пройденный по всем четырём вопросам чек лист занимает меньше часа, а хранит от ложных ожиданий на месяцы вперёд. Сознательный выбор в этом вопросе отличает хозяйство, где диск подбирают, от хозяйства, где диск достаётся вместе с машиной по умолчанию.