Вычислительная техника! Конечно, у него очень долгая, яркая (а иногда и неловкая) история. Некоторые ключевые вехи включают:
- Египтяне, которые натянули несколько шариков на деревянную раму, чтобы немного расслабить свои мозги (и потели остаток дня над тоннами твердого гранита)
- Греки и их антикиферский механизм, который мог отслеживать движение планет с точностью до двух градусов на тысячелетие.
- Аналитическая машина Чарльза Бэббиджа.
- Разрушитель загадок Алана Тьюринга.
- Карманный калькулятор НАСА, который отправит человека на Луну.
- Deep Blue побеждает гроссмейстера Гарри Каспарова.
В соответствии со всем этим, парадигмы программных приложений также резко изменились. Начиная от чисто аппаратного программирования и заканчивая монолитами, модульностью, SOA, облаком, а теперь… бессерверным.
На данный момент бессерверный обычно означает FaaS (функции как услуга). А FaaS буквально означает AWS Lambda, как с точки зрения популярности, так и принятия.
Следовательно, не будет преувеличением сказать, что популярность бессерверной разработки может быть связана с простотой использования Lambdas. Либо это?
Ну, Lambda существует с 2015 года. Он уже интегрирован в большую часть экосистемы AWS и используется в производственной среде сотнями (если не тысячами) компаний. Итак, Lambda должна быть довольно интуитивно понятной и простой в использовании, не так ли?
Ну, в моем случае, похоже, нет.
А поскольку «мой случай» был одним из официальных примеров AWS, я не совсем уверен, что Lambda достаточно дружелюбна для новичков.
Для начала я хотел реализовать собственный пример использования создания эскизов AWS без следования их собственному руководству, чтобы посмотреть, как далеко я могу продвинуться.
Я, как программист, естественно начал с консоли управления Lambda. Код был уже написан щедрыми разработчиками AWS, так зачем изобретать велосипед? Скопируйте, вставьте, сохраните, запустите. Та-да!
Хм, похоже, мне нужно немного подрасти.
Привлекал внимание мастер Создание функции с таким количеством готовых чертежей. Жаль, что у него еще не было примера создания миниатюр S3, иначе эта история могла бы закончиться прямо здесь!
Поэтому я просто выбрал вариант «Автор с нуля», используя имя s3-thumbnail-generator
.
Ой, подождите, что это за штука с «ролью»? Это тоже необходимо. К счастью, у него есть опция «Создать новую роль из шаблона (ов)», которая спасла бы меня.
Не принимайте близко к сердцу. «Название роли»: s3-thumbnail-generator-role
. Но как насчет «шаблона политики»?
Возможно, мне стоит найти что-нибудь, связанное с S3, поскольку моя Lambda полностью S3.
Сюрприз! Единственное, что я получаю, когда ищу S3, - это «Разрешения только на чтение объекта S3». Не имея другого выхода, я просто схватил его. Посмотрим, как далеко я смогу пройти, прежде чем упаду лицом вниз!
Пора нажать «Создать функцию».
Вау, их конструктор Lambda выглядит действительно круто!
«Поздравляю! Ваша лямбда-функция «s3-thumbnail-generator» успешно создана. Теперь вы можете изменить его код и конфигурацию. Нажмите кнопку «Тест», чтобы ввести тестовое событие, когда вы будете готовы проверить свою функцию ».
Хорошо, время для моей миссии по копированию и вставке. Скопируйте образец исходного кода, Ctrl+A
и Ctrl+V
в редакторе кода лямбда. Простой!
Все зеленые (без красных). Хорошо знать.
«Сохранить» и «Проверить».
О, я должен был знать лучше. Ага, если я собираюсь «Тестировать», мне нужен «Тестовый ввод». Очевидно.
Я знал, что протестировать мою новенькую Lambda будет не так просто. Но я не ожидал, что придется собирать сериализованное событие JSON вручную.
К счастью, разработчики AWS проделали отличную работу и здесь, предоставив готовый шаблон события «S3 Put». Так что еще я бы выбрал?
Как и ожидалось, первый запуск оказался неудачным:
{ "errorMessage": "Cannot find module 'async'", "errorType": "Error", "stackTrace": [ "Function.Module._load (module.js:417:25)", "Module.require (module.js:497:17)", "require (internal/module.js:20:19)", "Object. (/var/task/index.js:2:13)", "Module._compile (module.js:570:32)", "Object.Module._extensions..js (module.js:579:10)", "Module.load (module.js:487:32)", "tryModuleLoad (module.js:446:12)", "Function.Module._load (module.js:438:3)" ] }
Блин, я должен был заметить эти require
строчки.
И, в любом случае, это у меня плохо. Страница, на которую я скопировал образец кода, имела большой жирный заголовок «Создать Lambda пакет развертывания» и четко объясняла, как объединить образец в zip-архив с возможностью развертывания Lambda.
Итак, я создал локальный каталог, содержащий мой код и package.json
, и запустил npm install
(хорошо, что у меня были предустановлены node
и npm
!).
Собрать, заархивировать и загрузить приложение было довольно легко, и, надеюсь, мне не пришлось бы проходить через миллион и один таких циклов, чтобы моя Lambda заработала.
(Кстати, я бы хотел сделать это в самом встроенном редакторе. Жаль, что я не смог придумать способ добавить зависимости.)
В любом случае, пришло время для моего второго теста.
{ "errorMessage": "Cannot find module '/var/task/index'", "errorType": "Error", "stackTrace": [ "Function.Module._load (module.js:417:25)", "Module.require (module.js:497:17)", "require (internal/module.js:20:19)" ] }
index
? Откуда это пришло?
Подожди ... у меня плохо, у меня плохо.
Похоже, что параметр Handler по-прежнему имеет значение по умолчанию index.handler
. В моем случае это должно быть CreateThumbnail.handler
(filename.method
).
Давай попробуем еще раз.
Шутки в сторону? Ни за что!
О да. Журналы не врут.
2018-02-04T17:00:37.060Z ea9f8010-09cc-11e8-b91c-53f9f669b596 Unable to resize sourcebucket/HappyFace.jpg and upload to sourcebucketresized/resized-HappyFace.jpg due to an error: AccessDenied: Access Denied END RequestId: ea9f8010-09cc-11e8-b91c-53f9f669b596
Справедливо. У меня нет sourcebucket
или sourcebucketresized
, но, вероятно, у кого-то есть. Отсюда отказ в доступе. Имеет смысл.
Поэтому я создал свои собственные сегменты s3-thumb-input
и s3-thumb-inputresized
, отредактировал ввод событий (благодаря раскрывающемуся списку «Настроить тестовое событие») и повторил попытку.
2018-02-04T17:06:26.698Z bbf940c2-09cd-11e8-b0c7-f750301eb569 Unable to resize s3-thumb-input/HappyFace.jpg and upload to s3-thumb-inputresized/resized-HappyFace.jpg due to an error: AccessDenied: Access Denied
В доступе отказано? Опять таки?
К счастью, на основе ввода события я выяснил, что 403 на самом деле может указывать на ошибку 404 (не найдено), поскольку в моем ведре на самом деле не было файла HappyFace.jpg
.
Подожди, дорогой читатель, а я кинулся к консоли S3 и загрузил свое счастливое лицо в свое новое ведро. Минуточку!
Хорошо, готов к следующему тесту.
2018-02-04T17:12:53.028Z a2420a1c-09ce-11e8-9506-d10b864e6462 Unable to resize s3-thumb-input/HappyFace.jpg and upload to s3-thumb-inputresized/resized-HappyFace.jpg due to an error: AccessDenied: Access Denied
Точно такая же ошибка? Опять таки? Ну давай же!
Для меня это не имело смысла. Почему моя собственная Lambda, запущенная в моем собственном аккаунте AWS, не будет иметь доступа к моей собственной корзине S3?
Подождите, это может быть связано с этой ролью исполнения? В той части, где я слепо назначил S3 права только для чтения?
Небольшой поиск в Google привел меня к чрезвычайно исчерпывающим документам AWS IAM для Lambda. Там я узнал, что Lambda выполняет свою собственную роль IAM. Мне пришлось бы вручную настроить роль в зависимости от того, какие сервисы AWS я буду использовать.
Что еще хуже, чтобы настроить роль, мне нужно пройти весь путь до консоли управления IAM. К счастью, это уже связано с раскрывающимся меню роли выполнения. Что еще более важно, он открывается в новой вкладке.
Скрестим пальцы, пока не загрузится страница пользовательской роли.
О нет ... Больше редактирования JSON?
В исходном руководстве разработчики AWS, похоже, прибили также и роль исполнения. Но было странно, что там не было упоминания о S3 (кроме названия). Они что-то упустили?
Хорошо, впервые в истории я собираюсь создать свою собственную роль IAM!
Благослови этих инженеров AWS, беглый поиск в Google показал их жемчужину генератора политик. Как раз то, что мне нужно.
Но избавление от синтаксиса JSON решает лишь небольшую часть проблемы. Как я могу узнать, какие разрешения мне нужны?
Гугл, приятель? Что-нибудь?
Ох… Вернемся к документации AWS? Большой…
Что ж, все было не так уж плохо, спасибо Руководству по разрешениям S3.
Хотя это было несколько ошеломляюще, я догадался, что мне нужны некоторые разрешения для «операций с объектами». К счастью, в документе была хорошая таблица, предполагающая, что мне нужны s3:GetObject
и s3:PutObject
(в соответствии с вызовами s3.getObject(...)
и s3.putObject(...)
в коде).
Поразмыслив, я получил «Политику IAM» с указанными выше разрешениями в моем сегменте (названный с утомительным синтаксисом arn:aws:s3:::s3-thumb-input
):
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1517766308321", "Action": [ "s3:PutObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::s3-thumb-inputresized" }, { "Sid": "Stmt1517766328849", "Action": [ "s3:GetObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::s3-thumb-input" } ] }
Я вставил и сохранил его в редакторе ролей IAM (который автоматически вернул меня на страницу консоли Lambda - как хорошо!)
Попробуйте снова…
Та же ошибка ?!
Оглядываясь назад на документ о разрешениях S3, я заметил, что права доступа к объектам содержат звездочку (суффикс /*
, вероятно, обозначающий файлы) под именем ресурса. Так что давайте попробуем и это с новой настраиваемой политикой:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1517766308321", "Action": [ "s3:PutObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::s3-thumb-inputresized/*" }, { "Sid": "Stmt1517766328849", "Action": [ "s3:GetObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::s3-thumb-input/*" } ] }
Опять таки! (это начинает звучать как Whiplash):
2018-02-04T17:53:45.484Z 57ce3a71-09d4-11e8-a2c5-a30ce229e8b7 Successfully resized s3-thumb-input/HappyFace.jpg and uploaded to s3-thumb-inputresized/resized-HappyFace.jpg
У-У-У !!!
Вы не поверите, но в моем s3-thumb-inputresized
ведре только что появился resized-HappyFace.jpg
файл! Ах, да!
Теперь, как я могу настроить мою Lambda для автоматического запуска, когда я помещаю файл в свою корзину?
К счастью, консоль Lambda (с ее интуитивно понятным макетом «триггерные функции-разрешения») дала кристально ясно, что мне нужен триггер S3. Поэтому я добавил один, с «Object Created (All)» в качестве «Тип события» и «jpg» в качестве суффикса, сохранил все и сразу же поместил файл JPG в свою корзину.
Ага, работает как шарм.
Чтобы увидеть, сколько времени занял весь процесс (в реальном исполнении, в отличие от «тестов»), я щелкнул ссылку «журналы» на (предыдущей) панели результатов выполнения и вошел в последний «поток журнала», показанный там. Ничего такого!
И что еще более подозрительно, последний журнал в новейшем потоке журнала был журналом «отказано в доступе», хотя я уже прошел эту точку и даже добился успешного изменения размера.
Может быть, мое последнее изменение нарушило способность Lambda вести журнал?
Благодаря Google и StackOverflow я обнаружил, что моя исполнительная роль также должна содержать некоторые разрешения, связанные с ведением журнала.
Теперь я помню, что в текстовом поле редактора разрешений были некоторые разрешения, когда я начал создавать свою настраиваемую роль. И снова я был достаточно невежественен, чтобы наклеить свои политики S3 прямо на них.
Еще один раунд редактирования политики:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1517766308321", "Action": [ "s3:PutObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::s3-thumb-inputresized/*" }, { "Sid": "Stmt1517766328849", "Action": [ "s3:GetObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::s3-thumb-input/*" }, { "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow", "Resource": "arn:aws:logs:*:*:*" } ] }
Еще одно падение файла, и на этот раз и изменение размера, и журналы работали безупречно… Наконец-то!
Теперь, когда все улажено, и мой эскиз ожидает в моем целевом сегменте, я запустил свой браузер, набрал http://s3-thumb-inputresized.s3.amazonaws.com/resized-HappyFace.jpg
(в соответствии с документацией виртуального хостинга S3). Я нажимаю Enter, ожидая взамен красивого эскиза.
<Error> <Code>AccessDenied</Code> <Message>Access Denied</Message> <RequestId>C8BAC3D4EADFF577</RequestId> <HostId>PRnGbZ2olpLi2eJ5cYCy0Wqliqq5j1OHGYvj/ HPmWqnBBWn5EMrfwSIrf2Y1LGfDT/7fgRjl5Io=</HostId> </Error>
Уже надоело это сообщение «Доступ запрещен»!
Очевидно, хотя мой код и генерирует файл, он не делает его общедоступным (но что хорошего в частном миниатюре, а?)
Покопавшись в документации AWS, я вскоре обнаружил параметр ACL
операции putObject
, который позволяет опубликовать загруженный файл S3. Надеясь, что это решит все проблемы на планете, я быстро обновил свой код, установив ACL файла на public-read
:
s3.putObject({ Bucket: dstBucket, Key: dstKey, Body: data, ContentType: contentType, ACL: 'public-read' }, next); }
Сохраните функцию и нажмите Test:
2018-02-04T18:06:40.271Z 12e44f61-19fe-11e8-92e1-3f4fff4227fa Unable to resize s3-thumb-input/HappyFace.jpg and upload to s3-thumb-inputresized/resized-HappyFace.jpg due to an error: AccessDenied: Access Denied
Опять таки?? Ты шутишь, что ли?!
К счастью, на этот раз я знал достаточно, чтобы сразу перейти к Руководству по разрешениям S3, которое сразу же показало, что мне также необходимо иметь разрешение s3:PutObjectAcl
в моей политике, чтобы использовать параметр ACL
в моем вызове putObject
.
Итак, еще один путь к редактору политик, к панели управления IAM и обратно к консоли Lambda.
2018-02-04T18:15:09.670Z 1d8dd7b0-19ff-11e8-afc0-138b93af2c40 Successfully resized s3-thumb-input/HappyFace.jpg and uploaded to s3-thumb-inputresized/resized-HappyFace.jpg
И на этот раз, к моему большому удовлетворению, браузер с радостью показал мне миниатюру моего счастливого лица, когда я ввел в него URL-адрес хостинга http://s3-thumb-inputresized.s3.amazonaws.com/resized-HappyFace.jpg
.
В общем, я удовлетворен тем, что наконец смог решить головоломку самостоятельно, сложив все разрозненные части вместе.
Но я не могу не представить, как было бы круто, если бы я мог построить свою Lambda в стиле фристайл, когда AWS самостоятельно позаботится о ролях, разрешениях и многом другом, не заставляя меня бегать вокруг блокировать.
Может, мне стоило с самого начала последовать этому официальному руководству…
… Но, опять же, где в этом веселье ?! :)