Это продолжение предыдущего поста про резервирование. Я решил сделать более интересный вариант:
- резервировать в холодный S3-бакет;
- прикрутить нотификации на телефон об ошибках и успехах резервирования;
- исправить пару недочётов из прошлой версии.
В прошлом посте можешь глянуть исходную версию скрипта. Здесь мы его скорректируем и нарастим вкусным мясом.
Копирование в S3
Эта часть оказалась для меня самой интересной. Я никогда ранее не работал с облачными провайдерами. Они казались мне каким-то страшным лесом: на красивой зелёной лужайке стоит красивая неоновая вывеска, тропа от коей ведёт в бесконечные непроглядные заросли диких растений-хищников, пытающихся сожрать твой кошелёк, и уродливых толстых стволов, к коим по всем конечностям привязаны измученные тела смельчаков с оборванными карманами на уцелевшей одежде и отсутствующими ногтями, истошно бормучащами что-то неразборчивое про вендор-лок.
К тому же, и необходимости-то в этом для меня не было, всегда как-то по-старинке справлялся VPS-ками и не парился. (Хотя, должен признаться, настройка серверов под себя уже выматывает, даже скриптами.)
Почему я всё-таки решил туда сунуться? Это банально выгоднее: если сейчас я использую услугу под бекапы от IHC на 5Гб за 500Р/год (и там обычная убунта с хомяком в /backup/...
), то в облаке за эти деньги на этот срок можно взять холодный S3 + немного исходящего трафика на крайняк.
Выгоднее? В ~20 раз. Интересно? Новый опыт соблазнителен.
Пошёл знакомиться с российскими провайдерами. Нашёл трёх, внушающих доверие:
- VK Cloud Solutions (https://mcs.mail.ru)
этот я приметил первым, просто наткнулся в одной из статей на хабре в блоге VK (не путать сДискомОблаком@Mail.ru); - Яндекс Cloud (https://cloud.yandex.ru)
про этот я просто вспомнил, когда-то слыхивал краем глаза где-то на просторах; - Selectel (https://selectel.ru)
их рекламу я очень часто слышу в подкастах, плюс в разное время использ(овал|ую), теперь уже принадлежащий им, vscale (ныне VDS Selectel).
На текущий момент я выбрал Яндекс потому, что:
- подходит основная учётка Яндекса;
- они дают 3 стартовых килорубля на 2 месяца;
- увидел у них сервис Lockbox для хранения секретов (сейчас встадии превью, не тарифицируется).
Остальные тоже попробую позже, коротко о результатах, пожалуй, напишу в своём канале. Но уже сейчас могу сказать, что VKCS чересчур навязчивые ребята: слишком сильно хотят моих денег, звонят, шлют рассылки «как у нас что угодно».
В целом, дальше на твоё усмотрение. Основная суть — купить холодное S3-хранилище объектов (bucket, storage, везде называется примерно одинаково) и настроить доступ к нему.
Холодные хранилища нужны для длительного хранения неизменяемых объектов (файлов), редкой загрузки и отдачи. Дешевле.
Стандартные (горячие) — для постоянной (пере)записи, загрузки и отдачи множества объектов. Дороже.
В случае с Яндекс.Cloud достаточно сделать следующее:
- зарегистрироваться (если не), опционально — активировать пробный период;
- взять 1 бакет, выставить в его настройках холодный класс хранения;
- создать сервисный аккаунт с нужными правами
storage.
* (я выбрал простоstorage.admin
, но лучше выставить поконкретнее); - создать для него статический ключ, запомнить идентификатор и секрет.
У них настолько хорошая документация, она настолько сильно перелинкована внутри себя, что можно заблудиться и запутаться. Это, пожалуй, во вред, но если надо разобраться — разберёшься. Вся документация по существу, без воды.
Аналогичные действия, полагаю, будут и в других провайдерах по твоему выбору.
Доступ к твоему хранилищу, скорее всего, будет не через scp/rsync или т.п., не по (s)ftp(s), а по http — через curl-запросы, REST API или иначе, это зависит от провайдера, но, как правило, все они (судя по докам) совместимы с амазоновским s3-протоколом.
А что делать нам? У нас весь бекапинг через cli bash скрипт, мы ведь делаем по-простому. Нам API не нужен.
Яндекс предлагает использовать для cli две утилиты: amazon-native aws-cli, либо более универсальный s3cmd. Я решил взять последний, с ним чуть меньше возни. Ставим, настраиваем:
$ sudo apt install -y s3cmd
$ s3cmd --configure
Access Key: <id стат. ключа>
Secret Key: <секрет стат. ключа>
Default Region: ru-central1
S3 Endpoint: storage.yandexcloud.net
DNS-style bucket+hostname:port template for accessing a bucket: %(bucket)s.storage.yandexcloud.net
Encryption password:
Path to GPG program: /usr/bin/gpg
Use HTTPS protocol: True
HTTP Proxy server name:
HTTP Proxy server port: 0
Всё. Для пробы можно что-нибудь скопировать в бакет, поэкспериментировать. Документация здесь (s3cmd --help
).
s3cmd put my/file.txt s3://ya.bucket.name/somedir
s3cmd put -r my/ s3://ya.bucket.name/
# больше примеров -- в доках s3cmd
Веб-морда Яндекса даёт возможность заглянуть в бакет. Много там не поделаешь, это не файловый менеджер: можно выставлять ACL (права доступа) на бакет/объекты и удалять объекты из бакета. Остальной функционал — через сторонние инструменты. Один из таких мы сейчас настроили.
Нотификации
Весьма удобно вовремя знать об успехе или ошибках бекапинга. Оперативность достигается с помощью нотификаций на смартфон. И достигать мы её будем с помощью ntfy.sh.
- Придумываем себе имя канала, на который подпишемся. Рекомендую использовать более-менее уникальное имя, чтобы подобрать его было сложно, ибо по умолчанию каналы публичны. (Хотя их можно закрывать логином-паролем, мне лень.) Проходить процедуры создания канала, регистрации учёток и прочих подтверждений, не требуется.
- Ставим ntfy на смартфон и подписываемся на придуманное название канала.
- Ставим ntfy на сервер для отправки нотификаций.
Собственно, отправка нотификаций в канал nagibator666
очень проста:
ntfy send \
--title "My backup script" \
--message "Проект успешно архивирован!" \
--tags "tada" \
--priority 2 \
nagibator666
Документация достаточно хороша, тулза очень гибкая, задержки или косяки при доставке нотификаций мной не замечались.
Допилинг мелочей
В прошлом посте я указывал некоторые вещи, которые следует улучшить. Из необходимого здесь я решил предусмотреть автоочистку старых бекапов и пропуск отправки несозданных (из-за ошибки) файлов.
Пропуск отправки несозданных архивов
Это очень просто. Если сейчас у нас такая схема:
делаем дамп бд
если ошибка
сообщаем об ошибке
иначе
сообщаем об успехе
конецесли
отправляем дамп бд
если ошибка
сообщаем об ошибке
иначе
сообщаем об успехе
конецесли
то нам надо перетащить отправку повыше:
делаем дамп бд
если успех
сообщаем об успехе
отправляем дамп бд
если успех
сообщаем об успехе
иначе
сообщаем об ошибке
конецесли
иначе
сообщаем об ошибке
конецесли
Автоудаление старых архивов
Над удалением следует посидеть чуть подольше. Первый вопрос: на какое время ты хочешь оставлять бекапы локально и удалённо?
Базово это решается так. Чтобы вывести директории старше пяти дней пишем:
find /backup -type d -mtime +5 | sort
Второй вопрос: как их удалить? Тут есть варианты:
find /backup -type d -mtime +5 -delete
find /backup -type d -mtime +5 -exec rm -rf {} \;
find /backup -type d -mtime +5 | xargs rm -rf
Количество дней и способ удаления — по вкусу, я выбрал последний.
Для удаления на дальнем сервере по ssh следует заключить find и остальное в «кавычки», а в начале дописать что-то типа:
ssh nagibator666@srvbak.com "find и остальное"
Третий вопрос: как быть с s3? В принципе, удалять объекты из бакета довольно легко:
s3cmd rm s3://ya.bucket.name/somedir/somefile
s3cmd rm -r s3://ya.bucket.name/somedir
Но мы заранее не знаем список файлов для удаления, так что нам придётся изловчиться, конечно:
OLDER_THAN=$(date -d "5 days ago" "+%s")
s3cmd ls -r $S3_DIR | while read -r line; do
FILETIME=$(echo "$line" | awk {'print $1" "$2'})
FILETIME=$(date -d "$FILETIME" "+%s")
if [[ $FILETIME -le $OLDER_THAN ]]; then
FILEPATH=$(echo "$line" | awk {'print $4'})
if [ $FILEPATH != "" ]; then
log "$line"
s3cmd del $FILEPATH
fi
fi
done
Подсмотрено здесь. Можно попробовать эксперименты с регулярками и прочим (s3cmd это позволяет), но я не стал заморачиваться.
Рефакторинг
Я давно привык к перебору написанного. Меня всегда не устраивает код, который я пишу. Даже если в моменте я доволен, через N времени я вернусь и всё перехуярю в мясо.
Поэтому я не смог удержаться и привёл в порядок код прошлого скрипта. В тот порядок, который считаю приемлимым сейчас.
Я разодрал скрипт на функции, которые отвечают за свои блоки алгоритма. Плюс насыпал новых переменных для конфигурации: всё, что напрашивалось для настройки и повторялось, теперь наверху и влияет на алгоритмику.
Хотел прикрутить ещё внешний конфиг, но это повлекло бы ещё тонну геморроя и каких-нибудь зависимостей.
А у нас всё должно быть просто. В конечном счёте получился вполне легко читаемый и обслуживаемый скрипт.
Готовый скрипт
Результат в гисте ниже.
Я пока не стал выкашивать работу по SSH, здесь он ещё остался для всякий случай. Но выкосить это несложно.