Platformy PaaS jako narzędzie do szybkiego prototypowania cz. 3. – Azure App Service

W poprzednim artykułach opisywałem Heroku, który idealnie pokrywa przypakdi hobbystyczne, co jednak kiedy chcemy przeprowadzić pewien mniej lub bardziej zaawansowany proof-of-concept w firmie, a management nie specjalnie ma ochotę na zawieranie nowych umów i sugeruje skorzystanie z już posiadanych przez nas subskrybcji.

W środowiskach korporacyjnych dominuje głównie dwóch dostawców pokrywających większość rynku i wyznaczających standardy dla konkurencji. Pierwszy z nich – AWS zapoczątkował wielką rewolucję chmurową, która odmieniła cały świat IT, zmuszając nawet najbardziej konserwatywne firmy jak banki do opracowania swoich rozwiązań (private cloud) lub wykorzystania chmury publicznej w części prowadzonych projektów (hybrid cloud).
Microsoft Azure powstał jako odpowiedź na rosnącą popularność chmur obliczeniowych i szybko stał się faworytem korporacji ze względu na ogromną ilość oferowanych usług w modelu SaaS (jak Office 365 i Dynamics). Jak już wspominałem wcześniej nawet jeśli twoja korporacja nie posiada jeszcze projektów realizowanych w chmurze Azure – jest duża szansa, że posiada subskrybcję Office365, czy Microsoft Dynamics.

W tym artykule chciałbym kontynuować naszą zabawę z modelem PaaS. Spróbujmy przenieść aplikację, którą zbudowaliśmy pod chmurę Heroku na Azure App Service. Jeśli nie popełniliśmy zasadniczych błędów projektowych, to nie powinniśmy stać się uzależnieni od dostawcy (ang. vendor lock-in) i migracja całości nie powinna kosztować nas zbyt dużo wysiłku.

Większość serwisów PaaS można uniezależnić całkowicie od języka programowania i platformy, poprzez odpowiednią konteneryzację. Jeśli pamiętacie heroku addons jak i buildpack’i wspomniane w poprzedniej części – to uniezależnienie się od nich stanowi klucz do uwolnienia naszego serwisu od określonego dostawcy i wspieranych przez niego technologii.

Przykładowa architektura:

źródło Azure Portal

Na czym zatem polega konteneryzacja?

Jest to rodzaj wirtualizacji na poziomie systemu operacyjnego (OS-level virtualization) i wbrew powszechnej opinii nie stanowi nowego wynalazku – jej wczesnym pierwowzorem były jail’e i chroot znany z systemów uniksowych (1982). W świecie backend developerów dopiero pojawienie się Docker’a upowszechniło konteneryzację. Od tej pory tworzone usługi i oprogramowanie mogły w całości uniezależnić się stack’u systemowego czy technologicznego.

Obraz Dockerowy można złożyć z kilku warstw za pomocą kilku wbudowanych poleceń takich jak FROM, CMD, COPY, ARG. Dla przykładu:

Po utworzeniu pliku Docker file jw. zbudowanie obrazu i uruchomienie kontenera sprowadza się do dwóch poleceń:

Rozbudowa aplikacji

W przypadku naszej aplikacji moglibyśmy wyodrębnić całą logikę poprzez przekopiowanie utworzonych artefaktów w następujący sposób:

W zasadzie poza skopiowaniem artefaktów i uruchomieniem naszej aplikacji zmieniamy jeszcze kontekst użytkownika na pozbawionego przywilejów ROOT’a (dobra praktyka).
Po próbie budowy, możemy niestety zaobserwować dość nieprzyjemny wyjątek:

W dość wymowny sposób pokazuje o czym zapomnieliśmy podczas uruchamiania/tworzenia obrazu.
Do uruchomienia potrzebujemy kilku dodatkowych zmiennych środowiskowych – w końcu w Heroku użyliśmy aż pięciu (!). Powinny one zostać przekazane do kontenera. Przygotujmy zatem plik w następującym formacie:

Wartości można oczywiście zabrać z naszej wcześniej utworzonej aplikacji na Heroku. Na powyższym przykładzie wychodzi też cena pokazanej wcześniej automagii.
Czy projektując aplikację nie pod konkretnego dostawcę podjęlibyśmy identyczną decyzję, jeśli chodzi o konfigurację podłączenia do bazy danych?
Zapewne zależałoby nam na rozdzieleniu pewnych elementów, dodatkowo moglibyśmy uniknąć zaprezentowanego wcześniej hack’a.
Kolejna próba z uwzględnieniem zmiennych środowiskowych i przekierowaniem portów pozwala już na lokalne uruchomienie skonteneryzowanej aplikacji:

Teraz wypadałoby poszerzyć nasz projekt o budowanie obrazu w pipelinie. Na szczęście przy oparciu naszego amatorskiego projektu o Gitlaba uzyskaliśmy możliwość skorzystania z ichniejszego rejestru obrazów (rozmiar całego repozytorium jak i rejestru posiada ograniczenie 10GB).
Użycie pipeline’ów w Gitlab sprawia, że uzyskanie do niego dostępu również jest banalnie proste poprzez predefiniowane zmienne:

Przygotowany etap wykonuje budowanie obrazu przy założeniu, że wcześniej odłożyliśmy je:

przykładowy rejestr

Po uruchomieniu kilku pipeline’ów zobaczymy, że rejestr zapełnia się kolejnymi tagami z kolejnymi wersjami aplikacji. Jak zatem powinniśmy decydować, która z nich powinna zostać zdepluyowan’a na nasze docelowe produkcyjne środowisko?

Można dodać do pipeline’u kolejny etap, którego celem będzie wykonanie właśnie tej operacji tj. odpowiednie tagowanie ostatniego build’a.

Et voilla. Nowy stage sprawi, że pod tagiem latest zawsze będzie się ukrywał najnowszy obraz pipeline’u masterowego.

Ktoś mógłby zadać pytanie, ale gdzie w tym wszystkim Azure? Dlaczego przygotowywać aplikację w ten sposób?
W następnej części cyklu zobaczymy uzysk z tych wszystkich operacji, ponadto zastanowimy się czy dałoby się podejść do tematu nieco inaczej.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *