Введение:

Трехуровневая архитектура менее чем за 20 долларов в месяц, с плавным процессом разработки, легким развертыванием версий и 90+ баллом по Google Page Speed.

Но почему?

  • Бюджетный
  • Минимальная настройка
  • Минимальное обслуживание
  • Простое развертывание и управление версиями

Допустим, у вас есть личный проект, вроде веб-сайта для открытия фильмов, сделанный не как бизнес, а как хобби. Естественно, вы хотели бы сделать это общедоступным, но не в том случае, если это означает, что сотни долларов ежемесячно тратятся на экземпляры баз данных и серверов, поэтому все должно быть дешево. Вы также не хотите идти на компромисс ни в процессе разработки / развертывания, ни в пользовательском опыте, поэтому все должно быть быстрым. Что вы делаете?

Размышляя над этим вопросом, позвольте мне рассказать историю того, что я сделал.

Оглавление

- Раздел 1 - Стек
- SSR React + Redux
- Быстрое и простое развертывание действий Github
- ECS Host
- Распределение
- Раздел 2 - Результаты
- Скорость Google
- Ежемесячная стоимость
- Раздел 3 - Дальнейшие улучшения
- Балансировка нагрузки, мульти-зона доступности, ECS-Fargate
- Автоматическое масштабирование
- Terraform полностью вниз

Раздел 1 - Стек

  • SSR React + Redux для клиента
  • Действия Github для развертывания.
  • ECS - EC2 для хоста
  • CloudFront + Routes 53 для распространения
  • Dynamo + Lambda + API Gateway для API

SSR React + Redux

  • Новое приложение nextJs
  • React app / redux
  • Настроить действия Github

Я выбрал React для интерфейса, так как он предлагает наиболее приятный опыт разработчика (работал над Angular, Angular4, HandleBars, jQuery и т. Д.), И выбрал NextJs из-за этих сладких преимуществ SSR (скорость и SEO являются основными единицы). Вы можете создать собственное локальное приложение NextJs, запустив npm init next-app «. Как только вы это сделаете, вы сможете более или менее разрабатывать свое приложение так же, как и SPA. Основное отличие заключается в способе обработки маршрутизации.

/ * Вкратце о маршрутизации NextJs * /

Next имеет свое собственное соглашение о преобразовании файлов в папке pages в фактические маршруты, поэтому, например, если в папке страниц у вас есть файл similar.js, то переход к / Подобный приведет к содержимому этого файла. Обработка динамических параметров в URL-адресе осуществляется за счет наличия вложенных папок с именем параметра в качестве имени файла между квадратными скобками, поэтому movie / [id] .js приводит к https://cinpick.com/ фильм / 360 . Прохладный ;). Его, конечно же, можно перезаписать вашим собственным экспресс-сервером, если вам нужно выполнить более сложную логику перед рендерингом страницы.

Когда вы импортируете ссылку из «next / link», вы в основном говорите next для загрузки только JS-файлов со страницы, на которую хотите перейти, и обновления DOM. Таким образом, ваше текущее состояние (например, Redux) не нужно повторно инициализировать при каждой навигации по страницам. Переход к динамическому URL-адресу осуществляется путем указания свойства «as» в ссылке:

‹Ссылка href = {« / movie / [id] »} as = {` / movie / $ {item.id} `}

/ * Маршрутизация в сторону завершена * /

Еще одна полезная вещь, которую нужно знать, это то, что вы можете контролировать файл document.html, который сначала обрабатывается и загружается браузером, создавая файл _document.js в папке ваших страниц. Здесь вы можете настроить различные аспекты документа (например, рендеринг стилей на стороне сервера)

Теперь, когда вы закончили настройку SSR, вы можете перейти к фактическому приложению React и управлению состоянием. Вот действительно хорошая статья по настройке Redux store для работы между страницами. Как видите, поставщик реализован на другой странице перезаписи Nextjs, которая называется _app.js. Это промежуточный уровень между документом и содержанием, и это место, где вы можете инициализировать другие библиотеки (например, Google Analytics, диспетчер тегов Google и т. Д.)

Быстрое и простое развертывание действий Github

Теперь, когда у вас есть работающий локальный веб-сайт, вам нужно запустить его где-нибудь в сети. Это будет выполняться в две части: создание образа докера и его отправка в ECR (репозиторий образов AWS) и запуск этого образа в ECS (служба контейнеров Docker AWS). Не расстраивайтесь, если вы раньше не работали с docker или ECS, весь процесс состоит в основном из написания некоторых файлов конфигурации и выполнения некоторых настроек на AWS, не займет больше часа;). (это безумие, я знаю ...)

Сначала создайте репозиторий GitHub и перейдите на вкладку «Действия».

Там вы можете выбирать между несколькими шаблонами действий, один из которых как раз то, что нам нужно. Так что найдите и выберите тот, который говорит «Развернуть в Amazon ECS».

Затем вас встретит документ aws.yml, который в настоящее время состоит из 5 шагов:

1. оформление заказа

2. настройка была учетными данными

3. войдите в ECR, создайте / отправьте образ

4. создать определение задачи

5. определение задачи развертывания

Я сделал это следующим образом: удалил последние два шага (почему вы увидите позже) и просто настроил первые три. В результате в ваш репозиторий ECR будет загружен новый образ докера.

Для более быстрого развертывания я изменил бит «on: release: types: [created]» с начала файла на «on: push: branch- master». . Это будет создавать новый образ каждый раз, когда вы нажимаете на мастер, но поскольку мы закомментировали шаги развертывания (последние 2 шага), у нас не будет проблем с обновлением нашего приложения, когда это не должно происходить.

Следующее, что вам нужно в этой конфигурации, - это добавить ваши AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY в качестве секретов в репозиторий Github. Не волнуйтесь, их значения будут зашифрованы, и никто не будет иметь к ним доступа.

Второе - это создание репозитория на ECR, поэтому создайте его, а затем скопируйте его имя и добавьте его в ECR_REPOSITORY на этапе сборки образа.

И последнее, что вам нужно, это создать файл с именем Dockerfile в папке вашего проекта и добавить к нему эти.

FROM node:12
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD [ “npm”, “start” ]

В случае, если вы использовали экспресс-сервер для обработки вашей маршрутизации, замените последнюю строку фактической командой запуска сервера (EX: CMD [«npm», «run», «prod_start»])

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

Хост ECS

  • Создать кластер + сервис + определение задачи
  • Создайте распространение Cloudfront с IP-адресом экземпляра
  • Объясните, как развернуть

Чтобы запустить образ на AWS, вам нужно настроить 3 вещи: кластер, службу и определение задачи. Приступим к кластеру.

/ * Вкратце о ECS * /

Вы можете думать о кластере ›Сервис› Задача, как это:

  • Определение задачи состоит из конкретных инструкций о вашем приложении (какой порт используется, как к нему следует обращаться, сколько ЦП / памяти ему требуется и т. д. ). Когда ваше приложение будет обновлено, вам также потребуется создать новую версию для определения вашей задачи.
  • Служба отвечает за маршрутизацию, запуск, перезапуск и масштабирование нескольких «задач» одного и того же определения.
  • Кластер отвечает за работу служб. Самое лучшее в Docker - это то, что вы можете без помех запускать множество разных сервисов (приложений) на одном экземпляре.

/ * ECS aside закончился * /

Перейдите к ECS ›кластеры и выберите Создать кластер . Дайте ему имя, измените тип экземпляра на t2 micro (это один из самых дешевых) и нажмите Подтвердить. Кластер ✅.

Как только он будет создан, перейдите к ECS ›Task Definitions и создайте новый. Выберите его тип как EC2 и нажмите «Далее», дайте ему имя, добавьте роль, установите 256 для памяти задач (МиБ) и ЦП задачи (единицы), а затем нажмите «Добавить контейнер». Когда откроется панель контейнера, добавьте имя, вставьте URI образа докера (скопируйте его из репозитория ECR), установите жесткий предел 250 и добавьте сопоставления горшков 80 (сообщение хоста), 3000 (порт контейнера) как TCP (протокол) и 250 для Среда ›Модули ЦП, а затем нажмите« Добавить ». Прокрутите вниз и нажмите «Создать». Определение задачи ✅.

Перейдите в кластер ECS ›вкладка« Сервис »и нажмите« Создать ». Выберите тип EC2, выберите последнюю версию определения задачи, дайте имя службе, выберите 1 для Количество задач, установите Минимальный процент работоспособности на 0 и Максимальный процент на 100, и нажимайте "Далее", пока служба не будет создана. Сервис

/ * Вкратце о ECS * /

Почему мы устанавливаем для параметра Минимальный процент работоспособности значение 0? Что ж, это позволит закрыть нашу старую версию перед запуском новой. Это означает, что на пару секунд при каждом обновлении наш сервис будет отключен. К сожалению, если старая версия все еще работает при запуске новой, это означает, что порт, используемый старой, занят, поэтому новая не сможет запуститься. Установив сначала значение 0, мы убеждаемся, что старый больше не работает. Я также добавил немного о развертывании без простоев в разделе «Дальнейшие улучшения» внизу, на случай, если вам это понадобится.

/ * ECS aside закончился * /

Вы знаете, что все работает, когда вы увидите это в своей службе: служба «ваше имя службы» достигла устойчивого состояния.

Вы можете получить IP-адрес своего запущенного экземпляра, если зайдете в ECS ›кластер› ваша служба ›вкладка задач› щелкните задачу ›разверните контейнер› внешняя ссылка.

Итак, вы закончили со всеми настройками, теперь ваш сайт работает в сети;). Но этот IP не так уж и хорош, не так ли? Если мы хотим разместить его за красивым доменом, нам нужно сделать еще две вещи: создать дистрибутив CloudFront для этого IP-адреса и направить на него Route 53.

Распределение

Cloudfront в основном отвечает за кеширование вашего контента. После правильной настройки вы увидите заголовок ответа x-cache: Hit от CloudFront. Это означает, что запрос больше не поступает к источнику (вашему серверу), а вместо этого обслуживается из кеша Cloudfront, что значительно ускорит процесс.

Перейдите в CloudFront и нажмите «Создать распространение».

  • выберите распространение в Интернете
  • для доменного имени Origin за пределами общедоступного DNS вашего запущенного экземпляра (вы можете получить его из ECS ›кластер› ваша служба ›вкладка задач› щелкните задачу ›Щелкните идентификатор экземпляра EC2› Описание ›Public DNS (IPv4)
  • выберите Да для Автоматически сжимать объекты.
  • Щелкните «Создать».

Вам нужно подождать около 15 минут, пока раздача будет создана, но как только это будет сделано, вы сможете увидеть свой сайт по URL-адресу, указанному в раздаче ›вкладка Общие› Доменное имя. (должно быть что-то вроде xxxxxx.cloudfront.net)

Последнее, что нам нужно сделать с дистрибутивом CloudFront, - это сослаться на него из Route 53, но для этого сначала необходимо выполнить несколько вещей. Нам надо:

  1. Зарегистрируйте домен
  2. Запросить сертификат SSL
  3. Обновите наше CName в раздаче CloudFront, чтобы включить домен и добавить свой сертификат SSL.

4. Создайте новую зону хостинга на Route 53 для своего домена.

5. Создайте новый набор записей в вашей размещенной зоне.

  • Оставьте черное имя для корневого домена (https://cinpick.com)
  • выберите тип IPv4-адреса
  • Добавьте свой облачный фронт-дистрибутив (это должно соответствовать CName в облачном раздаче шрифтов, поэтому, если у него был www, имя этой записи также должно быть у вас www)

6. Подождите несколько минут и попробуйте свой домен! :)

На данный момент у вас должна быть быстрая и дешевая инфраструктура для размещения вашего сайта. Теперь давайте рассмотрим, как можно обновить существующий образ докера. Как только вы снова нажмете на мастер, Github создаст и поместит другой образ в ECR.

Чтобы удалить это изображение, вам нужно перейти в ECS ›ваш кластер› ваша служба ›определение вашей задачи› Нажмите «Create new Revision» ›нажмите на имя контейнера (не на кнопку« Add container »)› вставьте URI нового изображения ›нажмите« Обновить »› нажмите «Создать». Это даст вам определение задачи с новым изображением.

Затем перейдите в ECS ›ваш кластер› ваша служба ›нажмите« Обновить »› измените версию на самую последнюю ›нажмите« Далее », пока обслуживание не будет завершено. Как только события снова достигнут «устойчивого состояния», ваш сервис будет обновлен.

Если вы используете CloudFront, это означает, что старый контент все еще кэшируется, поэтому вам нужно будет выполнить аннулирование кеша. Вы можете сделать это из CloudFront ›ваш дистрибутив› вкладка недействительности ›создать аннулирование› написать / * ›нажать недействительно.

Вот и все, ваш сайт обновлен. :)

Итак, резюмируем: вы нажимаете на GitHub, обновляете определение задачи новым изображением, обновляете службу с новым определением задачи, аннулируете кеш. Как только вы привыкнете, все это займет около 5 минут.

Раздел 2 - Результаты

Скорость Google

Ежемесячная стоимость

  • t2 micro $ 9,50
  • Зона хостинга Route53 $ 0,50
  • Доменное имя 1 доллар или 2 доллара в месяц
  • Налог AWS (около 10%) 1 доллар США

Итого около 15 долларов. Если вы получите сертификат SSL или более красивый домен, вы можете достичь 20 долларов в месяц.

Раздел 3 - Дальнейшие улучшения

Распределение нагрузки, несколько зон доступности, ECS-Fargate

Самое большое улучшение, которое я могу придумать, и причина, по которой я бы не рекомендовал эту конкретную архитектуру для бизнес-целей, заключается в том, что она не очень устойчива. У него только одна запущенная задача, а это означает, что это одна зона доступности, поэтому, если эта зона выйдет из строя, ваша служба также остановится. Это можно легко исправить, настроив несколько запущенных задач и балансируя нагрузку между ними. Это также даст вам возможность ссылаться на балансировщик нагрузки в дистрибутиве Cloudfront, поэтому, если ближайший экземпляр выйдет из строя и его IP-адрес изменится, вам не нужно будет обновлять раздачу.

Добавление балансировщика нагрузки также может решить проблему простоя. При сопоставлении порта приложения с точкой контейнера мы выбрали 80-3000-TCP, но если бы вы оставили порт хоста и 0 (или пустой), тогда ECS назначила бы ему случайный свободный порт, так что у стартовой задачи больше не было бы конфликта портов.

Причина, по которой я не выбрал многозональную архитектуру с балансировкой нагрузки, заключается в том, что другой экземпляр добавил бы к счету около 9 долларов, а балансировщик нагрузки добавил бы еще около 6 долларов, но если подумать о наличии высоконадежного и всегда доступная услуга стоит 15 долларов, я вас не виню. ;)

Автомасштабирование

Второй - настроить политику автоматического масштабирования на случай, если ваш проект станет вирусным в одночасье, и вы хотите идти в ногу со спросом.

Терраформировать полностью вниз

Третья рекомендация и моя личная цель - терраформировать все это. Terraform - это способ поддерживать конфигурацию вашей инфраструктуры в виде кода, поэтому вместо того, чтобы входить вручную и изменять имена в формах и переключать кнопки, у вас будут некоторые файлы конфигурации, в которых вы можете указать всю свою инфраструктуру. Terraform дает множество преимуществ, в том числе управление версиями файлов конфигурации. Еще одно большое преимущество, которое можно получить, - это возможность более легко изменить свое предложение (например, AWS или Microsoft Azure), но в случае личных проектов это случается довольно редко.

И это все, что касается хостинга сайта, надеюсь, вам это до сих пор понравилось. :)

Я слышал, вы спросите, что, если я хочу оживить ситуацию с помощью пары API? А что, если я захочу сохранить какие-то данные? В следующей части я напишу, как можно БЕСПЛАТНО получить полный бэкэнд API + Db!

Заглянем внутрь части 2:

  • Создать таблицу DynamoDb
  • Создать лямбду
  • Создайте ApiGateway и свяжите Lambda
  • Добавить файл действий Github
  • Заархивировать и загрузить zip на s3
  • Нажмите на Github и обновите лямбда