Вы когда-нибудь задумывались, каково это внутри лямбды? Хватит удивляться. Давай выясним.
С момента своего появления в 2014 году лямбда-функции AWS стали горячей темой, открывающей новые летописи в области безсерверных вычислений . Удовольствия без сохранения состояния, без платы за обслуживание и исполнение буквально меняют — если не искоренивают — самые корни парадигмы облачных вычислений. Пока в игру вступают другие игроки, такие как Google и MS Azure, AWS пока что является абсолютным победителем.
Хорошо, проповедуя в стороне, как это действительно выглядит внутри лямбда-функции?
Согласно AWS, лямбды управляются контейнерными технологиями ; если быть точным, AWS EC2 Container Service (ECS) . Следовательно, в этот момент лямбда — это просто контейнер Docker с ограниченным доступом извне. Однако код функции, который мы запускаем внутри контейнера, имеет практически неограниченный доступ к нему, за исключением привилегий root, включая файловую систему, встроенные и установленные команды и инструменты CLI, системные метаданные и статистику, журналы и многое другое. Не очень полезно для обычного лямбда-автора, но может быть и так, если вы собираетесь идти по колено в вещах уровня ОС.
Очевидно, что самый простой способ изучить все эти предложения на уровне ОС — это иметь доступ к командной оболочке CLI (оболочки). К сожалению, в настоящее время это невозможно; тем не менее, комбинируя безумно простой синтаксис, предоставляемый средой выполнения NodeJS, и тем фактом, что лямбды имеют время поддержки нескольких минут , мы можем легко написать десятистрочную лямбду, которая может эмулировать оболочку. Хотя настоящая «сессия» не может быть установлена таким образом (например, вы не можете запустить top
для представления обновления в реальном времени), вы можете многократно запускать серию команд, как будто вы взаимодействуете с пользовательской консолью.
01
02
03
04
05
06
07
08
09
10
|
let { exec } = require( 'child_process' ); exports.handle = (event, context, callback) => { console.log(event); exec (event.cmd, (err, stdout, stderr) => { console.log(stdout); if (err) console.log(stderr); callback(undefined, {statusCode: 200}); }); } |
К счастью для нас, поскольку код представляет собой простой набор из десяти строк с нулевыми внешними зависимостями, мы можем развернуть всю лямбду — включая код, конфигурации и роль выполнения — через один шаблон CloudFormation :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
AWSTemplateFormatVersion: '2010-09-09' Resources: shell: Type: AWS::Lambda::Function Properties: FunctionName: shell Handler: index.handle Runtime: nodejs6.10 Code: ZipFile: > let { exec } = require( 'child_process' ); exports.handle = (event, context, callback) => { console.log(event); exec (event.cmd, (err, stdout, stderr) => { console.log(stdout); if (err) console.log(stderr); callback(undefined, {statusCode: 200}); }); } Timeout: 60 Role: Fn::GetAtt: - role - Arn role: Type: AWS::IAM::Role Properties: ManagedPolicyArns: - arn:aws:iam::aws:policy /service-role/AWSLambdaBasicExecutionRole AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com |
Развернуть все это так же просто, как:
1
|
aws cloudformation deploy --stack-name shell --template- file /path/to/template .yaml --capabilities CAPABILITY_IAM |
или выберите и загрузите шаблон на панель мониторинга CloudFormation , если у вас нет интерфейса командной строки AWS, чтобы сделать это (см. выше).
После развертывания достаточно просто вызвать лямбду с полезной нагрузкой, содержащей желаемую команду оболочки:
1
|
{ "cmd" : "the command to be executed" } |
Если у вас есть интерфейс командной строки AWS, все это становится намного более сексуальным, когда вызывается с помощью следующего фрагмента оболочки:
1
2
3
4
5
6
7
8
9
|
echo -n "> " read cmd while [ "$cmd" != "exit" ]; do echo aws lambda invoke -- function -name shell --payload "{\"cmd\":\"$cmd\"}" --log- type Tail /tmp/shell .log --query LogResult --output text | base64 -d echo echo -n "> " read cmd done |
С этим сценарием все, что вам нужно, это вызвать сценарий; вам будет выдана фальшивая «оболочка», в которой вы сможете выполнить долгожданную команду, и лямбда выполнит ее и сразу же вернет вывод обратно на консоль, вернув вас обратно в приглашение «shell»:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
> free START RequestId: c143847d-12b8-11e8-bae7-1d25ba5302bd Version: $LATEST 2018-02-16T01:28:56.051Z c143847d-12b8-11e8-bae7-1d25ba5302bd { cmd: 'free' } 2018-02-16T01:28:56.057Z c143847d-12b8-11e8-bae7-1d25ba5302bd total used free shared buffers cached Mem: 3855608 554604 3301004 200 44864 263008 -/+ buffers /cache : 246732 3608876 Swap: 0 0 0 END RequestId: c143847d-12b8-11e8-bae7-1d25ba5302bd REPORT RequestId: c143847d-12b8-11e8-bae7-1d25ba5302bd Duration: 6.91 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 82 MB > |
С помощью этой хитрости вы можете узнать немного больше о среде обитания и образе жизни лямбда-функции. Для начала я узнал, что среда выполнения контейнеров включает в себя экземпляры Amazon Linux с около 4 ГБ (возможно, совместно используемой) памяти Memeey и несколькими (неиспользуемыми) дисковыми хранилищами значительного размера (в дополнение к «рекомендуемым для использования» 500 МБ). смонтировать на /tmp
):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
> df START RequestId: bb0034fa-12ba-11e8-8390-cb81e1cfae92 Version: $LATEST 2018-02-16T01:43:04.559Z bb0034fa-12ba-11e8-8390-cb81e1cfae92 { cmd: 'df' } 2018-02-16T01:43:04.778Z bb0034fa-12ba-11e8-8390-cb81e1cfae92 Filesystem 1K-blocks Used Available Use% Mounted on /dev/xvda1 30830568 3228824 27501496 11% / /dev/loop8 538424 440 526148 1% /tmp /dev/loop9 128 128 0 100% /var/task END RequestId: bb0034fa-12ba-11e8-8390-cb81e1cfae92 REPORT RequestId: bb0034fa-12ba-11e8-8390-cb81e1cfae92 Duration: 235.44 ms Billed Duration: 300 ms Memory Size: 128 MB Max Memory Used: 22 MB > cat /etc/ *-release START RequestId: 6112efb9-12bd-11e8-9d14-d5c0177bc74f Version: $LATEST 2018-02-16T02:02:02.190Z 6112efb9-12bd-11e8-9d14-d5c0177bc74f { cmd: 'cat /etc/*-release' } 2018-02-16T02:02:02.400Z 6112efb9-12bd-11e8-9d14-d5c0177bc74f NAME= "Amazon Linux AMI" VERSION= "2017.03" ID= "amzn" ID_LIKE= "rhel fedora" VERSION_ID= "2017.03" PRETTY_NAME= "Amazon Linux AMI 2017.03" ANSI_COLOR= "0;33" CPE_NAME= "cpe:/o:amazon:linux:2017.03:ga" HOME_URL= "http://aws.amazon.com/amazon-linux-ami/" Amazon Linux AMI release 2017.03 END RequestId: 6112efb9-12bd-11e8-9d14-d5c0177bc74f REPORT RequestId: 6112efb9-12bd-11e8-9d14-d5c0177bc74f Duration: 209.82 ms Billed Duration: 300 ms Memory Size: 128 MB Max Memory Used: 22 MB > |
Правда, формат вывода (который в основном является необработанным из журналов CloudWatch ) может быть значительно улучшен, в дополнение к десяткам других возможных улучшителей. Итак, давайте обсудим, под комментариями!
Смотреть оригинальную статью здесь: Внутри Lambda Runtime: заглянуть в безсерверное логово
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |