eFusion 23 января 2020

Запуск бессерверного JS-проекта с GitLab

Возможно, вы слышали о таких бессерверных FaaS-решениях, как AWS Lambda. Рассказываем, как это работает на примере запуска JavaScript-проекта с GitLab.
Запуск бессерверного JS-проекта с GitLab

Хочешь уверенно проходить IT-интервью?

Готовься к IT-собеседованиям уверенно с AI-тренажёром T1!

Мы понимаем, как сложно подготовиться: стресс, алгоритмы, вопросы, от которых голова идёт кругом. Но с AI тренажёром всё гораздо проще.

💡 Почему Т1 тренажёр — это мастхэв?

  • Получишь настоящую обратную связь: где затык, что подтянуть и как стать лучше
  • Научишься не только решать задачи, но и объяснять своё решение так, чтобы интервьюер сказал: "Вау!".
  • Освоишь все этапы собеседования, от вопросов по алгоритмам до диалога о твоих целях.

Зачем листать миллион туториалов? Просто зайди в Т1 тренажёр, потренируйся и уверенно удиви интервьюеров. Мы не обещаем лёгкой прогулки, но обещаем, что будешь готов!

Реклама. ООО «Смарт Гико», ИНН 7743264341. Erid 2VtzqwP8vqy


Идея сводится к написанию кода как набора дискретных функций, которые могут вызываться различными событиями. Заботы о подготовке сервера, масштабирование, управление внутренним стеком и другие операционные задачи абстрагируются. Это приводит к значительной экономии средств, поскольку вычислительные ресурсы предоставляются по требованию.

Хотите узнать секрет бессерверности, не выполнив ни одной команды в терминале? Всё что нужно – учётные записи GitLab и AWS.

Создание проекта

Для начала создадим проект с помощью бессерверного шаблона. Открываем страницу нового проекта и выбираем вкладку Create from template. Прокручиваем вниз и выбираем шаблон Serverless Framework/JS.

Запуск бессерверного JS-проекта с GitLab

Называем проект, создаём с помощью Create project.

Настройка учётной записи AWS

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

Запуск бессерверного JS-проекта с GitLab

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

Запуск бессерверного JS-проекта с GitLab

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

Запуск бессерверного JS-проекта с GitLab

Здесь нужно выбрать вкладку "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 .

Запуск бессерверного JS-проекта с GitLab

Нажимаем Review Policy, придумываем имя, например, GitLabServerlessPolicy. Кликаем Create policy.

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

Запуск бессерверного JS-проекта с GitLab

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

Запуск бессерверного JS-проекта с GitLab

После нажатия кнопки Create user будет показана страницу с учётными данными для доступа к новой учётной записи AWS. Выбираем Show рядом с secret access key и копируем его вместе с ID в укромное место.

Ввод учётных данных AWS

Вернёмся к GitLab. Нам нужно ввести данные в настройки CI/CD нашего проекта. Выберите Settings -> CI/CD в левом меню.

Запуск бессерверного JS-проекта с GitLab

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

Запуск бессерверного JS-проекта с GitLab

Используйте 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 и дадим ей любое значение. Это будет использоваться нашей функцией.

Запуск бессерверного JS-проекта с GitLab

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

Запуск бессерверного JS-проекта с GitLab

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

Запуск бессерверного JS-проекта с GitLab

Введите значение и нажмите 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 и посмотреть, как это работает.

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

Запуск бессерверного JS-проекта с GitLab

Вуаля, мы только что создали вашу собственную бессерверную функцию и развернули её без единой команды в терминале.

Как вам туториал? Хотели бы видеть больше таких статей?

Источники

МЕРОПРИЯТИЯ

Комментарии

ВАКАНСИИ

Добавить вакансию
Hotel Search Team Lead (Golang)
по итогам собеседования
Golang-разработчик
Пермь, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ