Budowanie tanich, wysoko wydajnych i wysoko dostępnych

Transkrypt

Budowanie tanich, wysoko wydajnych i wysoko dostępnych
Budowanie tanich, wysoko wydajnych
i wysoko dostępnych systemów
pod Linuksem
Mariusz Drozdziel
«[email protected]»
Klasyfikacja klastrów
Pojęcie klastra komputerowego ewoluuje od początków systemów informatycznych
razem z rozwojem technologii. Istnieje wiele mniej lub bardziej ścisłych definicji określających co nazywamy klastrem, a co jedynie przypomina go swoją charakterystyką.
W dość luźny sposób mianem klastra określana jest grupa komputerów ściśle ze sobą
współpracujących, wykonujących to samo lub zbliżone zadanie. Często dla odbiorcy
świadczonej usługi stwarzają one pozornie pojedynczą maszynę.
Sama nazwa „klastrów obliczeniowych” (compute cluster) w dość oczywisty sposób wyjaśnia przeznaczenie tego typu systemów. Głównym celem podczas budowania
takich rozwiązań jest uzyskanie jak najwyższej mocy obliczeniowej. Wydajność klastrów obliczeniowych mierzona jest w ilości operacji zmiennoprzecinkowych, którą
zespół komputerów jest w stanie wykonać na sekundę. Dalszy luźny podział klastrów
obliczeniowych bazuje na tym, jak ściśle powiązane są ze sobą poszczególne węzły.
W klastrach nazywanych Beowulf węzły połączone są sieciami o wysokich przepustowościach i przystosowane są do wymiany dużych ilości informacji. Na drugim końcu
klasyfikacji umieszczone są klastry typu grid, nazywane również rozproszonymi (distributed), gdzie węzły okresowo wymieniają porcje danych i skupiają się na obróbce
otrzymanych danych. Najbardziej znanym przykładem klastrów ostatniej kategorii
jest projekt Seti@Home.
Budowanie tanich, wysoko wydajnych. . .
9
W ramach drugiej dużej grupy można wyodrębnić „klastry usługowe”. Przeznaczeniem takich rozwiązań jest najczęściej budowanie systemów świadczących różnego rodzaju usługi. Dzięki rozproszeniu na wiele pojedynczych maszyn, serwery są w stanie
obsłużyć większą ilość klientów jednocześnie (load balancing), co pozwala zwiększyć
wydajność. Z drugiej strony ważnym zastosowaniem tego typu klastrów jest budowanie systemów wysoko dostępnych (high-availability) i zapewnienie redundancji.
Dzięki rozproszeniu systemów i zastosowaniu odpowiednich mechanizmów cała usługa uodporniona jest na awarie pojedynczych elementów. Tego typu rozwiązania pozwalają na zminimalizowanie czasu niedostępności usług podczas planowanych akcji
serwisowych. Przy odpowiednio zaplanowanych pracach można dokonać modyfikacje
na poszczególnych węzłach, cały czas zapewniając ciągłość pracy usług. Dostępne
obecnie nowoczesne rozwiązania pozwalają łączyć funkcjonalność load-balancingu
oraz high-availability. Awarie poszczególnych komponentów usług są przeźroczyste
dla klientów i powodują jedynie zmniejszenie wydajności całego rozwiązania. Jednocześnie rozwiązania tego typu są zupełnie niewidoczne po stronie odbiorcy usługi i nie
muszą być przez niego obsługiwane w specjalny sposób. Przez cały czas klient ma
wrażenie, że pracuje na pojedynczym serwerze, co jest podstawową zasadą budowania
rozwiązań klastrowych tego typu.
Dość trudno w jasny sposób wyodrębnić ogólne metody budowania klastrów zapewniających wysoką wydajność i wysoką dostępność usług. Konkretne usługi można
rozpraszać na bardzo wiele sposobów stosując różne mechanizmy. Często najtrudniejszym elementem konfiguracji klastrów jest dobre przeanalizowanie usług i dobór
odpowiedniego rozwiązania. Oprócz obecnej sytuacji należy również wziąć pod uwagę
ewentualną rozbudowę aplikacji w przyszłości. Dobrze dobrane rozwiązanie powinno
być skalowalne w poziomie, czyli pozwalać na łatwe zwiększenie wydajności całego
rozwiązania poprzez dodanie kolejnych węzłów bez konieczności skomplikowanych
rekonfiguracji.
Load balacing (load sharing) przy użyciu wielokrotnych wpisów
DNS
Najprostszym i jednocześnie najłatwiejszym sposobem rozłożenia obciążenia (load
balancing) na wiele maszyn są wielokrotne rekordy A/CNAME w konfiguracji DNS.
Oczywiście samo umożliwienie funkcjonowania usług na kliku maszynach jednocześnie może być skomplikowane. W sytuacji kiedy zostanie to osiągnięte, skierowanie
ruchu od klientów na kilka maszyn jest bardzo proste w konfiguracji. To rozwiązanie
jest sensowne, kiedy do usługi łączy się duża liczba klientów, co w praktyce oznacza usługi udostępnione w Internecie. Przy odpowiednio dużych ilościach połączeń
ruch powinien być statystycznie równo rozłożony na poszczególne węzły. Oczywistą
wadą takiego rozwiązania jest brak możliwości kontrolowania obciążenia czy funkcjonowania węzłów. Mocno obciążone serwery nadal będą otrzymywały takie same
ilości połączeń, jak pozostałe maszyny. W przypadku kompletnej awarii, usługa stanie się niedostępna dla części klientów. Przykładowo, jeżeli w takim rozwiązaniu
awarii ulegnie 1 z 5 serwerów, wówczas 20% odbiorców nie będzie mogło korzystać
z usługi. Korzystanie z load-balacingu opartego o DNS ma wiele innych wad. Podstawowe z nich to brak kontroli nad sposobem wysyłania zapytań przez klientów DNS
10
Mariusz Drozdziel
i metod cache-owania wpisów oraz utrudnione rekonfiguracje puli serwerów (albo
konieczność stosowania bardzo niskich wartości TTL dla rekordów).
Na przestrzeni lat powstawało kilka różnych projektów, których zadaniem była rozbudowa i usprawnienie load-balancingu opartego o DNS (lbnamed). Ponieważ jednak
samo wykorzystanie DNS do tego celu stwarza wiele problemów aplikacje te nigdy
nie rozwinęły się do bardzo zaawansowanego poziomu. Redundancja i mechanizmy
load balancing/high-availabilty zostały rozbudowane na innych warstwach i w innych
obszarach infrastruktury.
Obecnie load balancing oparty o DNS jest powszechnie wykorzystywany głównie w przypadku bardzo dużych (w skali światowej) serwisów, które odwiedzane są
przez miliony klientów. Często mechanizm ten wykorzystuje się do geograficznego
rozproszenia zapytań, a same adresy wskazują na różne centra danych. Pod samymi
adresami IP kryją się natomiast nie pojedyncze węzły, a kolejne systemy klastrowe,
oparte już o bardziej zaawansowane mechanizmy. W przypadku serwerów WWW lub
innych serwerów treści wpisy w DNS wskazują często na rozproszone systemy cache.
VRRP
Z założenia VRRP (Virtual Router Redundancy Protocol) to protokół opracowany
w celu zapewnienia wysokiej dostępności default gateway-a w segmentach sieci IP.
Dwa (lub więcej) fizyczne routery są skonfigurowane aby poprawnie pełnić tą funkcję
w segmencie. Jeden z nich rozgłasza faktyczny adres bramy i obsługuje ruch, podczas
gdy pozostałe są gotowe przejąć jego zadania w razie potrzeby. Kiedy aktywny router
(master) przestaje rozgłaszać pakiety VRRP oznacza to, że utracił możliwość poprawnego routowania ruchu. Wówczas jeden z zapasowych routerów (backup) przejmuje
jego funkcję. Wybór nowego mastera odbywa się bazując na podstawie prekonfigurowanych priorytetów. Idea działania i same implementacje VRRP są stosunkowo
proste. Również sama konfiguracja i zarządzanie nie są skomplikowane. W praktyce najczęściej spotyka się konfiguracje złożone z dwóch routerów, co w większości
przypadków zapewnia wystarczającą niezawodność. Architektura VRRP ma typową
charakterystykę protokołów active-passive. Przy odpowiedniej konfiguracji można jednak z powodzeniem aktywnie wykorzystywać więcej niż jedno urządzenie, zapewniając
zarówno równoważenie obciążenia, jak i wysoką dostępność.
Mimo że pole działania VRRP mieszczą się w obrębie warstwy sieciowej, to elastyczność protokołu pozwala wykorzystać go jako element klastrowania aplikacji. Najprostszym tego przykładem może być rozszerzenie opisywanego wcześniej rozwiązania
równoważenia obciążenia wykorzystującego DNS. Ograniczeniem VRRP w tej kwestii
jest konieczność umiejscowienia wszystkich węzłów w jednym segmencie (domenie
kolizyjnej) sieci LAN. W przykładowej realizacji domena, pod którą zlokalizowana
jest usługa, powinna zawierać kilka równoważnych rekordów A/CNAME wskazujących
na różne urządzenia. Wszystkie te adresy powinny być skonfigurowane jako funkcjonujące wirtualne adresy w różnych grupach VRRP [1]. Wszystkie elementy takiego
klastra powinny być we wszystkich grupach VRRP, a każda z tych grup powinna
mieć innego mastera. Dla przykładowego rozwiązania składającego się z 5 serwerów
w stanie początkowym przychodzący ruch będzie zrównoważony na wszystkie. Jeżeli
jeden z nich zostanie wyłączony, wówczas dzięki wykorzystaniu VRRP jego adres IP
Budowanie tanich, wysoko wydajnych. . .
11
Rys 1 Przykład load-balacingu opartego o DNS + VRRP
zostanie przypisany do któregoś z pozostałych 4 węzłów. Od tej chwili 3 elementy będą
obsługiwały po 20% ruchu, a jeden z nich 40%. Optymalnym stanem wyjściowym
byłaby sytuacja, kiedy po awarii jednego z węzłów jego ruch zostanie równo rozłożony
na działające serwery. Niestety powyższe rozwiązanie uniemożliwia taką konfigurację.
Jeżeli jeden z węzłów nie będzie w stanie nagle obsłużyć dwukrotnie większego ruchu
trzeba wykorzystać inne metody.
Oczywiście takie rozwiązanie nadal posiada bardzo wiele wad. W przedstawionej postaci brakuje przede wszystkim zaawansowanych mechanizmów sprawdzania
poprawnego funkcjonowania aplikacji. VRRP zadziała tylko wtedy, kiedy wirtualny
IP przestanie być rozgłaszany przez obecnego mastera. W przypadku awarii samej
aplikacji serwer nadal będzie poprawnie obsługiwał warstwę sieciową, co spowoduje
awarię usługi dla części odbiorców. Oczywiście do takiego rozwiązania można wprowadzić kolejne elementy, jak proste sprawdzanie działania aplikacji wewnątrz serwerów.
W przypadku stwierdzenia awarii prosty skrypt może wyłączyć podsystem VRRP, co
automatycznie spowoduje przeniesienie adresu IP na inną maszynę. Oczywiście samo rozwiązanie ma charakteryzować się prostotą. Jeżeli do poprawnej implementacji
całości konieczne jest stworzenie wielu dodatkowych mechanizmów, napisanie wielu
skryptów, wówczas warto przeanalizować cała sytuację i wybrać inne rozwiązanie.
Warto nadmienić, iż w powyższej konfiguracji aplikacje nie będą poprawnie nasłuchiwać na adresach IP, które pojawiły się na interfejsach dopiero po tym jak aplikacja
została uruchomiona. Aby aplikacja na serwerze, na który przeniesiono adres IP
poprawnie obsługiwała połączenia na ten adres, konieczna jest reinicjalizacja obsługi
12
Mariusz Drozdziel
sieci tej aplikacji. Niektóre aplikacje mają zaimplementowaną możliwość ponownego przeskanowania interfejsów bez przerywania dotychczasowej pracy - przykładowo
OpenSWAN (ipsec whack –listen). W skrajnych przypadkach awaria, bądź kontrolowane wyłączenie jednego z węzłów może oznaczać zerwanie połączeń nawiązanych
zarówno do wyłączanego węzła, jak i węzła, na którym dodany zostanie nowy adres
IP.
Rozwiązania oparte wyłącznie na VRRP mają więc bardzo wiele wad i są bardzo
ograniczone. Należy jednak pamiętać, że charakteryzuje je niesamowita prostota
działania i co za tym idzie prostota w konfiguracji, i zarządzaniu. W praktyce VRRP
lub podobne narzędzie spełniające podobną funkcję jest nieodzownym elementem
większości rozwiązań zapewniających wysoką dostępność systemów informatycznych.
Istnieje kilka implementacji protokołu VRRP działających pod Linuksem. Najbardziej popularny z nich to zapoczątkowany przez Jerome Etienne vrrpd. Poniższe
polecenia wykonane na dwóch systemach w jednej podsieci powodują uruchomić
obsługę VRRP i udostępnienie adresu IP 10.0.0.1, który w przypadku awarii serwera A będzie dostępny na serwerze B. Ilustruje to prostotę, jaką charakteryzuje się
obsługa tego rozwiązania.
SerwerA# vrrpd -D -i eth0 -v 50 -p 20 10.0.0.1
SerwerB# vrrpd -D -i eth0 -v 50 -p 10 10.0.0.1
Inną popularną aplikacją implementują między innymi VRRP jest keepalived.
Poza podstawową funkcjonalnością VRRP aplikacja pozwala również na definiowanie
skryptów, które zostaną wykonane po zmianach umiejscowienia adresów IP. Skrypty
można wykorzystać na przykład do poinformowania aplikacji, że na interfejsach pojawił się nowy adres IP, który powinien być przez aplikacje obsługiwany. Przykładowa
konfiguracja VRRP w keepalived na jednym z węzłów:
vrrp_instance VRRP_1 {
interface eth0
state MASTER
virtual_router_id 50
priority 20
virtual_ipaddress {
10.0.0.1/24
}
notify_backup "/usr/local/bin/vrrp.sh BACKUP VRRP_1"
notify_master "/usr/local/bin/vrrp.sh MASTER VRRP_2"
}
Przy okazji aplikacji implementujących automatyczny failover adresów IP warto
również wspomnieć o Common Address Redundancy Protocol – alternatywnej implementacji funkcjonalności VRRP, która powstała w ramach projektu OpenBSD.
Implementacja CARP pod nazwą ucarp istnieje również w wersji linuksowej i jest
dostępna w podstawowym zbiorze pakietów wielu popularnych dystrybucji.
Budowanie tanich, wysoko wydajnych. . .
13
LVS
Linux Virtual Server to rozwiązanie zapewniające zaawansowane metody rozkładania obciążenia pomiędzy wiele serwerów (load balancing). Jednym z podstawowych
założeń LVS, jest całkowita przeźroczystość rozwiązania dla użytkowników usługi.
W standardowych instalacjach faktyczna struktura klastra LVS jest całkowicie ukryta przed klientami i sprawia wrażenie pojedynczej usługi. Projekt jest intensywnie
rozwijany od ponad 10 lat. Kod LVS trafił do oficjalnej gałęzi kernela pod koniec
2003, tak więc w gałęzi 2.6 znajduje się od pierwszego wydania. Zarządzenie tablicą
LVS wykonywane jest przy użyciu oficjalnego narzędzia ipvsadm, które znajduje się
w większości popularnych dystrybucji. Na przestrzeni lat, kiedy LVS zyskiwał na popularności, powstało bardzo wiele zewnętrznych narzędzi. Usprawniają one zarządzanie i rozszerzają funkcjonalność LVS, ułatwiając budowanie bardzo zaawansowanych
instalacji.
Podstawowym elementem infrastruktury klastra LVS jest director – serwer zajmujący się przekierowywaniem połączeń na faktyczne maszyny z uruchomionymi
aplikacjami (real servers). Klienci, nawiązując połączenie z adresem usługi, łączą się
faktycznie do directora LVS, który bazując na swojej konfiguracji, przesyła pakiety
do faktycznych serwerów. LVS implementuje wiele różnych algorytmów szeregujących
połączenia. Korzystając z dodatkowych narzędzi można na bieżąco dostosowywać metrykę poszczególnych maszyn do faktycznych zasobów, jakie są na nich dostępne. Pozwala to na optymalne wykorzystanie zasobów na wszystkich maszynach. LVS działa
na warstwie transportowej, obsługując protokoły TCP, UDP a także ESP i AH. Usługi
poszczególnych wirtualnych serwerów definiuje się przez parę IP oraz port, na które
wysłany został pakiet lub bazując na markowaniu iptables (fwmark).
Ogólna zasada działania LVS jest bardzo prosta. Po otrzymaniu pakietu na adres,
na którym zdefiniowana jest wirtualna usługa, pakiet zostaje przekazany do serwera
wybranego na podstawie skonfigurowanego algorytmu szeregującego. Jednym z kluczowym elementów LVS jest metoda, jaką zostanie przekazany pakiet. Możliwe są
trzy sposoby: tłumaczenie adresów (NAT), bezpośredni routing (dr – direct routing)
oraz tunelowanie (TUN). Ostatnie dwie metody są bardzo zbliżone zarówno od strony
konfiguracji całego środowiska, jak i wydajności. Podstawowa różnica to konieczność
obsługi dekapsulacji IPIP po stronie węzłów. W przypadku dedykowanych urządzeń
może to niekiedy stanowić problem. Popularne systemy operacyjne (Linux/FreeBSD,
Windows 2000 i nowsze) posiadają tę możliwość.
LVS-NAT wykonuje przeadresowanie NAT adresów docelowych w pakiecie IP, który przekazywany jest do real serverów. Pakiet odbierany od directora przez serwer
faktyczny jest przeadresowany, tak więc nie potrzebna jest żadna dodatkowa konfiguracja po stronie węzłów. Oczywiście w celu zapewnienia poprawnego funkcjonowania
całej instalacji, pakiet wracający od serwera do klienta musi też przejść przez director. Aby klient poprawnie zinterpretował pakiet od serwera, musi odbyć się translacja
w drugą stronę. W praktyce takie rozwiązanie osiąga się bardzo prosto, umieszczając
director przekazujący pakiety w trybie LVS-NAT na domyślnej bramie w podsieci real
serverów. Siłą rzeczy LVS-NAT nie będzie poprawnie obsługiwał połączeń od komputerów w tej samej podsieci, w której znajdują się serwery usługowe. Pakiety od
serwerów do klientów ominą director i dotrą do klientów z innym niż oczekiwany
14
Mariusz Drozdziel
Rys 2 Przykład load-balacingu opartego o LVS-NAT
adres źródłowy. Niewątpliwą zaletą LVS-NAT jest prosta logika działania i bezproblemowe utrzymanie w przeciwieństwie do LVS-DR. Wadą tego rozwiązania w stosunku
do czystego przekazywania pakietów jest przede wszystkim zwiększenie opóźnienia
pakietów przechodzących przez director. Sytuacja jest zauważalna zwłaszcza przy
ruchu charakteryzującym się dużą ilością małych pakietów. Dodatkowym minusem
wariantu LVS-NAT jest kilkukrotnie większe zużycie mocy obliczeniowej procesora
na directorze (w porównaniu do LVS-DR).
LVS-DR polega na przekazywaniu pakietów bez żadnej ingerencji w ich zawartość.
LVS przesyła pakiet adresując go na warstwie łącza wedle adresu IP wybranego real
servera. Sam pakiet zawiera jednak w nagłówku pierwotny adres IP obsługiwany
na directorze. Aby serwer poprawnie zinterpretował taki pakiet, jego konfiguracja
musi być specjalnie modyfikowana. Nie tylko komplikuje to samą konfigurację, ale
ogranicza również liczbę systemów operacyjnych, które będą w stanie funkcjonować
jako węzły w klastrze LVS-DR (LVS-TUN). Najprostszym rozwiązaniem, jest konfiguracja tego samego adresu IP, pod którym funkcjonuje director również na real serverach.
Z oczywistych powodów adres IP na faktycznym serwerze nie może być rozgłaszany
w lokalnym segmencie sieci LAN. (serwer nie może odpowiadać na zapytania ARP
o ten adres IP). LVS-DR narzuca jeszcze wiele innych ograniczeń i w pewnych sytuacjach komplikuje konfigurację. Konfiguracja poszczególnych elementów i wydajnośc
LVS-TUN jest bardzo zbliżona do LVS-DR. Tunelowanie pozwala na umieszczenie
serwerów z aplikacjami w innej podsieci aniżeli sam director.
Budowanie tanich, wysoko wydajnych. . .
15
Rys 3 Przykład load-balacingu opartego o LVR-DR
Ogólną zaletą rozwiązań LVS-DR/TUN jest przede wszystkim wydajność. Nawet
w bardzo obciążonych instalacjach LVS nie różni się znacząco od zwykłego forwardowania pakietów. Dodatkowo, pakiety odsyłane z serwerów do klientów nie muszą
przechodzić przez director (w wielu sytuacjach nawet nie powinny).
Decyzja wyboru metody przekazywania pakietów nie jest prosta i zależy w dużej
mierze od konkretnej sytuacji. Sprowadza się to zazwyczaj to wyboru między łatwą
i prostą konfiguracją, a wydajnością. Narzut LVS-NAT nie jest jednak krytyczny i w
wielu sytuacjach będzie niezauważalny. Na stronie projektu LVS [2] można znaleźć
bardzo obszerne opracowania dotyczące wydajności różnych wariantów LVS w różnych
sytuacjach.
Dość istotną cechą LVS jest możliwość tworzenia skojarzeń klient – konkretny
serwer (opcja konfiguracyjna LVS persistance). W praktyce oznacza to, że nowe
połączenia przychodzące na director od tego samego klienta będą kierowane na ten
sam serwer. Taka zależność ma kluczowe znaczenie dla instalacji obsługujących
połączenia SSL, FTP, czy nawet HTTP (utrzymanie sesji).
Sam LVS obejmuje jedynie elementy zapewniające load balancing usług. Awaria
któregokolwiek z serwerów spowoduje częściową niedostępność usług, natomiast
awaria directora powoduje niedostępność całkowitą. Elementy te można wprowadzić
16
Mariusz Drozdziel
do systemu wykorzystując dodatkowe narzędzia. Najbardziej popularne rozwiązania
to keepalived czy ldirectord i heartbeat.
Keepalived
Główną ideą projektu keepalived [3] jest rozszerzenie LVS o dwie podstawowe funkcjonalności. Sprawdzanie dostępności usług oraz zapewnienie redundancji directorów
LVS poprzez wprowadzenie mechanizmu failover. Zaawansowany system sprawdzania dostępności usług potrafi na bieżąco dodawać i usuwać serwery z puli LVS.
Keepalived ma zaimplementowany niezależny stos VRRP2, wykorzystywany do obsługi redundancji samego directora LVS przez przenoszenie jego funkcjonalności na inną
maszynę.
Monitorowanie usług na poszczególnych serwerach w obrębie klastra LVS odbywa
się przez cykliczne symulowanie połączeń klienckich. Keepalived posiada wbudowaną obsługę kilku podstawowych testów pozwalających na proste monitorowanie
serwera HTTP, HTTPS, SMTP lub dowolnego portu TCP. Istnieje również możliwość
uruchomienia własnego skryptu, którego kod powrotu definiował będzie stan usługi. Ta funkcjonalność daje ogromną dowolność w konfigurowaniu testów i badanie
praktycznie każdego elementu klastra.
Wykrycie awarii serwisu powoduje automatyczne wyłączenie danego serwera z puli, na którą przekierowywane są połączenia. W praktyce spowoduje to, że obciążenie
zostanie rozłożone na pozostałe maszyny wedle ustalonych wcześniej reguł – zależnie
od algorytmu szeregującego i ewentualnej predefiniowanej wagi (metryki). Keepalived
pozwala również na definicję odrębnego serwera, na który ruch kierowany będzie dopiero podczas awarii wszystkich innych węzłów. W przypadku serwerów WWW może
to być przykładowo serwer wyświetlający czytelną informację o awarii.
Stos VRRP w keepalived wprowadza kolejną bardzo istotną funkcjonalność. Keepalived uruchomiony na dwóch lub więcej serwerach pozwala wprowadzić pełną
redundancję samego directora. W przypadku braku rozgłaszania pakietów VRRP
zapasowy keepalived przejmie adres IP i uruchomi alternatywny director.
W przypadku wykorzystania LVS-DR istnieje możliwość konfiguracji samego keepalived w trybie active-active. Wykorzystując dwie oddzielne wirtualne grupy
VRRP, możemy skonfigurować dwie pary directorów active-passive. Wpisując obydwa
adresy pod nazwa DNS usługi uzyskamy podobny efekt jak opisany wcześniej balancing DNS-VRRP. W tym przypadku pod adresami IP kryć się będą nie konkretne
usługi, ale directory LVS. W efekcie uzyskamy pełną konfigurację active-active w obrębie całego klastra. Zapewniona zostanie w ten sposób wysoka dostępność, failover
oraz optymalne wykorzystanie wszystkich zasobów.
LVS w połączeniu z keepalived pokrywa praktycznie wszystkie aspekty sprawnego rozdzielania obciążenia i redundancji systemów. Wszystkie omówione przypadki
przyjmują założenie, że dana usługa pracuje jednocześnie na wszystkich węzłach
klastra i w razie bezpośredniego połączenia jest w stanie w pełni obsługiwać klientów.
Powyższe rozwiązania w żaden sposób nie wspierają samego uruchamiania usług
na wielu serwerach. Stopień skomplikowania takiego procesu zależy ściśle od konkretnej usługi. W przypadkach aplikacji, które skalują się tylko w pionie zapewnienie
Budowanie tanich, wysoko wydajnych. . .
17
Rys 4 LVS-NAT + keepalived w konfiguracji active-passive
redundancji może odbywać się wyłącznie w trybie active-passive. Trywialnym rozwiązaniem takiego problemu może być prosta konfiguracja oparta o VRRP i skrypty
uruchamiane podczas przekazywania adresów IP. Możliwość monitorowania stanu
takich usług jest bardzo ograniczona i rozwiązanie sprawdzi się tylko w niektórych,
konkretnych przypadkach.
Linux-HA
Celem projektu Linux High Availability [4] jest implementacja zarządzenia klastrami usługowymi. Główne funkcjonalności pakietu to wzajemne monitorowanie stanu
pracujących serwisów realizowane przez program Heartbeat. Od wersji 2.0 w skład
projektu wszedł również bardzo zaawansowany CRM (Cluster Resource Manager),
obecnie wydzielony jako oddzielny projekt funkcjonujący pod nazwą Peacemaker.
CRM umożliwia zaawansowane zarządzanie zależnościami między aplikacjami wchodzącymi w skąd infrastruktury klastra. Lista obsługiwanych zasobów jest dość duża.
W przypadku typowych aplikacji zarządzanie przez Heartbeat odbywa się za pomocą
skryptów startowych aplikacji zgodnymi z System V.
18
Mariusz Drozdziel
Rys 5 LVS-DR + keepalived w konfiguracji active-active
Konfiguracja zasobów przez CRM pozwala na definiowanie złożonych zależności
oraz kolejności, w jakiej mają być uruchamiane usługi. Dzięki temu bez skomplikowanych konfiguracji można uruchomić zaawansowane systemy klastrowe pracujące
w trybie active-passive. Podczas awarii jednego z elementów systemu heartbeat będzie wiedział, które z aplikacji (również wśród pozornie działających) należy migrować
na zapasową maszynę, aby przywrócić funkcjonalność usługi. Uruchamianie usług
odbędzie się w predefiniowanej kolejności. W opisanym przypadku najpierw zostaną
przeniesione adresy IP, następnie zamontowane zostaną współdzielone zasoby dyskowe, a dopiero potem podniesiona zostanie aplikacja. Wykonanie tych czynności innej
kolejności zapewne doprowadziło by do całkowitego wyłączenia usług. Jednym z zasobów, które obsługuje heartbeat jest director LVS. Zestawienie heartbeat + ldirectord
(demon pozwalający na monitorowanie zasobów LVS) jest alternatywną w stosunku
do keepalived metodą zapewnienia wysokiej dostępności rozwiązań LVS.
Jednym z istotnych elementów, które implementuje heartbeat jest STONITH (shoot
the other node in the head) czyli forma „fencingu” węzłów klastra. W przypadku
wykrycia awarii jednego z węzłów bardzo ważne jest, żeby pozbawić go dostępu do jakichkolwiek wspólnych zasobów. W razie awarii części infrastruktury, usługi lub
pojedynczej aplikacji, węzeł nadal może wykonywać zmiany w bazach danych lub
modyfikować dane na współdzielonych zasobach. Niekiedy węzły korzystają z zasobów, które nie umożliwiają obsługi więcej niż jednego klienta (zasoby dyskowe oparte
Budowanie tanich, wysoko wydajnych. . .
19
na standardowych systemach plików np. ext3). W takiej sytuacji odcięcie uszkodzonego węzła jest zadaniem kluczowym, ponieważ w przeciwnym razie dojdzie do uszkodzenia danych. „Fencing’” polega na całkowitym odłączeniu węzła od jakichkolwiek
zasobów. W przypadku awarii węzła, status dowolnego jego elementu jest nieokreślony. Programowane metody fencingu operujące na interakcji z wadliwym systemem
są więc bardzo niepewne. Najpewniejsze efekty osiąga się poprzez zewnętrzne rozwiązania. W przypadku maszyn wirtualnych optymalnym rozwiązaniem jest wyłączenie
systemu z poziomu supervisora. Serwery fizyczne można wyłączać korzystając z zewnętrznych interfejsów zarządzających typu ILO/DRAC (HP/DELL) lub przez odcięcie
zasilania z poziomu UPS-a. Alternatywą jest fencing na poziomie samych zasobów,
na przykład poprzez fizyczne odłączenie portów FC (Fibre Channel) danego serwera
w switchu SAN.
Synchronizacja zasobów dyskowych
Jednym z głównych problemów podczas eliminowania pojedynczych punktów awarii
jest duplikacja zasobów dyskowych. Niektóre aplikacje (jak na przykład bazy danych)
posiadają własne mechanizmy pozwalające na replikację swoich danych na bliźniacze
systemy. Dzięki temu budowa wysokiej dostępności jest ułatwiona. Wiele aplikacji
korzysta bezpośrednio z danych składowanych na dyskach i w żaden sposób nie
wspiera ich replikacji. Rozwiązaniem tego problemu jest wprowadzenie redundancji
na poziomie blokowych urządzeń z których korzystają aplikacje. Alternatywą dla
zewnętrznych i drogich macierzy dyskowych jest replikacja urządzenia blokowego
przez sieć IP.
DRBD (Distributed Replicated Block Device) [5] to rozwiązanie, które umożliwia
mirrorowanie danych między dwoma serwerami w czasie rzeczywistym. W praktyce
rozwiązanie tworzy RAID-1 między dyskami różnych maszyn połączonych siecią IP.
Infrastruktura jest ukryta przed aplikacją, która korzysta ze standardowego urządzenia blokowego. Dostęp do takiego urządzenia odbywa się na dokładnie takiej
samej zasadzie, jak standardowy dostęp bezpośrednio do fizycznego urządzenia. Warstwa pośrednia między aplikacją, a urządzeniem zajmuje się synchronizacją danych
z zewnętrznym DRBD na innej maszynie.
Należy przy tym pamiętać, że standardowe systemy plików wykorzystywane pod Linuksem (ext3, xfs, jfs, etc.) nie umożliwiają jednoczesnego dostępu do danych
z różnych maszyn. Sam podsystem DRBD dba o to, aby zasób działający w trybie
active-passive nie był dostępny dla dwóch maszyn jednocześnie.
DRBD umożliwia również konfiguracje zasobów w trybie active-active. Wówczas
oba węzły mogą modyfikować dane jednocześnie. W takiej sytuacji konieczne jest
zastosowanie sieciowego systemu plików takiego jak GFS/GFS2 [6] lub OCFS/OCFS2
[7]. DRBD synchronizuje systemy plików na poziomie urządzeń blokowych. Aplikacje
obsługujące sieciowe systemy plików komunikują się między sobą w celu zapewnienia
integralności samych danych.
Jeżeli wystąpi utrata komunikacji między systemami na warstwie sieciowej (split
brain), ważne jest, aby poprawnie zadziałał „fencing”, który odłączy jeden z węzłów.
W przypadku niezależnych zmian systemu plików na obu węzłach po utracie komunikacji konieczna będzie ręczna interwencja. W przypadku poważniejszych awarii może
również dojść do uszkodzenia danych.
Mariusz Drozdziel
20
Rys 6 Zarys architektury DRDB i przebieg zapisu danych
Decyzja wyboru trybu pracy DRBD zależy od specyfiki klastrowanej usługi. Rozwiązanie active-passive wprowadza mechanizmy failover i wysoką dostępność, natomiast tryb active-active umożliwia load balancing usług.
W wielu przypadkach nie jest konieczne synchronizowanie danych w trybie ciągłym. Jeżeli w danym rozwiązaniu sprawdzi się okresowa synchronizacja danych zamiast DRBD można wykorzystać dużo prostsze narzędzia typu rsync. To rozwiązanie
doskonale sprawdza się do synchronizacji samych konfiguracji aplikacji. Nawet jeżeli
elementy usług nie muszą współdzielić żadnych zasobów, warto wprowadzić okresową
synchronizację samych ustawień. Zapewni to integralność konfiguracji i tym samym
bardzo uprości zarządzanie.
Podsumowanie
Pod Linuksem dostępne jest wiele bardzo zaawansowanych i wydajnych rozwiązań
wspierających wszelakiej maści klastrowanie usług. Najtrudniejszym elementem całego procesu budowania klastra jest zaplanowanie i opracowanie rozwiązania, które
będzie adekwatne do konkretnej sytuacji. Aby móc to osiągnąć, trzeba bardzo dobrze poznać dostępne mechanizmy kastrowania i przeanalizować wszystkie aspekty
danego rozwiązania pod kątem konkretnych usług.
Budowanie tanich, wysoko wydajnych. . .
21
Rys 7 Prosty klaster Apache + MySQL ze zrównoważonym obciążeniem
Samo przenoszenie starych usług na klastry niekoniecznie musi się wiązać się
z wprowadzeniem nowych fizycznych serwerów. Czasami okazuje się, że utylizacja
obecnie posiadanych rozwiązań jest bardzo niska. W takiej sytuacji dobry pomysł
i odpowiednie zaplanowanie klastra może zaoszczędzić sporych wydatków. Najefektywniejszym sposobem wprowadzenia do systemu nadmiarowości może być wzajemne kastrowanie usług w obrębie grupy serwerów. W klasycznym przykładzie Apache+MySQL pracujących na odrębnych maszynach można w prosty sposób wprowadzić redundancję. Wystarczy skonfigurować serwer MySQL jako zapasowy serwer dla
Apache, a serwer Apache jako backup dla MySQL. W ten sposób awaria którejkolwiek z maszyn nie spowoduje utraty usługi. Faktyczna utylizacja maszyn (w trakcie
normalnej pracy) nie ulegnie zmiany. Oczywiście dobrych sposobów implementacji
takiego rozwiązania jest bardzo wiele.
Na funkcjonowanie konkretnej usługi często składa się bardzo wiele aplikacji rozmieszczonych na różnych fizycznych serwerach. Projektując klaster należy przede
wszystkim zlokalizować wąskie gardła (bottle necks), czyli te elementy, które zużywają najwięcej zasobów. Przy projektowaniu rozwiązania opartego o load balancing,
najwięcej faktycznych zasobów należy przeznaczyć właśnie na te elementy usługi. Bardzo rzadko zdarza się, że wymagania usług wzrastają na każdym poziomie w takim
samym tempie.
Podobnie podczas wdrażania rozwiązań high-availablity należy zwrócić uwagę,
czy w systemie nie pozostaną pojedyncze punkty awarii. Nawet jeżeli nie ma realnej
możliwości wprowadzenia redundancji każdego elementu nadal warto duplikować
tam, gdzie jest to możliwe. Niepełna redundancja i występujące SPOF (single point
of failure) będą nadal rozwiązaniem lepszym niż brak jakiejkolwiek redundancji.
Wprowadzanie rozwiązań zapewniających wysoką dostępność ma chronić nie tylko przed niespodziewanymi awariami. Często opłaca się wykorzystywać nawet najprostsze rozwiązania. Być może nie gwarantują one zabezpieczenia przed wszystkimi
zdarzeniami, ale przynajmniej pozwalają na ręczne przełączanie węzłów i bezstresowe
prowadzenie prac serwisowych.
22
Mariusz Drozdziel
Literatura
1. Oficjalna specyfikacja protokołu VRRP - RFC2338:
http://www.ietf.org/rfc/rfc2338.txt
2. Strona projektu Linux Virtual Server:
http://www.linuxvirtualserver.org/
3. Strona projektu keepalived:
http://www.keepalived.org/
4. Informacje na temat projektu High Availability Linux:
http://www.linux-ha.org/
5. Strona projektu DRBD: http://www.drbd.org/
6. Informacje na temat systemu plików GFS2:
http://www.redhat.com/gfs/
7. System plików OCFS2:
http://oss.oracle.com/projects/ocfs2/