Audytowanie baz danych w The Grid
Opublikowany: 2018-09-29Ponieważ firma SendGrid niedawno stała się spółką notowaną na giełdzie, musieliśmy mieć pełne dzienniki kontrolne wszystkich zmian w podzbiorze naszych baz danych. Ten podzbiór obejmował kilka małych wystąpień, w których nie odnotowano dużego ruchu, ale także niektóre starsze klastry, które mają krytyczne znaczenie dla czasu działania naszego portalu klienta i przepływu rejestracji.
Wpłynęło to również na niektóre magazyny danych, które miały wysokie wymagania dotyczące czasu pracy, a wdrożenie online (bez przestojów związanych z zapisami) było pożądane. Mając pod ręką termin zewnętrzny i znając zakres projektu, przystępujemy do opracowania planu.
W fazie planowania zidentyfikowaliśmy kilka otwartych pytań, na które potrzebowaliśmy odpowiedzi:
- Jakie mamy opcje, jeśli chodzi o oprogramowanie, które to potrafi?
- Jaki wpływ na wydajność jest oczekiwany i jak bardzo możemy to wcześniej przetestować?
- Czy możemy to zrobić bez przestojów związanych z dostępnością zapisu?
Wybory, wybory
W SendGrid śledzimy proces projektowania planu dla każdego dużego projektu lub projektu międzyzespołowego. W projekcie tym uczestniczyło wiele zespołów jako interesariuszy, w tym:
- Audyt Wewnętrzny jako zespół odpowiedzialny za określenie, który magazyn danych jest objęty zakresem kontroli zgodności i za zbieranie dowodów w czasie audytu
- InfoSec jako zespół, który miał analizować i obsługiwać reakcje na incydenty pochodzące z tych dzienników audytu bazy danych
- DB Ops jako zespół piszący kod, który wdraża, zarządza i dostraja tę nową funkcję do baz danych w zakresie
Postanowiłem napisać ten projekt i upewnić się, że został przejrzany przez wszystkich interesariuszy i zatwierdzony przez nasz zespół ds. architektury. Mimo że kilka lat temu przeprowadziłem pewne badania na temat logowania audytowego w MySQL i miałem pewne pojęcie o tym, jak wygląda krajobraz opcji, nie chciałem podchodzić do projektu z uprzedzeniami i chciałem nadal zbadać więcej niż jeden i przedstawić wszystkim solidne uzasadnienie, dlaczego mielibyśmy wybrać jedno rozwiązanie, a nie inne.
Ten plan był niezwykły, ponieważ jednocześnie pisałem go, badając, jakie będzie rozwiązanie potrzeby biznesowej. Wiedziałem więc, że wiele szczegółów zostanie uzupełnionych, gdy przeprowadziliśmy pewne badania.
Nasze opcje to:
- Wtyczka audytu Percona
- Audyt McAfee MySQL
Chociaż nie są to jedyne opcje na rynku, uważaliśmy, że są one najbliższe naszej skali i praktykom rozwoju, które uzasadniają uwzględnienie w faktycznym wypieku. Inne opcje komercyjne na rynku nie przekroczyły tego progu, aby zostać uwzględnione w benchmarku.
To ostatnie było nowszym rozwiązaniem, które zostało niedawno otwarte przez firmę McAfee i było wystarczająco intrygujące, aby się temu przyjrzeć, ponieważ twierdziło, że obsługuje filtrowanie na poziomie tabeli, czego nie obsługuje wtyczka Percona. Ponieważ wiedzieliśmy, że jeden z naszych klastrów w zakresie rzeczywiście musi przeprowadzić audyt około 24 tabel z łącznej liczby 300, wydawało się, że jest to wystarczająco cenna funkcja, aby uczynić z wtyczki Mcafee rywala.
Z drugiej strony wtyczka Percona Audit była najczęściej używanym rozwiązaniem open source dla tej funkcji. Jest wbudowany, ale wyłączony w Percona Server - którego już używamy. Jednak nie zapewnia filtrowania zdarzeń na poziomie tabeli, co oznaczało, że musieliśmy to zrobić poza warstwą bazy danych.
Pieczenie
Z pomocą naszego zespołu partnerskiego w Pythian rozpoczęliśmy porównanie wypieków. Najpierw porównaliśmy, jak zainstalować i dostroić każdą opcję. Zespół szybko ustalił, że mamy kompromis. Chociaż wtyczka McAfee obsługiwała filtry tabel natywnie, nie obsługiwała używania rsyslog jako metody przesyłania strumieniowego swoich zdarzeń. Oznaczało to, że gdybyśmy mieli go użyć, musielibyśmy zapisywać pliki lokalnie na dysku i musielibyśmy zarządzać wysyłaniem ich do stosu monitorującego.
Uznano to za niepożądane, ponieważ najprawdopodobniej zwiększyłoby to spadek wydajności związany z używaniem wtyczki audytu. Zapisywanie zdarzeń audytu lokalnie, a następnie odczytywanie ich ponownie przez osobny proces zabiera pojemność IOPS z naszego rzeczywistego ruchu produkcyjnego i zwiększa ryzyko dla instancji bazy danych, ponieważ oznacza to, że musimy zarządzać rozmiarem tych plików na dysku, aby nie rozdęły się i spowodowały powstanie bazy danych przestój.
Z drugiej strony kompromisem był plugin Percona. Obsługuje wysyłanie zdarzeń do syslog natywnie, ale nie oferuje żadnych filtrów tabel. Wiedzieliśmy, że oznacza to, że bardziej zajęte klastry w zakresie wyślą dużą liczbę zdarzeń, z których większość nie pochodzi z tabel, które chcemy kontrolować. Stanowiło to zagrożenie dla warstwy syslog-receive/logstash stosu monitorowania InfoSec. Ponieważ DB ops nie ma do tego dostępu, oznaczało to, że sukces tego projektu był wspólnym przedsięwzięciem.
Ostatecznie zdecydowaliśmy się na użycie rozwiązania z mniejszą liczbą ruchomych części i zaplanowaliśmy wdrożenie, aby jak najszybciej wiedzieć, czy logstash wymaga skalowania, aby obsłużyć filtrowanie tysięcy zdarzeń na sekundę. Podjęto więc decyzję, aby przejść do przodu z wtyczką audytu Percony.
Planowanie wdrożenia
Zakres instalacji
Zdecydowaliśmy się na uproszczenie tego wdrożenia, instalując i włączając wtyczkę na wszystkich węzłach w danym klastrze, co oznaczało, że wyeliminowaliśmy potrzebę organizowania włączania i wyłączania funkcji audytu w przypadku zmiany węzła zapisującego w klastrze. Nie mieliśmy żadnych obaw, że strumień replikacji powoduje zduplikowane zdarzenia po zastosowaniu zmiany, ponieważ wtyczka z założenia nie rejestruje zmian strumienia replikacji.
Brak przestojów
Chcieliśmy, aby było to bezproblemowe wdrożenie bez przestojów w klastrach, których dotyczy problem. To znacznie zmniejszyłoby ilość planowania i orkiestracji, które musielibyśmy wykonać w zespołach dostawczych korzystających z tych klastrów i znacznie zmniejszyłoby wpływ na klienta. Chcieliśmy jednak również, aby wtyczka wysyłała swoje zdarzenia do rsyslog, w określonym obiekcie, z niestandardową konfiguracją, która wysyłałaby zdarzenia do serwera agregacji syslog zespołu InfoSec. Niektóre z tych konfiguracji są udokumentowane jako niedynamiczne przez Perconę, co przedstawia możliwość, że każda instancja w zakresie tego projektu będzie wymagała pewnego przestoju, gdy ponownie uruchomimy instancję mysql z wymaganą konfiguracją wtyczki audytu.
Rozpoczęliśmy testowanie różnych kolejności działania we wdrażaniu wtyczki z dedykowaną instancją testową w naszym środowisku pomostowym i byliśmy w stanie pokazać, że gdybyśmy mieli nasze zarządzanie konfiguracją, najpierw położyliśmy wszystkie niezbędne konfiguracje, a następnie uruchomiliśmy polecenie ładowania wtyczki , które uruchom z żądaną konfiguracją.
Okazało się to kluczowe zarówno w uproszczeniu planu ukończenia tego projektu, jak i skróceniu czasu do wydania go w środowisku produkcyjnym, dając nam czas na dopracowanie filtrowania zdarzeń i współpracę z zespołem ds. bezpieczeństwa nad analizą i wykrywaniem.
Użyj zarządzania konfiguracją
Używamy książek kucharskich szefa kuchni do zarządzania naszymi bazami danych, więc oczywiście planowaliśmy użyć szefa kuchni do wdrożenia, dostrojenia i monitorowania wtyczki audytu. Ale ponieważ musiało to być włączone tylko w podzbiorze naszych klastrów, oznaczało to, że potrzebowaliśmy sposobu kontrolowania tego, gdzie jest włączone, aby nie obciążać naszego magazynu dzienników danymi, które nie są związane z naszym celem biznesowym.
Do zarządzania bazami danych MySQL używamy modelu wrappera do zarządzania konfiguracją. Podstawowa „podstawowa” książka kucharska definiuje większość tego, jak instancja bazy danych powinna wyglądać, a następnie książka kucharska dla klastra obejmuje to, aby zmodyfikować atrybuty lub dodać konfigurację, gdy jest to istotne dla konkretnego klastra. Ten projekt ułatwił dodanie większości kodu, który tworzyłby potrzebne pliki konfiguracyjne, a następnie ładowanie wtyczki w jednym nowym przepisie, który możemy następnie włączać i wyłączać na podstawie atrybutu szefa kuchni. Biorąc pod uwagę zakres wprowadzanych przez nas zmian, zdecydowaliśmy również, że uzasadnia to wydanie tego kodu jako nowej, mniejszej wersji książki kucharskiej.
Upewniliśmy się również, że szef kuchni usunął wszelkie powiązane kontrole sensu i wyłączył strumieniowanie audytu, gdy atrybut ma wartość false. Miało to na celu zapewnienie, że szef kuchni może postąpić właściwie, jeśli klaster zostanie uznany za nie objęty zakresem lub będzie musiał zostać zatrzymany z jakiegoś nieciągłego powodu, więc nie musimy ręcznie zmieniać węzła, aby odzwierciedlić zmianę atrybutu.
Monitorowanie
Nie możesz zadeklarować sukcesu czegoś, czego nie monitorujesz. Ale również monitorowanie to coś więcej niż tylko poklepywanie niektórych kontroli sensu bez zastanawiania się, w jakich przypadkach awarii monitorujemy i jakich działań oczekujemy w odpowiedzi na niepowodzenie tych kontroli. Postanowiłem więc zaplanować monitorowanie w tym rurociągu, mając na uwadze 2 rzeczy
- Wszyscy musimy uzgodnić wyraźny zakres własności w tym systemie, zwłaszcza że obejmuje on obowiązki 2 zespołów z oddzielnymi rotacjami na wezwanie
- Wszelkie nowe kontrole dodane w tym celu muszą być dostarczane z elementem runbook, do którego prowadzimy link w czeku, wyjaśniając, dlaczego to sprawdzenie kończy się niepowodzeniem i jak to naprawić
Biorąc pod uwagę te 2 zasady, zacząłem dodawać bardzo szczegółowe kontrole. W tym momencie rozważałem również dodanie kompleksowego sprawdzania „syntetycznego”, ale od tego czasu powstrzymałem się od tego, ponieważ sprawdzanie od początku do końca nie powiedzie nam dokładnie, która część systemu zawiodła, co oznacza, że będziemy mieli trudne czas nawet wywołać nim odpowiedni zespół. I nie jestem zwolennikiem przywoływania ludzi w nocy „na wszelki wypadek”
Postanowiliśmy monitorować pod kątem:
- Sprawdź na żywo konfigurację mysql wtyczki audytu, aby upewnić się, że
- Wtyczka była w stanie aktywnym
- Audit_log_policy została ustawiona na QUERIES
To sprawdzenie potwierdza, że konfiguracja bazy danych w zasięgu nie została zmieniona w locie, ponieważ te ustawienia są dynamiczne i mogą ulec zmianie poza plikiem my.cnf na dysku .
- Sprawdź port, na którym wysyłamy logi do stosu monitorowania, aby upewnić się, że dane przepływają. Zasadniczo upewnienie się, że drugi koniec strumienia syslog działa. Ta kontrola jest obsługiwana jako to, co sens nazywa sprawdzeniem zbiorczym , więc nie powoduje nadmiernego stronicowania zespołu InfoSec
Przeszkody po drodze
Audyt konfiguracji wtyczki
Jedna z początkowych iteracji tego projektu miała na celu wykorzystanie funkcji audit_log_exclude_commands do ograniczenia emitowanych przez nas zdarzeń tylko do manipulacji danymi lub schematem. Szybko dowiedzieliśmy się, że lista, na której opiera się ta konfiguracja, jest znacznie dłuższa, niż można by się spodziewać.
konfiguracja rsysloga
Oto coś, czego nie wiedziałem przed tym projektem. Konfiguracja Rsyslog jest prawie własnym językiem. Na przykład:
- Użyj sekundy @ przed zdalnym miejscem docelowym, aby wysyłać logi przez TCP zamiast UDP. Chcieliśmy wykorzystać tę funkcję, aby dać nieco większą gwarancję, że logi są dostarczane.
- rsyslog ma dedykowaną stronę , jak skonfigurować go do niezawodnego przekazywania, co okazało się bardzo przydatne dla nowicjusza tego narzędzia, takiego jak ja.
- rsyslog domyślnie przesyła również swoje dane do /var/log/messages , co w moim przypadku było niepożądane, ponieważ jest to DUŻO zdarzeń. Jeśli chcesz, aby funkcja, której używasz, NIE robiła tego, musisz dodać local5.* ~ na końcu swojej konfiguracji
Wiertarka przeciwpożarowa
Później opowiem o wpływie na wydajność baz danych w zakresie, ale ponieważ rsyslog był używany jako kluczowa część tego projektu, musieliśmy również sprawdzić, jak zachowywałby się rsyslog, gdy jego zdalne miejsce docelowe nie jest dostępne lub nie odpowiada. Najlepszym sposobem, aby to zrobić, było spowodowanie zakłócenia tej komunikacji przy użyciu reguł iptables w produkcji w jednej z baz danych w zakresie, o którym wiedzieliśmy, że ma wysoką przepustowość transakcji, a zatem dużą liczbę zdarzeń audytu na sekundę. Oto jak przebiegło to ćwiczenie przeciwpożarowe.
- Potwierdź, że zdarzenia audytu przepływają przez wyznaczony port TCP
- Użyj reguły iptables, aby odrzucić cały ruch na tym porcie /sbin/iptables -A WYJŚCIE -p tcp –dport {NUMER-PORTU TUTAJ} -j DROP
- Obserwuj aktywność zapisu na dysku i pliki w skonfigurowanym katalogu roboczym w konfiguracji rsyslog . Nazwy plików będą oparte na ActionQueueFileName obiektu otrzymującego te zdarzenia
Zgodnie z oczekiwaniami pliki rozpoczęły buforowanie w tym katalogu. Zauważyliśmy gwałtowny wzrost aktywności procesorów IOP dysków. Gdy liczba plików, które zdefiniowały nazwę kolejki, została zsumowana do wartości ActionQueueMaxDiskSpace , rsyslog przestał tworzyć te pliki, znormalizowały się operacje we/wy dysku i stało się jasne, że teraz zrzucamy zdarzenia na podłogę w warstwie rsyslog. Bardziej imponujące było to, że po usunięciu reguły potable rsyslog ponownie wysyłał wszystkie zdarzenia, które buforował na dysk, więc nie mieliśmy utraty zdarzeń dla naszego magazynu analiz, o ile nie przekroczyliśmy rozmiaru buforu. Na podstawie tego eksperymentu dowiedzieliśmy się kilku rzeczy
- rsyslog zachowuje się zgodnie z dokumentacją. Zawsze lepiej to udowodnić eksperymentami z pierwszej ręki
- Najprawdopodobniej będziemy musieli zdefiniować inną przestrzeń dyskową kolejki na klaster w zależności od liczby generowanych zdarzeń. Ponieważ kolejkowanie na dysku zwiększa ryzyko dla pojemności procesorów IOP i pojemności dysku, będziemy musieli co jakiś czas sprawdzać i sprawdzać
W następnym poście opowiem o tym, jakie były nasze obserwacje po wdrożeniu tego projektu do produkcji i co sprawiło, że było to jak najmniej uciążliwe dla produkcji.