Migracja bez przestojów w klastrach Azure Kubernetes zarządzanych przez Terraform
tf i dostawcy. Jednak często sytuacja może się posypać jak domek z kart, gdy trzeba zmienić ustawienie, które „wymusza wymianę” podstawowego zasobu, co może skutkować niepożądanymi przestojami i utratą wcześniej zapewnionych zasobów , takich jak publiczny adres IP. Nie zawsze tak jednak powinno być : dzisiaj przyjrzymy się sztuczce, która może zaoszczędzić kilka godzin przestojów i sporo siwych włosów.
Dla mnie takim zasobem był klaster Kubernetes i jego domyślna pula węzłów, którą uruchamiamy na Azure . Jak się okazuje, gdy próbujesz zmienić rozmiar używanych przez niego maszyn wirtualnych , Twój dostawca azurerm zmusza Cię do odtworzenia całego klastra (wraz z zależnymi zasobami) . Jest to coś, czego zazwyczaj chciałbyś uniknąć , zwłaszcza na produkcji. Mimo że w tym artykule skupię się na usłudze Azure Kubernetes , jestem pewien, że można zmodyfikować tę technikę, aby nadawała się również do innych zasobów.
Pierwsze podejscie
Załóżmy , że Twój klaster wyrósł z kilku małych maszyn wirtualnych, które umieściłeś tam na początku. Pierwszą rzeczą, którą spróbujesz zrobić, to zmienić vm_size w konfiguracji terraforma i zastosować go. Dzieje się tak, gdy masz następującą sytuację:
To znaczy , jeśli jesteś uważny . W przeciwnym razie mógłbyś po prostu napisać „tak”, tracąc instancję wraz ze swoimi wdrożeniami, sekretami i wszelkimi danymi, które mogłeś tam przechowywać. Być może wiesz również, że klastry Kubernetes nie są udostępniane zbyt szybko, więc z mojego doświadczenia wynika, że przestój może wynosić 1,5–2 godziny.
Co więcej, mogłeś po prostu stracić coś, co zależało od konfiguracji terraforma, na przykład ten biedny, mały publiczny adres IP:
Może to powodować jeszcze więcej problemów, jeśli Twoje listy dozwolonych nie są zarządzane przez terraform lub po prostu istnieją strony trzecie, które wyraźnie zezwalają na Twoje adresy IP.
Nie możemy tolerować tego rodzaju przestojów we współczesnym świecie, w którym organizacje skupiają się na dostępności przez 99,9% czasu. Zobaczmy więc, jak możemy złagodzić taką irytację!
Możliwe rozwiązania
Istnieje kilka możliwych rozwiązań , które można zastosować, aby zachować zasoby w nienaruszonym stanie. Do najbardziej oczywistych należą :
- Zachowaj domyślną pulę węzłów, tworząc osobne o wymaganej wielkości ,
- Ręczna migracja do nowej puli węzłów przy użyciu tymczasowej .
Obie te opcje opierają się na możliwości tworzenia innych niż domyślne pul węzłów w AKS, co jest stosunkowo nową funkcją AKS , więc ciekawie będzie przyjrzeć się, jak możemy ją wykorzystać na naszą korzyść.
Dodatkowy basen
Najprostszym rozwiązaniem tego problemu jest zachowanie oryginalnej puli węzłów i dodanie do miksu dodatkowej puli (lub pul). Jest to bardzo łatwe do wdrożenia, biorąc pod uwagę fakt, że dostawca platformy Azure dla Terraform może teraz tworzyć oddzielne pule węzłów klastra. Jest to również bardzo przydatne, ponieważ możesz dodawać i usuwać dodatkowe pule węzłów według własnego uznania .
Może to jednak nie być to, czego chcesz, ponieważ Pule węzłów systemowych (a domyślne pule węzłów to Pule węzłów systemowych) mają pewne wymagania, które muszą spełnić , aby istnieć [link]:
- Pule systemowe osType muszą być Linuxem ,
- Pule systemowe muszą zawierać co najmniej jeden węzeł, a pule węzłów użytkownika mogą zawierać zero lub więcej węzłów ,
- Pule węzłów systemowych wymagają jednostki SKU maszyny wirtualnej składającej się z co najmniej 2 procesorów wirtualnych i 4 GB pamięci ,
- Pule węzłów systemowych muszą obsługiwać co najmniej 30 podów, zgodnie z wzorem na minimalną i maksymalną wartość dla podów .
Oznacza to, że nawet jeśli z niej nie korzystasz , będziesz musiał pozostawić co najmniej jedną maszynę wirtualną w tej puli węzłów i zapłacić za nią. Ponadto będzie to nadmiernie komplikuje obliczenia matematyczne podczas monitorowania i automatycznego skalowania ze względu na różnice w rozmiarze maszyn wirtualnych , zwłaszcza jeśli używasz instancji z możliwością rozdzielania.
Ręczna migracja
Nieco bardziej bolesną metodą , ale nadal preferowaną , jeśli chcesz zachować prostą infrastrukturę , jest utworzenie nowej puli węzłów i przeniesienie do niej podów , usuwając starą . Pozwól, że przeprowadzę Cię przez kroki potrzebne do osiągnięcia tego celu .
Krok 1: Utwórz nową pulę agentów
Po pierwsze: potrzebujemy nowej puli agentów, aby hostować nasze pody. Zalecam najpierw uzyskanie szczegółów istniejącej puli domyślnej, aby po zastosowaniu zmian w terraformie klaster nie został odtworzony. Możesz je uzyskać, uruchamiając to polecenie :
> az aks nodepool show –nazwa-klastra $YOUR_CLUSTER_NAME –grupa zasobów $RESOURCE_GROUP_NAME –nazwapula agentów
Który wyprodukuje coś takiego:
Zaznaczyłem na zielono , które właściwości musimy zachować, aby migracja przebiegła bezproblemowo. Na czerwono znajduje się wartość , którą zamierzamy zmienić. Przypadkowo większości tych wartości nie można zmienić podczas działania klastra , więc możesz użyć tej techniki również do zmiany innych wyróżnionych wartości – pamiętaj tylko o zaktualizowaniu ich w terraformie .
Mając te wartości na uwadze , możemy utworzyć nową pulę węzłów na potrzeby migracji:
> az aks nodepool add –nazwa-klastra $NAZWA_TWOJEGO_KLASTRA -g $NAZWA_GRUPY_ZASOBÓW -n pula agentów 1 –node-vm-size Standard_A4_v2 –node-count 3 –mode System -z 1 2 3 –node-osdisk-size 30
Widać, że są tam wszystkie podświetlone wartości, z wyjątkiem tej, którą zamierzamy zmienić ( Standard_A4_v2 ) i nazwy puli agentów. Ta nazwa została zmieniona, ponieważ Kubernetes nie pozwala nam na posiadanie wielu pul o tej samej nazwie. Aby zachować nazwę, powtórzymy tę samą procedurę po usunięciu oryginalnej puli agentów . Alternatywnie możemy zmienić nazwę w naszej definicji terraformy, co powinno działać dobrze, chyba że masz jakieś skażenia w oparciu o nazwę basenu.
Krok 2: Kordon i drenaż
Aby przeprowadzić tę migrację bez przestojów (lub jeśli masz określony budżet na zakłócenia dla swoich aplikacji), musisz mieć co najmniej dwa pody każdej aplikacji w tym samym czasie (jeśli jest to obsługiwane ) . Jeśli skalujesz liczbę replik , polecam użycie :
> kubectl cordon -l pula agentów=pula agentów
przed jego zmianą . Powinno to uniemożliwić planowanie podów w naszej starej puli agentów .
Teraz możemy eksmitować pody z naszej starej puli agentów :
> kubectl drenażu -l pula agentów=pula agentów
Jeśli Twoje kapsuły nie korzystają z pamięci lokalnej ani zestawów demonów , to powinno wystarczyć . W moim przypadku musiałem dodać jeszcze dwa parametry i wykonać następujące czynności :
> kubectl drenażu -l pula agentów=pula agentów –usuń-dane-lokalne –ignore-daemonsets
Niestety nie znalazłem sposobu na zarezerwowanie danych lokalnych , ale w większości przypadków będzie to po prostu pamięć podręczna . Powinieneś jednak sprawdzić to wchodząc.
Jeśli nadal otrzymujesz wyjątki, takie jak te, które widzisz poniżej ( w moim przypadku z istio ) , może być konieczne sprawdzenie, czy pody z budżetem na zakłócenia mają skonfigurowaną wystarczającą liczbę replik.
Krok 3: Usuń pulę węzłów
Na koniec możemy usunąć naszą starą pulę węzłów z klastra:
> az aks nodepool usuń – nazwa puli agentów -g $RESOURCE_GROUP_NAME –nazwa-klastra $TWOJA_NAZWA_KLASTRA
Zaskoczyło mnie , że mój stale działający test listonosza sprawdzający żywotność jednego z punktów końcowych nie powiódł się tylko na tym etapie , mimo że dla tej aplikacji nie działały żadne repliki:
Jest to jedyna przerwa w całym procesie , więc mogę powiedzieć, że migracja przebiegła pomyślnie , ale zostało nam jeszcze tylko kilka rzeczy do zrobienia.
Krok 4: Ponowny import
Możemy stąd wyjść na dwa sposoby:
- Powtórz powyższe kroki , aby zarezerwować nazwę naszej domyślnej puli agentów ( w moich przykładach „ pula agentów ”) ,
- Zostaw to tak jak jest („agentpool1”) i po prostu zmień go w terraformie .
Na potrzeby tego artykułu wybrałbym drugą opcję , która powinna wystarczyć, jeśli nie masz ustawionej tolerancji nazw puli dla swoich podów. Możesz przećwiczyć pierwszą opcję , ponieważ są to w zasadzie te same kroki , ale pod różnymi nazwami.
Aby to zadziałało , musimy zaktualizować nasze definicje terraform. Musisz znaleźć linię wyglądającą tak:
i zmień wartość na „agentpool1” (lub inną wybraną nazwę). Jeśli jednak zastosujemy nasze zmiany teraz, terraform wymusi odtworzenie naszego klastra (to tyle, jeśli chodzi o całą tę pracę!), ponieważ stary stan jest buforowany i nie może powiązać klastra z naszą nową pulą węzłów, z czym jest w państwie. Musimy ponownie zaimportować nasz klaster . Lubię używać :
> lista stanów terraform | grep kubernetes_cluster
Aby poznać pełną nazwę zasobu, ale jeśli Twoje definicje są raczej proste , możesz po prostu wpisać nazwę. Niezależnie od tego, jakie podejście preferujesz , powinniśmy teraz usunąć go ze stanu. Pamiętaj, że jeśli masz inne zasoby Kubernetes (takie jak przestrzenie nazw lub sekrety) utworzone w terraformie , musisz je również ponownie zaimportować. Podczas ponownego importu zachowaj ostrożność przy podawaniu identyfikatora zasobu – powinien on być taki sam, jak w poprzednim stanie (w terraformie rozróżniana jest wielkość liter!) .
> stan terraform rm $K8S_RESOURCE_NAME && import terraform $K8S_RESOURCE_NAME „/subscriptions/$subscriptionId/resourcegroups/$rg_name/providers/Microsoft.ContainerService/
zarządzaneClusters/$cluster_name”
Gdy to zrobimy , terraform „przyzwyczai się” do nowej puli węzłów i po prostu z niej skorzysta, jeśli zastosujemy terraformę:
Streszczenie
Jak widzieliśmy, istnieją różne strategie, których możemy użyć, aby skrócić przestoje podczas modernizacji infrastruktury zarządzanej przez terraform.
Może to wymagać pewnej pracy fizycznej, ale przy odpowiednim planowaniu można to osiągnąć . Teraz, gdy rozumiesz podejście , możesz je zmodyfikować, aby wykorzystać je do innych migracji , takich jak płynne przenoszenie aplikacji działających na maszynach wirtualnych , bazach danych itp.