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/