Идея сводится к написанию кода как набора дискретных функций, которые могут вызываться различными событиями. Заботы о подготовке сервера, масштабирование, управление внутренним стеком и другие операционные задачи абстрагируются. Это приводит к значительной экономии средств, поскольку вычислительные ресурсы предоставляются по требованию.
Хотите узнать секрет бессерверности, не выполнив ни одной команды в терминале? Всё что нужно – учётные записи GitLab и AWS.
Создание проекта
Для начала создадим
проект с помощью бессерверного шаблона. Открываем страницу нового
проекта и выбираем вкладку Create
from template
. Прокручиваем вниз и выбираем шаблон Serverless
Framework/JS
.

Называем проект, создаём с помощью Create project
.
Настройка учётной записи AWS
Проект создан, передаём доступ в AWS, чтобы его развернуть. Открываем консоль AWS, переходим в раздел IAM.
Здесь выбираем в левой колонке Users
и создаём нового пользователя
с помощью кнопки Add user
в верхней части списка.

Даём пользователю имя, например, gitlab-serverless
. Прежде чем нажать Next
, убедитесь, что включен флажок Programmatic access
.

Теперь нужно
предоставить пользователю соответствующие права для развёртывания бессерверных
функций. На странице Permissions
выбираем Attach existing policies directly
и нажимаем Create policy
– откроется новое окно.

Здесь нужно выбрать вкладку "JSON" и вставить следующее:
{
"Statement": [
{
"Action": [
"apigateway:*",
"cloudformation:CancelUpdateStack",
"cloudformation:ContinueUpdateRollback",
"cloudformation:CreateChangeSet",
"cloudformation:CreateStack",
"cloudformation:CreateUploadBucket",
"cloudformation:DeleteStack",
"cloudformation:Describe*",
"cloudformation:EstimateTemplateCost",
"cloudformation:ExecuteChangeSet",
"cloudformation:Get*",
"cloudformation:List*",
"cloudformation:PreviewStackUpdate",
"cloudformation:UpdateStack",
"cloudformation:UpdateTerminationProtection",
"cloudformation:ValidateTemplate",
"dynamodb:CreateTable",
"dynamodb:DeleteTable",
"dynamodb:DescribeTable",
"ec2:AttachInternetGateway",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateInternetGateway",
"ec2:CreateNetworkAcl",
"ec2:CreateNetworkAclEntry",
"ec2:CreateRouteTable",
"ec2:CreateSecurityGroup",
"ec2:CreateSubnet",
"ec2:CreateTags",
"ec2:CreateVpc",
"ec2:DeleteInternetGateway",
"ec2:DeleteNetworkAcl",
"ec2:DeleteNetworkAclEntry",
"ec2:DeleteRouteTable",
"ec2:DeleteSecurityGroup",
"ec2:DeleteSubnet",
"ec2:DeleteVpc",
"ec2:Describe*",
"ec2:DetachInternetGateway",
"ec2:ModifyVpcAttribute",
"events:DeleteRule",
"events:DescribeRule",
"events:ListRuleNamesByTarget",
"events:ListRules",
"events:ListTargetsByRule",
"events:PutRule",
"events:PutTargets",
"events:RemoveTargets",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:GetRole",
"iam:PassRole",
"iam:PutRolePolicy",
"iot:CreateTopicRule",
"iot:DeleteTopicRule",
"iot:DisableTopicRule",
"iot:EnableTopicRule",
"iot:ReplaceTopicRule",
"kinesis:CreateStream",
"kinesis:DeleteStream",
"kinesis:DescribeStream",
"lambda:*",
"logs:CreateLogGroup",
"logs:DeleteLogGroup",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:FilterLogEvents",
"logs:GetLogEvents",
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:PutBucketNotification",
"s3:PutBucketPolicy",
"s3:PutBucketTagging",
"s3:PutBucketWebsite",
"s3:PutEncryptionConfiguration",
"s3:PutObject",
"sns:CreateTopic",
"sns:DeleteTopic",
"sns:GetSubscriptionAttributes",
"sns:GetTopicAttributes",
"sns:ListSubscriptions",
"sns:ListSubscriptionsByTopic",
"sns:ListTopics",
"sns:SetSubscriptionAttributes",
"sns:SetTopicAttributes",
"sns:Subscribe",
"sns:Unsubscribe",
"states:CreateStateMachine",
"states:DeleteStateMachine"
],
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "2012-10-17"
}
Эта политика является
примером, охватывающим практически всё, что может понадобиться бессерверной
платформе на AWS. Но большая её часть даже не будет использована. Можно ограничить платформу в соответствии с вашими нуждами и требованиями безопасности. Как минимум
понадобится доступ: cloudformation
, iam
, lambda
, logs
и функции s3
.

Нажимаем Review Policy
, придумываем имя, например, GitLabServerlessPolicy
. Кликаем Create
policy
.
После этого возвращаемся во вкладку Add user
и находим недавно созданную политику (возможно,
потребуется нажать значок Refresh
). Устанавливаем флажок рядом
с этой политикой и нажимаем Next
.

Жмём на Next: Tags
или переходим к обзору. Последняя страница должна выглядеть следующим образом:

После нажатия кнопки Create user
будет показана страницу с учётными данными для доступа к
новой учётной записи AWS. Выбираем Show
рядом с secret
access key
и копируем его вместе с ID в укромное место.
Ввод учётных данных AWS
Вернёмся к GitLab. Нам
нужно ввести данные в настройки CI/CD нашего проекта. Выберите Settings
-> CI/CD
в левом меню.

На этой странице необходимо развернуть раздел с переменными и ввести учётные данные AWS:

Используйте
AWS_ACCESS_KEY_ID
и AWS_SECRET_ACCESS_KEY
в качестве ключей для двух значений,
скопированных из AWS на предыдущем шаге. Не забудьте нажать кнопку Save
variables
.
Развёртывание первой функции AWS Lambda
Теперь пришло время развернуть проект. Если вы делаете это на gitlab.com, у вас уже есть доступ к GitLab раннеру на 2000 бесплатных минут CI пайплайна. Если нет, то нужно настроить раннер.
Перейдите в меню CI/CD
-> Pipelines
слева и нажмите Run Pipeline
. Для
развлечения давайте введём переменную окружения с ключом A_VARIABLE
и дадим ей
любое значение. Это будет использоваться нашей функцией.

Нажимаем Run
Pipeline
, видим, как наши задания начинают выполняться. Этот
шаблон проекта содержит тесты, которые будут автоматически стартовать при
каждом запуске пайплайна. После их завершения задание "production"
задеплоит код в AWS Lambda и создаст страницу на GitLab Pages. Через несколько
минут процесс должен завершиться, и мы сможем посетить Settings ->
Pages
, чтобы увидеть ссылку, куда все развернулось.

В результате видим там следующее:

Введите значение и нажмите Run function
. Этот инпут отправится в бессерверную функцию, результат будет выведен в поле Function Output
. Обратите внимание, что здесь также присутствует значение среды, которое мы предоставили с помощью ключа A_VARIABLE
.
Внесение изменений
Как насчёт простого калькулятора? Откройте Web IDE и внесите следующие изменения.
Внутри src/handler.js
добавьте следующую
функцию:
module.exports.add = async function(event) {
const A = Number(event.queryStringParameters.A);
const B = Number(event.queryStringParameters.B);
const result = A + B;
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: result
};
};
Откройте public/index.html
и замените его на
следующее:
<!DOCTYPE html>
<html>
<head>
<title>GitLab Serverless Framework example</title>
</head>
<body>
<h3>Add two values:</h3>
<label>A: <input type="text" id="inputA" placeholder="0" name="A"/></label>
<label>B: <input type="text" id="inputB" placeholder="0" name="B"/></label>
<strong>=</strong>
<span id="functionOutput">?</span>
<br />
<button>Calculate!</button>
<script>
fetch("./stack.json").then(response => {
response.json().then(myJson => {
const functionUrl = myJson.ServiceEndpoint + "/add";
const inputA = document.querySelector("#inputA");
const inputB = document.querySelector("#inputB");
const output = document.querySelector("#functionOutput");
document.querySelector("button").addEventListener("click", () => {
const A = Number(inputA.value);
const B = Number(inputB.value);
fetch(functionUrl + "?A=" + A + "&B=" + B)
.then(response => response.text())
.then(result => (output.textContent = result));
});
});
});
</script>
</body>
</html>
Наконец, в serverless.yml
добавьте функцию "add" под "hello":
functions:
hello:
handler: src/handler.hello
events:
- http:
path: hello
method: get
cors: true
add:
handler: src/handler.add
events:
- http:
path: add
method: get
cors: true
Выполните коммит в
главную ветку. Это автоматически приведёт к запуску нового пайплайна. Можно посетить CI/CD -> Pipelines
и посмотреть, как это работает.
После завершения развёртывания страница проекта должна выглядеть следующим образом:

Вуаля, мы только что создали вашу собственную бессерверную функцию и развернули её без единой команды в терминале.
Комментарии
Хорошая статья! Всё четко, но насколько Lambda будет выгоднее обычного инстанса? Также я как понял у Lambda нет ограничения по мощности по аналогии с Aurora.