Узнайте, как использовать лямбда-слои, построив функцию изменения размера изображения с помощью Sharp

Lambda Layer — это настоящая находка в сфере лямбда-функций. Он предоставляет удобный способ упаковки библиотек и других зависимостей, которые могут быть использованы с функциями Lambda. Наш проект с открытым исходным кодом Webiny, который имеет 50 тыс. загрузок и 5,5 тыс. звезд на GitHub, использует лямбда-слои. Это помогает нам уменьшить размер функции Lambda на 12 МБ и позволяет нам совместно использовать библиотеку обработки изображений sharp во всех развертываниях Webiny.

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

Рабочий процесс будет выглядеть следующим образом: для каждого файла изображения, загруженного в ведро S3 (исходное ведро), будет вызываться лямбда-функция. Она будет считывать объект изображения из исходного ведра S3, создавать уменьшенное изображение и сохранять его в целевом ведре S3.

Предварительные условия

  • Учетная запись AWS — Для использования различных служб AWS вам потребуется учетная запись AWS. Перейдите по этой ссылке, чтобы создать учетную запись AWS.
  • Командная строка AWS — Для создания Lambda Function и Lambda Layer мы будем использовать командную строку AWS. Руководство по установке AWS CLI доступно здесь.

Шаг 1 — Создайте два ведра S3

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

Для создания ведер S3 выполните следующие шаги.

1.) Откройте консоль Amazon S3.
2.) Создайте два ведра S3 — исходное и целевое.

Имя целевого ведра должно быть source-bucket-name плюс суффикс -resized . Например, если исходное ведро называется mybucket, то целевое ведро должно быть названо mybucket-resized. Пожалуйста, следуйте этому соглашению об именовании, потому что мы будем использовать эту логику именования в функции Lambda.

Шаг 2 — Создание политики IAM

Теперь давайте создадим политику IAM, которая определяет разрешения для функции Lambda. Функция Lambda должна иметь разрешение на следующие операции:

  • Получить объект из исходного ведра S3.
  • Поместить объект с измененными размерами в целевое ведро S3.
  • Записывать журналы в Amazon CloudWatch Logs.

Чтобы создать политику IAM, выполните следующие действия.

1.) Откройте страницу Policies в консоли IAM.
2.) Выберите Создать политику.
3.) Выберите вкладку JSON, а затем вставьте следующую политику. Обязательно замените mybucket на имя исходного ведра, которое вы создали ранее.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:PutLogEvents",
                "logs:CreateLogGroup",
                "logs:CreateLogStream"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::mybucket/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::mybucket-resized/*"
        }
    ]
}
Войти в полноэкранный режим Выйдите из полноэкранного режима

4.) Выберите Next: Теги.
5.) Выберите Далее: Обзор.
6.) В разделе Review policy для Name введите AWSLambdaS3Policy.
7.) Выберите Создать политику.

Шаг 3 — Создание роли исполнения

Создайте роль исполнения, которая дает вашей функции Lambda разрешения на доступ к ресурсам AWS.

Чтобы создать роль исполнения

1.) Откройте страницу Роли в консоли IAM.
2.) Выберите Создать роль.
3.) Создайте роль со следующими свойствами:
— Тип доверенной сущности — AWS Service (Разрешить службам AWS, таким как EC2, Lambda или другим, выполнять действия в этой учетной записи).
— Вариант использования — Lambda (Позволяет функциям Lambda вызывать службы AWS от вашего имени).
— Политика разрешений — AWSLambdaS3Policy
— Имя роли — lambda-s3-role.

Шаг 4 — Создание резкого слоя Lambda

Здесь начинается особая часть этого руководства. В этом разделе мы создадим резкий Lambda Layer.

Вы будете выполнять эту часть урока на своей машине. Убедитесь, что у вас установлен npm (нам понадобится npm для установки пакета sharp).

1.) Создайте каталог с именем nodejs.
2.) Установите зависимость sharp в каталог nodejs, выполнив следующие команды:

npm install
Войти в полноэкранный режим Выйти из полноэкранного режима
SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install --arch=x64 --platform=linux sharp
Войти в полноэкранный режим Выйти из полноэкранного режима

После этого шага вы получите следующую структуру каталогов:

nodejs
|- node_modules
|- package-lock.json
Войти в полноэкранный режим Выход из полноэкранного режима

3.) Создайте файловый архив .zip из каталога nodejs.

zip -r nodejs.zip nodejs
Войти в полноэкранный режим Выйти из полноэкранного режима

4.) Теперь давайте опубликуем слой. Выполните следующую команду для создания и публикации слоя:

aws lambda publish-layer-version --layer-name sharp --description "Sharp dependency for image transformation" --zip-file fileb://nodejs.zip --compatible-runtimes "nodejs14.x" --region "us-east-1" --output "json"

Войти в полноэкранный режим Выйти из полноэкранного режима

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

Обратите внимание на LayerVersionArn, мы будем использовать его при создании лямбда-функции.

{
    "Content": {
        "Location": "https://prod-04-2014-layers.s3.us-east-1.amazonaws.com/snapshots/400803493251/sharp-539dd937-e29c-4418-bb52-2089f3945afc?versionId=4AMhQSZjY3uw3WI85Jcbf7j7Wj1x1X9i&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEJz%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJHMEUCIQDu5lMXWxGc7ydyD6HbmtJk2tnqLLxfRbCYqP7tAwi8wAIgAt3KpyhdECs9I7a2mSGNPjk1n4fq1BKjA7iOmBxOquUq%2BgMIRBAAGgw3NDk2Nzg5MDI4MzkiDOj9vGzyeEXkicvNUirXA9YvAlIvZPE3WdpgIYp51YCl28ISR4eL93paFfqBC0IguHOz%2BctOG2P5MwSc2Vj10UVBUBE4qTiGXYTbB3Gk4jCzTvgDEN90fXdMqQYWXCd8zDpq6OIcZ59qVTQPIFdjo2JZ8U3Tfu68BkIynFNLIiX4Y2WvBqxpJoFUlrmOcU4%2FtuXhSmiW6E7xyQus%2F%2BTq3A2n7JaJ2XgKOKPyINyOOBD3ZsonHjiZw0Djtjk7IgvwMjWVLb6Gn73c%2BG9bLKsHHW7aUnRaNEYSdhWejPpz1QEUlcOKpAkLI87kAgTMPCsljZMujUgWxozAth76hWebjXoE7OHUFx870jscKhpMH2DfJhaOCOsmyme69jpqc4%2FEN6jT2WGjIG42xlfUnxB90DpNBjkPguXFyghOHFlhR07bp9Rom0oW1XOriN9jnbxSZqyQsqDFwbrua4oKtOcJJrzDnUGmhKAlWPMkwE81wDyxXSB%2BGYlYQb%2F%2BXScqvqsieBtIpN5KOfAlB0VuoN17gi5BFXsP5ePaGeJPZ5MJ9COQtm6nXdvclUc8ENc0xPfw0l0485%2BVWe%2BzME%2FIIB0Sclg8TuyNSNcqrSxVxb7VVZMZfFrmMpXpU2FD1chXDGTv1tOP3x%2BthjDLvtWSBjqlATnNWnlBoAfJJE7C6ZqVOgRZU4EvDCpLchTmHT%2F99LoBvqYUU0qospR1VT4pGKtfBBEuNGgg9%2F8Dkj6l0q7p62mlxwt%2BENpVp2QOczzj6CDCjMg1E6jnsVGNzCoPeYiEEx8q6LBM51EOMcm2sSSVjNeVNRhTFrF84ch%2FCteFF5Ilr%2FTHW7pb9pJCaOOuJ%2FMZIpXy2w9CtOXxbO8%2BkG4kHHDarz8M9w%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20220412T121324Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIA25DCYHY3S4VTGYGI%2F20220412%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=d84c5f4e44cf6473e0a924f3a5fd57aea32c00b17480af1551a869e41693b030",
        "CodeSha256": "f9IchJrdt01ftKIlcSZ25z6ZRbf780hO8xVYCd6Uxhs=",
        "CodeSize": 8748397
    },
    "LayerArn": "arn:aws:lambda:us-east-1:400803493251:layer:sharp",
    "LayerVersionArn": "arn:aws:lambda:us-east-1:400803493251:layer:sharp:1",
    "Description": "Sharp dependency for image transformation",
    "CreatedDate": "2022-04-12T12:13:27.990+0000",
    "Version": 4,
    "CompatibleRuntimes": [
        "nodejs14.x"
    ]
}
Вход в полноэкранный режим Выход из полноэкранного режима

Шаг 5 — Создание лямбда-функции

Теперь давайте создадим лямбда-функцию, которая будет использовать лямбда-слой sharp. Как обсуждалось ранее, эта Lambda-функция будет вызываться при создании объекта в исходном ведре. Затем она создаст соответствующее уменьшенное изображение и сохранит его в целевом ведре. В приведенном ниже примере кода предполагается, что вы следуете соглашению об именах ведер S3, о котором говорилось в Шаге 1.

Шаг 5.1 Создание кода функции

Скопируйте следующий пример кода в файл с именем index.js.

// dependencies
const AWS = require('aws-sdk');
const util = require('util');
const sharp = require('sharp');

// get reference to S3 client
const s3 = new AWS.S3();

exports.handler = async (event, context, callback) => {

  // Read options from the event parameter.
  console.log("Reading options from event:n", util.inspect(event, {depth: 5}));
  const srcBucket = event.Records[0].s3.bucket.name;
  // Object key may have spaces or unicode non-ASCII characters.
  const srcKey    = decodeURIComponent(event.Records[0].s3.object.key.replace(/+/g, " "));
  const dstBucket = srcBucket + "-resized";
  const dstKey    = "resized-" + srcKey;

  // Infer the image type from the file suffix.
  const typeMatch = srcKey.match(/.([^.]*)$/);
  if (!typeMatch) {
      console.log("Could not determine the image type.");
      return;
  }

  // Check that the image type is supported
  const imageType = typeMatch[1].toLowerCase();
  if (imageType != "jpg" && imageType != "png") {
      console.log(`Unsupported image type: ${imageType}`);
      return;
  }

  // Download the image from the S3 source bucket.

  try {
      const params = {
          Bucket: srcBucket,
          Key: srcKey
      };
      var origimage = await s3.getObject(params).promise();

  } catch (error) {
      console.log(error);
      return;
  }

  // set thumbnail width. Resize will set the height automatically to maintain aspect ratio.
  const width  = 200;

  // Use the sharp module to resize the image and save in a buffer.
  try {
      var buffer = await sharp(origimage.Body).resize(width).toBuffer();

  } catch (error) {
      console.log(error);
      return;
  }

  // Upload the thumbnail image to the destination bucket
  try {
      const destparams = {
          Bucket: dstBucket,
          Key: dstKey,
          Body: buffer,
          ContentType: "image"
      };

      const putResult = await s3.putObject(destparams).promise();

  } catch (error) {
      console.log(error);
      return;
  }

  console.log('Successfully resized ' + srcBucket + '/' + srcKey +
      ' and uploaded to ' + dstBucket + '/' + dstKey);
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Шаг 5.2 Создание пакета развертывания

Пакет развертывания — это архив .zip, содержащий код вашей функции Lambda и ее зависимости.

1.) Откройте терминал командной строки или оболочку в среде Linux.
2.) Сохраните код функции как index.js в каталоге с именем lambda-s3.
После этого шага у вас будет следующая структура каталогов:

lambda-s3
|- index.js
Вход в полноэкранный режим Выход из полноэкранного режима

3.) Создайте пакет развертывания с кодом функции и его зависимостями. Установите опцию -r (рекурсивный) для команды zip, чтобы сжать вложенные папки.
Запустите эту команду из каталога lambda-s3.

zip -r function.zip .
Войти в полноэкранный режим Выйти из полноэкранного режима

Шаг 5.3 Создание функции Lambda

Мы будем использовать команду AWS CLI (aws lambda create-function) для создания функции Lambda.

Пожалуйста, замените параметр роли 123456789012 на ID вашей учетной записи AWS, а ARN слоя — на тот, который мы получили в шаге 4 (LayerVersionArn).

aws lambda create-function --function-name CreateThumbnail 
--zip-file fileb://function.zip --handler index.handler --runtime nodejs14.x 
--timeout 30 --memory-size 1024 
--role arn:aws:iam::123456789012:role/lambda-s3-role 
--region "us-east-1" 
--layers "arn:aws:lambda:us-east-1:400803493251:layer:sharp:1"
Войдите в полноэкранный режим Выйдите из полноэкранного режима

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

{
    "FunctionName": "CreateThumbnail",
    "FunctionArn": "arn:aws:lambda:us-east-1:400803493251:function:CreateThumbnail",
    "Runtime": "nodejs14.x",
    "Role": "arn:aws:iam::400803493251:role/lambda-s3-role",
    "Handler": "index.handler",
    "CodeSize": 1061,
    "Description": "",
    "Timeout": 30,
    "MemorySize": 1024,
    "LastModified": "2022-04-12T12:22:02.432+0000",
    "CodeSha256": "y0QVpF6+WN3wH1Zp+sbpbYlQEeAdkBuSf7p5aJV52Sc=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "64dc7cab-9adf-4472-b20b-e15237209939",
    "Layers": [
        {
            "Arn": "arn:aws:lambda:us-east-1:400803493251:layer:sharp:4",
            "CodeSize": 8748397
        }
    ],
    "State": "Pending",
    "StateReason": "The function is being created.",
    "StateReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Шаг 6 — Настройка Amazon S3 Trigger

Итак, мы создали все строительные блоки. Теперь давайте добавим последний элемент, где мы настроим Amazon S3 Trigger для вызова функции Lambda.
Когда файл загружается на S3, он должен вызвать функцию Lambda, которая изменит размер, создаст миниатюру и загрузит ее в целевое ведро S3.

Чтобы создать триггер Amazon S3, выполните следующие действия.

1.) Откройте страницу Lambda в консоли AWS.
2.) Откройте функцию CreateThumbnail.
3.) Выберите Добавить триггер в разделе Обзор функций
4.) Создайте триггер со следующими свойствами:
— Выберите триггер — S3
— Ведро — mybucket (имя вашего исходного ведра)
— Тип события — PUT

Шаг 7 — Все готово, давайте протестируем!

Отлично, у нас все готово с нашей функцией Lambda, которая использует резкий слой и создает уменьшенные изображения. Пожалуйста, загрузите изображение (jpg или png) в исходное ведро S3. После завершения загрузки вы сможете увидеть уменьшенную версию изображения в целевом ведре S3.

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

Если вы хотите изучить и узнать больше о лучших практиках кодирования и примерах кода, связанных с Lambda, вы можете заглянуть в репозиторий кода Webiny. Webiny — это бессерверная CMS корпоративного уровня с открытым исходным кодом.

Если у вас возникли вопросы по этому руководству или вы хотите оставить отзыв, пожалуйста, пишите нам в Slack сообщество!

Кредиты

Поскольку цель этого руководства — объяснить и продемонстрировать использование Lambda Layer, мы не стали изобретать велосипед и писать новую функцию Lambda для создания уменьшенных изображений. Код функции Lambda, используемый в этой статье для создания уменьшенных изображений, взят из этого официального руководства по AWS Lambda. Огромная благодарность авторам этого замечательного руководства по функции Lambda. 🙏🏻

Оцените статью
Procodings.ru
Добавить комментарий