Зачем же нужно делать резервные копии? Ведь оборудование весьма и весьма надежное, к тому же есть «облака», которые по надежности лучше физических серверов: при правильной настройке «облачный» сервер запросто переживет отказ инфраструктурного физического сервера, а с точки зрения пользователей сервисов, будет небольшой, еле заметный скачок времени обслуживания. К тому же дублирование информации зачастую требует оплатить «лишнее» процессорное время, дисковую нагрузку, трафик сети.
Идеальная программа работает быстро, не течет по оперативной памяти, не имеет дыр и не существует.
—Неизвестный
Поскольку программы все еще пишутся белковыми разработчиками, а процесс тестирования зачастую отсутствует, плюс поставка программ крайне редко происходит с применением «best practices» (которые сами по себе тоже программы, а следовательно, неидеальны), системным администраторам чаще всего приходится решать задачи, которые звучат кратко, но емко: «вернуть, как было», «привести базу к нормальной работе», «медленно работает — откатываем», а также мое любимое «не знаю что, но почини».
Кроме логических ошибок, которые вылезают в результате небрежной работы разработчиков, либо стечения обстоятельств, а также неполного знания или непонимания мелких особенностей построения программ — в том числе связующих и системных, включая операционные системы, драйвера и прошивки, — есть еще и другие ошибки. Например большинство разработчиков полагается на рантайм, совершенно забывая о физических законах, обойти которые с помощью программ все еще невозможно. Это и бесконечная надежность дисковой подсистемы и вообще любой подсистемы хранения данных (включая оперативную память и кэш процессора!), и нулевое время обработки на процессоре, и отсутствие ошибок при передаче по сети и при обработке на процессоре, и задержки сети, которые равны 0. Не стоит пренебрегать и пресловутым дедлайном, ведь если к нему не успеть — будут проблемы почище нюансов работы сети и диска.
Как же быть с проблемами, которые встают в полный рост и нависают над ценными данными? Живых разработчиков заменить нечем, да и не факт, что можно будет в ближайшее время. С другой стороны, полностью доказать, что программа будет работать как задумано, пока что получилось только у нескольких проектов, и совершенно не обязательно можно будет взять и применить доказательства на другие, схожие проекты. Также подобные доказательства занимают уйму времени, и требуют особых навыков и знаний, а это практически сводит к минимуму возможность их применения с учетом дедлайнов. К тому же мы еще не умеем в сверхбыструю, дешевую и бесконечно надежную технологию хранения, обработки и передачи информации. Подобные технологии, если и существуют, то в виде концептов, либо — чаще всего — только в фантастических книгах и фильмах.
Хорошие художники копируют, великие художники воруют.
—Пабло Пикассо.
Самые удачные решения и удивительно простые вещи обычно происходят там, где встречаются абсолютно несовместимые, на первый взгляд, понятия, технологии, знания, области наук.
Например, у птиц и у самолетов есть крылья, однако несмотря на функциональную схожесть — принцип действия в некоторых режимах совпадает, и технические проблемы решаются аналогично: полые кости, использование прочных и легких материалов и т.п., — результаты абсолютно разные, хоть и весьма похожие. Лучшие образцы, которые мы наблюдаем в нашей технике, также по большей части заимствованы у природы: герметичные отсеки у кораблей и подводных лодок — прямая аналогия с кольчатыми червями; построение raid-массивов и проверка целостности данных — дублирование цепочки ДНК; а также парные органы, независимость работы разных органов от ЦНС (автоматия работы сердца) и рефлексы — автономные системы в Интернет. Конечно брать и применять готовые решения «в лоб» чревато проблемами, но кто знает, может, других решений-то и нет.
Знать бы, где упадешь — соломки подстелил бы!
—Белорусская народная пословица
Значит, резервные копии жизненно необходимы тем, кто желает:
- Иметь возможность восстановить работу своих систем с минимальными простоями, а то и вовсе без них
- Смело действовать, потому что в случае ошибки всегда есть возможность отката
- Свести к минимуму последствия умышленной порчи данных
Любая классификация произвольна. Природа не классифицирует. Классифицируем мы, потому что для нас так удобнее. И классифицируем по данным, которые мы берем также произвольно.
—Жан Брюлер
Независимо от физического способа хранения логическое хранение данных можно условно разделить по 2 способам доступа к этим данным: блочное и файловое. Такое деление в последнее время весьма размыто, ведь чисто блочных, как и чисто файловых, логических хранилищ не существует. Однако для простоты будем считать, что они есть.
Блочное хранение данных подразумевает, что есть физическое устройство, куда записывают данные некоторыми фиксированными порциями, блоками. Доступ к блокам идет по некоторому адресу, каждому блоку соответствует свой адрес в пределах устройства.
Резервная копия обычно делается путем копирования блоков данных. Для обеспечения целостности данных на момент копирования приостанавливается запись новых блоков, а также изменение существующих. Если брать аналогию из обычного мира — ближе всего шкаф с одинаковыми пронумерованными ячейками.
Файловое хранение данных по принципу логического устройства близко к блочному и зачастую организуется поверх. Важные различия — наличие иерархии хранения и человекопонятные имена. Выделяется абстракция в виде файла — именованной области данных, а также каталога — специального файла, в котором хранятся описания и доступы к другим файлам. Файлы могут снабжаться дополнительными метаданными: время создания, флаги доступа и т.п. Резервируют обычно так: ищут измененные файлы, потом копируют их в другое, одинаковое по структуре файловое хранилище. Целостность данных обычно реализуют путем отсутствия файлов, в которые идет запись. Метаданные файлов резервируются аналогично. Ближайшая аналогия — библиотека, в которой есть разделы с разными книгами, а также есть каталог с человекопонятными именами книг.
В последнее время иногда описывают еще один вариант, с которого, в принципе, и началось файловое хранение данных, и у которого есть те же архаичные черты: объектное хранение данных.
От файлового хранения отличается тем, что не имеет вложенности больше одного (плоская схема), а имена файлов хотя и человекочитаемые, но все же больше приспособлены для обработки машинами. При резервном копировании объектные хранилища чаще всего обрабатывают подобно файловым, но изредка есть и другие варианты.
— Есть два вида системных администраторов, те кто не делает резервные копии, и те, кто УЖЕ делает.
— На самом деле три вида: есть еще те, кто проверяет, что резервные копии можно восстановить.—Неизвестный
Также стоит понимать, что сам процесс резервного копирования данных осуществляется программами, поэтому ему присущи все те же минусы, как и другой программе. Чтобы убрать (не исключить!) зависимость от человеческого фактора, а также особенностей — которые по отдельности не сильно влияют, но вместе могут дать ощутимый эффект, — применяют т.н. правило 3-2-1. Есть много вариантов, как его расшифровать, но мне больше нравится следующая трактовка: хранить надо 3 набора одних и тех же данных, 2 набора надо хранить в разных форматах, а также 1 набор надо иметь на географически удаленном хранилище.
Под форматом хранения следует понимать следующее:
- Если есть зависимость от физического способа хранения — меняем физический способ.
- Если есть зависимость от логического способа хранения — меняем логический способ.
Для достижения максимального эффекта правила 3-2-1 рекомендуется менять формат хранения обоими способами.
С точки зрения готовности резервной копии по ее прямому назначению — восстановлению работоспособности, — различают «горячие» и «холодные» резервные копии. Горячие от холодных отличаются только одним: они сразу же готовы к работе, в то время как холодные для восстановления требуют некоторых дополнительных действий: расшифровки, извлечения из архива и т.п.
Не стоит путать горячие и холодные копии с online и offline копиями, которые подразумевают физическую изоляцию данных, и по сути, являются другим признаком классификации способов резервного копирования. Так offline копия — не подключенная непосредственно к системе, где ее надо восстановить, — может быть как горячей, так и холодной (с точки зрения готовности к восстановлению). Online копия может быть доступна непосредственно там, где ее надо восстанавливать, и чаще всего является горячей, но бывают и холодные.
Кроме того, не стоит забывать, что сам процесс создания резервных копий обычно не заканчивается на создании одной резервной копии, а копий может быть достаточно большое число. Следовательно, надо различать полные резервные копии, т.е. те, которые восстановимы независимо от других резервных копий, а также разностные (инкрементальные, дифференциальные, декрементальные и т.п.) копии — те, которые не могут быть восстановлены самостоятельно и требуют предварительного восстановления одной или нескольких других резервных копий.
Разностные инкрементальные копии — попытка сэкономить размер пространства для хранения резервных копий. Таким образом в резервную копию пишутся только измененные данные с прошлой резервной копии.
Разностные декрементальные создаются с той же целью, но немного другим путем: делается полная резервная копия, но реально хранится только разница между свежей копией и предыдущей.
Отдельно стоит рассмотреть процесс резервного копирования поверх хранилища, которое поддерживает отсутствие хранения дубликатов. Таким образом, если писать полные резервные копии поверх него, реально будет записана только разница между резервными копиями, однако процесс восстановления резервных копий будет происходить аналогично восстановлению с полной копии и полностью прозрачно.
Quis custodiet ipsos custodes?
(Кто устережет самих сторожей? — лат.)
Весьма неприятно, когда резервных копий нет, однако гораздо хуже, если резервная копия вроде бы и сделана, но при восстановлении выясняется, что она не может быть восстановлена, потому что:
- Целостность исходных данных была нарушена.
- Хранилище с резервными копиями повреждено.
- Восстановление работает весьма неспешно, нельзя пользоваться данными, которые частично восстановлены.
Правильно построенный процесс резервного копирования обязан учитывать подобные замечания, особенно первые два.
Целостность исходных данных можно гарантировать несколькими способами. Наиболее часто используются следующие: а) создание слепков файловой системы на блочном уровне, б) «заморозка» состояния файловой системы, в) особое блочное устройство с хранением версий, г) последовательная запись файлов или блоков. Также применяются контрольные суммы, чтобы обеспечивать проверку данных при восстановлении.
Повреждения хранилища также можно обнаружить с помощью контрольных сумм. Дополнительный метод — применение специализированных устройств, либо файловых систем, в которых нельзя изменять уже записанные данные, но можно дописывать новые.
Для ускорения восстановления применяется восстановление данных с несколькими процессами для восстановления — при условии, что нет «бутылочного горлышка» в виде медленной сети или небыстрой дисковой системы. Для того, чтобы обойти ситуацию с частично восстановленными данными, можно разбить процесс резервного копирования на относительно небольшие подзадачи, каждая из которых выполняется отдельно. Таким образом, появляется возможность последовательно восстановить работоспособность с прогнозированием времени восстановления. Данная проблема чаще всего лежит в огранизационной плоскости (SLA), поэтому не будем останавливаться на этом подробно.
Знает толк в пряностях не тот, кто добавляет их в каждое блюдо, но тот, кто никогда не добавит в него ничего лишнего.
—В. Синявский
Практика в части применяемого ПО у системных администраторов может различаться, но общие принципы все равно, так или иначе, те же, в частности:
- Настоятельно рекомендуется применять готовые решения.
- Программы должны работать предсказуемо, т.е. не должно быть недокументированных особенностей или узких мест.
- Настройка каждой программы должна быть простой настолько, чтобы не приходилось всякий раз читать руководство или шпаргалку.
- Решение по возможности должно быть универсальным, т.к. сервера по своим аппаратным характеристикам могут различаться весьма и весьма.
Для снятия резервных копий с блочных устройств есть следующие распостраненные программы:
- dd, знакомая ветеранам системного администрирования, сюда же относятся схожие программы (та же dd_rescue, например).
- Встроенные в некоторые файловые системы обслуживающие программы (утилиты), создающие слепок (dump) файловой системы.
- Всеядные утилиты; например, partclone.
- Собственные, зачастую собственнические, решения; например, NortonGhost и более поздние.
Для файловых систем задача резервного копирования частично решается с помощью методов, применимых для блочных устройств, однако задачу можно решить и более эффективно, используя, например:
- Rsync, универсальную программу и протокол для синхронизации состояния файловых систем.
- Встроенные средства для архивации (ZFS).
- Сторонние средства для архивации; самый популярный представитель — tar. Есть и другие, например, dar — замена tar с ориентацией на современные системы.
Отдельно стоит упомянуть о программных средствах обеспечения консистентности данных при создании резервных копий. Чаще всего применяют следующие варианты:
- Монтирование файловой системы в режим только чтение (ReadOnly), или замораживание файловой системы (freeze) — метод применим ограниченно.
- Создание слепков состояния файловой систем или блочного устройства (LVM, ZFS).
- Применение сторонних средств для организации слепков, даже в тех случаях, когда предыдущие пункты не могут быть обеспечены по каким-либо причинам (программы вида hotcopy).
- Техника копирования при изменении (CopyOnWrite), однако она чаще всего привязана к используемой ФС (BTRFS, ZFS).
Итак, для небольшого сервера нужно обеспечить схему резервного копирования, отвечающую следующим требованиям:
- Простая в работе — не требуется особых дополнительных действий при работе, минимальные действия по созданию и восстановлению копий.
- Универсальная — работает как на больших, так и на малых серверах; это важно при росте числа серверов или масштабировании.
- Устанавливается пакетным менеджером, или в одну–две команды вида «скачать и распаковать».
- Стабильная — используется стандартный или уже давно устоявшийся формат хранения.
- Быстрая в работе.
Претенденты из тех, кто более-менее отвечает требованиям:
- rdiff-backup
- rsnapshot
- burp
- duplicati
- duplicity
- deja dup
- dar
- zbackup
- restic
- borgbackup
В качестве тестового стенда будет применяться виртуальная машина (на базе XenServer) со следующими характеристиками:
- 4 ядра 2.5 ГГц,
- 16 гб оперативной памяти,
- 50 гб hybrid storage (СХД с кэшированием на SSD в 20% от размера виртуального диска) в виде отдельного виртуального диска без разметки,
- 200 мбитс канал в Интернет.
В качестве сервера-приемника резервных копий будет применяться практически такая же машина, только с жестким диском на 500 гб.
Операционная система — Centos 7 x64: разбивка стандартная, дополнительный раздел будет использоваться как источник данных.
В качестве исходных данных возьмем сайт на wordpress, с медиафайлами размером 40 гб, базой данных на mysql. Так как виртуальные сервера весьма сильно различаются по характеристикам, а также для лучшей воспроизводимости, здесь есть
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Initializing random number generator from current time
Prime numbers limit: 20000
Initializing worker threads…
Threads started!
CPU speed:
events per second: 836.69
Throughput:
events/s (eps): 836.6908
time elapsed: 30.0039s
total number of events: 25104
Latency (ms):
min: 2.38
avg: 4.78
max: 22.39
95th percentile: 10.46
sum: 119923.64
Threads fairness:
events (avg/stddev): 6276.0000/13.91
execution time (avg/stddev): 29.9809/0.01
sysbench --threads=4 --time=30 --memory-block-size=1K --memory-scope=global --memory-total-size=100G --memory-oper=read memory run
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Initializing random number generator from current time
Running memory speed test with the following options:
block size: 1KiB
total size: 102400MiB
operation: read
scope: global
Initializing worker threads…
Threads started!
Total operations: 50900446 (1696677.10 per second)
49707.47 MiB transferred (1656.91 MiB/sec)
Throughput:
events/s (eps): 1696677.1017
time elapsed: 30.0001s
total number of events: 50900446
Latency (ms):
min: 0.00
avg: 0.00
max: 24.01
95th percentile: 0.00
sum: 39106.74
Threads fairness:
events (avg/stddev): 12725111.5000/137775.15
execution time (avg/stddev): 9.7767/0.10
sysbench --threads=4 --time=30 --memory-block-size=1K --memory-scope=global --memory-total-size=100G --memory-oper=write memory run
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Initializing random number generator from current time
Running memory speed test with the following options:
block size: 1KiB
total size: 102400MiB
operation: write
scope: global
Initializing worker threads…
Threads started!
Total operations: 35910413 (1197008.62 per second)
35068.76 MiB transferred (1168.95 MiB/sec)
Throughput:
events/s (eps): 1197008.6179
time elapsed: 30.0001s
total number of events: 35910413
Latency (ms):
min: 0.00
avg: 0.00
max: 16.90
95th percentile: 0.00
sum: 43604.83
Threads fairness:
events (avg/stddev): 8977603.2500/233905.84
execution time (avg/stddev): 10.9012/0.41
sysbench --threads=4 --file-test-mode=rndrw --time=60 --file-block-size=4K --file-total-size=1G fileio run
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Initializing random number generator from current time
Extra file open flags: (none)
128 files, 8MiB each
1GiB total file size
Block size 4KiB
Number of IO requests: 0
Read/Write ratio for combined random IO test: 1.50
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing random r/w test
Initializing worker threads…
Threads started!
Throughput:
read: IOPS=3868.21 15.11 MiB/s (15.84 MB/s)
write: IOPS=2578.83 10.07 MiB/s (10.56 MB/s)
fsync: IOPS=8226.98
Latency (ms):
min: 0.00
avg: 0.27
max: 18.01
95th percentile: 1.08
sum: 238469.45
Данной заметкой начинается большой
- Резервное копирование, часть 1: Зачем нужно резервное копирование, обзор методов, технологий
- Резервное копирование, часть 2: Обзор и тестирование rsync-based средств резервного копирования
- Резервное копирование, часть 3: Обзор и тестирование duplicity, duplicaty, deja dup
- Резервное копирование, часть 4: Обзор и тестирование zbackup, restic, borgbackup
- Резервное копирование, часть 5: Тестирование bacula и veeam backup for linux
- Резервное копирование, часть 6: Сравнение средств резервного копирования
- Резервное копирование, часть 7: Выводы
Автор: nAbdullin