Статьи

Создание лямбда-функции AWS для остановки и запуска экземпляра RDS

В мире Amazon Web Services (AWS) является довольно распространенной практикой, когда экземпляр службы реляционной базы данных (RDS) работает только в определенные пиковые периоды, а в другое время удобно отключается. Я хотел использовать AWS Lambda, используя Python, чтобы иметь возможность запускать и останавливать экземпляр RDS, и хотел, чтобы имя экземпляра БД было параметризовано как переменная среды. Поэтому, когда я перемещаю код из Dev в QA в Production, я могу изменить имя базы данных в переменной среды без необходимости изменения кода. Я предполагаю, что можно использовать одну и ту же технику для запуска и остановки разных типов экземпляров, таких как MySQL, MariaDB или PostgreSQL.

Итак, начнем.

Лямбда-функция для остановки экземпляра RDS

Шаг 1. Создание роли IAM

Мы создадим соответствующую роль IAM для обеспечения доступа к журналам CloudWatch, а также для запуска и остановки экземпляра RDS. В AWS теперь есть удобный визуальный редактор для выбора политик, если вы выберете его использование.

 Сначала я создам политику и затем присоединю ее к роли IAM.

  • Войдите в консоль IAM и нажмите

    • Политика и создание политики .
    • Вставьте следующее в редактор JSON.
{
    "Version": "2012-10-17",
    "Statement": [
        {           
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

  • Дайте имя политики: policy_start_stop_RDS вместе с описанием, затем нажмите « Создать политику» .

  • Теперь в консоли IAM нажмите « Роли» и « Создать роли».
  • Выберите AWS Services , Lambda в качестве вашего сервиса.
  • В строке поиска выполните поиск policy_,  и политика, созданная вами ранее, должна выглядеть следующим образом.

  • Укажите описательное имя роли (например), lambda-start-stop-rds и нажмите « Создать роль».

Шаг 2 — Автор функции

  • Убедитесь, что вы находитесь в правильном регионе для создания функций Lambda и в том же регионе, в котором был создан ваш экземпляр БД. В моем случае это Н. Вирджиния.
  • Получите имя экземпляра RDS и зону доступности от администратора.
  • Откройте консоль Lambda и нажмите « Создать функцию и создать автора с нуля».
  • Введите следующую информацию в окне

    • Имя: RDSInstanceStop
    • Время выполнения:   Python 2.7
    • Роль: выберите существующую роль
    • Имя роли: Lambda-start-stop-rds и нажмите « Создать функцию».

  • Будет создана лямбда-функция, которая будет выглядеть следующим образом:

  • В верхнем правом углу теперь есть ресурс ARN, созданный для функции Lambda. Это используется для предоставления разрешений для функции Lambda для доступа к Lambda API GetFunctionConfiguration и доступа к переменным среды.

  • Вернитесь к роли: lambda-start-stop-rds и нажмите « Добавить встроенную политику» .

  • Затем перейдите на вкладку JSON и введите:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:GetFunctionConfiguration",
            "Resource": "arn:aws:lambda:<region>:<Account_id>:function:RDSInstanceStop"
        }
    ]
}
  • Обязательно измените Ресурс на Lambda ARN, который вы только что создали.
  • Присвойте Lambda ARN описательное имя политики, например policy_rds_stop,  и нажмите « Сохранить».

  • Теперь вернитесь к функции Lambda, и добавленная AWS Lambda должна появиться в качестве ресурса.

Шаг 3 — Обновить код функции

  • В разделе кода функции Python вставьте следующее:
import sys
import botocore
import boto3
from botocore.exceptions import ClientError


def lambda_handler(event, context):

    rds = boto3.client('rds')
    lambdaFunc = boto3.client('lambda')

    print 'Trying to get Environment variable'
    try:
        funcResponse = lambdaFunc.get_function_configuration(
            FunctionName='RDSInstanceStop'
        )

        DBinstance = funcResponse['Environment']['Variables']['DBInstanceName']

        print 'Stoping RDS service for DBInstance : ' + DBinstance

    except ClientError as e:
        print(e)    

    try:
        response = rds.stop_db_instance(
            DBInstanceIdentifier=DBinstance
        )

        print 'Success :: ' 
        return response
    except ClientError as e:
        print(e)    
    return
    {
        'message' : "Script execution completed. See Cloudwatch logs for complete output"
    }

  • Основная часть линии , которая останавливает экземпляр БД   rds.stop_db_instance .
  •  lambdaFunc.get_function_configuration  возвращает словарь свойств функции  RDSInstanceStop .
  •  DBInstance Переменная содержит переменную среды,  DBInstanceName  которая является парой ключ-значение, которую можно использовать для разделения сред Dev, QA или Prod.

Шаг 4 — Настройте лямбда-функцию

  • Прокрутите вниз до Переменных среды и добавьте два элемента:

    • Ключ: DBInstanceName 
    • Значение: <  userDB instance name >. В моем примере я использовал тестовую базу данных.

  • Выберите роль выполнения   lambda-start-stop-rds  и сохраните функцию.

Шаг 5 — Время для тестирования

  • В правом верхнем углу экрана выберите « Тестировать и настраивать тестовые события».
  • Выберите Создать новое тестовое событие и выберите шаблон события Hello World .
  • Когда вы нажимаете «Сохранить», выполнение должно быть успешным. Если ваша БД не запущена, на самом деле останавливать нечего, и поэтому вы получите сообщение, похожее на «Экземпляр <> не доступен».

 Поздравляем, вы только что создали функцию Lambda для остановки экземпляра RDS.

Теперь давайте создадим функцию для запуска экземпляра RDS. Поскольку шаги повторяют шаги, описанные в функции «Лямбда-стоп», в инструкциях будут упоминаться только изменения к шагам, указанным выше. 

Лямбда-функция для запуска экземпляра RDS

Шаг 1. Создание роли IAM

   ПРИМЕЧАНИЕ. Мы определили действия запуска и остановки в более ранней роли IAM « policy_start_stop_RDS », поэтому в этом примере мы будем использовать одну и ту же роль.

Шаг 2 — Автор функции

  • Задайте те же настройки, что и выше, за исключением названия функции как « RDSInstanceStart ».

Шаг 3. Обновление роли IAM 

  • Мы обновим роль IAM,   lambda_start_stop_RDS  чтобы включить другую встроенную политику

  • Перейдите к IAM Roles  и выберите lambda-start-stop-rds  Role.

  • Нажмите « Добавить встроенную политику»  и измените JSON, как показано ниже. Обязательно измените идентификатор учетной записи и региона на ARN функции.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:GetFunctionConfiguration",
            "Resource": "arn:aws:lambda:<region>:<Account_id>:function:RDSInstanceStart"
        }
    ]
}
  • Сохраните политику как policy_rds_start.

  • Роль теперь имеет доступ для запуска и остановки функций, специально определенных вместе с любыми экземплярами RDS.

Шаг 4 — Обновите код функции

  • Обновите лямбда-функцию, как показано ниже:

import sys
import botocore
import boto3
from botocore.exceptions import ClientError


def lambda_handler(event, context):
    # TODO implement

    rds = boto3.client('rds')
    lambdaFunc = boto3.client('lambda')

    print 'Trying to get Environment variable'
    try:
        funcResponse = lambdaFunc.get_function_configuration(
            FunctionName='RDSInstanceStart'
        )
        #print (funcResponse)

        DBinstance = funcResponse['Environment']['Variables']['DBInstanceName']

        print 'Starting RDS service for DBInstance : ' + DBinstance

    except ClientError as e:
        print(e)    

    try:
        response = rds.start_db_instance(
            DBInstanceIdentifier=DBinstance
        )

        print 'Success :: ' 
        return response
    except ClientError as e:
        print(e)    
    return
    {
        'message' : "Script execution completed. See Cloudwatch logs for complete output"
    }

  • Важное направление коды отметить  ,  который начинается с RDS. rds.start_db_instance

Шаг 5 — Настройте лямбда-функцию

Выполните те же шаги, что и выше, чтобы настроить лямбда-функцию для переменных среды и роли выполнения.

Поздравляем, теперь вы можете запускать и останавливать экземпляр RDS из лямбда-функции.