Блог Amazon Web Services

Создание расширений для AWS Lambda (предварительный доступ)

Оригинал статьи: ссылка (Julian Wood, Senior Developer Advocate AWS)

AWS Lambda анонсировала программу предварительного ознакомления с Lambda-расширениями (Extensions) – нового подхода по интеграции Lambda с привычными вам инструментами мониторинга, наблюдения, безопасности и управления (governance). Расширения позволяют глубоко интегрироваться в среду выполнения Lambda с целью получения управления и участия в жизненном цикле функции. Этот новый подход позволяет упростить использование привычных вам утилит для ваших бессерверных приложений.

В этом блог-посте я расскажу, как работают Lambda-расширения, а также об изменениях в жизненном цикле Lambda функций и о том, как создать новое расширение. Дополнительную информацию по использованию расширений с Lambda-функциями вы можете найти в блог-посте «Introducing AWS Lambda extensions».

Расширения построены на основе нового API: Lambda Extensions API, который позволяет получить больше точек контроля жизненного цикла Lambda во время инициализации, запуска и завершения работы. Этот API построен на основе существующего Lambda Runtime API, который позволяет создавать кастомизированную среду выполнения (runtime) для запуска Lambda.

Вы можете использовать расширения, предоставляемые AWS, партнёрами AWS и open source проектами, для следующих сценариев: мониторинг производительности приложения, управление секретами и конфигурацией и обнаружение уязвимостей. И, конечно же, вы можете разработать расширение для интеграции с вашим собственным инструментарием на основе Extensions API.

На сегодня доступны расширения для следующих продуктов: AppDynamics, Check Point, Datadog, Dynatrace, Epsagon, HashiCorp, Lumigo, New Relic, Thundra, Splunk, AWS AppConfig и Amazon CloudWatch Lambda Insights. Для более подробной информации, прочитайте пост «Introducing AWS Lambda extensions».

Среда выполнения Lambda

Lambda-функции запускаются в изолированном (sandboxed) окружении, называемом среда выполнения. Таким образом обеспечивается изоляция одних функций от других, и выделяются необходимые ресурсы, такие как память, указанные в настройках Lambda-функции.

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

До этого момента, только исполняемый процесс (runtime) мог влиять на жизненный цикл среды выполнения. Он взаимодействует с Runtime API посредством HTTP API endpoint, который находится внутри среды выполнения и взаимодействует с сервисом Lambda.

Lambda и Runtime API

Исполняемый процесс использует API для получения сообщений вызовов из Lambda и доставки их внутрь исполняемого кода функции. Затем он уведомляет сервис Lambda о результатах обработки переданного сообщения. После этого сервис Lambda снова «замораживает» среду выполнения.

До этого момента, исполняемый процесс Lambda проходил через две независимые фазы жизненного цикла в среде выполнения Lambda: Init и Invoke.

  1. Init: в Init фазе, Lambda сервис инициирует исполняемый процесс (runtime), и затем запускает код инициализации функции (код за пределами обработчика main). Данная фаза происходит или в момент первичного запуска, или заранее – в случае включения Provisioned Concurrency режима.
  2. Invoke: в Invoke фазе, исполняемый процесс (runtime) получает событие вызова от сервиса Lambda и запускает обработчик функции. Затем он возвращает результат вызова в Runtime API.

После окончания выполнения функции сервис Lambda «замораживает» среду выполнения и сохраняет её какое-то время на случай последущего вызова.

Если Lambda функция не получает вызовы в течение какого-то времени, сервис Lambda удаляет среду выполнения.

Предыдущий жизненный цикл Lambda

С появлением Extensions API расширения могут оказывать влияние, управлять и участвовать в жизненном цикле среды выполнения. Например, они могут использовать Extensions API для контроля «замораживания» среды выполнения сервиса Lambda.

Среда исполнения AWS Lambda с появлением Extensions API

Расширения инициализируются перед исполняемым процессом (runtime) и функцией. Затем они продолжают исполнение параллельно с функцией, получая больше возможностей по управлению её исполнением, и могут произвести какое-то действие во время окончания работы функции.

Расширения позволяют интегрироваться с сервисом Lambda путём следующих изменений в его жизненном цикле:

  1. Изменения фазы Init. Теперь существует три независимых Init задачи: Init расширения, Init исполняемого процесса, Init функции. Благодаря этому, у нас есть порядок запуска, где расширение и исполняемый процесс могут произвести операции по настройке перед запуском самой функции.
  2. Больше контроля во время запуска. Во время фазы Invoke, как и раньше, исполняемый процесс (runtime) получает событие вызова от сервиса Lambda и запускает обработчик функции. В дополнение к этому, расширения могут получать и обрабатывать события об изменениях в жизненном цикле от сервиса Lambda. Они могут запускать логику обработки в ответ на полученные события и информировать сервис Lambda об окончании обработки. Сервис Lambda «замораживает» среду выполнения после получения подтверждения от всех расширений и исполняемого процесса. Таким образом, расширения могут теперь влиять на процесс «заморозки»-«разморозки» среды выполнения.
  3. Фаза завершения работы: также расширения теперь имеют возможность выполнить действия при завершении работы среды выполнения за счёт появления фазы «завершения работы». Сервис Lambda посылает событие о завершении работы, которое даёт сигнал исполняемому процессу и расширению, что среда исполнения вот-вот закончит свою работу.

Новый жизненный цикл Lambda с появлением расширений

Каждая фаза жизненного цикла Lambda начинается с события от сервиса Lambda, отосланного исполняемому процессу и всем зарегистрированным расширениям. Исполняемый процесс и расширения уведомляют о завершении обработки запросом события Next от Runtime и Extensions API. Lambda «замораживает» среду выполнения и все расширения, когда не остаётся событий для обработки.

Жизненный цикл Lambda для среды выполнения, исполняемого процесса, расширений и функции.

Дополнительную информацию о фазах жизненного цикла и Extensions API смотрите в документации.

Как расширения доставляются в Lambda и запускаются?

Вы добавляете расширения в виде слоёв Lambda, которые представляют собой ZIP архивы, содержащие библиотеки и другие зависимости.

Для добавления нового слоя используйте Консоль управления AWS, Интерфейс командной строки AWS (AWS CLI) или подходы «инфраструктура-как-код», с помощью AWS CloudFormation, AWS Serverless Application Model (AWS SAM) и Terraform.

Когда сервис Lambda запускает среду выполнения функции, он распаковывает файлы Расширений из слоя Lambda в папку /opt. Затем Lambda проверяет наличие каких-либо расширений в папке /opt/extensions и начинает процесс инициализации. Расширения должны быть исполняемыми файлами, такими как скрипты или запускаемые файлы. Расширения не могут изменять код функции, потому что папка с кодом функции доступна только на чтение.

Расширения могут запускаться в одном из двух режимов – внутренний и внешний.

  • Внутренние расширения запускаются как часть исполняемого процесса, в том же процессе, что и код вашей функции. Расширения в таком режиме не используют отдельные процессы. Внутренние расширения позволяют изменять процесс запуска исполняемого процесса, используя специфичные для языка переменные окружения и скрипты-обёртки. Вы можете использовать переменные окружения для добавления утилит к исполняемым процессам Java Correto 8 и 11, Node.js 10 и 12 и .NET Core 3.1. Скрипты-обёртки (Wrapper scripts) позволяют передать управление запуском рантайма вашему скрипту с целью дополнительной конфигурации процесса запуска. Вы можете использовать скрипты-обёртки с js 10 и 12, Python 3.8, Ruby 2.7, Java 8 и 11 и .NET Core 3.1. Для дополнительной информации смотрите раздел документации «Modifying the runtime environment».
  • Внешние расширения позволяют запускать отдельный процесс относительно исполняемого процесса, но в той же среде выполнения, что и Lambda-функция. Внешние расширения могут запускаться перед исполняемым процессом и могут продолжать работу после завершения исполняемого процесса. Внешние расширения работают с js 10 и 12, Python 3.7 и 3.8, Ruby 2.5 и 2.7, Java Corretto 8 и 11, .NET Core 3.1 и пользовательскими средами выполнения.

Внешние расширения могут быть написаны на языке программирования, отличающимся от языка Lambda-функции. Мы рекомендуем разрабатывать внешние расширения, используя компилируемый язык программирования, и распространять их в виде бинарных файлов (self-contained binary). Такой подход гарантирует совместимость со всеми поддерживаемыми средами выполнения. В случае использования некомпилируемых языков программирования, убедитесь, что вы включили необходимый исполняемый файл в ваше расширение.

Расширения запускаются в той же среде выполнения, что и функция, и делят с ней ресурсы: CPU, память и дисковое хранилище. Они также получают одинаковые переменные окружения и права доступа, используя ту же роль AWS Identity and Access Management (IAM), что и функция.

Чтобы узнать больше о ресурсах, безопасности и аспектах производительности расширений, читайте блог-пост «Introducing AWS Lambda extensions».

Примеры расширений и скриптов-обёрток для разработки ваших собственных расширений вы можете найти в GitHub репозитории.

Демонстрация расширений в действии

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

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

Для запуска демо перейдите в репозиторий GitHub и следуйте инструкциям в файле README.md.

Lambda-фунция использует пользовательскую среду выполнения provided.al2, основанную на Amazon Linux 2. Пользовательская среда выполнения помогает показать в деталях, как взаимодействуют все компоненты вместе: сервис Lambda, Runtime API и функция. Расширение поставляется в функцию в качестве слоя Lambda.

Среда выполнения, функция и расширение логируют события изменения своих статусов в Amazon CloudWatch Logs. Расширение инициализируется в отдельном процессе и ждёт получения события запуска функции от Extensions API. Затем оно засыпает на 5 секунд перед тем, как вызвать API повторно с целью получения следующего события. Засыпание расширения эмулирует логику обработки параллельного процесса. Это может быть, например, сбор телеметрии для отправки во внешний сервис мониторинга.

Когда Lambda-функция запускается, расширение, среда выполнения и функция выполняют следующие шаги. Для рассмотрения этих шагов мы будем использовать результаты вывода консоли логов.

  1. Сервис Lambda добавляет настроенное расширение из Lambda-слоя. Затем он ищет в папке/opt/extensions и находит расширение с названием extension1.sh. Расширение запускается перед инициализацией среды выполнения. Оно регистрируется в Extensions API для получения событий INVOKE и SHUTDOWN, используя следующий API вызов.
curl -sS -LD "$HEADERS" -XPOST "http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register" --header "Lambda-Extension-Name: ${LAMBDA_EXTENSION_NAME}" -d "{ \"events\": [\"INVOKE\", \"SHUTDOWN\"]}" > $TMPFILE

Обнаружение расширения, регистрация и запуск.

  1. Пользовательская среда выполнения Lambda provided.al2 инициализируется из bootstrap файла.

Инициализация среды выполнения

  1. Среда выполнения вызывает Runtime API для получения следующего события для обработки. Запрос HTTP «блокируется» и ждёт получения события.
curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next" > $TMPFILE &

Расширение вызывает Extensions API и ждёт следующего события. Запрос HTTP снова «заблокирован», пока не будет получен ответ.

curl -sS -L -XGET "http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/event/next" --header "Lambda-Extension-Identifier: ${EXTENSION_ID}" > $TMPFILE &

Среда выполнения и расширение вызывают API для получения следующего события

  1. Сервис Lambda получает событие вызова функции и отправляет данные этого события в Runtime API. Он, в свою очередь, отправляет событие в расширение, уведомляя его о вызове функции с помощью Extensions API.

Среда выполнения и расширение получают событие.

  1. Среда выполнения вызывает обработчик функции, передавая данные события вызова из предыдущего шага.

Среда выполнения вызывает обработчик функции

  1. Функция запускает исполняемый код. Среда выполнения Lambda получает результат обработки данных от функции и посылает его в Runtime API с помощью API вызова:
curl -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" > $TMPFILE

Среда выполнения получает ответ от функции и отправляет в Runtime API

  1. Среда выполнения Lambda затем ждёт прихода следующего события вызова (режим тёплого запуска).

    Среда выполнения ждёт следующего события

  1. Расширение продолжает обработку в течение 15 секунд, эмулируя реальный процесс обработки в рамках своего процесса. По завершению обработки, расширение использует Extensions API для повторной регистрации и ждёт следующего события.

    Процесс работы расширения

  1. Отчёт о вызове функции логируется.
  2. Когда Lambda готовится закончить работу и остановить среду выполнения, она отсылает в Runtime API сообщение об завершении работы.

    Среда выполнения Lambda – событие завершения работы

  1. Затем Lambda отсылает событие в расширения. Расширение заканчивает обработку на своей стороне и завершает свою работу уже после завершения работы среды выполнения.

    Событие завершения работы от расширения

Демо показывает этапы, происходящие в среде выполнения, функции и расширении, в рамках жизненного цикла Lambda.

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

Для ознакомления с диаграммой последовательности исполнения, смотрите документацию Extensions API.

Цена

Расширения используют ту же модель биллинга, что и Lambda-функции. Когда вы используете Lambda-функции с расширениями, вы платите за обработанные вызовы и за объединённые вычислительные ресурсы функции и всех расширений, порциями по 100мс. Для дополнительной информации о модели стоимости для расширений, читайте Вопросы и ответы по AWS Lambda.

Выводы

Расширения Lambda позволяют расширить среду выполнения Lambda для более удобной интеграции с привычными вам инструментами мониторинга, наблюдения, безопасности и управления (governance).

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

Вы можете разработать свои расширения для интеграции с вашими собственными системами с помощью нового Extensions API. Примеры расширений и скриптов-обёрток для среды выполнения вы можете найти в GitHub репозитории.

Расширения доступны для предварительного ознакомления в регионах: US East (N. Virginia), US East (Ohio), US West (N. California), US West (Oregon), AWS GovCloud (US-East), AWS GovCloud (US-West), Canada (Central), EU (Ireland, EU (London), EU (Paris), EU (Frankfurt), EU (Stockholm), EU (Milano), South America (Sao Paulo), Africa (Cape Town), Middle East (Bahrain), Asia Pacific (Tokyo), Asia Pacific (Seoul), Asia Pacific (Osaka), Asia Pacific (Singapore), Asia Pacific (Sydney), Asia Pacific (Mumbai), и Asia Pacific (Hong Kong).

Больше обучающей информации по бессерверным технологиям, ищите на https://serverlessland.com.