Как создать бессерверный сервис через 15 минут

1656586839 kak sozdat besservernyj servis cherez 15 minut

от Чарли Ли

R9Gc5kz1iOFdAMQkunKQgyINn4ScqS49cV4Q

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

Итак, что такое бессерверное?

Как следует из названия, бессерверный означает, что вы запускаете службу без сервера. Ну, технически, все еще есть сервер, на котором работает служба, но вам как владельцу службы не нужно беспокоиться об этом сервере.

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

И самое сладкое то, что это очень дешево. Amazon Lambda предоставляет 1 миллион бесплатных запросов и 400 000 ГБ-секунд бесплатных вычислений в месяц (это означает, что вычисления могут использовать 1 ГБ памяти в течение 400 000 секунд), чего достаточно для большинства небольших служб. По сравнению с EC2, где экземпляр nano будет стоить 0,0058 долларов в час (что составляет 0,14 долларов в день), Lambda гораздо дешевле.

Что мы будем делать здесь

В этой публикации я покажу вам, как создать небольшой персональный веб-сайт без сервера с помощью AWS. Веб-сайт имеет следующие характеристики:

  • Включает как фронтенд, так и заднюю часть
  • В основном статические или тяжелые передние панели
  • Запросы API – они редки, но необходимы
  • Бек-энд не требует слишком много памяти или ЦП (например, простой веб-счетчик, требующий только одного доступа к БД)

Наш сервис будет развернут в таких доменах (я использовал поддельные домены в этой публикации):

Бессерверное решение идеально как технически, так и с точки зрения стоимости. Мы будем использовать следующие сервисы AWS:

  • Lambda+API Gateway+S3, для сервера API
  • DynamoDB для хранения данных
  • S3, для статического веб-хостинга
  • Cloudfront, для распределенной CDN
  • AWS Certificate Manager (ACM) для создания сертификатов для нашего веб-сайта https
0uoj5U2PThzVHxYqiy1py0lyP0Qf6hx1Bpxd

Для сервера API мы будем использовать комбинацию Python+Flask и Zappa как бессерверный инструментарий.

Настройка среды AWS

Сначала нам нужно настроить среду AWS, чтобы мы могли получить доступ к AWS из нашего кода и zappa. Для этого нужно два шага:

  1. Нам нужно создать пользователь AWS для программного доступа
  2. Нам нужно настроить локальную среду AWS для использования для этого пользователя

Создайте пользователя AWS

Войдите в AWS и выберите службу «IAM» для управления учетными данными пользователя.

Создайте пользователя с именем «myservice-admin» (или любое другое имя пользователя, которое вы хотите использовать), и не забудьте пометить «Программный доступ” вариант.

RJm34WWNBf21zqZXF7y2tcuxoHEJi-Km5Ked

На следующем экране нажмите кнопку «Добавьте существующие политики напрямую», затем добавьте «Доступ администратора” пользователю.

Примечание. С точки зрения безопасности это не самая лучшая практика. Но для демонстрационных целей эта публикация не будет рассматривать детали сужения разрешений.

RL5qTOE2WERtOcGa5-Do8XBRpDeK8dGC3S-J

Нажмите кнопку «Далее», затем кнопку «Создать пользователя» и пользователя myservice-admin будет создан. На последнем экране Идентификатор ключа доступа и Секретный ключ доступа отображаются. Обязательно скопируйте и вставьте их в локальный файл. Это учетные данные API, которые мы будем использовать на следующем шаге.

Примечание: Это единственное место, где можно просмотреть секретные ключи доступа! Если вам не удастся сделать их копию, вам придется перейти на экран пользовательских данных и сгенерировать новую пару ключей доступа и секрета.

Настройте локальную среду AWS

Нам нужно создать локальную среду для использования AWS локально.

Сначала установим awscli инструмент, который поможет нам настроить среду:

$ sudo apt install awscli

После установки мы настроим AWS с помощью aws configureкоманда:

$ aws configureAWS Access Key ID [None]: ******AWS Secret Access Key [None]: ******Default region name [None]: us-east-1Default output format [None]: json

Здесь нам нужно ввести Идентификатор ключа доступа и Секретный ключ доступа мы получили с последнего шага. С точки зрения региона по умолчанию я использовал us-east-1. Вы можете выбрать любой регион, который вам нравится, но другие регионы могут вызвать определенные проблемы при настройке CloudFront.

Создайте таблицу в DynamoDB

Чтобы сохранить значение счетчика посетителей сайта в DynamoDB, нам нужен постоянный магазин. Следовательно, нам нужно создать таблицу и заполнить в ней первоначальное значение.

На консоли AWS выберите DynamoDB. Затем нажмите кнопку «Создать таблицу” кнопка. На экране «Создать таблицу DynamoDB» заполните Имя таблицы с myservice-dev и Первичный ключ поле с idа затем нажмите кнопку Создать таблицу кнопку.

M3vIGIOT73EbIWi3FaUexw-6k-OXH1BQ5h6I

Через пару секунд таблица должна быть создана. Выберите новую таблицу, выберите Предметы вкладку на правой панели, а затем нажмите кнопку Создать элемент и создайте элемент с помощью id='counter' и counter_value=0.

Примечание: вам нужно нажать знак плюс слева, чтобы добавить counter_value атрибут, и не забудьте установить тип counter_value к Номер.

S7qDIn8je7Zlbm9WONmR9LYTRsewyymMmNWr

Создайте службу API

Далее мы создадим службу API. Для демонстрационных целей эта служба API предоставит счетчику API, который повысит значение счетчика при нажатии. Значение счетчика будет сохранено в DynamoDB. Конечными точками API являются:

  • POST /counter/increase увеличивает счетчик и возвращает значение счетчика
  • GET /counter возвращает текущее значение счетчика

Кодирование службы API с помощью Python и Flask

Начнем с создания виртуальной среды Python и установки необходимых пакетов:

$ mkdir myservice && cd myservice$ python3 -m venv .env$ source .env/bin/activate(.env)$ pip install flask boto3 simplejson

flask это веб-фреймворк и boto3 пакет необходим для доступа к DynamoDB. simplejson может помочь нам решить некоторые проблемы с преобразованием JSON. Давайте создадим сервис, создав файл myservice.py с содержанием ниже:

import boto3from flask import Flask, jsonify
app = Flask(__name__)
# Initialize dynamodb accessdynamodb = boto3.resource('dynamodb')db = dynamodb.Table('myservice-dev')
@app.route('/counter', methods=['GET'])def counter_get():  res = db.get_item(Key={'id': 'counter'})  return jsonify({'counter': res['Item']['counter_value']})
@app.route('/counter/increase', methods=['POST'])def counter_increase():  res = db.get_item(Key={'id': 'counter'})  value = res['Item']['counter_value'] + 1  res = db.update_item(    Key={'id': 'counter'},    UpdateExpression='set counter_value=:value',    ExpressionAttributeValues={':value': value},  )  return jsonify({'counter': value})

Создать run.py файл, чтобы проверить эту службу API локально:

from myservice import appif __name__ == '__main__':  app.run(debug=True, host="127.0.0.1", port=8000)

Теперь запустите службу:

(.env)$ python run.py

И мы можем протестировать эту службу с помощью таких команд (откройте другой терминал, чтобы ввести эти команды):

$ curl localhost:8000/counter{  "counter": 0}$ curl -X POST localhost:8000/counter/increase{  "counter": 1}$ curl -X POST localhost:8000/counter/increase{  "counter": 2}$ curl localhost:8000/counter{  "counter": 2}

Мы видим, что наш код работает и он успешно увеличивает счетчик!

Развертывание нашего кода на Lambda с помощью Zappa

Развернуть наш API на Lambda очень легко с zappa. Сначала нам нужно установить zappa:

(.env)$ pip install zappa

Затем инициализируйте среду zappa с помощью zappa init. Он задаст вам несколько вопросов, но обычно вы можете использовать ответы по умолчанию для всех вопросов:

(.env)$ zappa init...What do you want to call this environment (default 'dev'): ...What do you want to call your bucket? (default 'zappa-ab7dd70x5'):
It looks like this is a Flask application.What's the modular path to your app's function?This will likely be something like 'your_module.app'.We discovered: myservice.appWhere is your app's function? (default 'myservice.app'): ...
Would you like to deploy this application globally? (default 'n') [y/n/(p)rimary]:
Okay, here's your zappa_settings.json:
{    "dev": {        "app_function": "myservice.app",        "aws_region": "us-east-1",        "profile_name": "default",        "project_name": "myservice",        "runtime": "python3.6",        "s3_bucket": "zappa-ab7dd70x5"    }}
Does this look okay? (default 'y') [y/n]: ...

После инициализации мы можем увидеть сгенерированный zappa_settings.json файл. Тогда мы можем начать развертывать наш сервис:

(.env)$ zappa deploy devCalling deploy for stage dev.....Deployment complete!: https://2ks1n5nrxh.execute-api.us-east-1.amazonaws.com/dev

Прекрасно! Наш сервис онлайн. Вы также можете протестировать этот сервис с помощью curl:

(.env)$ curl  curl -X POST  curl https://2ks1n5nrxh.execute-api.us-east-1.amazonaws.com/dev/counter{"counter":3}

Настройте специальный домен API

Однако с сервисом API есть одна проблема. Автоматически сгенерированная конечная точка API 2ks1n5nrxh.execute-api.us-east-1.amazonaws.com очень тяжело читать или использовать для потребления человеком. К счастью, мы можем привязать пользовательское доменное имя к этой конечной точке API.

Мы будем использовать пользовательский домен для этой службы API. Поскольку мы хотим обслуживать его с помощью https, нам сначала нужно получить сертификат. AWS предоставляет бесплатный сертификат с сервисом «Менеджер сертификатов», и он очень прост в использовании.

После создания сертификата мы можем использовать его для настройки специального домена для службы в AWS API Gateway.

Подайте заявку на получение сертификата

Перейдите на службу ACM на консоли управления AWS (на самом деле служба называется Certificate Manager, но вы можете ввести ACM, чтобы ее найти). Нажмите Запрос на сертификат кнопку, а затем выберите Спросите публичный сертификат на следующем экране. Сертификат бесплатный, если вы выберете публичный сертификат.

На следующем экране введите имя домена, для которого необходимо применить сертификат, а затем щелкните Дальше. Вот я подал заявку *.example.com что означает, что сертификат может использоваться всеми субдоменами под example.com. Таким образом, мы можем использовать тот же сертификат для нашего интерфейса на myfrontend.example.com без необходимости подавать заявку на новый.

ZaiecxZNM6qLZ0qSrsyUqICIgeayzFQmJsec

На следующем шаге нам нужно доказать, что мы являемся владельцем этого доменного имени. Поскольку я подал заявку на это доменное имя из Google Domains, я выберу Проверка DNS. Нажмите кнопку Обзор затем нажмите кнопку Подтвердить и подать запрос.

Запрос на сертификат будет создан, и отобразится экран проверки. Инструкции показывают, как проверить это доменное имя:

K-R1B8uuia0qoYkG5ICokjgNksKt7kspld7Z

На основе инструкций нам нужно добавить a CNAME записать и назначить заданное значение. В моем случае я открою Google Domains, найду свое доменное имя example.comи добавьте указанную запись CNAME:

7o2btPUTtH4wENbsBtPpemo9lTsAF6qjKiwm

Примечание: я добавил только случайную строку _2adee19a0967c7dd5014b81110387d11 в поле Имя, не вводя .example.com часть. Это нужно для того, чтобы избежать суффикса .example.com часть дублируется.

Теперь нам нужно подождать около 10 минут, пока AWS Certificate Manager проверит это доменное имя. После подтверждения в столбце «Статус» в сертификате появится зеленый цвет «Выдано».

POueIJUYfB1Fvk9GzQDvgcFq0OBwesN9Mqjp

Теперь, когда сертификат готов, мы можем начать привязывать наше пользовательское доменное имя к нашему API.

Настройка специального домена для службы API

Выделите службу API Gateway. С API на левой панели мы видим, что наш API myservice-dev уже создано zappa.

Нажмите «Пользовательские доменные имена” на панели влево, а затем нажмите кнопку Создайте пользовательское доменное имя на правой панели и заполните необходимые поля.

giptTgSYnBgKzDQk4wR2qQPKuY4chrJQoLzI

Здесь я хочу, чтобы моя служба API была открыта через CloudFront, чтобы к ней можно получить доступ с оптимальной скоростью по всему миру. Поэтому я выбрал Край оптимизирован в данной конфигурации. Вы можете выбрать Региональный если вам не требуется CloudFront.

Нажмите кнопку «Добавить отображение” ссылку ниже, а затем выберите наш API myservice-dev как Пункт назначенияи выберите разв за самый правый ящик. Таким образом, наш API не откроет название среды dev в URL-адресе. Оставьте Путь поле пустое.

5unYz3372TkXLMvB1iRaCcVRmp33yXi1FVc-

После нажатия кнопки Сохранить кнопку, будет создана наша пользовательская привязка домена. Фактическая привязка домена требует до 40 минут для инициализации, но мы можем настроить параметры DNS сейчас.

Из вышеприведенного снимка экрана мы видим, что фактическое доменное имя есть dgt9opldriaup.cloudfront.net. Нам нужно настроить а CNAME в нашем DNS, указывая myservice-api.example.com в субдомен CloudFront dgt9opldriaup.cloudfront.net.

Перейдите к Google Domains и добавьте CNAME к настройкам DNS:

oJ4YPm9XmMEhOMNaVowdRJbqFTrMb-7uPwq2

После этого шага подождите примерно 40 минут, пока не исчезнет сообщение «Инициализация…» в шлюзе API.

Теперь попробуйте наш новый сервис API!

(.env)$ curl /counter{"counter":3}(.env)$ curl -X POST /counter/increase{"counter":4}(.env)$ curl /counter{"counter":4}

Статический веб-сайт для интерфейса

Для следующей задачи мы создадим интерфейс для нашей совершенно новой службы API. Для демонстрационных целей мы создадим простую страницу с запускающей кнопкой /counter/increase Вызов API.

Кодирование передней части

Давайте создадим новый каталог под названием myfrontend:

$ mkdir myfrontend && cd myfrontend

Затем создайте простой файл HTML index.html:

<html><body>  <h1>Welcome to my homepage!</h1>  <p>Counter: <span id="counter"></span></p>  <button id="increase">Increase Counter</button>  <script>    const setCounter = (counter_value) => {      document.querySelector('#counter').innerHTML = counter_value;    };
    const api = '';    fetch(api + '/counter')      .then(res => res.json())      .then(result => setCounter(result.counter));
document.querySelector('#increase')      .addEventListener('click', () => {        fetch(api + '/counter/increase', { method: 'POST' })          .then(res => res.json())          .then(result => setCounter(result.counter));        }      );  </script></body></html>

Опубликуйте Front end в AWS S3

Чтобы создать статический сайт с S3, нам нужно создать ведро с таким же именем, что и наше доменное имя.

Примечание. Если вы придерживаетесь этого руководства, название сегмента myfrontend.example.com может быть недоступно, поскольку названия сегментов являются глобально уникальными. Кроме того, вам нужно будет создать имя сегмента на основе вашего общедоступного домена. Например,myfrontend.[yourdomain].com

Выделите службу S3 на консоли управления AWS. Поскольку мы хотим разместить статический веб-сайт на myfrontend.example.com, мы создадим ведро с таким названием. Нажмите кнопку Создать ведро и введите название сегмента, а затем продолжайте нажимать Дальше пока не будет создано ведро.

EjYD-VGI7VJmRnVIEmsr4Bzn5E-It5YQgFAx

Далее нам нужно включить статический веб-хостинг из этого ведра. Откройте это ведро, затем выберите Свойства вкладку и выберите Статический веб-хостинг. В диалоговом окне выберите Используйте это ведро для размещения веб-сайтазатем введите index.html в поле «Индексный документ». Нажмите Сохранить когда окончено.

POZJE4JrDzqtmXYYTmtW838Vw3Dku56h5iV-

Примечание. Ссылка «Конечная точка» показана в диалоговом окне выше. Мы проверим наш статический веб-сайт с этим URL позже.

Последнее, что нам нужно сделать, – это включить публичный доступ к ведру. Это можно сделать, добавив политику сегмента. Откройте это ведро и выберите Разрешения вкладку, а затем нажмите кнопку Политика ведра кнопку.

Введите следующее содержимое в качестве политики и нажмите кнопку Сохранить кнопку (не забудьте заменить myservice.example.com с вашим доменным именем).

{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "PublicReadGetObject",            "Effect": "Allow",            "Principal": "*",            "Action": "s3:GetObject",            "Resource": "arn:aws:s3:::myfrontend.example.com/*"        }    ]}

После сохранения мы сможем увидеть оранжевый знак «общедоступный». Политика ведра кнопка и Разрешения вкладка, указывающая, что наше ведро общедоступно.

Теперь ведро создано, но оно все еще пусто. Нам нужно загрузить наши файлы кода интерфейса в это ведро. Убедитесь, что мы в новом myfrontend каталог и введите следующую команду:

# Make sure you are in the `myfrontend` directory...$ aws s3 sync . s3://myfrontend.example.com

Приведенная выше команда копирует все файлы из текущего . каталог на S3.

Готово! Теперь мы можем протестировать этот статический веб-сайт с отображаемым ранее URL-адресом. Откройте этот URL-адрес в любом браузере (в моем случае, и увидите результат!

Ой! Счетчик вообще не отображается. ?

8HmkoqeY791wEFxKusCRKQRF6mS7ThvFBfLM

И, похоже, мы получили ошибку JavaScript. Мы видим такую ​​ошибку в консоли:

Failed to load /counter: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Очевидно, нам нужно установить заголовок CORS, чтобы этот скрипт работал, поскольку серверный API расположен в другом домене. Но поскольку мы собираемся настроить пользовательский домен для интерфейса, URL изменится, поэтому мы будем беспокоиться о CORS позже.

Настройка CloudFront для нашего статического веб-сайта

Последним шагом является настройка CloudFront для нашего интерфейса. Поскольку мы уже создали сертификат для *.example.comэтот шаг будет очень лёгким.

Выделите службу CloudFront на консоли управления AWS. Нажмите Создать распространение кнопку, а затем нажмите кнопку Начните кнопку в разделе «Веб».

На экране «Создать распространение» необходимо внести пять изменений:

  • Нажмите кнопку Начальное доменное имя поле ввода и выберите наше ведро S3 myfrontend.example.com.s3.amazonaws.com.
  • Затем смените Политика протокола просмотра чтобы «Направить HTTP на HTTPS», чтобы принудительно получить https.
  • В Альтернативные доменные имена введите наш пользовательский домен. В этом случае вводим myfrontend.example.com.
  • Прокрутите вниз до Сертификат SSL выберите «Специальный сертификат SSL», затем выберите наш *.example.com сертификат.
  • Изменить Корневой объект по умолчанию к index.html.

После создания дистрибутива мы увидим домен CloudFront в списке рассылки.

XVHiWsgZ5DzvulZNLv7qZ74dbaltssSU0Od2

Хотя статус все еще «В разработке», мы можем настроить нашу запись DNS сейчас. Выделите Google Domains и добавьте CNAME для этого домена:

IDE1BaGVdZi4v9-yjNyB9JaikGf1un-uylHq

Затем подождите, пока статус распространения не изменится на «Развернут». Теперь откройте браузер и попробуйте получить доступ myfrontend.example.com. Мы видим тот же статический веб-сайт!

Решите проблему CORS

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

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

Вернитесь в наш каталог API (myservice) и активируйте среду Python. Затем установите flask_cors пакет.

$ cd myservice$ source .env/bin/activate(.env)$ pip install flask_cors

Затем отредактируйте myservice.py и добавьте следующие строки (жирным):

import boto3from flask import Flask, jsonifyfrom flask_cors import CORS
app = Flask(__name__)CORS(app, origins=['https://myfrontend.example.com'])

Перенесите обновленную службу в AWS Lambda:

(.env)$ zappa update dev

Теперь попробуйте обновить наш браузер. Мы видим, что счетчик отображается правильно. Нажатие кнопки «Увеличить счетчик» может также увеличить счетчик.

50exWZDflbAEedy9W3Rjzd7h8oGxKLKuGmb8

Вывод

В этой публикации мы рассмотрели разные службы AWS, необходимые для создания простого сервиса без сервера. Если вы не знакомы с AWS, вам может показаться, что служб AWS слишком много, но большинство используемых здесь служб AWS предназначены для одноразового использования. После того как они настроены, нам не нужно вообще их касаться при дальнейшей разработке. Все, что вам нужно сделать, это бежать zappa update и aws s3 sync.

Кроме того, это гораздо проще, чем настроить приватный VPS, установить веб-серверы и написать задачи Дженкинса для постоянного развертывания.

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

  • Лямбда может запускать простую службу. Эта служба может быть открыта через API Gateway.
  • zappa – отличный инструмент, если вы хотите писать бессерверные службы на Python.
  • S3 bucket можно использовать для статического хостинга.
  • Подайте заявку на получение сертификата от AWS ACM, если хотите использовать https.
  • API Gateway и CloudFront поддерживают пользовательские доменные имена.

Надеюсь, вам понравился этот пост, и вы не стесняйтесь хлопать? для меня если бы ты сделал! Подпишитесь на меня, если вы хотите узнать больше о веб-разработке.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *