Начните работу с Serverless, Lambda и Docker

SAM - это фреймворк с открытым исходным кодом, который можно использовать для создания, тестирования и развертывания бессерверных приложений на AWS.

Основная цель этой статьи - познакомить вас с AWS SAM, чтобы вы могли тестировать свои лямбда-выражения на локальном компьютере без необходимости (повторно) развертывать их каждый раз на AWS. Я расскажу о различных интеграциях и примерах с SAM и лямбда.

SAM использует Docker для локального создания и запуска лямбда-выражений, поэтому необходимы базовые знания Docker.

Архитектура

Допустим, у компании много документов. В этих документах есть documentId и versionId. Также существует несколько версий одного документа.

Сотрудникам компании сложно найти конкретные версии документов. Компания разработала решение, позволяющее упростить запрос места хранения документа на основе его documentId и versionId.

Давайте переведем пример использования на техническую архитектуру в AWS. Мы будем использовать DynamoDB для хранения documentId, versionId и места хранения документа. Нам нужно заполнить таблицу DynamoDB информацией о существующем документе, а затем настроить интеграцию лямбда-прокси в API Gateway. Конечный пользователь сможет получить правильное место хранения документа, выполнив запрос GET с правильными параметрами (documentId и versionId) к конечной точке шлюза API.

Мы можем использовать SAM для развертывания этого стека в AWS, но одна из сильных сторон SAM заключается в том, что он предлагает простой способ локального тестирования ваших интеграций.

Мы будем использовать SAM local для:

  • Вызов лямбда-выражения один раз с помощью SAM CLI для заполнения DynamoDB.
  • Разместите нашу локальную конечную точку шлюза API с интеграцией лямбда-прокси.
  • Создайте образец события, которое шлюз API отправляет нашей лямбда-функции, когда кто-то ищет документ.

Когда все будет работать локально, мы развернем полный стек в AWS.

Начальная настройка

Чтобы можно было следить за этой демонстрацией, вам потребуются следующие предварительные условия:

Мы будем использовать Docker для запуска нашего локального экземпляра DynamoDB - но не только этого.

SAM также сильно зависит от Docker. Когда SAM CLI вызывает локальную лямбда-функцию, SAM запускает контейнер Docker, выполняет лямбда-код и уничтожает контейнер.

Давайте сначала создадим сеть моста Docker. Мы будем использовать этот тип сети Docker, чтобы наши контейнеры Docker могли взаимодействовать друг с другом, разрешая их имена контейнеров. Таким образом, мы можем общаться с нашим локальным контейнером Docker DynamoDB изнутри наших лямбда-контейнеров, управляемых SAM. Контейнер DynamoDB называется динамодб.

$ docker network create sam-demo
$ docker run --network sam-demo --name dynamodb -d -p 8000:8000 amazon/dynamodb-local

Когда контейнер запущен и работает, мы можем создать нашу таблицу DynamoDB. Первичный ключ нашей DynamoDB будет состоять из ключа разделения (documentId) и ключа сортировки (versionId).

$ aws dynamodb create-table --table-name documentTable --attribute-definitions AttributeName=documentId,AttributeType=N AttributeName=versionId,AttributeType=S --key-schema AttributeName=documentId,KeyType=HASH AttributeName=versionId,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 --endpoint-url http://localhost:8000

Использование SAM для создания и вызова локальной функции

Теперь клонируйте демонстрационный проект с GitHub.

Этот проект содержит template.yaml, который полностью описывает, как должен выглядеть стек. Он развертывает одну автономную лямбда-функцию с именем LoadDataFunction, которую мы запускаем вручную для загрузки данных в таблицу DynamoDB. Вторая функция называется GetDocumentFunction и запускается событием шлюза API.

Мы можем проверить, действителен ли шаблон:

$ cd aws-lambda-sam-demo
$ sam validate -t template.yml
xxx/template.yaml is a valid SAM Template

LoadDataFunction будет использоваться для заполнения нашей таблицы DynamoDB. Соберите функции с помощью SAM CLI. Если в вашей локальной среде не установлен Python3.7, вы можете использовать параметр --use-container для создания функции внутри контейнера Docker.

$ sam build --use-container

Это создает наши лямбда-функции, как описано в нашем template.yaml. Шаблоны SAM являются расширением шаблонов CloudFormation. Сборка загрузит необходимые зависимости, описанные в нашем requirements.txt, и создаст артефакты развертывания, хранящиеся в .aws-sam/build/functionName.

LoadDataFunction нужно выполнить только один раз, чтобы поместить существующие документы и их расположение в нашу таблицу DynamoDB. Давайте подробнее рассмотрим саму функцию:

Мы можем использовать SAM для вызова функции. Мы используем параметр, чтобы указать на нашу среду. Допустимые варианты: local или aws. Лямбда-функция подключается к правильной конечной точке DynamoDB на основе этого параметра.

Локальная лямбда-функция будет работать внутри контейнера Docker. Мы говорим SAM развернуть контейнер в той же сети Docker Bridge, что и наш контейнер DynamoDB. Теперь наша лямбда может взаимодействовать с контейнером DynamoDB, используя его имя.

$ sam local invoke LoadDataFunction --parameter-overrides ParameterKey=Environment,ParameterValue=local ParameterKey=DDBTableName,ParameterValue=documentTable --docker-network sam-demo

Когда лямбда-функция успешно завершится, мы сможем увидеть, правильные ли данные находятся в нашей таблице DynamoDB. Отсканируйте содержимое таблицы:

$ aws dynamodb scan --table-name documentTable --endpoint-url http://localhost:8000

Используйте SAM для создания образца полезной нагрузки

Следующая функция - GetDocumentFunction. Это инициируется событием шлюза API.

Настройка шлюза API определена в template.yaml. Мы развертываем интеграцию лямбда-прокси шлюза API, где GetDocumentFunction будет срабатывать, когда к API-GW-URL/document?documentId=xxx&versionId=xxx поступает запрос GET.

Прежде чем мы развернем эту конечную точку шлюза API, я хочу, чтобы мы протестировали GetDocumentFunction. Здесь мне нужно создать действительное событие, которое может запускать эту функцию. Следующая команда создаст действительный JSON, который мы можем использовать как поддельное событие шлюза API для запуска лямбда-выражения.

$ sam local generate-event apigateway aws-proxy --method GET --path document --body "" > local-event.json

К сожалению, SAM CLI не поддерживает (пока?) queryStringParameters во время генерации событий. Поэтому мы должны обновить это вручную в local-event.json. Помните, мы видели документ с documentId 1044 и version_id v_1 in DynamoDB, поэтому мы можем использовать их как допустимые значения параметров:

...
"queryStringParameters": {
 "documentId": "1044",
 "versionId": "v_1"
 },
...

Теперь протестируйте GetDocumentFunction, вызвав его с помощью нашего события:

sam local invoke GetDocumentFunction --event local-event.json --parameter-overrides ParameterKey=Environment,ParameterValue=local ParameterKey=DDBTableName,ParameterValue=documentTable --docker-network sam-demo

Настройка конечной точки локального шлюза API с интеграцией лямбда-прокси

Сотрудники компании будут использовать статический веб-сайт для выполнения действительного запроса GET к шлюзу API. Сотрудники заполняют documentId и versionId нужного им документа.

API Gateway перенаправит запрос на наш GetDocumentFunction. GetDocumentFunction будет использовать queryStringParameters для запроса правильного расположения в таблице DynamoDB.

Запустите нашу локальную конечную точку шлюза API:

$ sam local start-api --parameter-overrides ParameterKey=Environment,ParameterValue=local ParameterKey=DDBTableName,ParameterValue=documentTable --docker-network sam-demo

Репозиторий содержит базовую статическую веб-страницу в качестве визуализации. Сотрудники будут использовать это для разговора со шлюзом API. Шлюз API общается с серверной частью, которая является нашим GetDocumentFunction.

Это фактически выполнит следующий вызов GET:

$ curl "http://127.0.0.1:3000/document?documentId=1044&versionId=v_1"

Теперь нажмите «Отправить запрос». Это вызовет нашу лямбду.

Теперь я показал, как мы можем собрать и протестировать наш стек локально. После внесения изменений в ваш шаблон или лямбда-выражения вы должны снова запустить команду sam build и повторно активировать или повторно развернуть свои ресурсы.

Вот и все! Если у вас есть доступная учетная запись AWS, вы можете перейти к следующему шагу.

Разверните стек SAM в AWS (необязательно)

Теперь я покажу вам, как легко развернуть этот стек в AWS.

Мы уже выполнили sam build команду. Это привело к созданию наших артефактов развертывания в каталоге .aws-sam/build/.

sam deploy упаковывает и разворачивает наш стек. Мы должны указать корзину S3, в которую мы загружаем наши артефакты развертывания. Обратите внимание, что теперь мы указываем на AWS как на среду, а не на local. Теперь наши лямбды знают, что они должны подключаться к конечной точке AWS DynamoDB, а не к нашей локальной конечной точке.

$ sam deploy --template-file .aws-sam/build/template.yaml --s3-bucket lvthillo-sam-upload-bucket --parameter-overrides ParameterKey=Environment,ParameterValue=aws ParameterKey=DDBTableName,ParameterValue=documentTable --stack-name aws-lambda-sam-demo --capabilities CAPABILITY_NAMED_IAM

После успешного развертывания мы должны сначала запустить LoadDataFunction, чтобы заполнить нашу DynamoDB. Просто создайте пустое тестовое событие в лямбда-консоли и выполните функцию:

Правильные данные доступны в DynamoDB:

Теперь мы можем снова протестировать нашу интеграцию лямбда-прокси API Gateway:

Все работает! Наконец, мы можем повторно развернуть наш статический веб-сайт в сегменте S3, который создается нашим стеком. В этой демонстрации я использую public-static-site-bucket как bucket. Шаблон будет генерировать случайное имя сегмента, настроенного как статический веб-сайт.

Нам просто нужно обновить наше статическое приложение, чтобы оно указывало на правильный URL-адрес шлюза API. Чтобы найти этот URL, вы можете перейти в CloudFormation. Найдите свой стек и проверьте выходы. Стек настроен для вывода конечной точки шлюза API.

Для быстрого тестирования мы можем использовать curl и правильные (или неправильные) параметры.

$ curl "https://c8517wsgol.execute-api.eu-west-1.amazonaws.com/v1/document?documentId=1044&versionId=v_1"

Теперь мы можем обновить наше статическое приложение с помощью этого URL:

Теперь, когда мы обновили URL-адрес, мы можем загружать файлы в корзину S3. Обязательно сделайте объекты общедоступными во время или после загрузки.

Посетите свою корзину S3 как статический веб-сайт!

Правильный URL-адрес также выводится в консоли CloudFormation.

Заключение

Мы открыли для себя волшебство модели бессерверного приложения AWS.

Мы рассмотрели большинство важных вещей, которые вы можете с ним сделать. Мы использовали шаблон SAM для развертывания и тестирования лямбда-функций на нашей локальной машине. Мы даже развернули локальный API-шлюз! Убедившись, что все работает, мы развернули точно такой же стек на AWS.

Надеюсь, вам понравилось. Спасибо, что прочитали, и не стесняйтесь задавать любые вопросы!