Как связать шаблон CloudFormation с лямбда-функцией, которая создает новую базу данных на экземпляре Aurora PostgreSQL в RDS? - PullRequest
0 голосов
/ 03 марта 2020

Я надеюсь, вы можете помочь!

Цель

Я пытаюсь настроить следующий сценарий для AWS:

  1. В AW C CLI: вызов CloudFormation Шаблон для создания нового стека.
  2. В шаблоне: Call Lambda Функция.
  3. В функции Lambda : Подключение к Aurora PostgreSQL Экземпляр в RDS через pg .
  4. In PostgresSQL: создать новую базу данных .

Короткая история

Как только я добавляю свою лямбда-функцию к VP по умолчанию C, он больше не может отправлять ответ обратно CloudFormation и стек застряли в CREATE_IN_PROGRESS. Это работает, когда я удаляю VP C из конфигурации функции Lambda. Но тогда я больше не могу подключиться к другому компоненту, например к экземпляру базы данных RDS. Как с этим справиться?

Длинная история

Чтобы это сработало, мой первый шаг состоял в том, чтобы вручную подключиться к PostgreSQL и создать новую базу данных:

  1. Настройка группы безопасности по умолчанию для разрешения ВСЕХ входящих и ВСЕХ исходящих трафика c. Не беспокойтесь, только для тестирования. Я изменю это позже.
  2. Добавил группу безопасности в экземпляр RDS, чтобы принимать трафик c от и к другим компонентам в пределах того же VP C. Необходим для шага 3.
  3. Создана Cloud9 Среда для доступа к терминалу в VP C. Подключение к базе данных PostgreSQL и создание базы данных работает!

Теперь моей целью было создание новой базы данных с помощью функции Lambda:

  1. Вручную создал новую Лямбда-функцию, включающую новую роль с базовой c Лямбда-авторизацией. Также добавлено AdministratorAccess к роли. Не беспокойтесь, опять же только для тестирования. Функция Lambda работает на Node.js 12.x с тайм-аутом 15 секунд.
  2. Упаковал мой Lambda-скрипт и модуль pg в zip-файл и загрузил его. Сценарий выглядит так:
const { Client } = require('pg');
exports.handler = async (event, context) => {
    var databaseName = event.DatabaseName;
    var dbSuperUser = event.DBSuperUser;
    var dbSuperPassword = event.DBSuperPassword;

    const dbClient = new Client({
        host: "<Database Instance Endpoint>",
        port: 5432,
        database: "postgres",
        user: dbSuperUser,
        password: dbSuperPassword
    });

    await dbClient.connect();
    await dbClient.query("CREATE DATABASE " + databaseName);
    await dbClient.end();

    var response = {status: 'SUCCESS'};
    return response;
};
Вызов Lambda-скрипта из Cloud9 через aws lambda invoke приводит к таймауту. Такое поведение было ожидаемым, поскольку лямбда-функция не находится в том же VP C, что и экземпляр базы данных RDS. Добавлен VP C по умолчанию с тремя подсетями по умолчанию и группой безопасности по умолчанию в Lambda. Конфигурация функций. И вуаля, база данных создается! Мы на пути.

Теперь я попытался вызвать функцию Lambda и создать базу данных из базового c шаблона CloudFormation:

  1. Создан шаблон, включающий Пользовательский ресурс Ressource :
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "DatabaseName": {"Type": "String"}
    },
    "Resources": {
        "SampleInstance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "InstanceType": "t1.micro",
                "ImageId": {"Fn::GetAtt": ["CreateDatabase", "Id"]}
            }
        },
        "CreateDatabase": {
            "Type": "Custom::CreateDatabase",
            "Properties": {
                "ServiceToken": "<Lambda Function ARN>",
                "DBSuperUser": "<DBSuperUser>",
                "DBSuperPassword": "<DBSuperPassword>",
                "DatabaseName": {"Ref": "DatabaseName"}                
            }
        }
    }
}

Экземпляр EC2 является лишь примером и не удастся создать в любом случае, поскольку ImageId не будет действительным. Это просто проверить, получаю ли я ответ от лямбда-функции.

Изменена функция Lambda для получения события от CloudFormation и отправки ответа. Я мог бы использовать модуль cf c -response , но решил скопировать его код в мою функцию Lambda, чтобы посмотреть, что происходит под капотом. Пожалуйста, нажмите на ссылку выше и прокрутите вниз до Исходный код модуля , чтобы увидеть исходный код.

Также я изменил получение входных параметров следующим образом:

var customerName = event.ResourceProperties.CustomerName;
var dbSuperUser = event.ResourceProperties.DBSuperUser;
var dbSuperPassword = event.ResourceProperties.DBSuperPassword; 

И отправка ответа в CloudFormation так:

responseData = {Id: '1234567890'};
send(event, context, SUCCESS, responseData);

Запуск шаблона с помощью AWS Команда CLI aws cloudformation create-stack вызывает застревание стека в CREATE_IN_PROGRESS. Но база данных успешно создана!

Как только я удаляю конфигурацию VP C из функции Lambda, проблема исчезла. CloudFormation успешно получает ответ от функции и пытается создать образец образца EC2. Но теперь лямбда-функция больше не может получить доступ к RDS для создания базы данных.

Это приводит к следующим вопросам:

  • Вызывает ли конфигурация VP C в функции Lambda проблему с подключением к шаблону CloudFormation?
  • Если да, как это исправить?
  • Является ли конфигурация сети правильное место, чтобы посмотреть? Или я должен изменить свою кодировку?

Другие вещи, которые я проверил:

  • Я сравнил следующие переменные и объекты Lambda-скрипта в обоих прогонах (успешный и неудачный ответ): event, context, responseBody, parsedUrl, options, request. Они идентичны (за исключением некоторых идентификаторов и т. Д. c.).

Ждем ваших мыслей по этому поводу!

Приветствия

1 Ответ

2 голосов
/ 03 марта 2020

Код, который вы опубликовали, представляет собой простую лямбду и не сообщает о своем статусе в соответствии с требованиями пользовательского ресурса CloudFormation . Итак, первый шаг - убедиться, что вы соблюдаете требования.

Если это так, и ваш код блокируется при сообщении статуса обратно на S3, то наиболее вероятной причиной является то, что вы работаете в su bnet, который не имеет ни NAT , ни конечной точки S3 . Если вам не нужен NAT, конечная точка S3 свободна, поэтому это будет лучшим решением. Если у вас уже есть NAT, убедитесь, что Lambda работает в su bnet, где доступен NAT.

...