KAFKA W ŚWIECIE MULTI-TENANT: TY DOSTAJESZ QUOTĘ, I TY DOSTAJESZ QUOTĘ!
Chociaż Kafka nie jest technologią przeznaczoną do trwałego, długoterminowego przechowywania danych, zaprojektowanie bezpiecznej, zgodnej i wydajnej konfiguracji Kafki stwarza swoje własne wyzwania.
BEZPIECZEŃSTWO
Często powtarzam, że uważam Kafkę za protokół komunikacyjny. Mamy swoich consumers i producers, którzy mogą komunikować się ze sobą za pomocą Kafka topics. Jakie są zatem wyzwania, jeśli chodzi o bezpieczeństwo w Kafce?
Upewnienie się, że tylko określeni consumers i producers mają dostęp do konkretnych topics. Można to zrobić za pomocą ACLs – np. w środowisku microservices, można stworzyć użytkownika dla każdego microservice i odpowiednio skonfigurować ACLs, aby usługa mogła consume’ować/produkować z/do konkretnych topics. Podobnie, można to wykorzystać do rozdzielenia na poziomie środowiska – dev, stg i prod otrzymałyby własnych użytkowników i ACLs, aby zapewnić separację danych między etapami.
Tenant message encryption – podczas gdy w świecie single-tenant prawdopodobnie zaszyfrowałabym ruch do Kafka w transporcie i sam wolumen EBS, musiałabym pójść o krok dalej i zaszyfrować rzeczywisty payload wiadomości dla każdego tenant – co oznacza, że zarówno consumer, jak i producer musieliby mieć dostęp do klucza, aby zapisać lub odczytać wiadomość. Jeśli latency jest dużym problemem w systemie, należy uwzględnić czasy enkrypcji/dekrypcji w obliczeniach.
SPORY O ZASOBY
Spory o zasoby są, z mojego doświadczenia, najczęstszą przeszkodą w zarządzaniu multi-tenant Kafką. Kilka strategii zarządzania nimi obejmuje:
QUOTAS
Quotas są bardzo skutecznym, choć skomplikowanym mechanizmem w Kafka. Najczęstsze to network bandwidth quotas (ograniczające producers i consumers pod względem maksymalnej przepustowości danych) oraz request rate quotas (wyrażone jako procent network i I/O threads, zapobiegające przeciążeniu brokerów zbyt wieloma żądaniami).
Obie są ustawiane dla każdego użytkownika na każdym brokerze.
Network bandwidth quotas będą ograniczone np. przez typy instancji AWS. Tj. przez EBS i Network bandwidth. Przepustowość EBS jest tutaj kluczowa, ponieważ Kafka bardzo zachłannie zapisuje na dysk. Np. dla rg6.large i rg6.2xlarge, suma wszystkich producer i consumer byte rate quotas dla wszystkich użytkowników podłączonych do Kafka cluster nie może przekroczyć 4750Mi.
Request rate quotas są trudniejsze i będą zależeć od liczby network i I/O threads skonfigurowanych w klastrze. Request rate quotas ograniczają procent czasu, przez jaki klient może używać request handler i network threads każdego brokera podczas określonego przedziału czasowego. Jest to obliczane za pomocą następującego wzoru: ((num.io.threads + num.network.threads) * 100)%. Na przykład, jeśli mamy 3 I/O threads i 8 network threads, ta wartość w klastrze wyniesie 1100% ((3+8)*100%). Zatem 1100% będzie wartością, którą możemy rozdzielić między użytkownikami na każdym brokerze.
Quota, którą otrzyma każdy użytkownik, nie dyktuje ich użycia – jest to górna granica, której nie będą mogli przekroczyć, co pozwala nam na zarządzanie i zapobieganie zakłóceniom ze strony noisy neighbors.
Istnieją różne strategie wdrażania quotas, i nie ma jednego podejścia. Zależy to od przewidywanego użycia i krytyczności każdego klienta. W świecie microservices, gdzie każda z usług ma równe prawa do Kafki, najlepszym podejściem byłoby równe rozdzielenie quotas między wszystkie usługi (chyba że uznajemy konkretną usługę za bardziej krytyczną niż pozostałe). Wyzwania pojawią się, gdy dołączą nowe usługi, ponieważ quotas potencjalnie będą musiały zostać przeliczone dla wszystkich.
Jeśli system jest multi-environment zamiast multi-tenant (tj. jeden klient końcowy używa systemu, a wszystkie jego typy środowisk, takie jak dev, stg i production, korzystają z tej samej infrastruktury), sugeruję rozważyć nie wiązanie produkcji z żadnymi quotas, decydując się jedynie na ograniczenie niższych środowisk. W ten sposób, jeśli produkcja klienta potrzebuje więcej zasobów, będzie to widoczne w metrykach serwera Kafki zamiast w request throttling.
ODDZIELNE KLASTRY DO OBSŁUGI OBCIĄŻEŃ DEV & STG VS PROD
Innym podejściem jest rozdzielenie klastrów według typu obciążenia – tzn. przydzielenie produkcji własnego klastra, a niższe typy środowisk pozostawienie na innym klastrze. Wady tego podejścia obejmują zwiększone koszty i nieco inne środowiska niższych poziomów niż produkcja, więc jeśli chcemy, aby testy były jak najbardziej zbliżone do rzeczywistości, to może nie być najlepszym rozwiązaniem.
ZŁOŻONOŚĆ OPERACYJNA
Wszystko powyższe wpływa na złożoność operacyjną. Jest też kilka innych czynników.
UPGRADES
W Kafce, upgrade’y z reguły są dość bezbolesne. Klienci mogą używać starszej wersji klienta Kafki niż wersja serwera Kafki. Kafka jest niesamowicie kompatybilna wstecz. Kiedy po raz pierwszy zaczynałam pracować z Kafką, przeprowadziłam test z moim zespołem, aby sprawdzić upgrade’y po zmianie API/protocolu, która nastąpiła w wersji 0.10. Testowaliśmy upgrade z Kafki 0.9.0.1 do 2.7.0, podczas gdy producenci nadal zapisywali do topików, a consumerzy nadal z nich czytali. System był całkowicie stabilny, i wszyscy nadal mogli zapisywać i czytać wiadomości.
Mimo to, choć wszystko działa, nie ma gwarancji, że wszystko będzie działać szybko. Na przykład podczas jednego z incydentów odkryliśmy, że kilku consumerów używało starszego klienta Kafki z naszym nowszym serwerem Kafki. Wiadomości były przetwarzane, ale widzieliśmy dziwne lagi, dodające czasem nawet sekundę do całkowitego czasu przetwarzania. Przy aktualizacji multi-tenant Kafka klastra do nowszej wersji zatem trzeba rozważyć, jak każdy tenant będzie musiał być skoordynowany w celu aktualizacji swojego klienta.
OBSERVABILITY
Dodatkowym czynnikiem, który sprawia, że multi-tenancy w Kafce jest bardziej wymagająca, jest observability. Oprócz regularnego monitorowania metryk klienta i serwera (np. metryki brokerów oraz producentów/consumerów), warto zbudować dashboardy specyficzne dla tenantów oraz dashboardy monitorujące quotas. Idealnie, dashboard specyficzny dla tenanta powinien zawierać dane ze strony klienta (tj. aby zobaczyć, ile czasu zajmuje przetwarzanie wiadomości z perspektywy klienta) oraz ze strony serwera (ile czasu serwer faktycznie potrzebuje na przetworzenie wiadomości), wraz z metrykami throttling, aby sprawdzić, czy quotas są skonfigurowane zgodnie z użyciem.
CAPACITY PLANNING & BLAST RADIUS
Pytanie, jak będzie wyglądał Kafka cluster pod względem brokerów, jest częstym punktem. Wybór skalowania pionowego lub poziomego to ważna kwestia. Na szczęście, w przeciwieństwie do niektórych innych technologii, skalowanie w dół w Kafce z odpowiednimi replication factor i partition reassignment jest dość łatwe, więc nie trzeba wybierać jednego lub drugiego.
Więc, jak skalować Kafkę? Podobnie jak z quotas, nie ma jednego właściwego podejścia.
Ogólnie rzecz biorąc, Kafka jest zaprojektowana do skalowania poziomego – z Zookeeper, klaster składający się z 500 brokerów może działać normalnie; z Kraft, teoretycznie, możemy skalować do ponad 1000 node’ów. Observability dla takiej liczby brokerów będzie wyzwaniem, więc osobiście nie poszłabym tak daleko bez wyraźnej potrzeby. Powszechny soft limit dla partycji per broker wynosi 4000, więc należy przydzielić odpowiednią liczbę brokerów, aby to pomieścić, pamiętając, że replication factor zwiększy całkowitą liczbę partycji.
W świecie multi-tenant, wszystko, co robimy, będzie miało większy blast radius. Dodając dodatkowych brokerów, ważne jest, aby wziąć pod uwagę obciążenie klastra – podczas dużego obciążenia dodawanie brokerów nie jest dobre, ponieważ nowe brokery nie obsługują jeszcze żądań, a jednocześnie proszą istniejące brokery o wysyłanie im danych. Skalowanie pionowe może być w tym scenariuszu lepsze, gdy potrzebujemy szybkiego zwiększenia wydajności. Niemniej jednak, podczas resize brokera, ten broker stanie się niedostępny na pewien czas, co oznacza mniejszą pojemność, dopóki resize nie nastąpi.
Moją zasadą jest zazwyczaj początkowe udostępnianie większej liczby małych lub średnich node’ów oraz skalowanie w górę pionowo podczas działania, jeśli zajdzie taka potrzeba. Ponieważ quotas są obliczane na broker, daje mi to również wyższą wartość bezwzględną do rozdzielenia między użytkownikami Kafki.