Zbieramy i konfigurujemy własne CDN

Sieci dostarczania treści (CDN) są używane na stronach internetowych i w aplikacjach głównie w celu przyspieszenia ładowania elementów statycznych. Dzieje się tak dzięki buforowaniu plików na serwerach CDN, zlokalizowanych w różnych regionach geograficznych. Wysyłając żądanie za pośrednictwem CDN, użytkownik otrzymuje dane z najbliższego serwera.

Zasada działania i funkcjonalności wszystkich sieci dostarczania treści są w zasadzie takie same. Po otrzymaniu żądania dotyczącego pobrania pliku, serwer CDN jednorazowo pobiera go z oryginalnego serwera i przekazuje użytkownikowi, buforując go jednocześnie na określony czas. Na wszystkie kolejne żądania odpowiedź jest dostarczana z pamięci podręcznej. Wszystkie CDN oferują opcje wstępnego ładowania plików, czyszczenia pamięci podręcznej, ustawiania czasu jej przechowywania i wiele innych.

Bywa, że z różnych powodów zachodzi konieczność zorganizowania własnej sieci dostarczania treści, więc – oto instrukcja dotycząca budowy kolejnego roweru.

Zbieramy i konfigurujemy własne CDN
Źródło: Infografika stworzona przez pikisuperstar – www.freepik.com

Kiedy potrzebny jest własny CDN

Rozważmy przypadki, w których uruchomienie własnego CDN ma sens:

  • gdy chcesz zaoszczędzić, a obecne wydatki nawet przy użyciu tanich CDN, takich jak BunnyCDN wynoszą kilka setek dolarów miesięcznie
  • jeśli chcemy uzyskać stałą pamięć podręczną lub pamięć podręczną bez sąsiadów w serwerze i kanale
  • w potrzebnym regionie usługi CDN nie mają punktów obecności
  • wymagana jest jakakolwiek szczególna konfiguracja dostarczania treści
  • chcemy przyspieszyć dostarczanie dynamicznych treści, umieszczając serwery produkcyjne bliżej użytkowników
  • istnieją obawy, że zewnętrzna usługa CDN może nielegalnie zbierać lub wykorzystywać informacje o zachowaniu użytkowników (przywitaj usługi bez zgodności z GDPR) lub zajmować się innymi nielegalnymi działaniami

W większości pozostałych przypadków bardziej rozsądne jest wykorzystanie istniejących, gotowych rozwiązań.

Co jest potrzebne do uruchomienia

Dobrze, jeśli masz własny autonomiczny system (AS). Można z nim przypisać ten sam adres IP kilku serwerom i zgodnie z tą instrukcją na poziomie sieci kierować użytkowników do najbliższego. Warto zaznaczyć, że nawet z blokiem adresów /24 można zbudować sieć dostarczania treści. Niektórzy dostawcy serwerów pozwalają na ogłoszenie dotyczące wykorzystania we wszystkich dostępnych u nich regionach.

Jeśli nie jesteś szczęśliwym posiadaczem bloku adresów IP, do uruchomienia prostego CDN potrzebujesz:

  • nazwa domeny lub subdomena
  • minimum dwóch serwerów w różnych regionach. Serwer może być zarówno dedykowany, jak i wirtualny
  • narzędzie geoDNS. Dzięki niemu użytkownik, zwracając się do domeny, zostanie skierowany na najbliższy serwer

Rejestrujemy domenę i zamawiamy serwery

Rejestracja domeny jest prosta — rejestrujemy w dowolnej strefie u dowolnego rejestratora. Możemy również użyć subdomeny do CDN, na przykład coś takiego jak cdn.nazwadomeny.com. Właściwie w naszym przykładzie postąpimy dokładnie tak.

Co się tyczy zamawiania serwerów — należy je wynajmować w regionach i krajach, gdzie znajduje się twoja docelowa grupa użytkowników. Jeśli projekt jest międzykontynentalny, warto wybrać dostawców hostingu oferujących serwery na całym świecie. Przykłady: OVH, Leaseweb i 100Tb — dla serwerów dedykowanych, Vultr i DigitalOcean — dla serwerów wirtualnych*.

Dla naszego prywatnego CDN zamówimy 3 wirtualne serwery na różnych kontynentach. Na Vultr serwerze za 5 USD/mies otrzymamy 25GB SSD miejsca i 1 TB transferu. Przy instalacji wybierzemy najnowszy Debian. Nasze serwery:

Zbieramy i konfigurujemy własne CDN Frankfurt, ip: 199.247.18.199

Zbieramy i konfigurujemy własne CDN Chicago, ip: 149.28.121.123

Zbieramy i konfigurujemy własne CDN Singapur, ip: 157.230.240.216

* Vultr i DigitalOcean obiecują 100 USD kredytu dla użytkowników zarejestrowanych za pośrednictwem linków w artykule, od razu po dodaniu metody płatności. Autor również z tego otrzymuje mały komplement, który jest dla niego teraz bardzo istotny. Proszę, weźcie to pod uwagę ze zrozumieniem.

Konfigurujemy geoDNS

Aby użytkownik przywołujący domenę lub subdomenę CDN był kierowany na odpowiedni (najbliższy) serwer, potrzebujemy serwera DNS z funkcją geoDNS.

Zasada i sposób działania geoDNS jest następujący:

  1. Określa IP klienta, który wysłał zapytanie DNS, lub IP rekurencyjnego serwera DNS używanego podczas przetwarzania zapytania klienta. Takimi serwerami rekurencyjnymi są zazwyczaj DNS-y dostawców.
  2. Na podstawie IP klienta ustala jego kraj lub region. Do tego wykorzystuje się bazy GeoIP, których jest dziś mnóstwo. Są też całkiem niezłe opcje darmowe.
  3. W zależności od lokalizacji klienta zwraca mu IP najbliższego serwera CDN.

Serwer DNS z funkcją geoDNS można zbudować samodzielnie, ale lepiej skorzystać z gotowych rozwiązań z siecią serwerów DNS na całym świecie i Anycast w zestawie:

  • ClouDNS od 9,95 USD/mies, taryfa GeoDNS, domyślnie zawiera jeden DNS Failover
  • Zilore od 25 zł/mies, w tym DNS Failover
  • Amazon Route 53 od 35 zł/mies za 50M czystych zapytań geolokalizacyjnych. DNS Failover jest naliczany osobno
  • DNS Made Easy od 125 zł/mies, dostępnych 10 DNS Failover
  • Cloudflare, funkcja „Geo Steering” dostępna w taryfach Enterprise

Przy zamawianiu geoDNS należy zwrócić uwagę na liczbę zapytań uwzględnionych w taryfie i mieć na uwadze, że rzeczywista liczba zapytań do domeny może znacznie przekroczyć oczekiwania. Miliony robotów, skanery, spamery i inne niepożądane byty pracują nieustannie.

Praktycznie wszyscy dostawcy usług DNS w cenę wliczają niezastąpioną dla budowy CDN usługę — DNS Failover. Dzięki temu można skonfigurować monitorowanie działania swoich serwerów, a w przypadku braku oznak życia automatycznie zamieniać w odpowiedziach DNS adres niedziałającego serwera na zapasowy.

Do budowy naszego CDN skorzystamy z ClouDNS, taryfa GeoDNS.

Dodamy w panelu osobistym nową strefę DNS, podając swoją domenę. Jeśli CDN będzie budowany na subdomenie, a główna domena jest już używana, to zaraz po dodaniu strefy nie zapomnij dodać istniejących działających rekordów DNS. Następnym krokiem będzie stworzenie dla CDN domeny/subdomeny kilku rekordów A, z których każdy będzie stosowany do wskazanego przez nas regionu. Jako regiony można podać kontynenty lub kraje, dla USA i Kanady dostępne są subregiony.

W naszym przypadku CDN będzie uruchomiony na subdomenie cdn.sayt.in. Dodając strefę sayt.in, stworzymy dla subdomeny pierwszy rekord A i skierujemy całą Amerykę Północną na serwer w Chicago:

Zbieramy i konfigurujemy własne CDN
Powtórzymy działanie dla innych regionów, nie zapominając o utworzeniu jednego rekordu dla regionów domyślnych. Oto co uzyskamy na koniec:

Zbieramy i konfigurujemy własne CDN

Ostatni domyślny rekord na zrzucie ekranu oznacza, że wszystkie nieokreślone regiony (a więc Europa, Afryka, użytkownicy internetu satelitarnego itd.) będą kierowane na serwer we Frankfurcie.

To jest podstawowa konfiguracja DNS zakończona. Pozostaje tylko wejść na stronę rejestratora domeny i zmienić obecne NS-y domeny na te, które wydał ClouDNS. A podczas aktualizacji NS-ów przygotujemy serwery.

Instalacja certyfikatów SSL

Nasz CDN będzie działał przez HTTPS, więc jeśli już masz certyfikaty SSL dla domeny lub subdomeny, — załaduj je na wszystkie serwery, na przykład do katalogu /etc/ssl/вашдомен/

Jeśli nie masz certyfikatów, możesz uzyskać darmowy od Let’s Encrypt. Do tego świetnie nadaje się skrypt ACME Shell. Klient jest łatwy do skonfigurowania i, co najważniejsze, pozwala na przeprowadzanie walidacji domeny/subdomeny przez DNS za pośrednictwem API od ClouDNS.

Zainstalujemy acme.sh tylko na jednym z serwerów — europejskim 199.247.18.199, z którego certyfikaty będą kopiowane na wszystkie pozostałe. Aby zainstalować, wykonamy:

root@cdn:~# wget -O - https://get.acme.sh | bash; source ~/.bashrc

W trakcie instalacji skryptu zostanie utworzone zadanie CRON do dalszego aktualizowania certyfikatów bez naszego udziału.

Walidacja domeny przy wydawaniu certyfikatu będzie przeprowadzana przez DNS z użyciem API, dlatego w panelu użytkownika ClouDNS w menu Reseller API należy utworzyć nowego użytkownika API i ustawić dla niego hasło. Uzyskany auth-id wraz z hasłem zapiszemy w pliku ~/.acme.sh/dnsapi/dns_cloudns.sh (nie mylić z plikiem dns_clouddns.sh). Oto linie, które należy odkomentować i edytować:

CLOUDNS_AUTH_ID=
CLOUDNS_AUTH_PASSWORD=""

Teraz zażądajmy otrzymania certyfikatu SSL dla cdn.sayt.in

root@cdn:~# acme.sh --issue --dns dns_cloudns -d cdn.sayt.in --reloadcmd "service nginx reload"

W parametrach, na przyszłość, określiliśmy polecenie do automatycznego przeładowania konfiguracji serwera www po każdym przedłużeniu ważności certyfikatu.

Cały proces uzyskiwania certyfikatu może zająć do 2 minut, nie przerywaj go. Jeśli wystąpi błąd walidacji domeny, spróbuj ponownie uruchomić polecenie. Na końcu zobaczymy, gdzie zostały załadowane certyfikaty:

Zbieramy i konfigurujemy własne CDN

Zapamiętaj te ścieżki, będą one potrzebne przy kopiowaniu certyfikatu na inne serwery, jak również w ustawieniach serwera www. Na błąd podczas przeładowania konfiguracji Nginx nie zwracaj uwagi — na w pełni skonfigurowanym serwerze podczas aktualizacji certyfikatów nie powinno go być.

Wszystko, co nam pozostało w kwestii SSL, to skopiować uzyskany certyfikat na dwa inne serwery z zachowaniem ścieżki do plików. Stwórzmy na każdym z nich takie same katalogi i wykonajmy kopię:

root@cdn:~# mkdir -p /root/.acme.sh/cdn.sayt.in/
root@cdn:~# scp -r root@199.247.18.199:/root/.acme.sh/cdn.sayt.in/* /root/.acme.sh/cdn.sayt.in/

Aby aktualizacja certyfikatów odbywała się regularnie, utwórzmy na obu serwerach codzienne zadanie CRON z poleceniem:

scp -r root@199.247.18.199:/root/.acme.sh/cdn.sayt.in/* /root/.acme.sh/cdn.sayt.in/ && service nginx reload

Przy tym dostęp do zdalnego serwera źródłowego powinien być skonfigurowany za pomocą klucza, tzn. bez wprowadzania hasła. Nie zapomnij o tym.

Instalacja i konfiguracja Nginx

Do dostarczania statycznej zawartości użyjemy Nginx skonfigurowanego jako serwer proxy z buforowaniem. Zaktualizujemy listy pakietów i zainstalujemy go na wszystkich trzech serwerach:

root@cdn:~# apt update
root@cdn:~# apt install nginx

Zamiast domyślnego użyjemy konfiguracji z poniższego spoilera:
nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 4096;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log off;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_disable "msie6";
    gzip_comp_level 6;
    gzip_proxied any;
    gzip_vary on;
    gzip_types text/plain application/javascript text/javascript text/css application/json application/xml text/xml application/rss+xml;
    gunzip on;

    proxy_temp_path /var/cache/tmp;
    proxy_cache_path /var/cache/cdn levels=1:2 keys_zone=cdn:64m max_size=20g inactive=7d;
    proxy_cache_bypass $http_x_update;

server {
  listen 443 ssl;
  server_name cdn.sayt.in;

  ssl_certificate /root/.acme.sh/cdn.sayt.in/cdn.sayt.in.cer;
  ssl_certificate_key /root/.acme.sh/cdn.sayt.in/cdn.sayt.in.key;

  location / {
    proxy_cache cdn;
    proxy_cache_key $uri$is_args$args;
    proxy_cache_valid 90d;
    proxy_pass https://sayt.in;
    }
  }
}

W konfiguracji edytujemy:

  • max_size — rozmiar pamięci podręcznej, który nie przekracza dostępnego miejsca na dysku
  • inactive — czas przechowywania danych w pamięci podręcznej, do których nikt nie uzyskiwał dostępu
  • ssl_certificate i ssl_certificate_key — ścieżki do plików certyfikatu SSL i klucza
  • proxy_cache_valid — czas przechowywania danych w pamięci podręcznej
  • proxy_pass — adres oryginalnego serwera, z którego CDN będzie pobierać pliki do buforowania. W naszym przykładzie jest to sayt.in

Jak widać, wszystko jest proste. Trudności mogą wystąpić jedynie przy ustawieniu czasu buforowania ze względu na podobieństwo dyrektyw inactive i proxy_cache_valid. Rozbijmy je na naszym przykładzie. Oto co się dzieje przy inactive=7d i proxy_cache_valid 90d:

  • jeśli żądanie nie powtórzy się przez 7 dni, dane zostaną usunięte z pamięci podręcznej po upływie tego okresu
  • jeśli żądanie będzie powtarzane chociaż raz na 7 dni, dane w pamięci podręcznej będą uznawane za przestarzałe po upływie 90 dni, a przy następnym żądaniu Nginx je zaktualizuje, pobierając je z oryginalnego serwera

Kiedy skończymy edytować nginx.conf, przeładujmy konfigurację:

root@cdn:~# service nginx reload

Nasz CDN jest całkowicie gotowy. Za 15 USD/mies. mamy punkty obecności na trzech kontynentach i 3 TB ruchu: po 1 TB w każdej lokalizacji.

Sprawdzamy działanie CDN

Przyjrzymy się pingom do naszego CDN z różnych lokalizacji geograficznych. Do tego posłużą dowolne usługi ping.

Punkt startowy
Host
IP
Średni czas, ms

Niemcy, Berlin
cdn.sayt.in
199.247.18.199
9.6

Holandia, Amsterdam
cdn.sayt.in
199.247.18.199
10.1

Francja, Paryż
cdn.sayt.in
199.247.18.199
16.3

Wielka Brytania, Londyn
cdn.sayt.in
199.247.18.199
14.9

Kanada, Toronto
cdn.sayt.in
149.28.121.123
16.2

USA, San Francisco
cdn.sayt.in
149.28.121.123
52.7

USA, Dallas
cdn.sayt.in
149.28.121.123
23.1

USA, Chicago
cdn.sayt.in
149.28.121.123
2.6

USA, New York
cdn.sayt.in
149.28.121.123
19.8

Singapur
cdn.sayt.in
157.230.240.216
1.7

Japan, Tokyo
cdn.sayt.in
157.230.240.216
74.8

Australia, Sydney
cdn.sayt.in
157.230.240.216
95.9

Wyniki są dobre. Teraz umieścimy testowy obrazek w głównym katalogu strony. test.jpg i sprawdzimy prędkość jego ładowania przez CDN. Powiedziano, — zrobione. Treści są szybko dostarczane.

Napiszemy mały skrypt na wypadek, gdybyśmy chcieli wyczyścić cache w punkcie CDN.
purge.sh

#!/bin/bash
if [ -z "$1" ]
then
    echo "Purging all cache"
    rm -rf /var/cache/cdn/*
else
    echo "Purging $1"
    FILE=`echo -n "$1" | md5sum | awk '{print $1}'`
    FULLPATH=/var/cache/cdn/${FILE:31:1}/${FILE:29:2}/${FILE}
    rm -f "${FULLPATH}"
fi

Aby usunąć cały cache, wystarczy go uruchomić, a osobny plik można wyczyścić w ten sposób:

root@cdn:~# ./purge.sh /test.jpg

Zamiast wyników

Na koniec chciałbym dać kilka przydatnych wskazówek, aby od razu przejść przez pułapki, które w swoim czasie sprawiły mi ból głowy:

  • Aby zwiększyć odporność na awarie CDN, zaleca się skonfigurowanie DNS Failover, co pomaga szybko zmienić rekord A w przypadku awarii serwera. Dzieje się to w panelu zarządzania rekordami DNS domeny.
  • Strony o szerokim zasięgu geograficznym bez wątpienia wymagają wielu punktów CDN, ale zróbmy to z umiarem. Najprawdopodobniej użytkownik nie zauważy istotnej różnicy w porównaniu z płatnym CDN, jeśli umieścisz serwery w 6-7 miejscach: Europa, Północna Ameryka (wschód), Północna Ameryka (zachód), Singapur, Australia, Hongkong lub Japonia.
  • Czasami hosterzy nie pozwalają na używanie wynajmowanych serwerów do celów CDN. Dlatego, jeśli zdecydujesz się na uruchomienie sieci dostarczania treści jako serwisu, nie zapomnij wcześniej przeczytać zasady konkretnego dostawcy hostingu.
  • Zbadaj mapę podmorskich komunikacji, aby zobaczyć, jak kontynenty są połączone i uwzględnić to przy budowaniu sieci dostarczania treści.
  • Spróbuj sprawdzić pingi z różnych miejsc do swoich serwerów. W ten sposób można zobaczyć najbliższe regiony do punktów CDN i lepiej skonfigurować GeoDNS.
  • W zależności od zadań, warto dostosować Nginx do konkretnych wymagań dotyczących pamięci podręcznej i z uwzględnieniem obciążenia serwera. W tym bardzo pomogły mi artykuły dotyczące pamięci podręcznej Nginx — tutaj i przyspieszania działania przy dużych obciążeniach: tutaj i tutaj

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster