Автор оригинала: FreeCodeCapm Team.
Charlee Li
Слово «Serverless» было популярным в течение довольно давно. Когда Amazon выпустила AWS Lambda Service в 2015 году, появились многие инструменты, чтобы помочь людям строить сервисы без сервеса всего несколькими командами. По сравнению с традиционными службами всегда на службах Serverless очень легко разрабатывать, развернуть и поддерживать. Они также чрезвычайно экономически эффективны, особенно для этих простых услуг, которые не имеют слишком большого количества трафика.
Так что же безведно?
По мере того, как его имя подразумевает, «Serverless» означает, что вы запускаете услугу без сервера. Ну, технически, есть еще сервер, запущенный сервис, но вы, как владелец услуг, не нужно беспокоиться об этом сервере.
Например, AWS Lambda позволяет развертывать «функцию», чтобы иметь дело с запросами. У AWS есть сервер для запуска всех функций, когда они запрашиваются. Но вам не нужно беспокоиться о том, как работает этот сервер или как сделать ваш код работать с этим сервером. Все, что вам нужно знать, это то, что вы пишете функцию, затем нажмите на службу лямбда.
И самая сладкая часть состоит в том, что это очень дешево. Amazon Lambda предоставляет 1M бесплатные запросы и 400 000 GB-секунды свободно вычислите время в месяц (что означает, что ваши вычисления могут использовать память 1 ГБ в течение 400 000 секунд), что достаточно для большинства небольших услуг. По сравнению с EC2, где нано-экземпляр будет стоить вам 0,0058 долл. США в час (что составляет $ 0,14 в день), лямбда находится дешевле.
Что мы будем делать здесь
В этом посте я покажу вам, как построить небольшой персональный сайт без сервеса, используя AWS. На сайте есть следующие характеристики:
- Включает в себя как передний и задний конец
- В основном статичный или передний тяжелый
- API-запросы – это редки, но необходимо
- Back-End не требует слишком много памяти или процессора (например, простой веб-счетчик, который требует только одного доступа DB)
Наш сервис будет развернут в следующих доменах (я использовал поддельные домены в этом посте):
- API Сервис: https://myservice-api.example.com.
- Передний конец: https://myfrontend.example.com.
Решение без сервеса идеально подходит как технически, так и с точки зрения затрат. Мы будем использовать следующие услуги AWS:
- Lambda + API Gateway + S3, для API-сервера
- Dynamodb, для хранения данных
- S3, для статического веб-хостинга
- Cloudfront, для распределенного CDN
- AWS сертификат Manager (ACM) для генерации сертификатов для нашего сайта HTTPS
Для API-сервера мы будем использовать комбинацию Python + Flask и Zappa в качестве Serverless Toolkit.
Настройка среды AWS
Сначала нам нужно настроить среду AWS, чтобы мы могли получить доступ к AWS из нашего кода и Заппа Отказ Это занимает два шага:
- Нам нужно создать пользователь AWS для программного доступа
- Нам нужно настроить локальную среду AWS, чтобы использовать для этого пользователя
Создать пользователь AWS
Войдите в AWS и выберите службу «IAM» для управления учетными данными пользователя.
Создайте пользователь под названием «MyService-admin» (или любое другое имя пользователя, которое вы хотели бы использовать), и не забудьте проверить опцию « программный доступ ».
На следующем экране нажмите « Приложить существующую политику напрямую », затем добавьте « AdministratorAccess » пользователю.
Нажмите на кнопку «Далее», а затем кнопка «Создать пользователя», а также пользователь MyService-Admin
будет создан. На последнем экране Доступ к ключу ID и Секретный ключ доступа отображаются. Обязательно скопируйте и вставьте их в локальный файл. Это учетные данные 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
Здесь нам нужно набрать в Доступ к ключу ID и Секретный ключ доступа Мы получили с последнего шага. С точки зрения региона по умолчанию я использовал США-Восток-1
Отказ Вы можете выбрать любой регион, который вам нравится, но другие регионы могут привести к возникновению проблем при настройке CloudFront.
Создать таблицу в Dynamodb
Чтобы сохранить значение счетчика посетителей сайта в Dynamodb, нам нужен постоянный магазин. Поэтому нам нужно создать таблицу и заполнить начальное значение внутри него.
В пределах консоли AWS выберите Service Dynamodb. Затем нажмите кнопку « Create Table ». В экране «Создание таблицы Dynamodb» заполните Назначение таблицы с MyService-Dev
и Первичный ключ поле с ID
Затем нажмите на Создать таблицу кнопка.
Через пару секунд стол должен быть создан. Выберите вновь созданную таблицу, выберите Предметы Вкладка с правой панели, затем нажмите на Создать товар кнопка и создать элемент с ID = «счетчик»
и counter_value = 0
Отказ
Создать службу API
Далее мы создадим службу API. Для демонстрационных целей эта служба API обеспечит счетчик API, который увеличит значение счетчика при нажатии. Значение счетчика будет храниться в Dynamodb. Конечные точки API:
Пост/счетчик/Увеличение
Увеличивает счетчик и возвращает счетчик счетчиковПолучить/счетчик
Возвращает текущее значение счетчика
Кодирование службы API с Python и Flask
Мы начнем с создания виртуальной среды Python и установить необходимые пакеты:
$ mkdir myservice && cd myservice$ python3 -m venv .env$ source .env/bin/activate(.env)$ pip install flask boto3 simplejson
колбу
это веб-каркас и 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}
Мы видим, что наш код работает, и он успешно увеличивает счетчик!
Развертывание нашего кода на лямбда с 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 https://2ks1n5nrxh.execute-api.us-east-1.amazonaws.com/dev/counter{"counter":2}(.env)$ curl -X POST https://2ks1n5nrxh.execute-api.us-east-1.amazonaws.com/dev/counter/increase{"counter":3}(.env)$ 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.
Мы будем использовать пользовательский домен https://myservice-api.example.com
Для этой службы API. Поскольку мы хотим обслуживать его с HTTPS, нам нужно сначала получить сертификат. AWS предоставляет бесплатный сертификат с обслуживанием «Диспетчер сертификатов», и он очень прост в использовании.
После создания сертификата мы можем использовать его для настройки пользовательского домена для нашего сервиса в сервисе Gateway AWS API.
Подать заявку на сертификат
Переключитесь на службу ACM в консоли управления AWS (сервис на самом деле называется диспетчером сертификата, но вы можете ввести «ACM» для его поиска). Нажмите Запросить сертификат кнопка, затем выберите Запросить публичный сертификат Опция на следующем экране. Сертификат свободен до тех пор, пока вы выбираете публичный сертификат здесь.
На следующем экране введите имя домена, которое вы хотите применить сертификат, затем нажмите Следующий Отказ Здесь я подал заявку на * .example.com
Что означает, что сертификат может быть использован всеми подгруппами под example.com
Отказ Таким образом, мы можем использовать тот же сертификат для нашего переднего конца на myfrontend.example.com
без необходимости подать заявку на новый.
На следующем шаге нам нужно доказать, что у нас есть это доменное имя. Поскольку я подал заявку на это доменное имя из доменов Google, я выберу DNS Валидация Отказ Нажмите на Обзор кнопка затем нажмите Подтвердите и запросите Отказ
Запрос сертификата будет создан, и будет отображаться экран проверки. Инструкции показывают, как подтвердить это доменное имя:
Основываясь на инструкциях, нам нужно добавить Cname
Запись и назначить его заданное значение. В моем случае я открою домены Google, найдите мое доменное имя example.com
и добавьте указанную запись CNAME:
Примечание: я добавил только случайную строку _2adee19a0967c7dd5014b81110387d11
В поле имени, не набрав .example.com
часть. Это следует избегать суффикса .example.com
Часть дублируется.
Теперь нам нужно ждать около 10 минут до тех пор, пока AWS Sermerch Manager не проверяет это доменное имя. После подтверждения столбца «Статус» в сертификате будет отображаться «выпущено» в зеленом.
Теперь, когда у нас есть сертификат готов, мы можем начать привязать ваше пользовательское доменное имя на вашу API.
Настройка пользовательского домена для вашей службы API
Перейдите на службу «Gateway API». Из «API» на левой панели мы можем увидеть, что наши API MyService-Dev
уже создан Zappa.
Нажмите на « пользовательские доменные имена » с левой панели, затем нажмите на Создать пользовательское доменное имя Кнопка на правой панели и заполните необходимые поля.
Здесь я хочу, чтобы моя поддержка API должна быть выставлена через Cloudfront так, чтобы она была доступна с оптимальной скоростью по всему миру. Так что я выбрал Оптимизирован по краю В этой конфигурации. Вы можете выбрать Региональный Если вам не нужно Cloudfront.
Нажмите « Добавить сопоставление » Ниже, затем выберите наш API MyService-Dev
Как Назначение и выберите dev для правильной самой коробки. Таким образом, наша API не будет подвергать названию окружающей среды dev
в URL. Оставь Путь поле пусто.
После нажатия на Сохранить Кнопка, наш пользовательский привязки домена будет создан. Фактическое привязку домена требует до 40 минут для инициализации, но мы можем настроить настройки DNS сейчас.
С вышеуказанного скриншота мы можем видеть, что фактическое доменное имя – DGT9OPLDRIAUP.CLUDFRONT.NET
Отказ Нам нужно настроить Cname
В наших DNS, указывая myservice-api.example.com
в поддомен Cloudfront DGT9OPLDRIAUP.CLUDFRONT.NET
Отказ
Перейдите в Google Domains и добавьте CNAME в настройки DNS:
После этого шага подождите около 40 минут до тех пор, пока не исчезнет «Инициализация …» в сервисе API Gateway.
Теперь попробуйте нашу новую службу API!
(.env)$ curl https://myservice-api.example.com/counter{"counter":3}(.env)$ curl -X POST https://myservice-api.example.com/counter/increase{"counter":4}(.env)$ curl https://myservice-api.example.com/counter{"counter":4}
Статический сайт для переднего конца
Для следующей задачи мы будем создавать передний конец для нашей новой службы API. Для демонстрационных целей мы создадим простую страницу с кнопкой, которая вызывает /счетчик/увеличение
API Call.
Кодирование передней части
Давайте создадим новый каталог под названием Myfrontend
:
$ mkdir myfrontend && cd myfrontend
Затем сделайте простой HTML-файл index.html
:
Welcome to my homepage!
Counter:
Опубликовать переднюю часть AWS S3
Чтобы создать статический веб-сайт с S3, нам нужно создать ведро с тем же именем, что и наше доменное имя.
Переключитесь на службу S3 в консоли управления AWS. Так как мы хотим провести статический сайт на myfrontend.example.com
Мы создадим ведро с этим именем. Нажмите на Создать ведро Кнопка и заполните имя ведра, затем продолжай щелкнуть Следующий пока ведро не будет создано.
Далее нам нужно включить статический веб-хостинг из этого ведра. Откройте это ведро, затем выберите Свойства Вкладка и выберите Статический веб-хостинг Отказ В диалоговом окне выберите Используйте это ведро для размещения веб-сайта Затем введите index.html
В поле «Индекс документа». Нажмите Сохранить когда закончено.
Последнее, что нам нужно сделать, это включить публичный доступ на ведро. Это можно сделать, добавив политику ведра. Откройте это ведро и выберите Разрешения Вкладка, затем нажмите на Ковш политика кнопка.
Введите следующий контент в качестве политики, затем нажмите на Сохранить Кнопка (не забудьте заменить 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 с любым браузером (в моем случае http://myfrontend.example.com.s3-website-us-east-1.amazonaws.com/) и увидеть результат!
Упс! Счетчик вообще не отображается. ?
И похоже, что у нас есть ошибка JavaScript. Мы можем видеть следующую ошибку в консоли:
Failed to load https://myservice-api.example.com/counter: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://myfrontend.example.com.s3-website-us-east-1.amazonaws.com' 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 Backend находится на другом домене. Но поскольку мы собираемся настроить пользовательский домен для Frestend, URL-адрес изменится, поэтому мы будем беспокоиться о CORS позже.
Настройка CloudFront для нашего статического веб-сайта
Последний шаг - настроить Cloudfront для нашего переднего конца. Так как мы уже создали сертификат на * .example.com
Этот шаг будет очень прост.
Переключитесь на службу Cloudfront в консоли управления AWS. Нажмите Создать распределение кнопка, затем нажмите на Начать Кнопка в разделе «Веб».
В экране «Создание распределения» нам необходимо сделать пять изменений:
- Нажмите на Происхождение доменного имени Входная коробка и выберите наше ведро S3
myfrontend.example.com.s3.amazonaws.com
Отказ - Затем измените Политика просмотра просмотра Чтобы «перенаправить http httts https», чтобы заставить доступ HTTPS.
- В Альтернативные доменные имена коробка, введите на нашем пользовательском домене. В этом случае мы введем
myfrontend.example.com
Отказ - Прокрутите вниз до SSL сертификат Раздел, выберите «Пользовательский SSL-сертификат», затем выберите наш
* .example.com
Сертификат. - Изменить Уровень корня по умолчанию к
index.html
Отказ
После создания распределения мы можем увидеть домен CloudFront в списке рассылки.
Хотя статус все еще находится «в процессе», мы можем настроить нашу запись DNS сейчас. Перейдите в Google Domains и добавьте CNAME для этого домена:
Затем подождите, пока статус распределения не изменится на «развернуто». Теперь откройте свой браузер и попробуйте получить доступ к myfrontend.example.com
Отказ Мы видим точно такой же статический веб-сайт!
Исправить проблему CORS
Сейчас единственная проблема влевающая, это CORS. Поскольку мы используем другое доменное имя на бэкэнда и Frestend, нам нужно добавить поддержку 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
Теперь попробуйте обновить наш браузер. Мы можем видеть, что счетчик отображается правильно. Нажатие кнопки «Увеличить счетчик» может также увеличить счетчик.
Заключение
В этом посте мы исследовали различные услуги AWS, необходимые для создания простых сервисов без сервеса. Вы можете чувствовать, что есть слишком много услуг AWS, если вы не знакомы с AWS, но большинство услуг AWS, которые мы использовали здесь, предназначены для одноразового использования. Как только они будут установлены, нам не нужно прикасаться к ним вообще в дальнейшем развитии. Все, что вам нужно сделать, это запустить Zappa Update
и AWS S3 Sync
Отказ
Кроме того, это просто проще, чем настройка частного VPS, устанавливая веб-серверы и написание работы Jenkins для непрерывного развертывания.
Как резюме, вот ключевые вынос из этого поста:
- Лямбда может запустить простую услугу. Эта услуга может быть выставлена шлюзом API.
- Zappa - отличный инструмент, если вы хотите написать сервисы без сервеса в Python.
- Ведро S3 можно использовать для статического хостинга.
- Подать заявку на сертификат от AWS ACM, если вы хотите использовать HTTPS.
- API Gateway и CloudFront Оба отзывы о поддержке пользовательских доменных имен.
Надеюсь, вам понравится этот пост и не стесняйтесь хлопать? Для меня, если вы сделали! Следуйте за мной, если вы хотите прочитать больше о веб-разработке.