Udostępnij przez


Co to jest Cloud Native?

Wskazówka

Ta zawartość jest fragmentem e-książki, Architektura Cloud Native .NET Applications for Azure, dostępnej w .NET Docs lub jako bezpłatny plik PDF do pobrania, który można czytać offline.

Natywne aplikacje .NET dla chmury Azure - okładka miniatury eBooka.

Zatrzymaj to, co robisz, i poproś współpracowników o zdefiniowanie terminu "Cloud Native". Istnieje duża szansa, że otrzymasz kilka różnych odpowiedzi.

Zacznijmy od prostej definicji:

Architektura i technologie natywne dla chmury to podejście do projektowania, konstruowania i obsługi obciążeń, które są wbudowane w chmurze i w pełni korzystają z modelu przetwarzania w chmurze.

Fundacja Cloud Native Computing Foundation zawiera oficjalną definicję:

Technologie natywne dla chmury umożliwiają organizacjom tworzenie i uruchamianie skalowalnych aplikacji w nowoczesnych środowiskach dynamicznych, takich jak chmury publiczne, prywatne i hybrydowe. Kontenery, siatki usług, mikrousługi, niezmienna infrastruktura i deklaratywne interfejsy API są przykładem tego podejścia.

Te techniki umożliwiają luźno powiązane systemy, które są odporne, możliwe do zarządzania i zauważalne. W połączeniu z niezawodną automatyzacją umożliwiają inżynierom wprowadzanie zmian o dużym wpływie, często i przewidywalnie, przy minimalnym wysiłku.

Chmura natywna dotyczy szybkości i elastyczności. Systemy biznesowe ewoluują od umożliwienia możliwości biznesowych do broni strategicznej transformacji, która przyspiesza szybkość działalności biznesowej i rozwój. Konieczne jest natychmiastowe uzyskanie nowych pomysłów na rynek.

Jednocześnie systemy biznesowe stają się coraz bardziej złożone, a użytkownicy domagają się więcej. Oczekują szybkiego reagowania, innowacyjnych funkcji i zerowego przestoju. Problemy z wydajnością, powtarzające się błędy i brak możliwości szybkiego działania nie są już akceptowalne. Twoi użytkownicy odwiedzą konkurenta. Systemy natywne dla chmury zaprojektowano tak, aby obejmowały szybkie zmiany, dużą skalę i odporność.

Oto niektóre firmy, które wdrożyły techniki natywne dla chmury. Zastanów się nad szybkością, elastycznością i skalowalnością, jaką osiągnęli.

Firma Doświadczenie
Netflix Ma ponad 600 usług w fazie produkcyjnej. Wdraża 100 razy dziennie.
Uber Ma ponad 1 000 usług w środowisku produkcyjnym. Kilka tysięcy wdrożeń odbywa się każdego tygodnia.
WeChat Ma ponad 3000 usług w środowisku produkcyjnym. Wdraża 1000 razy dziennie.

Jak widać, Netflix, Uber i WeChat udostępniają systemy natywne dla chmury, które składają się z wielu niezależnych usług. Ten styl architektoniczny pozwala im szybko reagować na warunki rynkowe. Natychmiast aktualizują małe obszary aktywnej, złożonej aplikacji bez pełnego ponownego wdrożenia. Indywidualnie skalują usługi zgodnie z potrzebami.

Filary chmury natywnej

Szybkość i elastyczność natywnej chmury wynikają z wielu czynników. Przede wszystkim jest infrastruktura chmury. Ale jest więcej: Pięć innych podstawowych filarów pokazanych na rysunku 1-3 zapewnia również podstawy dla systemów natywnych dla chmury.

Podstawowe filary cloud-native

Rysunek 1–3. Podstawowe filary chmury-natywnej

Pośmińmy trochę czasu, aby lepiej zrozumieć znaczenie każdego filaru.

Chmura

Systemy natywne dla chmury korzystają w pełni z modelu usług w chmurze.

Zaprojektowane tak, aby rozwijać się w dynamicznym, zwirtualizowanym środowisku chmury, systemy te intensywnie korzystają z infrastruktury obliczeniowej platformy jako usługi (PaaS) i usług zarządzanych. Traktują podstawową infrastrukturę jako wykorzystywaną czasowo — uruchamiana w minutach i zmieniana, skalowana lub niszczoną na żądanie — za pośrednictwem automatyzacji.

Rozważ różnicę między tym, jak traktujemy zwierzęta domowe i towary. W tradycyjnym centrum danych serwery są traktowane jako zwierzęta domowe: maszyna fizyczna, mająca znaczącą nazwę i dbana o nie. Skalowanie można przeprowadzić, dodając więcej zasobów do tej samej maszyny (skalowanie w górę). Jeśli serwer zachoruje, trzeba przywrócić go do zdrowia. Jeśli serwer stanie się niedostępny, wszyscy zauważą.

Model usług towarowych jest inny. Aprowizujesz każde wystąpienie jako maszynę wirtualną lub kontener. Są one identyczne i przypisane identyfikator systemu, taki jak Service-01, Service-02 itd. Skalowanie odbywa się przez utworzenie większej liczby wystąpień (skalowanie w poziomie). Nikt nie zauważa, gdy wystąpienie stanie się niedostępne.

Model towarów obejmuje niezmienną infrastrukturę. Serwery nie są naprawiane ani modyfikowane. Jeśli jedna z nich zakończy się niepowodzeniem lub wymaga aktualizacji, zostanie ona zniszczona, a nowa zostanie aprowizowana — wszystko odbywa się za pośrednictwem automatyzacji.

Systemy natywne dla chmury obejmują model usług towarów. Nadal działają one, gdy infrastruktura się skaluje w górę lub w dół, bez względu na maszyny, na których są uruchomione.

Platforma w chmurze platformy Azure obsługuje tego typu wysoce elastyczną infrastrukturę z automatycznym skalowaniem, samonaprawieniem i możliwościami monitorowania.

Nowoczesny projekt

Jak zaprojektować aplikację natywną dla chmury? Jak wyglądałaby Twoja architektura? Jakie zasady, wzorce i najlepsze praktyki stosowałbyś? Jakie kwestie związane z infrastrukturą i operacjami byłyby ważne?

Aplikacja Twelve-Factor

Powszechnie akceptowaną metodologią tworzenia aplikacji opartych na chmurze jest aplikacjaTwelve-Factor. Opisano w nim zestaw zasad i praktyk, które deweloperzy przestrzegają w celu konstruowania aplikacji zoptymalizowanych pod kątem nowoczesnych środowisk w chmurze. Szczególną uwagę należy zwrócić na przenośność w środowiskach i automatyzację deklaracyjną.

Chociaż ma zastosowanie do dowolnej aplikacji internetowej, wielu praktyków uważa, że Twelve-Factor jest solidną podstawą do tworzenia aplikacji natywnych dla chmury. Systemy oparte na tych zasadach umożliwiają szybkie wdrażanie i skalowanie oraz dodawanie funkcji w celu szybkiego reagowania na zmiany na rynku.

W poniższej tabeli przedstawiono metodologię Twelve-Factor:

Czynnik Wyjaśnienie
1 — Podstawa kodu Pojedyncza baza kodu dla każdej mikrousługi przechowywanej we własnym repozytorium. Śledzone przy użyciu systemu kontroli wersji, może być wprowadzane w wielu środowiskach (QA, Staging, Production).
2 — Zależności Każda mikrousługa oddziela i zarządza swoimi zależnościami, adaptując się do zmian bez wpływania na cały system.
3 — Konfiguracje Informacje o konfiguracji są przenoszone poza mikrousługę i zewnętrznie zarządzane za pomocą narzędzia do zarządzania konfiguracją, które działa niezależnie od kodu. To samo wdrożenie może rozprzestrzeniać się w różnych środowiskach przy właściwej konfiguracji.
4 — Usługi zapasowe Zasoby pomocnicze (magazyny danych, pamięci podręczne, brokery komunikatów) powinny być udostępniane za pośrednictwem adresowego adresu URL. Powoduje to oddzielenie zasobu od aplikacji, co umożliwia jego wymianę.
5 — Kompilacja, Wydanie, Uruchamianie Każda wersja musi wymuszać ścisłe rozdzielenie między etapami kompilacji, wydania i uruchamiania. Każdy powinien być oznaczony unikatowym identyfikatorem i umożliwiać wycofanie. Nowoczesne systemy ciągłej integracji/ciągłego wdrażania pomagają realizować tę zasadę.
6 — Procesy Każda mikrousługa powinna być wykonywana we własnym procesie izolowanym od innych uruchomionych usług. Przenieś wymagany stan do usługi wspomagającej, takiej jak rozproszona pamięć podręczna lub magazyn danych.
7 — Powiązanie portu Każda mikrousługa powinna być autonomiczna, z własnymi interfejsami i funkcjonalnością, udostępniana na własnym porcie. Zapewnia to izolację od innych mikrousług.
8 — Współbieżność Gdy pojemność musi wzrosnąć, przeprowadź skalowanie usług w poziomie w wielu identycznych procesach (kopiach), w przeciwieństwie do skalowania w górę pojedynczego dużego wystąpienia na najbardziej wydajnej dostępnej maszynie. Twórz aplikację tak, aby mogła być współbieżna, co pozwala bezproblemowo skalować w górę w środowiskach chmury.
9 — Jednorazowość Instancje usług powinny być tymczasowe. Preferować szybkie uruchamianie, aby zwiększyć możliwości skalowalności, oraz łagodne zamknięcia, aby pozostawić system w prawidłowym stanie. Kontenery platformy Docker wraz z orkiestratorem z natury spełniają to wymaganie.
10 — Parzystość dev/Prod Zachowaj środowiska w całym cyklu życia aplikacji tak samo, jak to możliwe, unikając kosztownych skrótów. W tym przypadku wdrożenie kontenerów może znacznie przyczynić się dzięki promowaniu tego samego środowiska wykonywania.
11 — Rejestrowanie Traktuj dzienniki generowane przez mikrousługi jako strumienie zdarzeń. Przetwarzaj je za pomocą agregatora zdarzeń. Przesyłanie danych dziennika do narzędzi do analizy danych i zarządzania dziennikami, takich jak Azure Monitor lub Splunk, a ostatecznie do długoterminowego archiwizowania.
12 — Procesy administracyjne Uruchom zadania administracyjne/zarządzania, takie jak oczyszczanie danych lub analiza obliczeniowa, jako jednorazowe procesy. Użyj niezależnych narzędzi do wywoływania tych zadań ze środowiska produkcyjnego, ale niezależnie od aplikacji.

W książce Beyond the Twelve-Factor App autor Kevin Hoffman szczegółowo opisuje każdy z oryginalnych dwunastu czynników, opisanych w 2011 roku. Ponadto omawia trzy dodatkowe czynniki odzwierciedlające dzisiejszy nowoczesny projekt aplikacji w chmurze.

Nowy czynnik Wyjaśnienie
13 — Najpierw interfejs API Utwórz wszystko jako usługę. Załóżmy, że Twój kod będzie używany przez klienta front-end, bramkę lub inną usługę.
14 — Telemetria Na stacji roboczej masz głęboki wgląd w aplikację i jej zachowanie. W chmurze tego nie zrobisz. Upewnij się, że projekt zawiera kolekcję danych monitorowania, specyficznych dla domeny i kondycji/systemu.
15 — Uwierzytelnianie/autoryzacja Wprowadź tożsamość od samego początku. Rozważ funkcje kontroli dostępu opartej na rolach (RBAC) dostępne w chmurach publicznych.

Będziemy odnosić się do wielu z 12+ czynników w tym rozdziale i w całej książce.

Dobrze zaprojektowana struktura platformy Azure

Projektowanie i wdrażanie obciążeń opartych na chmurze może być trudne, szczególnie w przypadku implementowania architektury natywnej dla chmury. Firma Microsoft udostępnia standardowe rozwiązania branżowe, które ułatwiają Tobie i Twojemu zespołowi dostarczanie niezawodnych rozwiązań w chmurze.

Platforma Microsoft Well-Architected Framework udostępnia zestaw wskazówek, które mogą służyć do poprawy jakości obciążenia natywnego dla chmury. Struktura składa się z pięciu filarów doskonałości architektury:

Zasady Opis
Zarządzanie kosztami Skoncentruj się na wczesnym generowaniu wartości przyrostowej. Zastosuj zasady Build-Measure-Learn, aby przyspieszyć czas wprowadzenia na rynek i uniknąć rozwiązań intensywnie korzystających z kapitału. Korzystając ze strategii płatności zgodnie z rzeczywistym użyciem, zainwestuj w miarę zwiększania skali, zamiast dokonywać dużych inwestycji z góry.
doskonałość operacyjna Zautomatyzuj środowisko i operacje, aby zwiększyć szybkość i zmniejszyć liczbę błędów ludzkich. Szybkie wycofywanie lub wdrażanie poprawek problemów. Zaimplementuj monitorowanie i diagnostykę od samego początku.
Wydajność Efektywnie wypełniaj wymagania dotyczące zadań roboczych. Preferuj skalowanie poziome (skalowanie w poziomie) i uwzględnij je w projektowaniu swoich systemów. Nieustannie przeprowadzaj testy wydajności i obciążenia, aby zidentyfikować potencjalne wąskie gardła.
Niezawodność Twórz obciążenia, które są zarówno odporne, jak i dostępne. Odporność umożliwia obciążeniom odzyskiwanie po awariach i kontynuowanie działania. Dostępność zapewnia użytkownikom możliwość korzystania z twojej usługi w każdej chwili. Zaprojektuj aplikacje w taki sposób, aby były odporne na awarie i potrafiły się z nich odzyskiwać.
Bezpieczeństwo Zaimplementuj zabezpieczenia w całym cyklu życia aplikacji— od projektowania i implementacji po wdrażanie i operacje. Należy zwrócić szczególną uwagę na zarządzanie tożsamościami, dostęp do infrastruktury, zabezpieczenia aplikacji oraz niezależność i szyfrowanie danych.

Aby rozpocząć pracę, firma Microsoft udostępnia zestaw ocen online , które ułatwiają ocenę bieżących obciążeń w chmurze pod kątem pięciu dobrze zaprojektowanych filarów.

Mikrousługi

Systemy natywne dla chmury obejmują mikrousługi, popularny styl architektury do tworzenia nowoczesnych aplikacji.

Zbudowany jako rozproszony zestaw małych, niezależnych usług, które współdziałają za pośrednictwem udostępnionej sieci szkieletowej, mikrousługi mają następujące cechy:

  • Każda z nich implementuje określoną funkcję biznesową w większym kontekście domeny.

  • Każda z nich jest opracowywana autonomicznie i może być wdrażana niezależnie.

  • Każda z nich samodzielnie hermetyzuje własną technologię przechowywania danych, zależności i platformę programowania.

  • Każdy działa we własnym procesie i komunikuje się z innymi przy użyciu standardowych protokołów komunikacyjnych, takich jak HTTP/HTTPS, gRPC, WebSockets lub AMQP.

  • Razem tworzą aplikację.

Rysunek 1-4 przedstawia porównanie podejścia do aplikacji monolitycznej z podejściem opartym na mikrousługach. Zwróć uwagę, że monolit składa się z architektury warstwowej, która jest wykonywana w jednym procesie. Zwykle korzysta z relacyjnej bazy danych. Jednak podejście mikrousług dzieli funkcje na niezależne usługi, z których każda ma własną logikę, stan i dane. Każda mikrousługa hostuje własny magazyn danych.

Wdrażanie monolityczne a mikrousługi

Rysunek 1–4. Architektura monolityczna a mikrousług

Zwróć uwagę, jak mikrousługi promują zasadę Procesy z Twelve-Factor Application, omówionej wcześniej w rozdziale.

Czynnik #6 określa, że "każda mikrousługa powinna być wykonywana we własnym procesie, odizolowana od innych działających usług".

Dlaczego mikrousługi?

Mikrousługi zapewniają elastyczność.

Wcześniej w rozdziale porównaliśmy aplikację do handlu elektronicznego utworzoną jako monolityczną aplikację z mikrousługami. W tym przykładzie przedstawiono pewne wyraźne korzyści:

  • Każda mikrousługa ma autonomiczny cykl życia i może ewoluować niezależnie i często wdrażać. Nie musisz czekać na kwartalną wersję, aby wdrożyć nową funkcję lub aktualizację. Możesz zaktualizować mały obszar aplikacji na żywo z mniejszym ryzykiem zakłócania całego systemu. Aktualizację można wykonać bez pełnego ponownego wdrożenia aplikacji.

  • Każda mikrousługa może być skalowana niezależnie. Zamiast skalować całą aplikację jako pojedynczą jednostkę, można skalować w poziomie tylko te usługi, które wymagają większej mocy obliczeniowej w celu spełnienia żądanych poziomów wydajności i umów dotyczących poziomu usług. Precyzyjne skalowanie zapewnia większą kontrolę nad systemem i pomaga zmniejszyć ogólne koszty podczas skalowania części systemu, a nie wszystkiego.

Doskonałym przewodnikiem referencyjnym dotyczącym rozumienia mikrousług jest mikrousługi platformy .NET: architektura konteneryzowanych aplikacji .NET. Książka zawiera szczegółowe informacje na temat projektowania i architektury mikrousług. Jest to uzupełnienie referencyjnej architektury mikrousługi full-stack dostępnej do bezpłatnego pobrania od firmy Microsoft.

Tworzenie mikrousług

Mikrousługi można tworzyć na dowolnej nowoczesnej platformie programistycznej.

Platforma Microsoft .NET jest doskonałym wyborem. Bezpłatne i „open source”, jest wyposażone w wiele wbudowanych funkcji, które upraszczają tworzenie mikrousług. Platforma .NET jest międzyplatformowa. Aplikacje można tworzyć i uruchamiać w systemach Windows, macOS i większości dystrybucji systemu Linux.

Platforma .NET jest wysoce wydajna i uzyskała dobre wyniki w porównaniu z Node.js i innymi konkurencyjnymi platformami. Co ciekawe, TechEmpower przeprowadził obszerny zestaw testów porównawczych wydajności w wielu platformach i strukturach aplikacji internetowych. Platforma .NET zdobyła wynik w czołowej dziesiątce - znacznie przewyższając Node.js i inne konkurencyjne platformy.

Platforma .NET jest utrzymywana przez firmę Microsoft i społeczność platformy .NET w witrynie GitHub.

Wyzwania związane z mikrousługą

Chociaż rozproszone mikrousługi natywne dla chmury mogą zapewnić ogromną elastyczność i szybkość, stanowią one wiele wyzwań:

Komunikacja

W jaki sposób aplikacje klienckie front-endu będą komunikować się z rdzeniowymi mikrousługami back-endu? Czy zezwolisz na bezpośrednią komunikację? Czy możesz abstrahować mikrousługi zaplecza przy pomocy fasady bramki, która zapewnia elastyczność, kontrolę i bezpieczeństwo?

Jak podstawowe mikrousługi back-end będą komunikować się ze sobą? Czy zezwolisz na bezpośrednie wywołania HTTP, które mogą zwiększyć sprzężenie i wpływać na wydajność i elastyczność? Czy możesz rozważyć oddzielenie komunikatów za pomocą technologii kolejek i systemów tematów?

Komunikacja jest omówiona w rozdziale Wzorce komunikacji natywnej dla chmury .

Elastyczność

Architektura mikrousług przenosi system z procesu do komunikacji sieciowej poza procesem. W architekturze rozproszonej co się stanie, gdy usługa B nie odpowiada na wywołanie sieciowe z usługi A? A co się stanie, gdy usługa C stanie się tymczasowo niedostępna, a inne usługi wywołujące ją staną się zablokowane?

Odporność jest omówiona w rozdziale Natywna odporność chmurowa.

Dane rozproszone

Zgodnie z projektem każda mikrousługa hermetyzuje własne dane, ujawniając operacje za pośrednictwem interfejsu publicznego. Jeśli tak, w jaki sposób wykonujesz zapytania o dane lub implementujesz transakcję w wielu usługach?

Dane rozproszone zostały omówione w rozdziale Wzorce danych natywnych dla chmury .

Tajemnice

W jaki sposób mikrousługi będą bezpiecznie przechowywać wpisy tajne i poufne dane konfiguracji oraz zarządzać nimi?

Tajemnice są szczegółowo omówione w bezpieczeństwie natywnym chmury.

Zarządzanie złożonością przy użyciu języka Dapr

Dapr to rozproszone środowisko uruchomieniowe aplikacji typu open source. Dzięki architekturze składników wpinanych znacznie upraszcza ona infrastrukturę za aplikacjami rozproszonymi. Zapewnia ona dynamiczny klej, który wiąże aplikację z wstępnie utworzonymi możliwościami i składnikami infrastruktury ze środowiska uruchomieniowego Dapr. Rysunek 1–5 przedstawia Dapr z 20 000 stóp.

Dapr na 20 000 stóp . Rysunek 1-5. Dapr na 20 000 stóp.

W górnym wierszu rysunku zwróć uwagę, jak język Dapr udostępnia zestawy SDK specyficzne dla języka dla popularnych platform programistycznych. Język Dapr w wersji 1 obejmuje obsługę platform .NET, Go, Node.js, Python, PHP, Java i JavaScript.

Zestawy SDK specyficzne dla języka zwiększają środowisko deweloperskie, ale język Dapr jest niezależny od platformy. Pod maską model programowania Dapr uwidacznia możliwości za pośrednictwem standardowych protokołów komunikacyjnych HTTP/gRPC. Każda platforma programistyczna może wywoływać język Dapr za pośrednictwem natywnych interfejsów API HTTP i gRPC.

Niebieskie pola na środku rysunku reprezentują bloki konstrukcyjne Dapr. Każdy uwidacznia wstępnie skompilowany kod kanalizacji dla funkcji aplikacji rozproszonej, którą aplikacja może wykorzystywać.

Wiersz składników reprezentuje duży zestaw wstępnie zdefiniowanych składników infrastruktury, z których aplikacja może korzystać. Pomyśl o składnikach jako kodzie infrastruktury, którego nie trzeba pisać.

W dolnym wierszu podkreślono, że Dapr jest przenośnym rozwiązaniem, które może działać w zróżnicowanych środowiskach.

Patrząc w przyszłość, Dapr ma potencjał, aby mieć głęboki wpływ na tworzenie aplikacji natywnych dla chmury.

Containers

Normalne jest usłyszeć termin kontener w dowolnych rozmowach o chmurze natywnej. W książce Cloud Native Patterns, autor Cornelia Davis zauważa, że "Kontenery są doskonałym elementem oprogramowania natywnego dla chmury". Cloud Native Computing Foundation umieszcza konteneryzację mikrousług jako pierwszy krok w Cloud-Native Trail Map — wskazówki dla przedsiębiorstw rozpoczynających swoją podróż natywną dla chmury.

Konteneryzowanie mikrousługi jest proste i nieskomplikowane. Kod, jego zależności i środowisko uruchomieniowe są pakowane do pliku binarnego nazywanego obrazem kontenera. Obrazy są przechowywane w rejestrze kontenerów, który działa jako repozytorium lub biblioteka obrazów. Rejestr może znajdować się na komputerze dewelopera, w centrum danych lub w chmurze publicznej. Sama platforma Docker obsługuje rejestr publiczny za pośrednictwem usługi Docker Hub. Chmura platformy Azure zawiera prywatny rejestr kontenerów do przechowywania obrazów kontenerów w pobliżu aplikacji w chmurze, które będą je uruchamiać.

Gdy aplikacja zostaje uruchomiona lub skalowana, obraz kontenera jest przekształcany w działające wystąpienie kontenera. Wystąpienie działa na dowolnym komputerze z zainstalowanym silnikiem środowiska wykonawczego kontenera. W razie potrzeby można mieć dowolną liczbę wystąpień usługi konteneryzowanej.

Rysunek 1–6 przedstawia trzy różne mikrousługi, z których każda jest w swoim kontenerze, wszystkie uruchomione na jednym hoście.

Wiele kontenerów uruchomionych na hoście kontenera

Rysunek 1–6. Wiele kontenerów uruchomionych na hoście kontenera

Zwróć uwagę, że każdy kontener zachowuje własny zestaw zależności i środowiska uruchomieniowego, który może się różnić od siebie. W tym miejscu widzimy różne wersje mikrousługi Product uruchomionej na tym samym hoście. Każdy kontener udostępnia fragment bazowego systemu operacyjnego hosta, pamięci i procesora, ale jest odizolowany od siebie.

Zwróć uwagę, jak dobrze model kontenera obejmuje zasadę Zależności z aplikacjiTwelve-Factor.

Składnik #2 określa, że "Każda mikrousługa izoluje i pakuje własne zależności, obejmując zmiany bez wpływu na cały system".

Kontenery obsługują obciążenia systemów Linux i Windows. Chmura platformy Azure otwarcie obejmuje oba te rozwiązania. Co ciekawe, jest to system Linux, a nie Windows Server, który stał się bardziej popularnym systemem operacyjnym na platformie Azure.

Chociaż istnieje kilku dostawców kontenerów, Docker zdobył lwią część rynku. Firma napędza ruch kontenerów oprogramowania. Stało się to de facto standardem tworzenia pakietów, wdrażania i uruchamiania aplikacji natywnych dla chmury.

Dlaczego kontenery?

Kontenery zapewniają przenośność i gwarantują spójność w różnych środowiskach. Hermetyzując wszystko w jednym pakiecie, należy odizolować mikrousługę i jej zależności od podstawowej infrastruktury.

Kontener można wdrożyć w dowolnym środowisku hostującym silnik uruchomieniowy Docker. Konteneryzacja obciążeń również eliminuje wydatki związane z wstępnym konfigurowaniem każdego środowiska za pomocą struktur, bibliotek oprogramowania i silników wykonawczych.

Dzięki udostępnieniu bazowego systemu operacyjnego i zasobów hosta kontener ma znacznie mniejszy rozmiar niż pełna maszyna wirtualna. Mniejszy rozmiar zwiększa gęstość lub liczbę mikrousług, które dany host może uruchomić jednocześnie.

Orkiestracja kontenerów

Narzędzia, takie jak Platforma Docker, tworzą obrazy i uruchamiają kontenery, ale potrzebne są również narzędzia do zarządzania nimi. Zarządzanie kontenerami odbywa się za pomocą specjalnego programu programowego nazywanego orkiestratorem kontenerów. W przypadku działania na dużą skalę z licznymi niezależnie działającymi kontenerami orkiestracja jest niezbędna.

Rysunek 1–7 przedstawia zadania zarządzania, które koordynatorzy kontenerów automatyzują.

Co robią koordynatorzy kontenerów

Rysunek 1–7. Co robią koordynatorzy kontenerów

W poniższej tabeli opisano typowe zadania orkiestracji.

Zadania Wyjaśnienie
Harmonogramowanie Automatycznie udostępniaj wystąpienia kontenerów.
Koligacja/anty-koligacja Umieszczaj kontenery w pobliżu lub daleko od siebie, co wspomaga dostępność i wydajność.
Monitorowanie kondycji Automatycznie wykrywaj i poprawiaj błędy.
Przełączenie awaryjne Automatyczne ponowne przypisanie zasobów dla wystąpienia, które nie powiodło się, na maszynie w dobrym stanie.
Skalowanie Automatyczne dodawanie lub usuwanie wystąpienia kontenera w celu spełnienia wymagań.
Sieć Zarządzanie nakładką sieciową na potrzeby komunikacji kontenerów.
Odnajdywanie usług Umożliwianie kontenerom lokalizowania siebie nawzajem.
Uaktualnienia stopniowe Koordynuj uaktualnienia przyrostowe z zerowym przestojem wdrożenia. Automatycznie wycofaj problematyczne zmiany.

Zwróć uwagę, w jaki sposób orkiestratory kontenerów stosują zasady Jednorazowości oraz Współbieżności z aplikacjiTwelve-Factor.

Czynnik #9 określa, że "Instancje usług powinny być łatwe do usunięcia, preferując szybkie uruchamianie w celu zwiększenia możliwości skalowalności i przyjazne wyłączenia, aby pozostawić system w prawidłowym stanie". Kontenery Docker wraz z orkiestratorem z natury spełniają to wymaganie.

Czynnik #8 określa, że "Usługi są skalowane w poziomie w dużej liczbie małych identycznych procesów (kopii), w przeciwieństwie do skalowania w górę pojedynczego dużego wystąpienia na najbardziej wydajnej dostępnej maszynie".

Chociaż istnieje kilka orkiestratorów kontenerów, Kubernetes stał się de facto standardem dla świata aplikacji chmurowych. Jest to przenośna, rozszerzalna platforma typu open source do zarządzania konteneryzowanymi obciążeniami.

Możesz hostować własną instancję Kubernetes, ale wówczas będziesz odpowiedzialny za przydzielanie i zarządzanie jej zasobami, co może być skomplikowane. Chmura platformy Azure oferuje platformę Kubernetes jako usługę zarządzaną. Usługi Azure Kubernetes Service (AKS) i Azure Red Hat OpenShift (ARO) umożliwiają pełne wykorzystanie funkcji i możliwości platformy Kubernetes jako usługi zarządzanej bez konieczności instalowania i konserwacji.

Orkiestracja kontenerów jest szczegółowo omówiona w książce Skalowanie Cloud-Native Aplikacji.

Usługi zapasowe

Systemy natywne dla chmury zależą od wielu różnych zasobów pomocniczych, takich jak magazyny danych, brokerzy komunikatów, monitorowanie i usługi tożsamości. Te usługi są nazywane usługami zapasowymi.

Rysunek 1–8 przedstawia wiele typowych usług zapasowych używanych przez systemy natywne dla chmury.

Typowe usługi tworzenia kopii zapasowych

Rysunek 1–8. Typowe usługi tworzenia kopii zapasowych

Możesz hostować własne usługi zapasowe, ale wtedy będziesz odpowiedzialny za licencjonowanie, aprowizowanie i zarządzanie tymi zasobami.

Dostawcy usług w chmurze oferują bogaty asortyment zarządzanych usług zapasowych. Zamiast być właścicielem usługi, po prostu go używasz. Dostawca usług w chmurze obsługuje zasób na dużą skalę i ponosi odpowiedzialność za wydajność, bezpieczeństwo i konserwację. Monitorowanie, nadmiarowość i dostępność są wbudowane w usługę. Dostawcy gwarantują wydajność poziomu usług i w pełni obsługują swoje usługi zarządzane — otwórz bilet i rozwiążą twój problem.

Systemy natywne dla chmury preferują zarządzane usługi zapasowe od dostawców usług w chmurze. Oszczędności w czasie i pracy mogą być znaczące. Ryzyko operacyjne związane z własnym hostingiem i napotkaniem problemów może szybko stać się kosztowne.

Najlepszym rozwiązaniem jest traktowanie usługi zapasowej jako dołączonego zasobu, dynamicznie powiązanego z mikrousługą z informacjami o konfiguracji (adresem URL i poświadczeniami) przechowywanymi w konfiguracji zewnętrznej. Te wskazówki zostały opisane we wcześniejszej części rozdziału Twelve-Factor Application.

Składnik #4 określa, że usługi pomocnicze "powinny być udostępnione poprzez adresowalny adres URL. Powoduje to oddzielenie zasobu od aplikacji, dzięki czemu może być wymienny".

Czynnik #3 określa, że "Informacje konfiguracyjne są przenoszone z mikrousługi i zewnętrznie zarządzane za pomocą narzędzia do zarządzania konfiguracją, znajdującego się poza kodem".

Za pomocą tego wzorca usługę zapasową można dołączać i odłączać bez zmian kodu. Możesz podwyższyć poziom mikrousługi z kontroli jakości do środowiska przejściowego. Należy zaktualizować konfigurację mikrousług, aby wskazywała usługi zapasowe w środowisku przejściowym i wprowadzała ustawienia do kontenera za pomocą zmiennej środowiskowej.

Dostawcy usług w chmurze udostępniają interfejsy API do komunikowania się z ich własnymi usługami zaplecza. Te biblioteki hermetyzują zastrzeżoną instalację wodną i złożoność. Jednak bezpośrednie komunikowanie się z tymi interfejsami API spowoduje ścisłe połączenie kodu z daną usługą zapasową. Jest to powszechnie akceptowana praktyka izolowania szczegółów implementacji interfejsu API dostawcy. Wprowadź warstwę pośredniczącą lub pośredni interfejs API, eksponując operacje ogólne w kodzie usługi oraz opakuj kod dostawcy w tej warstwie. To luźne sprzężenie umożliwia zamianę jednej usługi zapasowej na inną lub przeniesienie kodu do innego środowiska chmury bez konieczności wprowadzania zmian w kodzie usługi mainline. Dapr, omówiony wcześniej, działa według tego modelu z zestawem wstępnie utworzonych bloków konstrukcyjnych.

Kończąc myśl, usługi wsparcia również promują zasadę bezstanowości z aplikacją Twelve-Factor Application, która została omówiona wcześniej w rozdziale.

Czynnik #6 określa, że "Każda mikrousługa powinna być wykonywana we własnym procesie, odizolowana od innych uruchomionych usług. Przenieś wymagany stan do zewnętrznej usługi, takiej jak rozproszona pamięć podręczna lub magazyn danych.

Usługi zapasowe zostały omówione w wzorcach danych natywnych dla chmury i wzorcach komunikacji natywnej dla chmury.

Automation

Jak już wiesz, systemy natywne dla chmury obejmują mikrousługi, kontenery i nowoczesny projekt systemu w celu osiągnięcia szybkości i elastyczności. Ale to tylko część historii. Jak aprowizować środowiska chmury, na których działają te systemy? Jak szybko wdrażać funkcje i aktualizacje aplikacji? Jak zaokrąglić pełny obraz?

Wprowadź powszechnie akceptowaną praktykę infrastruktury jako kodu lub IaC.

Dzięki usłudze IaC automatyzujesz aprowizowanie platformy i wdrażanie aplikacji. Zasadniczo stosujesz praktyki inżynieryjne oprogramowania, takie jak testowanie i przechowywanie wersji w praktykach DevOps. Infrastruktura i wdrożenia są zautomatyzowane, spójne i powtarzalne.

Automatyzowanie infrastruktury

Narzędzia, takie jak Azure Resource Manager, Azure Bicep, Terraform z platformy HashiCorp i interfejs wiersza polecenia platformy Azure, umożliwiają deklaratywne tworzenie skryptów wymaganej infrastruktury w chmurze. Nazwy zasobów, lokalizacje, pojemności oraz tajemnice są sparametryzowane i dynamiczne. Skrypt jest wersjonowany i ewidencjonowany w kontroli źródła jako artefakt projektu. Skrypt jest wywoływany, aby zapewnić spójną i powtarzalną infrastrukturę w środowiskach systemowych, takich jak QA, staging i produkcyjne.

Wewnątrz systemu IaC jest idempotentny, co oznacza, że ten sam skrypt można uruchamiać wielokrotnie bez skutków ubocznych. Jeśli zespół musi wprowadzić zmianę, edytuje i ponownie uruchamia skrypt. Dotyczy to tylko zaktualizowanych zasobów.

W artykule What is Infrastructure as Code (Co to jest infrastruktura jako kod), Author Sam Guckenheimer opisuje, w jaki sposób "Zespoły, które implementują IaC, mogą szybko i na dużą skalę dostarczać stabilne środowiska. Unikają ręcznej konfiguracji środowisk i wymuszają spójność, reprezentując żądany stan swoich środowisk za pomocą kodu. Wdrożenia infrastruktury z funkcją IaC są powtarzalne i uniemożliwiają problemy ze środowiskiem uruchomieniowym spowodowane dryfem konfiguracji lub brakującymi zależnościami. Zespoły DevOps mogą współpracować z ujednoliconym zestawem rozwiązań i narzędzi, aby dostarczać aplikacje i ich infrastrukturę pomocniczą szybko, niezawodnie i na dużą skalę".

Automatyzowanie wdrożeń

Omówiona wcześniej aplikacjaTwelve-Factor wywołuje oddzielne kroki podczas przekształcania ukończonego kodu w uruchomioną aplikację.

Składnik #5 określa, że "Każda wersja musi wymuszać ścisłe rozdzielenie między etapami kompilacji, wydania i uruchamiania. Każdy powinien być oznaczony unikatowym identyfikatorem i umożliwiać możliwość wycofywania.

Nowoczesne systemy ciągłej integracji/ciągłego wdrażania pomagają realizować tę zasadę. Zapewniają one oddzielne kroki kompilacji i dostarczania, które pomagają zapewnić spójny i jakościowy kod, który jest łatwo dostępny dla użytkowników.

Rysunek 1–9 przedstawia rozdzielenie procesu wdrażania.

Kroki wdrożeń w pipelinie ciągłej integracji/ciągłego wdrażania

Rysunek 1–9. Kroki wdrażania w potoku ciągłej integracji/ciągłego wdrażania

Na poprzedniej ilustracji zwróć szczególną uwagę na rozdzielenie zadań:

  1. Deweloper tworzy funkcję w swoim środowisku projektowym, iterując przez to, co jest nazywane "wewnętrzną pętlą" kodu, uruchamiania i debugowania.
  2. Po zakończeniu ten kod jest wypychany do repozytorium kodu, takiego jak GitHub, Azure DevOps lub BitBucket.
  3. Wypychanie wyzwala etap kompilacji, który przekształca kod w artefakt binarny. Praca jest implementowana przy użyciu potoku ciągłej integracji. Automatycznie kompiluje, testuje i pakuje aplikację.
  4. Etap wydania pobiera artefakt binarny, stosuje informacje o konfiguracji aplikacji zewnętrznej i środowiska oraz tworzy niezmienną wersję. Wydanie jest wdrażane w określonym środowisku. Praca jest realizowana za pomocą pipeline Continuous Delivery (CD). Każde wydanie powinno być możliwe do zidentyfikowania. Możesz powiedzieć: "To wdrożenie działa w wersji 2.1.1 aplikacji".
  5. Na koniec wdrożona funkcja jest uruchamiana w docelowym środowisku wykonawczym. Wydania są niezmienne, co oznacza, że każda zmiana musi utworzyć nowe wydanie.

Stosując te praktyki, organizacje radykalnie ewoluowały, jak wysyłają oprogramowanie. Wiele z tych wersji zostało przeniesionych z kwartalnych wersji do aktualizacji na żądanie. Celem jest złapanie problemów na wczesnym etapie cyklu programowania, gdy są one tańsze do rozwiązania. Im dłuższy czas między integracjami, tym droższe staje się rozwiązywanie problemów. Dzięki spójności w procesie integracji zespoły mogą częściej zatwierdzać zmiany kodu, co prowadzi do lepszej współpracy i jakości oprogramowania.

Infrastruktura jako kod i automatyzacja wdrażania wraz z usługami GitHub i Azure DevOps zostały szczegółowo omówione w temacie DevOps.