Obiecywałem sobie, że napiszę piękny, duży artykuł o cfengine, który będzie wprowadzać czytelnika do wszystkiego: do składni reguł (CFE 2.x), do narzędzi, których używam, do sposobów pracy, a nawet będzie służył za cfengine cheat sheet. Dupa, raczej nic z tego nie wyjdzie. Jestem zbyt leniwy.
W zamian za to stworzę parę mniejszych artykułów. Coś na wzór pisania na wiki: najpierw szkic artykułu, a potem po jednej, po dwie informacje. Małe przyrostowe edycje są zawsze łatwiejsze w przeprowadzeniu niż jeden big bang. Dziś chciałem przede wszystkim pokazać mój model pracy.
Przy czterech setkach serwerów wiadomo, że potrzebny jest jakiś system automatyzacji pracy. Na rynku jest wiele różnych, z których niektóre opierają się na jednoczesnej pracy -- mniej lub bardziej interaktywnej -- na wielu serwerach (ClusterSSH, PSSH, Pdsh), inne na wysyłaniu skryptów na serwery docelowe (Spacewalk, zdaje się że IBM Tivoli), a jeszcze inne na ściąganiu napisanego w dedykowanym języku skryptu ze zdalnego serwera. Popularnymi przykładami są cfengine i Puppet.
Najbardziej udanymi są (moim zdaniem) cfengine i Puppet. Są niezawodne i samodzielne. Rozumiem przez to, że operator przygotowuje zestaw reguł do wykonania i wywiesza w Wiadomym Miejscu™ i może zaufać swojej infrastrukturze, że ta wykona zlecone zadania i reguły nie wywalą się na obecności jakiegoś nadmiarowego katalogu. Jest to istotnie różna sytuacja od dystrybuowania skryptów shellowych do wykonania. Skrypty trzeba pisać defensywnie, pamiętając za każdym razem, że nowo tworzony katalog może już istnieć, że komenda cd może się nie powieść i o podobnych, mało ciekawych, a mogących spowodować spore zniszczenia szczegółach.
Skoro mamy niezawodny mechanizm aplikowania plików konfiguracyjnych i wykonywania innych zadań administracyjnych, pora przyjrzeć się zarządzanym serwerom. W wśród czterystu serwerów większość da się przydzielić do grup na podstawie funkcji, jaką serwery pełnią i na podstawie usług, jakie mają włączone. W obrębie grup funkcyjnych zestaw usług będzie podobny, więc operacje do wykonania (zatem i reguły cfengine) nie będą się zbytnio różnić. W obrębie grup usługowych podobne będą pliki konfiguracyjne (jeśli będą miały dużo dużych różnic, to pora zastanowić się, czy na pewno tak powinny wyglądać; to duży kłopot, gdy każdy serwer jest inaczej skonfigurowany).
Konfigi danej usługi będą (powinny być) do siebie podobne na wszystkich serwerach. Mogą się różnić szczegółami, ale będą miały podobną strukturę. Dlaczego by nie zastosować systemu szablonów i utrzymywać jednego tylko pliku?
W tym miejscu na arenę wkracza cfgen. To narzędzie dostaje listę serwerów (poszczególne serwery są reprezentowane przez pliki z parametrami) i zestaw szablonów dla poszczególnych usług, a wynikiem jego działania jest zbiór gotowych konfigów, po jednym zestawie dla każdego serwera. cfgen jako języka szablonów używa Template::Toolkita, a parametry serwerów są zapisane w formacie YAML. cfgen posługuje się pojęciem usługi: lista usług oczekiwanych na serwerze jest zdefiniowana w jego parametrach. Tej listy cfgen używa do wygenerowania konfigów (niepotrzebne nie są wypełniane, bo i po co?), a przy okazji dostarcza ją do szablonów, czego można użyć do wypełnienia listy klas w szablonie reguł dla cfengine.
Puppet jest zintegrowany z systemem szablonów ERB. Nie podoba mi się to, ponieważ ERB ma brzydką składnię (przez pociąg rubystów do wsadzania Rubyego gdzie popadnie, również tam, gdzie nie jest to wygodne). Poza tym, skoro to nie jest zewnętrzne narzędzie (jak na przykład jest to zrobione z Facterem), trudno jest je wymienić albo użyć z innym systemem zarządzania serwerami.
Mamy już system dystrybucji konfiguracji (wraz z wykonywaniem operacji na serwerach), mamy system szablonów, mamy listę serwerów z ich parametrami. Przydałoby się teraz zapisać szablony i parametry (które razem wzięte nazywam źródłami) w systemie kontroli wersji. W sumie niegłupim byłoby wersjonować również gotowe konfigi (choć nie jest to niezbędne; każdy punkt w czasie można wygenerować wypełniając szablony parametrami).
Jeśli oba, źródła i gotowe konfigi, znajdują się w różnych repozytoriach, przydatnym będzie narzędzie do przebudowywania zmian. cronbuilder powstał właśnie jako takie uniwersalne narzędzie. Potrafi sobie poradzić z gitem i z Subversion (w dowolnej kombinacji source/destination). Osobiście uważam, że do źródeł lepszy jest git, a do wygenerowanych konfigów SVN.
Serwery zarządzane teraz mogą zostać skonfigurowane tak, żeby używać kopii roboczej repozytorium z gotowymi konfigami. Zysk z tego jest taki, że widać z daleka, która maszyna ma przestarzałe reguły (co jest objawem jakichś problemów). Oczywiście można się też zdać na metodę transportową cfengine.
Przydaje się też parę procedur RPC (xmlrpcd), głównie przy rejestracji nowego serwera w sieci CFE (trzeba mu przecież utworzyć plik z parametrami i wygenerować konfigi). Aktualnie i procedura rejestracji, i skrypt uruchamiany na rejestrowanym serwerze są napisane specjalnie dla mojej sieci, ale przynajmniej skrypt mam zamiar przepisać jako bardziej uniwersalne narzędzie.
Na koniec przydałby się system zbierania informacji o zadaniach wykonanych na poszczególnych serwerach. Wprawdzie cfengine jest całkiem samodzielny, ale przecież zdarzają się problemy, z którymi sobie nie poradzi. Napisałem zestaw skryptów i procedur XML-RPC do transportowania logów audytowych cfengine, ale to nie jest eleganckie rozwiązanie. Lepszym pomysłem jest Fluentd, daemon służący do transportu logów. Niestety nie znalazłem go w momencie pisania systemu -- stąd sznurek i taśma klejąca, ale planuję zastąpić moją konstrukcję gotowym klockiem. W każdym razie, logi lądują w bazie danych, skąd są wyciągane w postaci raportów (domowej roboty narzędzie webowe).
Podsumujmy:
- mam listę znanych serwerów
- każdy serwer ma listę usług, których się po nim oczekuje (i parametrów dla tych usług)
- każdej usłudze przysługuje zestaw plików konfiguracyjnych (a raczej szablonów) i reguł cfengine
- zmiany w szablonach i parametrach są rejestrowane w systemie kontroli wersji
- z wykonania reguł logi są zbierane i agregowane w bazie danych, skąd są wyciągane jako raporty
- mam też (pomysł na) narzędzie do rejestracji serwerów w sieci
Cóż, ledwie opisałem swój pomysł na architekturę systemu, a już zajmuje tyle miejsca. Ile by zajął pełnoprawny artykuł o cfengine?