Развертывание отказоустойчивой архитектуры с прерываемыми виртуальными машинами
В этом руководстве вы создадите функцию Yandex Cloud Functions на языке Node.js, которая будет вызываться по расписанию и запускать прерываемую ВМ Yandex Compute Cloud, если ВМ остановлена.
Описанная в руководстве архитектура подходит для ВМ с некритичной нагрузкой. Архитектура позволяет использовать ценовое преимущество тарифов на прерываемые ВМ и при этом в случае отключения ВМ обеспечивать время простоя не более одной минуты.
Чтобы развернуть отказоустойчивую архитектуру с прерываемой ВМ:
- Подготовьте окружение.
- Подготовьте ZIP-архив с кодом функции.
- Создайте функцию.
- Создайте триггер.
- Протестируйте работу функции.
Если созданные ресурсы вам больше не нужны, удалите их.
Перед началом работы
Зарегистрируйтесь в Yandex Cloud и создайте платежный аккаунт:
- Перейдите в консоль управления
, затем войдите в Yandex Cloud или зарегистрируйтесь. - На странице Yandex Cloud Billing
убедитесь, что у вас подключен платежный аккаунт, и он находится в статусеACTIVE
илиTRIAL_ACTIVE
. Если платежного аккаунта нет, создайте его и привяжите к нему облако.
Если у вас есть активный платежный аккаунт, вы можете создать или выбрать каталог, в котором будет работать ваша инфраструктура, на странице облака
Подробнее об облаках и каталогах.
Необходимые платные ресурсы
В стоимость поддержки инфраструктуры входят:
- Плата за вычислительные ресурсы ВМ (см. тарифы Compute Cloud).
- Плата за диски ВМ (см. тарифы Compute Cloud).
- Плата за использование динамического или статического публичного IP-адреса (см. тарифы Yandex Virtual Private Cloud).
- Плата за хранение секрета и запросы к нему (см. тарифы Yandex Lockbox).
- Плата за количество вызовов функции, вычислительные ресурсы, выделенные для выполнения функции, и исходящий трафик (см. тарифы Cloud Functions).
- Плата за запись и хранение данных в лог-группе (см. тарифы Yandex Cloud Logging), если вы используете сервис Cloud Logging.
Подготовьте окружение
- Создайте сервисный аккаунт, от имени которого будет вызываться функция, и назначьте ему роли
functions.functionInvoker
иlockbox.payloadViewer
. - Создайте прерываемую ВМ.
Создайте секрет
Создайте секрет Yandex Lockbox для хранения OAuth-токена.
Примечание
Используйте OAuth-токен, если у вас нет возможности автоматически запрашивать IAM-токен. IAM-токен обновляется чаще, поэтому более безопасен.
- В консоли управления
выберите каталог, в котором хотите создать секрет. - В списке сервисов выберите Lockbox.
- Нажмите кнопку Создать секрет.
- В поле Имя введите имя секрета, например
oauth-token
. - В поле Тип секрета выберите
Пользовательский
. - В блоке Версия:
- В поле Ключ введите
key_token
. - В поле Значение введите значение OAuth-токена
, необходимого для авторизации функции.
- В поле Ключ введите
- Нажмите кнопку Создать.
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра --folder-name
или --folder-id
.
Чтобы создать секрет, выполните команду:
yc lockbox secret create --name oauth-token \
--payload "[{'key': 'key_token', 'text_value': '<OAuth-токен>'}]"
Где text_value
— значение OAuth-токена
Результат:
done (1s)
id: e6qu9ik259lb********
folder_id: b1g9d2k0itu4********
...
status: ACTIVE
payload_entry_keys:
- key_token
-
Опишите в конфигурационном файле параметры секрета:
resource "yandex_lockbox_secret" "oauth-token" { name = "oauth-token" } resource "yandex_lockbox_secret_version" "my_version" { secret_id = yandex_lockbox_secret.my_secret.id entries { key = "key_token" text_value = "<OAuth-токен>" } }
Где:
name
— имя секрета.key
— ключ секрета.text_value
— значение OAuth-токена , необходимого для авторизации функции.
Примечание
Рекомендуется использовать ресурс
yandex_lockbox_secret_version_hashed
, он хранит в состоянии Terraform значения в хешированном виде. Поддержка ресурсаyandex_lockbox_secret_version
остается.Более подробную информацию о ресурсе
yandex_lockbox_secret_version_hashed
см. в документации провайдера .Более подробную информацию о параметрах используемых ресурсов в Terraform см. в документации провайдера:
-
Проверьте корректность конфигурационных файлов.
-
В командной строке перейдите в папку, где вы создали конфигурационный файл.
-
Выполните проверку с помощью команды:
terraform plan
Если конфигурация описана верно, в терминале отобразится список создаваемых ресурсов и их параметров. Если в конфигурации есть ошибки, Terraform на них укажет.
-
-
Разверните облачные ресурсы.
-
Если в конфигурации нет ошибок, выполните команду:
terraform apply
-
Подтвердите создание секрета: введите в терминал слово
yes
и нажмите Enter.
-
Чтобы создать секрет, воспользуйтесь методом REST API create для ресурса Secret или вызовом gRPC API SecretService/Create.
Подготовьте ZIP-архив с кодом функции
-
Сохраните следующий код в файл с названием
index.js
:import { serviceClients, Session, cloudApi } from '@yandex-cloud/nodejs-sdk'; const { compute: { instance_service: { ListInstancesRequest, GetInstanceRequest, StartInstanceRequest, }, instance: { IpVersion, }, }, } = cloudApi; const FOLDER_ID = process.env.FOLDER_ID; const INSTANCE_ID = process.env.INSTANCE_ID; const OAUTHTOKEN = process.env.OAUTHTOKEN; export const handler = async function (event, context) { const session = new Session({ oauthToken: OAUTHTOKEN }); const instanceClient = session.client(serviceClients.InstanceServiceClient); const list = await instanceClient.list(ListInstancesRequest.fromPartial({ folderId: FOLDER_ID, })); const state = await instanceClient.get(GetInstanceRequest.fromPartial({ instanceId: INSTANCE_ID, })); var status = state.status if (status == 4){ const startcommand = await instanceClient.start(StartInstanceRequest.fromPartial({ instanceId: INSTANCE_ID, })); } return { statusCode: 200, body: { status } }; };
-
Сохраните следующий код в файл с названием
package.json
:{ "name": "my-awesome-package", "version": "1.0.0", "type": "module", "dependencies": { "@yandex-cloud/nodejs-sdk": "latest" } }
-
Добавьте файлы
index.js
иpackage.json
в ZIP-архивfunction-js.zip
.
Создайте функцию
- В консоли управления
перейдите в каталог, в котором хотите создать функцию. - В списке сервисов выберите Cloud Functions.
- Создайте функцию:
- Нажмите кнопку Создать функцию.
- В открывшемся окне введите имя функции
function-restart-vms
. - Нажмите кнопку Создать.
- Создайте версию функции:
- Выберите среду выполнения
nodejs18
, отключите опцию Добавить файлы с примерами кода и нажмите кнопку Продолжить. - В поле Способ выберите
ZIP-архив
. - В поле Файл нажмите кнопку Прикрепить файл и выберите архив
function-js.zip
, который создали ранее. - Укажите точку входа
index.handler
. - В блоке Параметры укажите:
- Таймаут, c —
3
. - Память —
128 МБ
. - Сервисный аккаунт — выберите созданный ранее сервисный аккаунт с правами на вызов функции.
- Переменные окружения:
FOLDER_ID
— идентификатор каталога, в котором вы хотите запускать остановленные ВМ.INSTANCE_ID
— идентификатор ВМ, которую вы хотите запускать при прерывании.
- Секреты Lockbox:
- В поле Переменная окружения укажите
OAUTHTOKEN
. - В поле Идентификатор секрета выберите созданный ранее секрет
oauth-token
. - В поле Идентификатор версии выберите версию секрета.
- В поле Ключ секрета выберите имя ключа
key_token
.
- В поле Переменная окружения укажите
- Если вы не хотите сохранять логи и платить за использование сервиса Cloud Logging, в блоке Логирование, в поле Назначение, выберите
Не задано
, чтобы отключить логирование.
- Таймаут, c —
- Нажмите кнопку Сохранить изменения.
- Выберите среду выполнения
-
Создайте функцию
function-restart-vms
:yc serverless function create --name function-restart-vms
Результат:
id: d4ebrmenrr7l******** folder_id: b1g9d2k0itu4******** created_at: "2023-10-28T17:26:58.200799757Z" name: function-restart-vms http_invoke_url: https://functions.yandexcloud.net/d4ebrmenrr7l******** status: ACTIVE
-
Создайте версию функции
function-restart-vms
:yc serverless function version create \ --function-name function-restart-vms \ --memory=128m \ --execution-timeout=3s \ --runtime=nodejs18 \ --entrypoint=index.handler \ --service-account-id=<идентификатор_сервисного_аккаунта> \ --environment FOLDER_ID=<идентификатор_каталога>,INSTANCE_ID=<идентификатор_ВМ> \ --secret name=oauth-token,version-id=<идентификатор_версии_секрета>,key=key_token,environment-variable=OAUTHTOKEN \ --source-path=./function-js.zip \ --no-logging
Где:
--function-name
— имя функции, версия которой создается.--memory
— объем RAM.--execution-timeout
— максимальное время выполнения функции до таймаута.--runtime
— среда выполнения.--entrypoint
— точка входа.--service-account-id
— идентификатор сервисного аккаунта с правами на вызов функции.--environment
— переменные окружения:FOLDER_ID
— идентификатор каталога, в котором вы хотите запускать остановленные ВМ.INSTANCE_ID
— идентификатор ВМ, которую вы хотите запускать при прерывании.
--secret
— данные секрета Yandex Lockbox:name
— имя секрета.version-id
— идентификатор версии секрета.key
— ключ секрета.environment-variable
— переменная окружения, в которой будет храниться секрет.
--source-path
— путь к созданному ранее ZIP-архивуfunction-js.zip
.- (опционально)
--no-logging
— укажите этот флаг, если вы не хотите сохранять логи и платить за использование сервиса Cloud Logging.
Результат:
done (16s) id: d4etv5f4sjet******** function_id: d4ebrmenrr7l******** ... log_options: disabled: true folder_id: b1g9d2k0itu4********
Если у вас еще нет Terraform, установите его и настройте провайдер Yandex Cloud.
-
Опишите в конфигурационном файле параметры функции
function-restart-vms
и ее версии:resource "yandex_function" "function-restart-vms" { name = "function-restart-vms" user_hash = "first function" runtime = "nodejs18" entrypoint = "index.handler" memory = "128" execution_timeout = "3" service_account_id = "<идентификатор_сервисного_аккаунта>" folder_id = "<идентификатор_каталога>" environment = { FOLDER_ID = "<идентификатор_каталога>" INSTANCE_ID = "<идентификатор_ВМ>" } secrets { id = "<идентификатор_секрета>" version_id = "<идентификатор_версии_секрета>" key = "key_token" environment_variable = "OAUTHTOKEN" } content { zip_filename = "./function-js.zip" } }
Где:
name
— имя функции.user_hash
— произвольная строка, определяющая версию функции.runtime
— среда выполнения функции.entrypoint
— точка входа.memory
— объем памяти в мегабайтах, отведенный для выполнения функции.execution_timeout
— таймаут выполнения функции.service_account_id
— идентификатор сервисного аккаунта с правами на вызов функции.folder_id
— идентификатор каталога, в котором вы создаете функцию.environment
— переменные окружения:FOLDER_ID
— идентификатор каталога, в котором вы хотите запускать остановленные ВМ.INSTANCE_ID
— идентификатор ВМ, которую вы хотите запускать при прерывании.
secrets
— данные секрета Yandex Lockbox:id
— идентификатор секрета.version_id
— идентификатор версии секрета.key
— ключ секрета.environment_variable
— переменная окружения, в которой будет храниться секрет.
zip_filename
— путь к созданному ранее ZIP-архивуfunction-js.zip
.
Более подробную информацию о параметрах ресурса
yandex_function
см. в документации провайдера . -
Проверьте корректность конфигурационных файлов.
-
В командной строке перейдите в папку, где вы создали конфигурационный файл.
-
Выполните проверку с помощью команды:
terraform plan
Если конфигурация описана верно, в терминале отобразится список создаваемых ресурсов и их параметров. Если в конфигурации есть ошибки, Terraform на них укажет.
-
-
Разверните облачные ресурсы.
-
Если в конфигурации нет ошибок, выполните команду:
terraform apply
-
Подтвердите создание функции: введите в терминал слово
yes
и нажмите Enter.После этого в указанном каталоге будет создана функция
function-restart-vms
. Проверить появление ресурсов и их настройки можно в консоли управления или с помощью команды CLI:yc serverless function get function-restart-vms
Результат:
id: d4ees84gsdsd******** folder_id: b1g9d2k0itu4******** created_at: "2023-08-09T10:11:40.740Z" name: function-restart-vms log_group_id: ckgjitlio5aj******** http_invoke_url: https://functions.yandexcloud.net/d4ees84gsdsd******** status: ACTIVE
-
Чтобы создать функцию, воспользуйтесь методом create для ресурса Function или вызовом gRPC API FunctionService/Create.
Чтобы создать версию функцию, воспользуйтесь методом createVersion для ресурса Function или вызовом gRPC API FunctionService/CreateVersion.
Создайте триггер
Примечание
Триггер начинает работать в течение 5 минут после создания.
- В консоли управления
перейдите в каталог, в котором хотите создать триггер. - В списке сервисов выберите Cloud Functions.
- На панели слева выберите
Триггеры. - Нажмите кнопку Создать триггер.
- В блоке Базовые параметры:
- Введите имя триггера —
timer
. - В поле Тип выберите
Таймер
. - В поле Запускаемый ресурс выберите
Функция
.
- Введите имя триггера —
- В блоке Настройки таймера введите
* * ? * * *
или выберитеКаждую минуту
. - В блоке Настройки функции выберите функцию
function-restart-vms
и укажите:- Тег версии функции —
$latest
. - Сервисный аккаунт с правами на вызов функции, который создали ранее.
- Тег версии функции —
- Нажмите кнопку Создать триггер.
Чтобы создать триггер, который вызывает функцию, выполните команду:
yc serverless trigger create timer \
--name timer \
--cron-expression '* * ? * * *' \
--invoke-function-name function-restart-vms \
--invoke-function-service-account-id <идентификатор_сервисного_аккаунта>
Где:
--name
— имя триггера.--cron-expression
— расписание вызова функции в формате cron-выражения.--invoke-function-name
— имя вызываемой функции.--invoke-function-service-account-id
— идентификатор сервисного аккаунта с правами на вызов функции.
Результат:
id: a1sv54ekvknb********
folder_id: b1g9d2k0itu4********
created_at: "2023-08-08T19:46:22.860681482Z"
...
function_tag: $latest
service_account_id: ajeh2dukocg3********
status: ACTIVE
Чтобы создать триггер, который запускает функцию:
-
Опишите в конфигурационном файле параметры триггера
timer
:resource "yandex_function_trigger" "timer" { name = "timer" timer { cron_expression = "* * ? * * *" } function { id = "<идентификатор_функции>" service_account_id = "<идентификатор_сервисного_аккаунта>" } }
Где:
name
— имя триггера.cron_expression
— расписание вызова функции в формате cron-выражения.id
— идентификатор функции, которую будет запускать триггер.service_account_id
— идентификатор сервисного аккаунта с правами на вызов функции.
Более подробную информацию о параметрах ресурсов в Terraform см. в документации провайдера
. -
Проверьте корректность конфигурационных файлов.
-
В командной строке перейдите в папку, где вы создали конфигурационный файл.
-
Выполните проверку с помощью команды:
terraform plan
Если конфигурация описана верно, в терминале отобразится список создаваемых ресурсов и их параметров. Если в конфигурации есть ошибки, Terraform на них укажет.
-
-
Разверните облачные ресурсы.
-
Если в конфигурации нет ошибок, выполните команду:
terraform apply
-
Подтвердите создание ресурсов: введите в терминал слово
yes
и нажмите Enter.После этого в указанном каталоге будет создан триггер
timer
. Проверить появление ресурсов и их настройки можно в консоли управления или с помощью команды CLI:yc serverless trigger get timer
Результат:
id: a1s4bvdvmod0******** folder_id: b1g9d2k0itu4******** created_at: "2023-08-09T10:19:12.356Z" ... function_id: d4ebrmenrr7l******** service_account_id: ajeh2dukocg3******** status: ACTIVE
-
Чтобы создать таймер, воспользуйтесь методом REST API create для ресурса Trigger или вызовом gRPC API TriggerService/Create.
Протестируйте работу функции
- В консоли управления
перейдите в каталог, в котором создана ваша прерываемая ВМ. - В списке сервисов выберите Compute Cloud.
- На панели слева выберите Виртуальные машины.
- Напротив имени нужной ВМ нажмите значок
и выберите Остановить. - В открывшемся окне нажмите кнопку Остановить. Статус ВМ изменится на
Stopped
. - Проверьте состояние ВМ через 1 минуту или более. Статус ВМ должен измениться на
Running
.
Как удалить созданные ресурсы
Чтобы перестать платить за созданные ресурсы:
- Удалите триггер.
- Удалите функцию.
- Удалите секрет.
- Удалите ВМ.
- Если вы записывали логи в лог-группу, удалите ее.