Как создать и настроить собственный CDN
Сети доставки контента (CDN) используются на сайтах и в приложениях в основном для ускорения загрузки статических элементов. Происходит это за счет кеширования файлов на CDN-серверах, расположенных в разных географических регионах. Запросив данные через CDN, пользователь получает их с ближайшего сервера. Бывает, что в силу тех или иных причин требуется организовать собственную сеть доставки контента, и тогда — да будет в помощь нам инструкция по сборке очередного велосипеда.
Принцип работы и функционал у всех сетей доставки контента примерно одинаков. Получив запрос на загрузку файла, CDN сервер единоразово берет его с оригинального сервера и отдает пользователю, вместе с тем кешируя у себя на заданный промежуток времени. На все последующие запросы ответ отдается из кеша. У всех CDN есть опции предварительной загрузки файлов, очистки кеша, настройки срока его хранения, и многое другое.
Когда нужен собственный CDN
Рассмотрим случаи, когда запуск собственного CDN имеет смысл:
- когда есть желание сэкономить, а текущие расходы даже при использовании недорогих CDN вроде BunnyCDN составляют несколько сотен долларов в месяц
- если хотим получить постоянный кеш или кеш без соседей по серверу и каналу
- в нужном вам регионе у CDN сервисов нет точек присутствия
- требуются какие-либо особые настройки доставки контента
- хотим ускорить доставку динамического контента, разместив ближе к пользователям продакшн сервера
- есть опасение, что сторонний CDN сервис может неправомерно собирать или использовать информацию о поведении пользователей (привет сервисам без GDPR-compliant) или заниматься другими неправомерными действиями
В большинстве остальных случаев целесообразнее выбрать готовый CDN.
Что нужно для запуска
Чудно, если у вас есть своя автономная система (AS). С ней можно назначить одинаковый IP нескольким серверам и на уровне сети направлять пользователей к ближайшему. Cтоит сказать, что даже с блоком адресов /24 есть возможность построить сеть доставки контента. Некоторые сервер-провайдеры позволяют сделать анонс для использования во всех доступных у них регионах.
Если же вы не счастливый обладатель блока IP адресов, то для запуска простого CDN вам понадобятся:
- доменное имя или субдомен
- минимум два сервера в разных регионах. Сервер может быть как виртуальный, так и выделенный
- geoDNS инструмент. С его помощью пользователь, обратившись к домену, будет направлен на ближайший сервер
Регистрируем домен и заказываем сервера
С регистрацией домена все просто — регистрируем в любой зоне у любого регистратора. Также для CDN можно использовать субдомен, например что-то вроде cdn.имядомена.com. Собственно в нашем примере мы так и поступим.
Что касается заказа серверов — их стоит арендовать в регионах и странах, где находится ваша пользовательская аудитория. Если проект интерконтинентальный, то удобно выбирать хостинг-провайдеров, предлагающих сразу сервера по всему миру, к примеру PQ.hosting.
Для нашего частного CDN закажем 3 виртуальных сервера на разных континентах. При установке выберем последний Debian или Ubuntu. Наши сервера:
- Франкфурт (Германия), ip: 199.247.18.199
- Чикаго (США), ip: 149.28.121.123
- Сингапур, ip: 157.230.240.216
Настраиваем geoDNS
Чтобы пользователь при обращении к домену или субдомену CDN направлялся на нужный (ближайший к нему) сервер, нам понадобится DNS сервер с функцией geoDNS.Принцип и порядок работы geoDNS следующий:
- Определяет IP клиента, пославшего DNS запрос, или IP рекурсивного DNS-сервера, который используется при обработке клиентского запроса. Такими рекурсивными серверами обычно являются DNS-ы провайдеров.
- По IP клиента узнает его страну или регион. Для этого используются базы GeoIP, коих сегодня превеликое множество. Есть неплохие бесплатные варианты.
- В зависимости от местоположения клиента отдает ему IP-адрес ближайшего CDN сервера.
DNS сервер с функцией geoDNS можно собрать самостоятельно, но лучше использовать готовые решения с сетью DNS-серверов по всему миру и Anycast из коробки. Пример: СlouDNS.
При заказе geoDNS следует обращать внимание на количество включенных в тариф запросов и учитывать, что реальное число обращений к домену может в разы превзойти ожидания. Миллионы пауков, сканнеров, спамеров и прочей нечисти работают безустанно.
У многих DNS-сервисов доступна незаменимая для построения CDN услуга — DNS Failover. С ее помощью можно настроить мониторинг работы своих серверов и в случае отсутствия признаков жизни автоматически заменять в DNS-ответах адрес нерабочего сервера на резервный.
Для построения нашего CDN воспользуемся ClouDNS, тариф GeoDNS.
Добавим в личном кабинете новую DNS-зону, указав свой домен. Если CDN будем строить на субдомене, а главный домен уже используется, то сразу после добавления зоны не забудьте добавить существующие рабочие DNS-записи. Следующее действие — создание для CDN домена/субдомена нескольких A-записей, каждая из которых будет применяться для заданного нами региона. В качестве регионов можно указать континенты или страны, для США и Канады доступны субрегионы.
В нашем случае CDN будет поднят на субдомене cdn.sayt.in. Добавив зону sayt.in, создадим для субдомена первую A-запись и направим всю Северную Америку на сервер в Чикаго:
Повторим действие для других регионов, не забыв создать одну запись для регионов по умолчанию. Вот что получится в итоге:
Последняя дефолтная запись на скриншоте означает, что все незаданные регионы (а это Европа, Африка, пользователи спутникового интернета и т.д.) будут направляться на сервер во Франкфурте.
На этом базовая настройка DNS завершена. Осталось зайти на сайт регистратора домена и заменить текущие NS-ы домена на те, что выдал ClouDNS. И пока NS-ы будут обновляться мы подготовим сервера.
Установка SSL сертификатов
Наш CDN будет работать по HTTPS, поэтому если у вас уже имеются SSL сертификаты для домена или субдомена, — загрузите их на все сервера, например в директорию /etc/ssl/вашдомен/
Если сертификатов нет, можно получить бесплатный от Let's Encrypt. Для этого отлично подойдет ACME Shell script. Клиент удобен и прост в настройке, а главное — позволяет проводить валидацию домена/субдомена по DNS через API от ClouDNS.
Мы поставим acme.sh только на одном из серверов — европейском 199.247.18.199, с него сертификаты будут копироваться на все остальные. Для установки выполним:
В ходе установки скрипта будет создано CRON задание для дальнейшего обновления сертификатов без нашего участия.
Проверка домена при выдаче сертификата будет проводиться по DNS с использованием API, поэтому в личном кабинете ClouDNS в меню API&Resellers нужно создать нового API пользователя и задать для него пароль. Полученный <auth-id> с паролем пропишем в файле ~/.acme.sh/dnsapi/dns_cloudns.sh (не путать с файлом dns_clouddns.sh). Вот строки, которые требуется раскомментировать и отредактировать:
Теперь запросим получение SSL сертификата для cdn.sayt.in
В параметрах, на будущее, мы указали команду для автоматической перезагрузки конфигурации веб-сервера после каждого обновления срока действия сертификата в дальнейшем.
Весь процесс получения сертификата может занять до 2 минут, не прерывайте его. Если возникнет ошибка валидации домена, попробуйте запустить команду еще раз. В конце мы увидим, куда были загружены сертификаты:
Запомним эти пути, их нужно будет указать при копировании сертификата на другие сервера, а также в настройках веб-сервера. На ошибку перезагрузки конфигов Nginx не обращаем внимания, — на полностью настроенном сервере при обновлении сертификатов ее не будет.
Все что нам осталось по SSL, — это скопировать полученный сертификат на два других сервера с сохранением пути к файлам. Создадим на каждом из них такие же директории и сделаем копию:
Чтобы обновление сертификатов было регулярным создадим на обоих серверах ежедневное CRON задание с командой копирования:
При этом доступ к удаленному серверу-источнику должен быть настроен по ключу, т.е. без ввода пароля. Не забудьте сделать это.
Установка и настройка Nginx
Для отдачи статического контента мы будем использовать Nginx, сконфигурированный в режиме кеширующего proxy-сервера. Обновим списки пакетов и установим его на всех трех серверах:
Вместо содержимого дефолтного nginx.conf вставим следующий конфиг:
В конфиге отредактируем:
- max_size — размер кеша, не превышающий доступное на диске место
- inactive — время хранения закешированых данных, к которым никто не обращался
- ssl_certificate и ssl_certificate_key — пути к файлам SSL сертификата и ключа
- proxy_cache_valid — время хранения закешированых данных
- proxy_pass — адрес оригинального сервера, с которого CDN будет запрашивать файлы для кеширования. В нашем примере это sayt.in
Как видим, всё просто. Сложность лишь может возникнуть в настройке времени кеширования из-за схожести директив inactive и proxy_cache_valid. Разберем их на нашем примере. Вот что происходит при inactive=7d и proxy_cache_valid 90d:
- если запрос не повторится в течение 7 дней, то данные удалятся из кеша по истечении этого периода
- если запрос будет повторяться хотя бы раз в 7 дней, то данные в кеше будут считаться устаревшими по истечении 90 дней и при очередном запросе Nginx обновит их, взяв с оригинального сервера
Закончив править nginx.conf, перезагрузим конфигурацию:
Наш CDN с точками присутствия на трех континентах полностью готов.
Проверяем работу CDN
Посмотрим на пинги к CDN сети из разных географических локаций. Для этого подойдут любые пинг-сервисы.
Результаты хорошие. Разместим теперь в корне основного сайта тестовую картинку test.jpg и проверим скорость ее загрузки через CDN на PingAdmin. Контент отдается быстро.
В заключение, напишем небольшой bash-скрипт purge.sh на случай, если захотим на CDN-точке очистить кеш:
Для удаления всего кеша достаточно просто запустить его, отдельный файл можно почистить так:
Вместо выводов
Напоследок хочу дать несколько полезных советов, дабы сразу переступить через грабли, сделавшие в свое время больную голову мне:
- Оцените целесообразность и стоимость поддержки своей будущей сети доставки контента. В большинстве случаев гораздо дешевле и проще купить недорогой CDN, который может работать стабильнее и качественнее
- Для повышения отказоустойчивости CDN рекомендуется настроить DNS Failover, помогающий быстро сменить A запись в случае поломки сервера. Делается это в панели управления DNS записями домена
- Сайты с широким географическим охватом без сомнения требуют большого числа точек CDN, но давайте без фанатизма. Скорее всего пользователь не заметит существенной разницы в сравнении с платным CDN, если вы разместите сервера в 6-7 местах: Европа, Северная Америка (восток), Северная Америка (запад), Сингапур, Австралия, Гонконг или Япония
- Иногда хостеры не разрешают использовать арендованные сервера для целей CDN. Поэтому, если вы вдруг решите развернуть сеть доставки контента как сервис, не забудьте заранее прочитать правила конкретного хостинг-провайдера
- Изучите карту подводных коммуникаций, чтобы представлять, как связаны континенты и учитывать это при построении сети доставки контента
- Попробуйте проверить пинги из разных мест к вашим серверам. Так можно увидеть ближайшие к CDN-точкам регионы и правильнее настроить GeoDNS
- В зависимости от задач нелишним будет донастроить Nginx под конкретные требования кеширования и с учетом нагрузки на сервер. В этом мне очень помогли статьи о кеше Nginx — здесь и ускорении работы при больших нагрузках: здесь и здесь