CI/CD pipeline z użyciem Kubernetesa, AWS, Azure i .NET Core – stawianie klastra na Azure (AKS) oraz deploy

Opublikowane przez admin w dniu

Jest to ostatni wpis z serii CI/CD pipeline z użyciem Kubernetesa, AWS, Azure i .NET Core. Dziś postawimy klaster w Azure oraz wypromujemy aplikacje ze środowiska testowego na produkcyjne.

Seria CI/CD pipeline z użyciem Kubernetesa, AWS, Azure i .NET Core:

  1. Stawianie klastra na AWS
  2. Helm 3.0 i ACR
  3. Dodawanie klastra w Octopus Deploy
  4. Deploy na klaster testowy
  5. Stawianie klastra na Azure oraz deploy

Przegląd architektury

Stawianie klastra na Azure (AKS)

Postawimy teraz klaster na AKS. W przeciwieństwie do klastra który stawialiśmy na AWS, klaster AKS jest w części zarządzany przez Azure. Nadal musimy samodzielnie aktualizować wersje k8s oraz restartować maszyny, kiedy system operacyjny dostanie jakąś łatkę. Nody typu master, są zarządzane w pełni, nie mamy do nich dostępu. Do stworzenia klastra AKS, potrzebna nam będzie narzędzie AzureCli, ponieważ z poziomu portalu nie wszystkie opcje są konfigurowalne. Jeśli jeszcze nie masz AzureCli, to tutaj możesz je pobrać. Po pobraniu zaloguj się, wpisując np. powershella “`az login“`. Poniższa komenda stworzy nam klaster w Azure:

az aks create --resource-group itdepends 
              --name itdepends-prod-env  
              --enable-addons monitoring 
              --network-plugin kubenet
              --network-policy calico 
              --kubernetes-version 1.16.9 
              --generate-ssh-keys 
              --zones 1 2 3

Lista wszystkich dostępnych konfiguracji znajduje się tutaj. Oczywiście w zależności od potrzeb konfiguracja może być inna. Omówmy sobie teraz, niektóre parametry z powyższej komendy:

  • “`–enable-addons monitoring“` – zostanie dodany monitoring dla kontenerów w naszym klastrze, który będzie dostępny w portalu Azure. Domyślnie dostajemy tylko monitoring zużycia zasobów maszyn wirtualnych. Można go zintegrować także z Prometheusem.
  • “`–network-plugin kubenet“` – jest to jeden z dwóch dostępnych pluginów sieci w AKS. W portalu oznaczony jako “`Basic“`. Drugim dostępnym jest “`azure cni“` (w portalu Advanced). Główną różnicą pomiędzy tymi dwoma pluginami jest komunikacja pomiędzy podami znajdujących się w różnych nodach (maszynach wirtualnych). W wersji basic (kubenet) adresy IP w subnecie sieci wirtualnej dostają tylko nody. Pody nie zależą do sieci wirtualnej w Azure. Komunikacja pomiędzy podami odbywa się wtedy dzięki włączonemu IP forwardingowi na interfejsach sieciowych nodów oraz tabeli routingu. Z kolei w wersji advanced (azure cni), każdy pod otrzymuje swój adres IP w subnecie sieci wirtualnej. Pody nalezą wtedy do sieci wirtualnej w Azure. Dzięki temu są one widoczne w sieci i każda usługa w tej sieci może się do nich bezpośrednio odwoływać. Więcej o tym tutaj
  • “`–network-policy calico“` – polityka sieci umożliwia nam tworzenie reguł komunikacji wychodzącej i wchodzącej do naszych podów w klastrze. Dla przykładu, by zwiększyć bezpieczeństwo, możemy wdrożyć politykę, gdzie ruch sieciowy do podów z “`back-endem“` aplikacji X, mógłby się tylko dostać, przychodząc od podów z “`front-endem“` aplikacji X. W AKS mamy dostępne dwa rodzaje polityk sieciowych: “`calico“` i “`azure“`. Tej drugiej możemy użyć tylko wtedy gdy plugin sieciowy w naszym klastrze to “`Advanced“`. O różnicach polityk można przeczytać tutaj.
  • “` –generate-ssh-keys“` –  wygenerowane zostaną klucze na naszej maszynie pod domyślną ścieżką na windowsie “`%HOMEDRIVE%%HOMEPATH%\.ssh“`. Dzięki nim będziemy mogli nawiązać połączenie ssh z nodami AKS’a.
  • “`–zones 1 2 3“` – określa, w jakich availability zonach nasze nody zostaną stworzone. Ma to spore znaczenie jeśli chcemy tworzyć klaster typu HA. Mówiliśmy już o tym tutaj

Warto wspomnieć o domyślnych oraz nieużytych parametrach:

“`–attach-acr“` –  dzięki temu parametrowi nasz “`service principal“`, który został stworzony wraz z klastrem (lub ten, który wskazaliśmy jawnie) otrzyma role “`AcrPull“` w ACR. Będzie to ułatwiać pobieranie obrazów w naszym klastrze AKS. Nie będziemy wtedy musieli tworzyć secretów takich jak w poprzednim wpisie. Jednak aby, tego użyć musimy być zalogowani w AzureCli, na tego właśnie principala. W naszym przypadku pominiemy ten krok, by nie komplikować procesu w Octopusie i stworzymy secret z credentialami service principala. 

“` –node-count “` – domyślnie dla zapewnienia HA naszych aplikacji liczbą nodów, które zostaną stworzone to 3. O HA w k8s mówiliśmy przy okazji klastra na AWS.

“`–node-vm-size“` – domyślnie rozmiar maszyny wirtualnej to  “`Standard_DS2_v2“`

“`–enable-cluster-autoscaler“` – automatyczne skalowanie nodów klastra w zależności od obciążenia. AKS używa do tego scale setów.

“`–max-pods -m“` – maksymalna liczba podów per node. Domyślnie jest to 110 przy basic networking, 30 przy Advanced. Maksymalnie 250 przy obu pluginach. 

Dodatkowo AKS posiada także dwie konfiguracje, które są warte uwagi:

  1. Node pools – pozwalają nam dodawać do klastra maszyny wirtualne różnego typu. Dla przykładu jeśli niektóre z naszych aplikacji wykonują sporo obliczeń, możemy stworzyć pulę maszyn z mocnymi GPU, a następnie deployować tam tylko te aplikacje np. używając nodeSelectorów.
  2. Virtual nodes – jest to narzędzie pozwalające na dodanie do AKS usługi ACI jako node. AKS używa do tego narzędzia virtual-kubelet, które opakowuje zwykłego kubernetesowego kubeleta i rejestruje różne usługi tj. właśnie ACI, czy Fargate na AWS jako nody w k8s. Ma to sporą zaletę jeśli chodzi o szybkie i dynamiczne skalowanie. Kontenery w ACI wstają znacznie szybciej niż cała maszyna wirtualna w scale secie.

 

O co jeszcze warto zadbać na produkcji ?

  1. Logowanie np. z użyciem ELK Stack
  2. Metryki np. Graphana i Prometheus 
  3. Distributed tracing np. Jaeger
  4. Zarządzanie certifikatami np. cert manager
  5. Ingress controller. Na ten moment w przykładowej aplikacji deployujemy serwis typu “`load balancer“` w k8s. Może to powodować niepotrzebne koszty w chmurze (nowe adresy IP, czy fizyczne LB). Z pomocą tutaj przychodzi Ingress Controller w k8s, np. app gateway lub nginx.
  6. Zabezpieczenie kube-apiserver. Warto nałożyć restrykcje dostępowe jeśli chodzi o adresy IP, jakie mogą się dobić do naszego kube-apiserver. W Azure możemy stworzyć także prywatny klaster.

 

Jeśli podczas uruchomienia powyższej komendy dostajesz błąd:

Operation failed with status: ‘Bad Request’. Details: The credentials in ServicePrincipalProfile were invalid. Please see https://aka.ms/aks-sp-help for more details. (Details: token contains an invalid number of segments)

Spróbuj po prostu powtórzyć komendę do skutku lub stwórż i przekaż w parametrach service principala. Pamiętaj że za każdym uruchomieniem tworzy się nowy sp. Może to narobić sporego bałaganu. Issue do tego problemu tutaj.

Dodawanie klastra AKS w Octopusie

Po zdeployowaniu klastra na Azure musimy go dodać jako produkcyjne środowisko w Octopusie. Jak dodać klaster k8s do Octopusa pisałem już tutaj. Należy pamiętać, żeby dodać go w nowym środowisku “Production“. Dodatkowe kroki, jakie musimy podjąć to:

  1. Dodać secrety do ACR.
  2. Jeśli dodałeś do nowego deployment targetu nowe role w Octopusie, musisz je także dodać do każdego kroku w deployment procesie.
  3. Dodać wartości do zmiennych (connection string itd.) stworzonych w poprzednim wpisie dla środowiska produkcyjnego. 

Deploy na produkcje

Zróbmy teraz jakąś małą zmianę w aplikacji. Dodajmy jeden tag “`h1“` w widoku Index.csthml

<h1>First release on prod!!</h1>

Po zbudowaniu zobaczymy ją najpierw na środowisku testowym.

Następnie w Octopusie, po wejściu w najnowszy release, mamy z prawej strony możliwość zdeployowania go na środowisko produkcyjne.

 

Jeśli wszystko poszło po naszej myśli, na nowym klastrze pojawi się aplikacja z nowymi zmiennymi.

Zaletą tego podejścia jest to, że dokładnie ta sama aplikacja (obraz), która została przetestowana na środowisku testowym, zostanie “wypromowana” na produkcje.

Konfiguracja DNS w Azure

Ten krok jest opcjonalny, przechodziliśmy go także przy okazji tworzenia klastra na AWS, używając usługi Route 53. Możemy oczywiście używać jednej usługi DNS dla obydwu środowisk, co raczej nawet ma więcej sensu, jednak warto wiedzieć także jak dokonać tego w Azure. W tym celu w portalu wyszukujemy zasoby “`DNS Zones“`. Wpisujemy domenę (w moim przypadku było to kube.com.pl) i wybieramy resource grupę.  Po utworzeniu przekopiowujemy nazwy name serwerów do zakładki “Zewnetrzne serwery DNS” w nazwa.pl.

Zmiana konfiguracji może zająć chwilę. Dla sprawdzenia możemy użyć narzędzia “`nslookup“`.

nslookup -type=soa kube.com.pl

Następnie w naszej DNS Zonie w Azure klikamy “Record set”.  Wpisujemy nazwę, (może być wildcard) i resztę pól jak poniżej. W polu Azure resource wybieramy adres IP,  pod którym dostępna jest nasza aplikacja na ten moment.

Po dodaniu rekordu nasza aplikacja jest dostępna pod adresem prod.kube.com.pl

Jeśli chcesz zestawić połączenie SSL, to potrzebna będzie Ci Ingress np. nginx https://docs.microsoft.com/pl-pl/azure/aks/ingress-tls

Podsumowanie

Cała seria wpisów za nami. Od teraz możemy z łatwością deployować aplikacje na k8s w chmurach.