Пошаговая инструкция по деплою статического сайта в облако, прикрутке к нему сертификата Let’s Encrypt, домена второго уровня и настройке API-шлюза
Идея познакомиться с serverless на практике меня привлекала так же сильно как и желание потестировать с пользой один из генераторов статических сайтов.
Я присматривалась к скоростному Gatsby c пушечными стартерами — платформе open source, сделанной на React, и к облачной платформе Yandex.Cloud, где есть опция хостинга статических сайтов. К тому же надо было обновить портфолио.
C нуля и до деплоя я реализовала свои идеи: serverless + быстрый сайт + портфолио. В процессе загрузки своего приложения в облако Яндекса я познакомилась с дружелюбным и быстрорастущим коммьюнити Yandex.Cloud в Telegram и побывала на конференции Gatsby. Это еще пара мощных профитов ко всему полученному опыту.
Хочу поделиться пошаговым процессом деплоя в облако и прикрутки к облаку своего домена разными способами — к бакету и к API Gateway. Пусть мое руководство сэкономит время таким же страстным поклонникам красивых быстрых serverless-технологий и адептам JAM-подхода.
Из текста вы узнаете, как:
выложить статический сайт на Gatsby в Object Storage;
выпустить и привязать сертификат Let's Encrypt через Yandex Certificate Manager;
подключить Object Storage и привязать домен к API Gateway или бакету.
1. Создаем свой сайт на Gatsby
Идем на сайт Gatsby и находим раздел со стартерами. Залипание на стартерах можно оставить на потом. Первым делом устанавливаем генератор статических сайтов.
npm install -g gatsby-cli
Выбираем стартер и клонируем его себе. Под каждым стартером есть команда со ссылкой на репозиторий:
gatsby new my-gatsby-project https://github.com/gatsbyjs/gatsby-starter-blog
Переходим в папку проекта:
cd gatsby-starter-blog
Запускаем локальный сервер для разработки сайта:
gatsby develop
По умолчанию Gatsby запускает локальную среду разработки на порту 8000:
Если история с шаблонами неинтересна, можно создать заготовку своего проекта на Gatsby.
gatsby new gatsby-site
cd gatsby-site
На этом все настройки для создания своего статического сайта на Gatsby по готовому шаблону закончены. Можно начинать адаптировать сайт под себя.
2. Регистрируем домен
Вам нужен домен третьего уровня — это основная идея. Так вы избежите танцев с www-бубном, которые я исполняла, когда захотела разместить свой сайт на домене второго уровня — edibleclouds.ru.
Почему третьего? Для домена третьего уровня можно прописать CNAME DNS-запись, указывающую на URL. Кроме того, домен третьего уровня нужен для создания API-шлюза.
Если у вас уже есть готовый домен второго уровня, и вы хотите, чтобы ваш сайт работал из облака именно на нем, а еще через API-шлюз, то придется немного покружиться в шаманском танце из пунктов 11-13 данного руководства.
После того как домен создан, переходим к работе с хранилищем через сервис Object Storage.
3. Создаем бакет в объектном хранилище
Заходим на Yandex.Cloud и жмем Подключиться. Если вы обычный, а не федеративный пользователь, то для подключения понадобится аккаунт на Яндексе.
Мы оказываемся в личном кабинете Yandex.Cloud, где создаем свое Облако, а в нем — сервисный каталог, из которого удобно работать со всеми используемыми сервисами Yandex.Cloud.
В консоли управления слева находим сервис Object Storage. В инструкции Как начать работать с Yandex Object Storage описано, как начать с ним работать. Объектное хранилище Yandex.Cloud совместимо с аналогичной технологией Amazon S3. Им тоже можно управлять через CLI и пользоваться для хостинга статических сайтов.
В самом хранилище мы создаем бакет. Делаем один, если у вас домен третьего уровня и два — если у вас домен второго уровня. Второй бакет называем по имени домена, но с приставкой www. Он будет дополнительным.
Называем бакеты в точности, как домены: бакеты не переименовываются, их можно только удалить.
Пройдемся по параметрам бакета.
Макс. размер — указываем примерный вес сайта, не больше: так проще будет контролировать расходы и меньше шансов выйти за допустимый предел. Мы платим за объем, который занимают наши данные.
Доступ на чтение объектов — нам нужен вариант «Публичный», чтобы на клиенте корректно рендерилась верстка и отрабатывали скрипты.
Доступ к списку объектов и Доступ на чтение настроек — в «Ограниченном» режиме бакет будет работать как внутреннее хранилище файлов.
Класс хранилища — оставляем «Стандартный». Пользователи будут скачивать файлы при каждом новом посещении. А значит, это тоже влияет на стоимость услуги.
Объяснение к параметрам бакета я взяла на Хабре, в примере размещения в Object Storage сайта на Angular.
Все, бакет с именем домена готов к тому, чтобы задеплоить в него локальный проект. Но наш проект сделан на Gatsby, он не собран, и просто руками перетащить файлы туда не получится. Я поизучала работу Yandex.Cloud и залила в бакет сырой проект со всеми node_modules весом 500 МБ через командную строку:
aws --endpoint-url=https://storage.yandexcloud.net s3 cp --recursive local_files/
s3://bucket-name/path_style_prefix/
За это в Yandex.Cloud улетело около 18 из 3000 рублей, предоставленных на пробный период. Ну, хорошо, что не как в эпичном кейсе ребят из калифорнийского стартапа MilkyWay, которые сожгли на тесте Google Cloud и Firebase 72K $ за два часа.
Serverless-провайдеры хороши тем, что берут плату только за те ресурсы, которые ты тратишь — это главный принцип бессерверности. Если нужно больше ресурсов, масштабирование происходит автоматически.
Для сборки и деплоя моего сайта мне пригодился плагин S3, который есть у Gatsby. Чтобы им воспользоваться, мне понадобились: сервисный аккаунт, статический ключ доступа и консольные клиенты — CLI Yandex и AWS CLI.
Чтобы все это получить, я прошла процедуру аутентификации через Yandex Identity and Access Management — сервис идентификации и контроля доступа, который помогает централизованно управлять правами доступа пользователей к вашим ресурсам.
4. Устанавливаем CLI Yandex.Cloud и создаем профиль
Интерфейс командной строки Yandex.Cloud нам понадобится для работы от имени сервисного аккаунта:
curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash
Чтобы создать профиль, получаем OAuth-токен в сервисе Яндекс.OAuth. Токен будет сохранен в конфигурации профиля, и аутентификация будет происходить автоматически.
Пошаговый процесс установки CLI и получения OAuth-токена описан в документации Yandex.Cloud, в разделе Начало работы с интерфейсом командной строки.
5. Создаем сервисный аккаунт, назначаем ему роли, проходим аутентификацию от его имени
От имени сервисного аккаунта программы могут управлять ресурсами в Yandex.Cloud.
Подробно о том, зачем нужны сервисные аккаунты, написано в документации Yandex.Cloud, в разделе Сервисные аккаунты.
Как аутентифицироваться от имени сервисного аккаунта написано в разделе Аутентификация от имени сервисного аккаунта.
Как назначить роли сервисному аккаунту и какие они бывают, читайте в разделе Назначение роли сервисному аккаунту.
6. Cоздаем статический ключ доступа для сервисного аккаунта в Yandex.Cloud
Статические ключи доступа — секретный ключ и идентификатор ключа — используются только в сервисных аккаунтах для аутентификации в сервисах с AWS-совместимым API, например в Object Storage.
Как создать статический ключ доступа, читайте в документации Yandex.Cloud, в разделе Создание статических ключей доступа.
Дальше, чтобы каждый раз не указывать переменные окружения при деплое, мы создаем файл с расширением env и прописываем в нем секретный ключ и идентификатор ключа, которые мы получили:
AWS_ACCESS_KEY_ID =
AWS_SECRET_ACCESS_KEY =
И добавляем файл в проект.
7. Настраиваем консольный клиент к S3
Object Storage поддерживает некоторые методы HTTP API Amazon S3, поэтому тут можно воспользоваться популярными инструментами для работы с этим сервисом. Настроим консольный клиент — AWS CLI. Нам нужна вторая версия.
Читайте раздел AWS Command Line Interface, чтобы понять, как пользоваться AWS CLI для работы с Object Storage.
7. Подключаем плагин S3
Теперь осталось подключить плагин, добавить несколько строк кода и можно деплоить проект в бакет.
Устанавливаем плагин:
npm i gatsby-plugin-s3
Добавляем код в папку plugins файла gatsby-config.js. Подставляем вместо <bucket-name> имя бакета. Обратите внимание на регион. Оставляем его именно таким, несмотря на то, что в инструкциях можно встретить указание везде прописывать ru-central1.
{
resolve: 'gatsby-plugin-s3',
options: {
bucketName: '<bucket-name>',
region: 'us-east-1',
customAwsEndpointHostname: 'storage.yandexcloud.net'
}
}
В package.json в секцию scripts добавляем "deploy".
{
"scripts": {
"deploy": "gatsby-plugin-s3 deploy --yes"
}
}
9. Run&Deploy = Enjoy
Запускаем. Проект сбилдится и загрузится в указанный бакет.
npm run build && npm run deploy
Не обращайте внимания на вывод в консоли. Там будет указан адрес для AWS S3 независимо от того, какой хост указан в переменной customAwsEndpointHostname.
Теперь сайт открывается по адресу http://edibleclouds.ru.website.yandexcloud.net/
В разделе Статический веб-сайт в Yandex Object Storage в пунктах 4-10 описано, как настроить главную страницу и страницу ошибки.
Но наш сайт сейчас работает по HTTP. Создадим защищенный протокол.
10. Выпускаем сертификат Let’s Encrypt
Сертификат нам понадобится как для создания безопасного соединения по HTTPS, так и для API Gateway, чтобы использовать домен для обращения к API.
Создаем сертификат через сервис Certificate Manager. Инструкция по созданию лежит в разделе Создание сертификата от Let's Encrypt документации.
Для тех, у кого домен второго уровня: я создаю сертификат сразу для двух доменов — с www и без.
Добавить второй домен к уже созданному сертификату Let’s Encrypt не получится, придется проходить всю процедуру валидации, а значит и выпуска сертификата заново. Процесс проверки может занимать от шести минут до суток. С каждым разом попытки проверки становятся реже — до одного раза в шесть часов.
Как мы видим на скриншоте, можно выбрать два способа проверки: через HTTP или через DNS. В инструкции Как начать работать c Certificate Manager, по которой я шла, было сказано выбрать тип проверки HTTP. Но во всех других инструкциях, например в инструкции Проверка прав на домен, было написано, что можно выбрать любой тип.
Поскольку я выбрала HTTP, то процесс запуска процедуры валидации такой же, как в разделе Проверка прав на домен.
Для HTTP-валидации нужно создать файлы для обоих доменов с названием, указанным в блоке Ссылка для размещения файла, положить туда Содержимое и добиться того, чтобы эти файлы открывались по ссылке. Обратите внимание — файлы должны быть без расширения txt в конце. Это критично для процедуры проверки.
Как только мы убедились, что оба файла доступны по ссылке, можем переключаться на другие дела. Процедура проверки запущена. В лучшем случае через шесть минут статус из Pending сменится на Valid, а Validating — на Issued.
11. Настраиваем доступ по HTTPS
Сертификаты готовы, и теперь мы можем настроить доступ по HTTPS к нашим бакетам и доменам.
Идем в бакет, слева в меню находим вкладку HTTPS, жмем на нее, выбираем из списка нужный сертификат и добавляем его.
Если делать валидацию через DNS, то сертификат продлевается автоматически.
Доступ к бакету по HTTPS открывается в течение получаса после выбора сертификата.
12. Подключаем домен к бакету
Наша облачная тренировка подходит к концу, но есть еще несколько упражнений, которые необходимо выполнить, чтобы сайт работал на домене. Подключим домен к бакетам.
Домен второго уровня подключить к Облаку напрямую нельзя — такие домены не направляются на другой хост при помощи изменения записи CNAME. Поэтому мы создавали два бакета и делали сертификат на каждый. Подробнее об этом читайте в документе Common DNS Operational and Configuration Errors, п.2.4.
Сейчас пришло время добавить ресурсную запись CNAME у субдомена. В моем случае это www.edibleclouds.ru. Для этого в редакторе DNS у своего регистратора прописываем:
www CNAME edibleclouds.ru.website.yandexcloud.net
И далее направляем домен на бакет:
а) Через IP
Способ рабочий, но не самый надежный. IP облака может измениться, сайт упадет, а вы про это даже не узнаете. По словам Джорджа из облачного чата, IP у облака не менялся уже два года, и ничего не предвещает изменений в будущем.
Чтобы мой основной домен edibleclouds.ru смотрел в облако, нужно у регистратора поменять запись типа A, указав IP Облака вместо IP того сервера, на чьи DNS мой домен делегирован.
Затем идем в редактор DNS своего регистратора и меняем в А-записи этот адрес на адрес Yandex.Cloud — 93.158.134.163. Все, через минут 10 домен будет смотреть в облако.
б) Через DNS у регистратора
На примере reg.ru процесс настройки собственного домена третьего уровня через DNS пошагово описан в разделе Статический веб-сайт в Yandex Object Storage документации.
В случае работы с доменом второго уровня делаем переадресацию из бакета с www на бакет с именем домена второго уровня во вкладке Веб-сайт.
13. Cоздаем API-шлюз, подключаем домен к шлюзу
В Yandex.Cloud можно создать API-шлюз и настроить свой домен третьего уровня для обращения к шлюзу. С технической точки зрения для статического сайта выгоднее и удобнее размещать сайт и прикручивать домен к Object Storage. Это дешевле и требует меньше настроек.
Но сервис API Gateway позволяет более гибко настроить сайт и добавить в него динамику, когда это потребуется. Я подключила домен к API Gateway еще на статике, и потому рассказываю тут, как это делается.
Домен можно использовать из сервиса Certificate Manager, при этом для TLS-соединения будет использован привязанный к домену сертификат. В моем случае это домен www.edibleclouds.ru и сертификат Let’s Encrypt.
Чтобы подключить домен к шлюзу сначала мы создаем шлюз, а затем подключаем домен.
Для этого я также размещаю у своего регистратора (в моем случае это nic.ru) CNAME-запись такого вида.
Домен в консоли должен быть в списке и в статусе Valid. Статус означает, что Yandex.Cloud может принимать трафик с вашего домена.
Проверить, что домен подключен и все работает, можно обратившись к этому домену. В логах API Gateway должен отобразиться соответствующий запрос.
Чтобы домен работал как шлюз, нам нужно настроить шлюз на бакет — интегрировать API Gateway c Object Storage. Это делается в спецификации YAML. Найдите в правом верхнем углу меню Редактировать.
Можно скопировать спецификацию отсюда. Только замените url, bucket и service_account_id на свои:
openapi: 3.0.0
info:
title: Test API
version: 1.0.0
servers:
- url: https://<служебный домен>.apigw.yandexcloud.net
- url: https://www.edibleclouds.ru
paths:
/:
get:
x-yc-apigateway-integration:
type: object_storage
bucket: ваш бакет
object: index.html
service_account_id: идентификатор сервисного аккаунта
/{file+}:
get:
x-yc-apigateway-integration:
type: object_storage
bucket: ваш бакет
object: '{file}'
service_account_id: идентификатор сервисного аккаунта
parameters:
- explode: false
in: path
name: file
required: true
schema:
type: string
style: simple
Всё, мой сайт edibleclouds.ru, сделанный на платформе Gatsby, теперь размещён на Yandex.Cloud, и обращаться к моему API-шлюзу можно через домен www.edibleclouds.ru. Домен второго уровня edibleclouds.ru я могу настроить на API-шлюз также через A-запись у регистратора. При этом придется надеяться, что IP‑адрес шлюза в ближайший год не изменится.
Чтобы настроить домен на API-шлюз, берем нужный технический домен (API Gateway или Object Storage), узнаем его IP (например, с помощью команды host %api_gw_id%.apigw.yandexcloud.net), и полученный IP указываем в значении A-записи. На этом тренировка закончена.
Используемые технологии
Для создания и размещения сайта на своем домене в облаке при помощи платформ Gatsby и Yandex.Cloud мне пригодились технологии:
· VSCode
· Git
· Node.js
· NPM
· React
· Python
· Yandex Identity and Access Management
· СLI Yandex.Cloud
· AWS CLI
· Яндекс.OAuth
· Object Storage
· Yandex Certificate Manager
· Yandex API Gateway
А также были полезны официальные чаты Yandex.Cloud без флуда и мусора — Yandex.Cloud и Yandex Serverless Ecosystem. Это скорая помощь №1 при работе с облачной платформой Яндекса.