«Из коробки» Elastic такого решения не предлагает, по крайней мере, в версии 5.х. Немного поспрашивав у Гугла Всемогущего, мы решили создать собственный велосипед. Пусть немного неуклюжий, зато родной.
Итак, дано:
Сервер с установленной на нём ОС Linux. На сервере установлен, настроен и работает Elasticsearch версии 5.х, в Elasticsearch хранятся индексы с именами вида project_name-yyyy.mm.dd
Задача:
Архивировать каждый индекс старше N дней, сжав его в отдельный файл для возможности восстановления данного конкретного индекса за нужную дату. По завершению процесса архивирования индекс удалить из Elasticsearch.
Решение
Архивирование индексов
Для работы с индексами нам потребуется curator версии старше 5.0.
Вытаскивать индексы из Elasticsearch будем через снапшоты. Поэтому для начала убедимся, что в файле конфигурации elasticsearch, обычно это файл /etc/elasticsearch/elasticsearch.yml, прописан путь до файлового репозитория:
path.repo: /opt/elasticsearch/snapshots
Если такой строки нет, пропишем и перезагрузим elasticsearch.
Далее создадим репозиторий, в котором мы будем размещать снапшоты:
mkdir -p /opt/elasticsearch/snapshots/repository
curl -XPUT 'http://localhost:9200/_snapshot/repository' -H 'Content-Type: application/json' -d '{
"type": "fs",
"settings": {
"location": "repository",
"compress": true
}
}'
И сразу же создадим ещё один репозиторий с именем «recovery», он нам понадобится для восстановления индексов:
mkdir -p /opt/elasticsearch/snapshots/recovery
curl -XPUT 'http://localhost:9200/_snapshot/recovery' -H 'Content-Type: application/json' -d '{
"type": "fs",
"settings": {
"location": "recovery",
"compress": true
}
}'
Ну и сам скрипт архивирования индексов. Из списка индексов, подлежащих архивированию, исключаем индексы .kibana и elastalert_status. Значения переменных, заданных в шапке скрипта, естественно, можно вытащить наружу и передавать скрипту в качестве аргументов, дело вкуса.
В качестве хранилища архивов в скрипте указана локальная папка, но это, конечно же, не очень хорошая практика, и лучше архивы складывать куда-нибудь подальше в надёжное место.
Процесс архивирования логируется, файл лога задаётся переменной $LOG. Не забывайте настроить ротацию для файла лога.
Логика работы скрипта описана в комментариях. Не забудьте поправить значения переменных, если ваши настройки будут отличаться от дефолтных.
#!/bin/bash
DAYS=31 #Количество дней, от текущей даты, старше которого индексы будут архивироваться
SNAPSHOT_DIRECTORY="/opt/elasticsearch/snapshots"
BACKUP_DIR="/opt/elasticsearch/elasticsearch_backup"
REPOSITORY="repository"
LOG="/var/log/elasticsearch/elasticsearch_backup.log"
DATE=`date`
#Проверим существование папки для архивов и если нет, создадим её
if ! [ -d $BACKUP_DIR ]; then
mkdir -p $BACKUP_DIR
fi
#Получаем массив индексов, которые старше $DAYS
INDICES=`curator_cli --config /etc/elasticsearch/curator-config.yml --host localhost --port 9200 show_indices --filter_list "[{\"filtertype\":\"age\",\"source\":\"creation_date\",\"direction\":\"older\",\"unit\":\"days\",\"unit_count\":\"$DAYS\"},{\"filtertype\":\"kibana\",\"exclude\":\"True\"},{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"elastalert_status\",\"exclude\":\"True\"}]"`
#Проверим, не пустой ли список
TEST_INDICES=`echo $INDICES | grep -q -i "error" && echo 1 || echo 0`
if [ $TEST_INDICES == 1 ]
then
echo "$DATE Не найдено индексов для обработки" >> $LOG
exit
else
# Составляем цикл для каждого индекса в массиве $INDICES
for i in $INDICES
do
# Создаём снапшот для индекса $i
curator_cli --config /etc/elasticsearch/curator-config.yml --timeout 600 --host localhost --port 9200 snapshot --repository $REPOSITORY --filter_list "{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"$i\"}"
# Заносим в переменную имя снапшота для индекса $i
SNAPSHOT=`curator_cli --config /etc/elasticsearch/curator-config.yml --host localhost --port 9200 show_snapshots --repository $REPOSITORY`
# Архивируем папку репозитория и складываем архив в хранилище
cd $SNAPSHOT_DIRECTORY/$REPOSITORY && tar cjf $BACKUP_DIR"/"$i".tar.bz" ./*
# Удаляем snapshot
curator_cli --config /etc/elasticsearch/curator-config.yml --host localhost --port 9200 delete_snapshots --repository $REPOSITORY --filter_list "{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"$SNAPSHOT\"}"
# Удаляем индекс
curator_cli --config /etc/elasticsearch/curator-config.yml --host localhost --port 9200 delete_indices --filter_list "{\"filtertype\":\"pattern\",\"kind\":\"regex\",\"value\":\"$i\"}"
# Очищаем папку репозитория
rm -rf $SNAPSHOT_DIRECTORY/$REPOSITORY/*
done
fi
Удаление устаревших архивов
Отлично! Мы получили архивы индексов в хранилище, но их-то тоже нужно периодически чистить. Сделаем для этого отдельный скрипт /opt/elasticsearch/delete_archives.sh
#!/bin/bash
# Удаление бекапов старше $DAYS дней
# ВАЖНО! В имени файла архива может быть только один знак "-" перед датой. Дата должна быть в формате "yyyy.mm.dd".
# Например: aaa_bbb.ccc-yyyy.mm.dd.tar.bz
DAYS=91
BACKUP_DIR="/opt/elasticsearch/elasticsearch_backup"
#Определяем пороговую дату для удаления архивов
THRESHOLD=$(date -d "$DAYS days ago" +%Y%m%d)
#echo "THRESHOLD=$THRESHOLD"
FILES=`ls -1 $BACKUP_DIR`
TODELETE=`for i in $FILES; do echo $i | awk -F- '{printf "%s\n",$2 ;}' | awk -F. '{printf "%s%s%s \n",$1,$2,$3 ;}' | sed "s/$/$i/"; done`
echo -e "$TODELETE" |while read DATE FILE
do
[[ $DATE -le $THRESHOLD ]] && rm -rf $BACKUP_DIR/$FILE
done
Ну вот, теперь осталось установить скрипты в крон. У нас они выполняются раз в сутки по ночам. Вывод скриптов перенаправим в файл лога
0 1 * * * /bin/bash /opt/elasticsearch/backup_snapshot.sh >> /var/log/elasticsearch/elasticsearch_backup.log
0 3 * * * /bin/bash /opt/elasticsearch/delete_archive.sh >> /var/log/elasticsearch/elasticsearch_backup.log
Восстановление индексов из архива
Процесс восстановления индексов тоже несложный. Для удобства обернём процесс восстановления индекса из архива в скрипт, которому на вход в качестве аргумента будем передавать имя файла архива. Для работы скрипта необходимо установить утилиту jq. Папку репозитория /opt/elasticsearch/snapshots/recovery для восстановления индекса и сам репозиторий в Elasticsearch мы создали ранее.
#!/bin/bash
#Зададим переменные
ARCHIVE=$1
BACKUP_DIR="/opt/elasticsearch/elasticsearch_backup"
RECOVERY_DIR="/opt/elasticsearch/snapshots/recovery/"
# На всякий случай очищаем папку репозитория
rm -rf $RECOVERY_DIR/*
# Разархивируем индекс в папку репозитория
tar xjf $BACKUP_DIR/$ARCHIVE -C $RECOVERY_DIR
# Заносим в переменную $SNAPSHOT имя снапшота в репозиториии
SNAPSHOT=`curl -s -XGET "localhost:9200/_snapshot/recovery/_all?pretty" | jq '.snapshots[0].snapshot' | sed 's/\"//g'`
# Восстанавливаем индекс из снапшота
curl -XPOST "localhost:9200/_snapshot/recovery/$SNAPSHOT/_restore?pretty"
# Нужно выставить небольшую задержку, чтобы Elasticsearch не ругался на удаление восстанавливаемого снапшота
sleep 30
# Удалим снапшот из репозитория
curl -XDELETE "localhost:9200/_snapshot/recovery/$SNAPSHOT?pretty"
# Очистим папку репозитория
rm -rf $RECOVERY_DIR/*
Подводим итог
Мы сделали архивирование каждого индекса в отдельный файл, настроили удаление устаревших архивов и научились восстанавливать индекс за нужную дату из архива.
Можно позволить себе взять с полки пирожок.
Комментарии (11)
Darklord
15.02.2018 20:32Просто оставлю это здесь — elasticsearch-curator
BuddyGlass Автор
16.02.2018 10:27Добрый день!
вы хотите сказать, что в elasticsearch-curator есть описанный функционал из коробки и затея со скриптами — лишние танцы с бубном? Т.е. куратор может не только сделать выборку нужных мне индексов по фильтрам, но и сжать их? Может я что-то пропустил, но если так, буду вам очень благодарен, если укажете в документации к куратору, как это можно сделать. Спасибо.Darklord
16.02.2018 10:57фильтрация есть, для сжатия сможно shrink использовать
BuddyGlass Автор
17.02.2018 16:41Насколько я понимаю, shrink не сжимает данные как таковые. Он лишь позволяет снизить количество шардов, на которые растащен индекс по вашему кластеру. Проще говоря, если в вашем кластере 3 ноды и ваш индекс шардится на все три ноды, а вам нужно на одной из нод освободить место, то shrink вам в помощь.
surkov_nsk
15.02.2018 20:32Здорово, так часто бывает, что надо что-то быстро сделать, нет времени задумываться, и так не хватает понятной инструкции. А тут — вот она)
nightvich
15.02.2018 23:23Некоторое время назад писал скрипт, который позволяет снимать/удалять/восстанавливать снапшоты и индексы за указанный период времени, n последних, разность между снятыми снапшотами и текущими индексами и т.д. Привязка была к формату хранения индексов за период времени в формате ISO week.
chemtech
16.02.2018 07:24Можно ли Вас попросить выложить его на github или куда-нибудь чтобы люди могли пользоваться
olku
17.02.2018 12:26Бесплатная ГУИ-тула, умеет бакап и рестор, может кому пригодится kaizen.artcom-venture.de
Sovigod
А как же дедупликация данных, которая в классическом бекапе из коробки?