Chmura

Jak chmura ułatwia codzienne życie programisty?

Wpis Sponsorowany
8

Myślę, że wszyscy zgodzimy się z tym, że pojawienie się chmurowej rewolucji zmieniło sposób, w jaki patrzymy na projektowanie i wdrażanie rozwiązań IT. Zasoby, na które kiedyś musieliśmy czekać miesiącami, dziś dostępne są dla każdego użytkownika chmury AWS w ciągu paru kliknięć myszką (w dodatku jutro możemy je podwoić, czy też zmniejszyć o połowę, według własnego widzimisię!). Z pewnością od razu kojarzy nam się to z wpływem na sposób pracy wielu zespołów IT, architektów, administratorów, specjalistów od bezpieczeństwa oraz innych. Jednak jak odnosi się to do samych deweloperów i zmian ich nawyków? Tutaj należałoby wskazać, że (w mojej prywatnej opinii) to właśnie tę grupę osób najbardziej „dosięgła” chmura, diametralnie zmieniając metodologie ich pracy poprzez odblokowanie nowej gamy możliwości.

Autorem wpisu jest Michał Adamkiewicz, Enterprise Solutions Architecture – CEE w AWS

Sam sobie złóż platformę

Patrzenie na chmurę jedynie przez pryzmat centrum danych z olbrzymią ilością wirtualnych maszyn i dysków nie przyniesie nam sporej korzyści. Znacznie sensowniejszym będzie powiedzenie, że chmura daje nam do dyspozycji komponenty, z których w zależności od własnych potrzeb możemy złożyć gotową platformę. Nie będzie tutaj żadnym zaskoczeniem, że przecież wciąż mamy rzecz jasna do dyspozycji (jeśli tego chcemy) komponenty typowo infrastrukturalne, takie jak sieci czy maszyny wirtualne. Jednak miejsce, w którym chmura pokazuje swoje prawdziwe oblicze, to są te składowe, dzięki którym kompletujemy całe, pełnowymiarowe usługi – bazy danych, kolejki, kontenery. Z kolei jednym ze sposobów na ich dostarczenie jest model serverless – czyli „weź co potrzebujesz, zapłać za tyle ile zużyłaś/eś”.

Gdyby spojrzeć na to hierarchicznie, tworząc aplikację w środowisku chmurowym, bardzo często rozpoczynamy budowę architektury właśnie na usługach serverless, dzięki czemu zapewniamy sobie skalowanie praktycznie „real-time” oraz efektywność kosztową (zaś to tylko część z założeń paradygmatu serverless). Jeżeli to nie wystarcza, sięgamy dalej, do usług, które również mogą nam dać np. całą funkcjonalność relacyjnej bazy danych, jednak już niekoniecznie w modelu serverless. Tam, gdzie jest to konieczne, schodzimy do artefaktów infrastrukturalnych, aby zaadresować brakujące elementy w naszym ekosystemie.

Zyskujący na popularności (już od długiego czasu!) sposób dostarczania usług serverless sprawia, że deweloper otrzymuje de facto niezbędną logikę biznesową, bez całej otoczki martwienia się o operacyjność takiego rozwiązania. Choć porównanie może wydawać się śmieszne, to jednak, czy komukolwiek z nas przychodzi czasem do głowy pytanie, w jaki sposób i kto dostarcza prąd do gniazdka w ścianie? Po prostu zakładamy, że on tam jest, i w odpowiednim momencie chcemy z niego skorzystać. Choć jest to olbrzymie uproszczenie, to jednak coraz częściej możemy analogicznie myśleć u usługach – wykorzystać komponent, tu i teraz, w ilości, jaka jest nam potrzebna. Skoro już zaczęliśmy o serverless, to wypadałoby powiedzieć, ile tych bez-serwerowych komponentów jest dostępnych w AWS, albo raczej jakie są ich kategorie (nie, nie będę tutaj rzucać wszystkimi nazwami usług AWS, lecz skupię się, aby zaznaczyć obszary, w których możemy skorzystać z produktów budowanych jako serverless):

- Usługi obliczeniowe

- Przechowywanie danych

- Usługi analityczne i bazy danych (relacyjne i nierelacyjne)

- Integracje aplikacji, w tym API oraz systemy kolejkowe

- Usługi obsługujące streaming

- Monitoring i logowanie (ang. observability)

Jak widać, serverless to już nie tylko computing, który jakimś sposobem przychodzi ludziom do głowy jako pierwszy. To nie tylko stawiana jako pierwowzór podejścia serverless usługa AWS Lambda (dla tych, którzy nie wiedzą czym jest AWS Lambda, odsyłam do tego linku -> https://www.cloudzero.com/blog/aws-lambda). Serverless przesuwa granicę dalej, co sprawia, że można zadać sobie pytanie, czy warstwa aplikacji, infrastruktura i elementy integracyjne są jeszcze rozłączne? Czy programowanie to wciąż myślenie głównie w kategoriach funkcji, metod oraz logiki stającej za nimi? Z całą pewnością serverless zaciera granice do niedawna bardzo jawne i klarowne dla większości z nas.

Chciałbym przytoczyć tutaj cytat, z którym mocno się identyfikuję – Gregor Hohpe, Enterprise Stategist w firmie AWS powiedział: „I firmly believe that we are just starting to realize the true potential of cloud automation. Modern cloud automation isn’t just about reducing toil. (…) it can help us blur the line between application and automation code.”. Zatem parafrazując na nasz ojczysty język – pełen potencjał automatyzacji, który daje nam chmura, stoi przed nami otworem, zaś jego wykorzystanie będzie postępować coraz bardziej wpływając na kod aplikacji samych w sobie.

Zdarzenia są wszędzie

Kolejnym kierunkiem, w który zmierza technologia chmury, jest architektura sterowana zdarzeniami (ang. event oriented architecture). Tak naprawdę wszystko w chmurze możemy traktować jako serie zdarzeń, zaś aplikacje wyznające taki paradygmat, wydają się nadzwyczaj dobrze funkcjonować w środowisku chmurowym. Taki paradygmat, czyli jaki? A no właśnie, styl architektury, w którym wykorzystujemy zdarzenia do kontroli przepływu. Wyobraźmy sobie, iż zamiast wirtualnej maszyny, która musi być włączona 24 godziny po to, aby zaplanowane zadanie (skrypt) miał możliwość się wykonać, wykorzystamy… zdarzenia. Nasz kod (np. konwertujący fotografie) wykona się np. w momencie, gdy w odpowiednim miejscu pojawi się wysłane przez użytkownika zdjęcie (zdarzenie!). Informacja o tym zostanie zapisana do bazy No-SQL (kolejne zdarzenie!), co w dalszej kolejności spowoduje wysłanie e-maila (i znów zdarzenie…) wraz z linkiem do nowego pliku multimedialnego. Już na bazie tak prozaicznego przypadku można dostrzec, że w aplikacjach sterowanych zdarzeniami możemy wyróżnić producenta i konsumenta. Producentem będzie dosyć często usługa, która wygenerowała pierwsze zdarzenie. Takich przykładów można by mnożyć bez liku, bowiem finalnie zdarzeniem jest praktycznie wszystko… od zalogowania się, poprzez użycie klucza szyfrującego, czy umieszczenie wiadomości w kolejce. W tym miejscu również przytoczę kolejny cytat, tym razem samego Jeffa Bezosa, który powiedział (ang.): „The only sustainable advantage you can have over others is agility, that’s it.”. Co interpretując na język polski oznaczałoby mniej więcej to, iż aby osiągnąć przewagę (trwałą, ciągłą!) konieczna jest... zwinność! Z kolei aplikacje oparte na zdarzeniach, stanowią kwintesencję zwinności, w pełnym tego słowa znaczeniu! Dlaczego tak się dzieje? Tutaj należałoby wrócić do akapitu ze wspomnianym już serverlessem. Otóż model dostarczania serverless jest po prostu idealnie pasującym puzzlem dla aplikacji pisanych w taki sposób. Dość powiedzieć, że jedno bez drugiego nie miałoby prawa istnieć. Obydwie te rzeczy zapewniają nam charakterystykę pracy aplikacji, która chowa szczegóły implementacyjne, z kolei każdy jej element jest całkowicie niezależny (z ang. „loosely coupled”). Możliwość konsumowania efektów naszej aplikacji przez wielu odbiorców równolegle zapewnia nam płynna skalowalność. I nie sposób nie dodać jeszcze jednej ważnej cechy – efektywności w zakresie zasobów obliczeniowych. Bowiem jeżeli nasłuchujemy na zdarzenia (i tylko na nie!) wówczas nasza architektura pracuje i utylizuje realnie usługi tylko i wyłącznie w momentach faktycznego przetwarzania tychże zdarzeń. Płacimy wówczas za faktyczny czas, kiedy nasza aplikacja funkcjonowała. W rozrachunku końcowym architektury zdarzeniowe dają nam sposobność szybszego i łatwiejszego adoptowania się do bieżących wymagań biznesowych z uwagi na eliminację konieczności użycia złożonych monolitów, w których każda zmiana jest swoistym wyzwaniem.

To, czego możemy być pewni, to fakt, że usługi AWS na bazie których jesteśmy w stanie budować zdarzeniowe aplikacje już na dobre zadomowiły się w chmurze, zaś z biegiem czasu ich możliwości będą się powiększać. Już obecnie AWS pozwala nam na logowanie/nagrywanie ciągów zdarzeń przy użyciu tzw. „event busów”, dając jednocześnie sposobność przekierowania ich pomiędzy rożnymi kontami czy też ich filtrację na podstawie konkretnych wzorców.

Zapisz chmurę jako kod

Wysoce prawdopodobne, że zdarzyło Ci się niejednokrotnie usłyszeć o zjawisku nazywanym z ang. „Infrastructure as a Code”. Jest to kolejna rewolucja (choć może należałoby powiedzieć ewolucja) spośród wielu innych, które chmura wprowadziła do codziennego życia wielu specjalistów IT, w tym także deweloperów. Jeżeli chmura pozwala nam w czasie paru kliknięć utworzyć bazę danych, load balancer, czy wirtualny firewall, to czy stoi coś na przeszkodzie, abyśmy nie mogli utworzyć tego samego z użyciem kodu? Odpowiedź oczywiście jest jasna. Wszystko, co tylko możemy wyobrazić sobie jako obiekt w chmurze AWS, możemy także zapisać w postaci odpowiedniej struktury w kodzie. Argumentów, dlaczego chcielibyśmy to robić, można by wytoczyć bardzo wiele. Jak zapewne każdy się zgodzi, to co jest zapisane i przechowywane w repozytorium kodu jest (a przynajmniej powinno być)… jedynym źródłem prawdy. Zatem wersjonujemy, logujemy, pracujemy w grupie poprzez inkrementacyjne zmiany w protokole git. Jeżeli to wciąż mało, to wyobraźmy sobię kreowanie rozbudowanej architektury i konieczność ręcznego tworzenia każdego komponentu jeden po drugim – co jeśli chcemy postawić klon naszego systemu w drugim regionie? Powtarzalność i re-używalność to kolejne z atutów wszystkiego co da się serializować (zapisywać) w postaci kodu. Finalnie deklaracje naszych chmurowych zasobów możemy poddawać testom i rygorystycznym politykom bezpieczeństwa – w końcu jest to przecież interpretowany zapis obiektu, stąd też poprzez analizę statyczną możemy np. upewnić się, że nie powstanie maszyna wirtualna większa aniżeli konkretny rozmiar, czy też, że szyfrowanie będzie zawsze włączone.

Trend zapisywania wszystkiego jako kod istniał w AWS już od bardzo dawna – dzięki szczegółowej dokumentacji, istniejącemu CLI, licznym SDK dla języków programowania, i co najważniejsze usłudze AWS CloudFormation. To właśnie ona odpowiada za interpretację zapisu (w postaci YAML lub JSON) na postawie którego powoływane do życia są poszczególne komponenty. Jednak prawdziwa rewolucja (z punktu widzenia programisty) przyszła w 2019 roku, kiedy to udostępniony publicznie został AWS Cloud Development Kit, w skrócie CDK. Utorowało to drogę dla wszystkich osób znających takie języki programowania jak chociażby Python, TypeScript czy Java do natywnego sposobu deklarowania i zarzadzania obiektami (usługami) w AWS! Innymi słowy, deweloper specjalizujący się w swoim języku programowania może napisać zarówno kod definiujący infrastrukturę pod aplikację, jak i samą aplikację (zawierającą logikę biznesową). Kolejny raz, kiedy to niegdyś dobrze oznaczona granica, zaczęła się zacierać.

Niech IDE przemówi

Przyszedł czas na zmiany również i w tym aspekcie. Obecnie nikogo już nie powinna dziwić integracja większości popularnych IDE z usługami AWS dzięki użyciu tzw. „toolkita” który służy wsparciem dla programisty na potrzeby deploymentu oraz lokalnego testowania usług (np. funkcji Lambda!). Gotowe pluginy znajdziemy do ściągnięcia chociażby w takich aplikacjach jak Eclipse, PyCharm, IntelliJ, Visual Studio czy Visual Studio Code (jak i paru innych). Jednakże w sytuacji, gdyby programista nie posiadał z różnych przyczyn swojego domyślnego IDE (np. kwestie licencyjne) również i tutaj chmura przychodzi z pomocą. Usługa Cloud9 stanowi swoiste środowisko online (otwarte open source) zawierające narzędzia dla większości języków wraz z niezbędnymi SDK oraz podstawowymi bibliotekami i zależnościami. Efektywne i dopasowane środowisko pracy (IDE) stanowi rzecz jasna element niezbędny w codziennej aktywności zawodowej.

Jednakże tym, co naprawdę zaczyna stwarzać różnicę, jest pojawiający się trend uczenia maszynowego, które ma za zadanie wspomóc obowiązki dewelopera. Omówić tutaj należałoby przynajmniej dwie usługi, które odbiły się szerokim echem w świecie chmury. Pierwszą z nich jest Amazon CodeGuru. Adresuje ona tak naprawdę wiele aspektów, zaś jego pierwszym obszarem działania jest integracja z CI/CD oraz popularnymi repozytoriami kodu, takimi jak GitHub, BitBucket czy AWS CodeCommit. W tych miejscach wyszukuje krytyczne fragmenty kodu, które mogą stanowić niebezpieczeństwo, lub być niezoptymalizowane. Omawiana usługa do tego stopnia wkomponowuje się w rytm codziennej pracy, iż tak naprawdę każde utworzenie Pull Request będzie przez nią monitorowane, zaś inkrementalne zmiany śledzone i skanowane. Na rysunku poniżej możemy zobaczyć przykład ekranu z konsoli, ukazujący pojawienie się nowego Pull Requestu na repozytorium GitHub, który został przechwycony przez usługę:

Sam kod napisany na potrzeby przykładu w języku Python (dla przypomnienia Amazon CodeGuru wspiera języki Python albo Java) jest do tego stopnia banalnie prosty, iz nie ma sensu go tutaj przytaczać, należy natomiast wspomnieć, że jedna z operacji pobiera aktualny czas, zaś inna tworzy klienta usługi AWS S3 (w celach edukacyjnych linia kodu zawiera zapisane dane do uwierzytelnienia). Na tej postawie możemy ujrzeć dwie rekomendacje:

Ponadto dzięki natywnej integracji, już na poziomie GitHub możemy zobaczyć wygenerowane rekomendacje, które Amazon CodeGuru zamieścił w formie komentarzy:

Powyższy przykład stanowi jedynie drobny wycinek tego, w jaki sposób usługa może uprościć codzienność tworzenia kodu. Bazując na zgromadzonej wiedzy (budowanej między innymi w oparciu o naukę z otwartych projektów, jak i bazy własnej AWS) CodeGuru będzie wnioskować, rekomendować i wykrywać takie zjawiska, jak chociażby brak korzystania z protokołu HTTPs, brak szyfrowania, wycieki zasobów, deadlocki czy race conditions.

Co jednak z samym pomiarem wydajności naszej aplikacji? Tutaj wkracza druga część usługi AWS CodeGuru, a konkretniej CodeGuru Profiler. Aby wykorzystać jego moc, musimy zintegrować bibliotekę z naszą aplikacją (analogicznie jak robi się to na przykładzie klientów APM – Application Performance Monitoring). W tym przypadku usługa prócz wspomnianych wcześniej Pythona oraz Javy daje nam wsparcie również dla języków Kotlin i Scala. Agent zbiera dane w ramach funkcjonującej aplikacji i w odstępach 5 minutowych przesyła je do analizy, na podstawie której w dalszej kolejności powstaje tzw. Flame Graph oraz osobny zbiór rekomendacji. Dane są zbiorczo agregowane, zaś w przypadku wystąpienia anomalii usługa wygeneruje dla nas odpowiedni alert. W głównej mierze profiler skupia się na CPU (aktywny czas CPU oraz wall clock) oraz pamięci operacyjnej (w tym oczywiście heap summary dla Java wraz z innymi językami opartymi o JVM). Poniżej możemy zobaczyć ponownie fragment konsoli z wygenerowanym diagramem dotyczącym czasu CPU:

Drugą usługą, która powoli toruje sobie drogę do naszych IDE, jest AWS CodeWhisperer. CodeWhispeper wspiera różne języki takie jak: Python, Java oraz Javascript. Jaki problem twórcy usługi postanowili rozwiązać poprzez zastosowanie pluginu do IDE (usługa integruje się ze środowiskiem pracy poprzez wspomniany wcześniej AWS Toolkit)? Cel, którego realizacja jest bardzo nietrywialnym zadaniem – podnieść wydajność dewelopera poprzez automatyczne generowanie fragmentów kodu! AWS CodeWhisperer jest usługą zbudowaną w całości na uczeniu maszynowym, która reaguje na wszystko co zostanie napisane w IDE, generując tym samym gotowe snippety kodu wraz z wykorzystaniem konkretnych funkcji i bibliotek do zaadresowania logiki w chmurze AWS. Aby nadać temu realny wymiar, wyobraźmy sobie nasze otwarte IDE (z ustawionym runtime: Python 3.8) w którym wpisujemy jako komentarz: „# function that open CSV from S3 and insert into DynamoDB”. Po chwili oczekiwania (czas niezbędny na kontakt z serwisem zdalnym AWS i wywołanie ML) funkcja auto-uzupełniania pokażę nam np. taki fragment kodu:

Oczywiście jak zapewne można się domyślić, generowany kod będzie w dużej mierze zależeć od sposobu i dokładności, z jaką tworzymy komentarze w naszym edytorze. Niemniej jednak usługa nie tylko będzie nam pomocna do tworzenia całych fragmentów funkcji (które potem można dostosować do własnych potrzeb), lecz także świetnie poradzi sobie, uzupełniając kod linijka po linijce wspomagając dewelopera np. poprzez sugestie użycia konkretnej metody z bibliotek AWS. Nadmienię tutaj, że specjalnie na cele tego artykułu postanowiłem zapisać się na preview AWS CodeWhisperer i rezultaty przeszły moje najśmielsze oczekiwania. Potrafię sobie wyobrazić moment, w którym użytkownik nie będzie musiał już mieć otwartej dokumentacji dla konkretnego języka, aby odszukać metodę i zestaw argumentów, które przyjmuje. Zamiast tego środowisko samo podpowie składnie i wstawi brakujący fragment logiki w bieżące miejsce! Co konkretnie usługa ML analizuje w trakcie generowania sugestii? Składowych są trzy: przede wszystkim kod już napisany przez użytkownika, komentarze w języku angielskim, a także obecne położenie kursora myszki, tak aby podpowiedzi były maksymalnie spersonalizowane w ramach bieżącego kontekstu. Ostatecznie mogłoby paść pytanie, czy kod wygenerowany w naszym imieniu przez algorytmu sztucznej inteligencji jest własnością AWS czy jednak naszą? Bez nadmiernych komplikacji, służę tutaj od razu z odpowiedzią: kod pozostaje tylko i wyłącznie własnością naszą (dewelopera).

Podsumowując, wydaje mi się, że zebrane tutaj przykłady posłużyły za dowód na to, jak bardzo chmura dokonuje niemal codziennie rewizji naszych dotychczasowym przyzwyczajeń i metod pracy z technologią. Coraz częściej zdarzają się sytuacje, w których niekiedy nie jesteśmy nawet świadomi faktu, że korzystamy w danym momencie z usług świadczonych za pośrednictwem chmury. Sposób tworzenia nowych aplikacji i produktów różni się diametralnie od tego, który możemy znać sprzed wielu lat. Ewolucja, którą zapoczątkowała chmura dopiero nabiera rozpędu. Sadzę personalnie, że przed nami jeszcze wiele większych i mniejszych rewolt, których prowodyrem będzie właśnie wspomniana chmura, zaś sam kierunek jakim są usługi chmurowe będzie (już jest) trendem numer jeden w świecie technologii IT.

-

Wpis powstał przy współpracy z AWS

Hej, jesteśmy na Google News - Obserwuj to, co ważne w techu