un*x admin's best practices
Wpis ten miał początkowo być wstępem do cfengine, ale poszczególne punkty za bardzo mi się rozrosły żebym jeszcze rozpychał tekst o oryginalny pomysł. cfengine opiszę następnym razem. A tymczasem okazuje się, że dobry unix-admin musi całkiem sporo umieć i powinien zbudować sobie pokaźną infrastrukturę.
Spis treści
- Historia pewnego chaosu
- Punkt pierwszy: użytkownicy
- Punkt drugi: zdrowy sen
- Punkt trzeci: nowe serwery
- Punkt czwarty: nazwy
- Punkt piąty: używaj lustra
- Punkt szósty: ./configure && make
- Punkt siódmy: spójna konfiguracja
- Punkt ósmy: systematyczne sprzątanie
Historia pewnego chaosu
Każdy administrator systemów w pewnym momencie rozbudowuje swoje środowisko o nowe maszyny. Tych maszyn robi się więcej i więcej, ani się obejrzysz i już masz pod opieką kilkanaście systemów i dokładasz kolejne. Serwery baz danych, serwery aplikacji, poczty, Jabbera, webaplikacji, backupu, logów, monitorowania...
Coraz więcej czasu poświęcasz na logowanie się na właściwy serwer i dokładanie cegiełki konfiguracyjnej albo sprawdzanie co było jak zrobione. O, tu mnie jeszcze nie było? Nie mam tu konta ani katalogu domowego? To root i tworzymy co trzeba... Nie ma mojej powłoki? To doinstalujmy... Nie ma tcpdumpa i iftopa? Nie ma lsof, strace, perlowego DBD::mysql? Damn, jak to się wolno ściąga, może ftp.pl.debian.org jednak nie był takim dobrym pomysłem i trzeba było postawić własny mirror repozytorium pakietów? A gdzie się podziały skrypty do sporządzania zrzutów bazy danych? O tutaj, ale która to wersja? Najnowsza aby? Czego one tam wymagały oprócz Pythona? Sprawdzę na innej maszynie, tylko znajdę hasło roota... Pamiętasz jeszcze w ogóle od czego się zaczął ten koszmarny ciąg zadań?
Jeśli twoja codzienna praca administratora przypomina takie bezładne szamotanie się między kolejnymi rzeczami do zrobienia, pora zacząć automatyzować i centralizować co się da. A właściwie to pora już dawno minęła, teraz zostało ci jedynie ratować się przed wypaleniem zawodowym. Bo taki chaos jest bardzo męczący. Zero czasu na rozwój, tylko koszmar debuggowania niedziałających usług.
Punkt pierwszy: użytkownicy
Punktem startowym do zrobienia jest centralizacja zarządzania użytkownikami i grupami. NIS, LDAP -- cokolwiek, byle nie było rozwiązaniem domowej roboty (nie sprawdza się na dłuższą metę). Dobrym pomysłem jest zapewnienie względnej niezależności serwerów (replikacja LDAP). Katalogi domowe w takim środowisku powinny się tworzyć same, w miarę potrzeb -- pam_mkhomedir twoim przyjacielem.
Wraz z tym powinna iść możliwość zalogowania się z twojego rozdystrybuowanego wszędzie użytkownika na roota, żeby wykonać odpowiednie zadania administracyjne. sudo z zezwoleniem dla wybranej grupy będzie dobrym pomysłem. W końcu może ktoś do ciebie dołączy do zespołu?
Punkt drugi: zdrowy sen
Kolejnym przystankiem jest system backupów. To jest konieczność. Kopie zapasowe służą do zapewniania administratorowi spokojnego snu i pracy: cokolwiek zepsujesz podczas prac porządkowych, będziesz mógł to przywrócić do stanu używalności we w miarę przewidywalnym czasie.
Jeśli nie stać cię na napęd taśmowy (czy wręcz zmieniarkę taśm), backup na dysk wystarczy. Na tym etapie nie martwisz się awarią maszyn, tylko omyłkami popełnionymi przez ciebie. Ważne żeby backup wykonywał się automatycznie i wymagał jak najmniej twojej ingerencji. Backup kłopotliwy dla administratora to backup, który jest często pomijany, to z kolei prosta droga do utraty danych.
Tu podpowiedź: backup bezwzględnie zbieraj i trzymaj na dedykowanej maszynie. To może być maszyna wirtualna, byle dobrze zabezpieczona przed przypadkowym jej skasowaniem. Tej maszyny nie ruszasz, z wyjątkiem dodawania zadań i odzyskiwania plików.
A jeśli nie masz pomysłu co backupować, zacznij od /etc/ i listy zainstalowanych pakietów (/var/lib/apt i /var/lib/dpkg pod Debianem). To jest administratorski no brainer. Nie kosztuje wiele zasobów, a bywa bardzo, bardzo przydatny. Zadania dla kolejnych usług będziesz dokładać w miarę postępów prac.
Punkt trzeci: nowe serwery
Do tej pory doszedł ci co najmniej jeden serwer (serwer kopii zapasowych). Przypomnij sobie teraz: co na nim trzeba było zainstalować? (tcpdump! iftop!) Co skonfigurować? (NIS/LDAP! sudo! adresy sieciowe! routing!) Jakie polecenia wydać? (dpkg-reconfigure locales!) W jakiej kolejności? (najpierw wybór mirrora repozytorium pakietów, potem instalacja iftopa)
Spisz to wszystko. To jest twoja procedura instalacji nowych serwerów. Najlepiej spisz to na wiki, bo pierwsza wersja tej procedury z pewnością nie będzie kompletna. Powiem więcej: nawet gdy będzie kompletna, będzie ulegać zmianom. Przecież co jakiś czas trzeba dodać nowe pakiety na wszystkich maszynach albo coś przekonfigurować (np. zmieni się adres serwera DNS albo dodasz software do inwentaryzacji sprzętu). Nie chcesz przecież co jakiś czas się budzić na nowym serwerze bez tego, co na innych maszynach już przecież jest, prawda?
Żebyśmy mieli jasność: procedura ma się dać wydrukować i odkreślać w miarę postępów instalacji. Więcej: drukuj ją i odkreślaj dla każdego serwera. Jeśli cokolwiek ci przerwie instalację, będziesz wiedzieć od którego momentu ją wznowić. Nie czarujmy się, jesteś administratorem i użytkownicy wzywają cię do każdej pierdoły; nie uda ci się za jednym zamachem zainstalować i skonfigurować całego serwera.
Punkt trzeci (a): odzyskiwanie danych
Masz już przygotowane miejsce do trzymania procedur. Pora na drugą procedurę: instrukcję odzyskiwania danych z backupu. Zgadza się, właśnie tak: instrukcję odzyskiwania danych. Po co? Wyobraź sobie że przez niedopatrzenie wyleciała ci w powietrze połowa /etc. Im mniej będziesz się zastanawiać i przypominać sobie, tym lepiej. Wydrukuj sobie tę procedurę i powieś w widocznym miejscu.
Wbrew pozorom instrukcja nie jest takim hop-siup. Musisz wiedzieć w pierwszym rzędzie jakim poleceniem wybrać pliki do odzyskania, jak nastawić miejsce, gdzie pliki wylądują (serwer i katalog na serwerze) i jak je skopiować z powrotem. Owszem, czasem wystarczy po prostu skopiować pliki. Ale czasem będzie trzeba je jakoś importować albo zarejestrować (np. skrzynki Cyrus IMAP-a tak mają; zwykle też trzeba to zrobić zrzutom baz danych, jak MySQL, PostgreSQL czy LDAP). No i prawie zawsze trzeba zrestartować serwis, którego operacja dotknęła. A czasem nawet kilka serwisów. W instrukcji masz mieć spisaną procedurę dla każdego zadania backupowego, choćby lakoniczne "skopiować pliki na miejsce; nic więcej nie trzeba robić".
Punkt czwarty: nazwy
W miarę możliwości postaw własny serwer DNS. Każdemu serwerowi przypisz rekord A odpowiadający jego nazwie.
Unikaj nadawania serwerom nazw wprost wskazujących przeznaczenie. Nie chodzi o względy bezpieczeństwa (zresztą to by było tylko urojone bezpieczeństwo). Serwery mają tendencję do gromadzenia większej niż początkowo zakładana ilości usług. Nagle się okazuje że serwer pocztowy pal sześć, ważniejszy jest LDAP który tam stoi. Co odpowiesz na pytanie "gdzie znajduje się LDAP"? Bo przecież nie "na mail.nabla.net". Lepiej: "na serwerze szafir".
Z drugiej strony usługi mają tendencję do wędrowania między serwerami i może się okazać, że ldap.nabla.net jest serwerem plików, główna instancja LDAP stoi na mail.nabla.net, a poczta jest serwowana przez samba.nabla.net. Lepiej oddziel nazwy serwerów od ich funkcji.
Nazwy serwerów to jedno, ale do usług trzeba się jakoś dostać.
- Po pierwsze: nie stosuj adresów IP. Używaj nazw DNS.
- Po drugie: nigdy, przenigdy nie stosuj adresów IP.
- Po trzecie: nie używaj nazw serwerów. Nie po to były oddzielane od nazw serwowanych usług żeby je teraz mieszać.
No OK, ale co w zamian? Dla każdej usługi dodaj rekord DNS typu CNAME (albo przynajmniej A; dla poczty na przykład nie wolno używać CNAME) wskazujący na serwer, który tę usługę świadczy. Używaj CNAME kiedy się da. Gdy przyjdzie do lokalizowania usługi wystarczy że odpytasz DNS, on ci rozwiąże alias do nazwy serwera, a nazwę do adresu IP. Masz dwa za jednym zamachem: ustalenie który to serwer i poznanie adresu usługi.
Nawet awaryjne postawienie usługi na innym serwerze będzie łatwe. Wystarczy że zmienisz wpis w DNS i już można korzystać z tymczasowego serwera.
A pamiętasz o backupie stref DNS?
Punkt piąty: używaj lustra
Postaw lokalny mirror repozytorium pakietów, przynajmniej tego używanego do instalacji serwera. Przestrzeń dyskowa jest względnie tania. Łącze wprawdzie też, ale twój czas już nie. Zyskasz również możliwość zadbania o to żeby wszystkie maszyny miały tę samą wersję pakietów: to ty przecież kontrolujesz częstotliwość uaktualnień mirrora. A jeśli adres, z którego sporządzasz mirror, przestanie być aktywny -- zmieniasz wszystko tylko w jednym miejscu.
Przypominam, że tej usłudze przysługuje osobna nazwa, niezależnie od serwera na którym wyląduje.
Punkt szósty: ./configure && make burdel
Jednym z większych grzechów administratora jest pomijanie systemu pakietów. Instalacja programów przez własnoręczną kompilację to Zło[tm]. Poprawną metodą jest instalacja pakietu; w Debianie to będzie polecenie dpkg -i. Widzisz jaka to wersja jest, widzisz jakie toto ma zależności od innych pakietów, możesz pakiet usunąć nie obawiając się że zostawi jakieś śmieci po sobie. Podczas reinstalacji maszyny albo stawiania drugiej takiej samej szybciej będzie ci zainstalować pakiet niż kompilować wszystko od początku.
Że co proszę? W dystrybucyjnym repozytorium pakietu nie ma albo jest za stary? To zbuduj sobie pakiet z nowszą wersją -- ale zbuduj pakiet. Możesz się posłużyć źródłami pakietu dystrybucyjnego, to zwykle dobry punkt startowy. A myślisz że jak się pakiety dostały do repozytorium? Nie spadły z nieba, ktoś je zbudował.
To naprawdę procentuje. Aktualizacje w przyszłości będą prostsze, zwłaszcza jeśli masz zachowany pakiet źródłowy (*.src.rpm dla Red Hata, *.dsc i okolice dla Debiana).
Punkt szósty (a): własne repozytorium
Gdy już masz własne pakiety, zacznij się zastanawiać co zrobić, żeby te pakiety instalowało się tak samo jak dystrybucyjne. Czyli: jak zrobić własne repozytorium z pakietami. Przecież nie będziesz kopiować tej samej paczki na kilkanaście różnych serwerów, prawda? Mnie by się nie chciało. Poza tym yum i apt-get same pociągną ewentualne zależności pakietu. To też ważne. Uruchamianie apt-get install dla każdego z ośmiu pakietów wymaganych przez twój foo_1.0-1_all.deb jest uciążliwe.
Punkt siódmy: spójna konfiguracja
Masz już masę serwerów. Prawdopodobnie na każdym masz MTA (Exim, może Postfix albo ssmtp), wszędzie jest NIS/LDAP, serwer SSH, sudo, syslog, klient systemu backupów... Dużo tego, zwłaszcza przemnożone przez ilość instancji.
A teraz dodaj wszędzie opcje AcceptEnv ORIGIN_HOST do sshd_config i SendEnv ORIGIN_HOST do ssh_config.
Pewnie zaczniesz od pętli for, ale to rozwiązanie ma krótkie nogi. W pewnym momencie okaże się że pisanie skryptów seda jest mało wygodne (zwłaszcza przy nieznanym stanie konfigów), za którymś razem trzeba skopiować kilka plików na maszyny docelowe, a tobie niezbędny się okaże terminal interaktywny żeby uruchomić normalny ekranowy edytor do wprowadzenia zmian.
Prawdopodobnie znajdziesz ClusterSSH, ale to wystarczy na góra dziesięć maszyn (ileż można mieć terminali naraz otwartych?) i działa tylko dla usługi, która ma bardzo podobne konfigi na wszystkich maszynach (kursor w edytorze musi się znaleźć w odpowiednim miejscu -- i jeszcze musisz sprawdzić czy aby na pewno wszędzie jest tam gdzie trzeba).
Co ci jest teraz potrzebne, to centralizacja: system dystrybucji plików konfiguracyjnych i system szablonów do generowania tych plików.
Punkt siódmy (a): dystrybucja konfigów
Do wyboru masz dwa: cfengine i Puppet. Dla Debiana 5.0 oba znajdują się w oficjalnym repozytorium (cfengine jako cfengine2). Pakiety dla Red Hat Enterprise Linux znajdziesz w repozytorium RPMforge.
Tak naprawdę jest jeszcze bcfg2, ale konfiguracji oczekuje w XML-u, co go dyskwalifikuje. Ten format ledwo się nadaje do formatowania tekstu, a używa się go gdzie popadnie.
cfengine i Puppet służą w pierwszym rzędzie do kopiowania plików z serwera, do kopiowania plików na miejsce robocze (to nie to samo!), do przeładowywania usług, których konfigi się zmieniły i do instalacji potrzebnych pakietów. Potrafią wprawdzie nieco więcej, ale na razie tyle ci wystarczy. Chociaż jeśli o kopiowanie z centralnej kopii konfiguracji chodzi, to poradzimy sobie inaczej.
Z dwóch wymienionych osobiście wolę cfengine. Puppetowi musisz z góry powiedzieć czego się spodziewasz po maszynie ("tu i tu ma się znajdować Fcron; dodaj symlink /usr/bin/crontab wskazujący na fcrontab"), natomiast cfengine potrafi wykryć co trzeba i poradzić sobie ze stanem zastanym ("jeśli Fcron jest zainstalowany, to dodaj symlink /usr/bin/crontab wskazujący na fcrontab"). Oczywiście cfengine'owi można też nakazać instalację ("na tej maszynie ma być serwer LDAP"). Po prostu masz wybór.
Punkt siódmy (b): generowanie konfigów
Na potrzeby pracy sporządziłem jakiś czas temu system szablonów oparty o Perla, YAML i Template Toolkit. Zasada działania jest prosta: w plikach *.yaml trzymasz parametry specyficzne dla hostów, a szablony te parametry wykorzystują. Skrypt służy do wypełnienia szablonów parametrami.
Niestety nie znam żadnego gotowego narzędzia do tego (inaczej zresztą bym go użył zamiast pisać własne), a obecnej wersji cfgena brakuje przyjaźniejszej instrukcji obsługi.
Tak czy owak, generator konfiguracji jest ci potrzebny. Możesz poszukać czegoś lepszego od cfgena, możesz napisać własny, możesz też przegryźć się przez kod cfgena i przykładowe szablony. Bo chyba nie masz zamiaru edytować ręcznie konfiguracji dla kilku (nastu?) serwerów?
Punkt siódmy (c): system kontroli wersji
Weź przykład z zawodowych programistów: szablony i zmienne trzymaj w systemie kontroli wersji. Po co?
- każda zmiana będzie opatrzona datą ("od dwóch dni nie dochodzi do mnie poczta" -- a potem zgaduj co było wtedy zmieniane...)
- każda zmiana będzie opatrzona opisem co i po co robi (łatwo będzie ją wycofać, powtórzyć w innej instalacji albo pokazać komuś)
- każda zmiana będzie opatrzona autorem (jeśli adminów jest więcej niż jedna sztuka, to pozwoli ustalić kogo kopać w d*** za zepsucie usługi)
- pamiętane są wszystkie zmiany, więc dostajesz automatycznie backup, tylko o drobniejszej granulacji niż zwykle (repozytorium oczywiście też backupuj! to na pewno nie zaszkodzi)
- przypadkowe usunięcie szablonu lub pliku ze zmiennymi dla hosta skutkuje utratą zmian najwyżej od ostatniego commita
System kontroli wersji w podstawowym użyciu nie robi wiele więcej niż kopia na boku, ale jest o niebo wygodniejszy, głównie przez zapisanie całkiem sporej ilości danych (czas, autor, zmiany od wersji poprzedniej), wszystko za jednym krótkim poleceniem.
Ja najbardziej lubię gita, ale Mercurial, Subversion czy nawet od biedy CVS też się nadadzą (choć ostatniego nie polecam, bo ma topornego klienta).
A teraz sztuczka: system kontroli wersji, o ile jest zabezpieczony przez protokół SSL/TLS (git, Mercurial i Subversion pozwalają na to bez problemu) i uwierzytelnianie klienta (np. kliencki certyfikat X.509 albo para login+hasło), może zostać użyty do dystrybucji plików konfiguracyjnych (to oznacza, że pliki wygenerowane z szablonów również powinny się znaleźć pod kontrolą wersji). Z crontaba może się uruchamiać zadanie aktualizujące kopię roboczą z konfigami (a sam wpis może przecież dodać cfengine!), a cfengine będzie się zajmować aplikowaniem nowych ustawień, jeśli któreś pliki się zmieniły.
Punkt siódmy (*): komentarze
Z mojego doświadczenia wynika, że wygodniej jest trzymać wszędzie jak najbardziej podobną konfigurację, w miarę możliwości taką samą. Jeśli usługa pozwala rozróżniać fragmenty konfiguracji przysługujące takiemu lub innemu hostowi -- skorzystaj z tego. Dobrym przykładem są sudo i sam cfengine. Jeżeli systemowi dystrybucji konfiguracji cokolwiek się stanie, możesz skopiować konfig z innej maszyny i będzie działać bez większych zmian. Może się też okazać, że będziesz potrzebować porównać konfigi. Jeśli będą identyczne albo będą występować dwie-trzy grupy identycznych konfigów, wystarczy ci jeden rzut okiem na md5sum.
Nie jest to jakoś specjalnie niezbędne, ale czasem się przydaje.
Punkt ósmy: systematyczne sprzątanie
Teraz, skoro już masz generator i dystrybutor konfigów, możesz obejmować systemem kolejne usługi, które masz pod opieką. Cokolwiek pojawia się na więcej niż jednej maszynie, powinno być konfigurowane z tego samego miejsca! Dzięki temu i dołożenie kolejnej instancji będzie łatwe, i odzyskanie instalacji po awarii będzie łatwiejsze.
Dobrze zrobisz od razu dokładając zadanie backupu dla takiej usługi. Przecież może ci coś nie wyjść, ręka się omsknie i skrypt restore.sh skasuje ważne dane.
Na koniec podpowiem ci kapitalną rzecz. Możesz praktycznie całą procedurę instalacji serwera opisać jako reguły systemu zarządzania konfiguracją! Genialne, prawda? Niech automat przygotuje wszystko co trzeba, ty później tylko sprawdzisz czy działa (checklista!).
Wysłany: 05 czerwca 2010, 01:50:38; 17 komentarzy