Создание снимков дисков по расписанию с Yandex Cloud Functions

Николай Матросов

    Так как пока что в Облаке отсутсвует нативная возможность настроить создание снимков дисков по расписанию, можно сделать эту функциональность из подручных средств.

    Для начала нужно разметить диски, для которых мы создаем бэкапы. Для этого при помощи интерфейса командной строки YC CLI назначим ему значение атрибута labels.

    yc compute disk update --id ef34spdueq1ps7b37m51 --labels snapshot=1

    Выбранный диск

    Теперь создадим функцию.

    const ycsdk = require("yandex-cloud/api/compute/v1");
    const FOLDER_ID = process.env.FOLDER_ID;
    async function handler(event, context) {
        const snapshotService = new ycsdk.SnapshotService();
        const diskService = new ycsdk.DiskService();
        const diskList = await diskService.list({
            folderId: FOLDER_ID,
        });
        for (const disk of diskList.disks) {
            if ('snapshot' in disk.labels) {
                snapshotService.create({
                    folderId: FOLDER_ID,
                    diskId: disk.id
                });
            }
        }
    }
    exports.handler = handler;
    

    SDK для работы с Яндекс.Облаком по умолчанию доступен в окружении, в котором будет исполняться функция. Поэтому если, как в примере выше, единственной внешней зависимостью функции является yandex-cloud, то node_modules можно не добавлять в архив.

    Если же в зависимостях есть и другие модули, нам потребуется:

    1. Установить модули с указанием платформы Linux. Именно на ней будет запускаться функция в облаке. Так как если модуль использует бинарные зависимости, то по умолчанию они ставятся для той системы, на которой происходит сборка.
    npm install --arch=x64 --platform=linux --target=12.14.0
    
    1. Следующим шагом делаем из кода функции и установленных node_modules архив и заливаем его в Object Storage. Потому что на прямую загрузку архива есть лимит в 3,5 МБ. Но после npm install мы почти наверняка не влезем в этот лимит.

    node_modules

    Теперь можно заливать архив и переходить к следующим шагам:

    • создайте сервисный аккаунт с ролью editor Создание сервисного аккаунта
    • создайте функцию Создание функции
    • создайте триггер Создание триггера

    Отдельно стоит отметить, что триггер ожидает cron-выражение не в linux формате, а в AWS. Документация по формату доступна по ссылке.

    Можно руками запустить функцию и убедиться, что снимок диска создался.

    Тестирование

    Снимок диска

    Приведённое выше решение будет хорошо работать, если у вас в каталоге мало дисков. Но если у вас их хотя бы 16, то вы столкнетесь с тем, что не сможете делать снимки со всех дисков одновременно.

    В Облаке есть квота на количество одновременно запущенных операций. По умолчанию она равна 15. Её, конечно, можно поднять, но рано или поздно вы всё-равно упрётесь в жёсткий лимит. Так что можно подойти к проблеме с другой стороны, и спроектировать чуть более сложную систему бэкапа, которая будет автоматически запускать операции создания снимка, если что-то пойдёт не так и позволит нам не беспокоиться об этой квоте.

    Для этого нам понадобится очередь сообщений и две функции. Первая функция будет запускаться по cron-триггеру и складывать в очередь задачи для второй функции. Вторая же будет вычитывать задачи из очереди сообщений и обрабатывать их, создавая снимки дисков.

    Схема первой функции

    При создании снимка диска в поле expiration_ts будет добавляться время, когда этот снимок можно будет удалять. На основе этой информации ещё одна функция, запускающаяся по cron-триггеру, будет чистить устаревшие снимки.

    Схема второй функции

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