W poprzednim blogu #4-jak-zbudowac-rest-api-dla-prostego-formularza-kontaktowego-wykorzystujacy-ajax stworzyliśmy aplikacje, która
w cudowny sposób umożliwia ludziom odwiedzającym nasz serwis wysłać nam wiadomość e-mail poprzez formularz kontaktowy w html i js.
Teraz posiadając gotową aplikacje, chcielibyśmy ją w końcu uruchomić „produkcyjnie”, czyli prosto mówiąc potrzebujemy hostingu dla udostępnia aplikacji. Moglibyśmy to zrobić w tradycyjny sposób kupując maszynę wirtualną i następnie:
- zainstalować i skonfigurować wszystkie na niej potrzebne komponenty,
- wpiąć ją w jakiś sensowny monitoring,
- ogarnąć dla niej sieć, firewalle, potrzebne dostępy,
- a z czasem przydałby się też mechanizm do wysokiej dostępności aplikacji na wypadek większego ruchu( Black friday),
- no i nie zapomnijmy też o aspekcie utrzymania takiego systemu ( updaty, naprawa po updatach, ansible…).
…. i tu nagle robi się kupę roboty, aplikacja jest już gotowa, a prac administracyjnych na start zrobiło się z 20h 🙁
Pragniemy, żeby nasza aplikacja działała w jak najlepszy sposób, ale nie mamy zamiaru w to wszystko się bawić…
Naszym wybawieniem jest tutaj usługa AWS Elastic Beanstalk, która praktycznie rozwiązuję nam wszystkie poruszone kwestie administracyjne potrzebne dla aplikacji i pozwala nam się całkowicie oderwać od tematów hostingowych ( mniej serwerów ), czyli:
- Balansowania ruchu do aplikacji (wysoka dostępność). Automatycznie stworzy nam potrzebny AWS Elastic Load Balancer i skalowanie ilości potrzebnych instancji aplikacji zależnie od użytego średniego CPU wszystkich instancji poprzez czujkę w AWS CloudWatch alarm.
- Wszystkie elementy sieciowe tworzą się automatycznie, ale jak najbardziej możemy mieć to dalej pod kontrolą (security group,vpc, subnet).
- Nie interesuje nas utrzymanie i konfigurowanie całego systemu. Cała nasza praca polega na wrzuceniu nowej wersji aplikacji.
- Dostajemy system do automatycznego wdrożenia nowej wersji aplikacji i możliwości dzielenia jej na środowiska (np. TEST, PRODUKCJA).
- Mamy do dyspozycji historie i wersjonowanie wrzucanych paczek, w przypadku haniebnego błędu na produkcji, jednym kliknięciem (lub enterem) wracam do poprzedniej stabilnej wersji.
- Monitoring podstawowych metryk (CPU, IOPSY) dostajemy z pudełka, jest on dostępny w usłudze AWS Cloudwatch i jeśli mamy potrzebę zbierania logów to możemy włączyć AWS Cloudwatch Log Stream.
Nie brzmi to wszystko cudownie? a wiec do dzieła 🙂
1. Słowniczek
- AWS ( Amazon web service) – hosting, miejsce gdzie możemy wykupić moc obliczeniową i dyski dla naszej aplikacji. Dostawca dąży do zapewnienia jak największego serverless.
- Serverless – sposób lub metoda na udostępnianie aplikacji, w której jak najmniej zajmujemy się tematami serwerowymi. Serwery mają być dla nas przezroczyste, interesuje nas tylko aplikacja i dane zapisywane przez nią.
- Cloudwatch – system do trzymania logów i metryk na podstawie których możemy stworzyć Dashboardy i alarmy (np. kończące się cpu kredyty). Można ją porównać funkcyjnie do mocno ograniczonej grafany.
- Elastic Beanstalk – Mechanizm do umożliwienia jak najłatwiejszego wdrożenia aplikacji, osoba nie posiadająca wiedzy serwerowej na podstawie prostego webowego interfejsu może w łatwy i szybki sposób wdrożyć swoją aplikacje (jest tylko małe ale – aplikacja musi spełniać warunki awsowe). Domyślnie aplikacja jest uruchamiana w wysokiej dostępności.
- Elastic Load Balancer – Usługa do balansowania ruchu pomiędzy naszymi instancjami. Z definicji jest oparta o mechanizm faillover (istnieją przynajmniej dwie instancje do obsługi naszego ruchu), do używania go dostajemy do dyspozycji endpoint (adres http) .
- EC2 ( Elastic compute cloud )– awsowa wirtualka, istotnym parametrem jest jej typ, on definiuje ile zasobów ( RAM, CPU) dostaniemy za $.
2. Cel
Uruchomienie aplikacji api napisanej w pythonie 2.7 wykorzystującej bibliotekę falcon api (wsgi) oraz serwowanie statycznych plików html i js poprzez usługę Elastic Beanstalk. Wynikiem tych prac ma być w pełni działający formularz kontaktowy, który został stworzony w #4-jak-zbudowac-rest-api-dla-prostego-formularza-kontaktowego-wykorzystujacy-ajax. Ma być dostępny pod jednym linkiem, aplikacja ma mieć cechę wysokiej dostępności.
3. Realizacja
Do wykonania założonego celu możemy się posłużyć webowym interfejsem , który jest bardzo intuicyjny i przyjemny lub wykorzystać konsole aws api eb do wydawania poleceń.
Mój wybór pada na wydawanie komend do api, ponieważ komenda poleceń jest nie odłączną częścią mojego życia i według mnie daje większe możliwości do automatyzowania każdego procesu w formie skryptu 😉
3.1 Przygotowanie konta AWS do wydawania komend aws api eb.
Żeby w ogóle nasze konto mogło się komunikować z api to na użytkowniku, który posiada uprawnienia do tworzenia zasobów (np. ma podpiętą politykę AdministratorAccess ) musimy też włączyć Programmatic access co pozwoli mu na wygenerowanie Access key id i Secret Access key. Para kluczy jest używana do autoryzacji z api i jest wymagana do używania awsebcli.
Po uzyskaniu access key id i secret access key możemy przystąpić do instalacji narzędzi i stworzyć potrzebną instancje elastic beasnstalk dla naszej aplikacji:
Powyższe polecenie stworzyło na naszym koncie aws, zarodek naszej aplikacji pod nazwą contact, teraz czas na przygotowanie aplikacji do mod’u wsgi i środowiska dla niej w elastic beanstalk 🙂
3.2 Przygotowanie aplikacji contact do uruchomienia w środowisku produkcyjnym.
Elastic beanstalk, jakby nie patrzeć to wirtualka
( EC2 ) z już przygotowanym linuxem (Amazon Linux oparty o CentOs), która ma już na swoim pokładzie skonfigurowanego apache2 i mod_wsgi.
Żeby mod_wsgi mógł się w ogóle dogadać z naszą aplikacją, musimy mu przekazać parametr WSGIPath: api/app.py który wskaże w jakim pliku
znajduje się główny proces aplikacji, główny proces musi mieć zawsze nazwę application.
A także musimy przekazać systemowi jakie pakiety powinny już być zainstalowane na instancji ec2 przed uruchomieniem aplikacji.
Zależności do aplikacji definiujemy w pliku ./requirements.txt, a konfiguracje mod_wsgi i apache2 odbywają się w plikach ./$(WSGIPath)/.ebextensions/*.config
Struktura katalogów w naszym przypadku powinna wyglądać tak:
Pilk requirements.txt :
Prosty plik tekstowy, każda linia to nazwa jednego programu do zainstalowania przez pip install.
Plik api/.ebextensions/static.config :
Ten plik definiujemy w yamlu, tutaj podajemy wszystkie parametry do skonfigurowania mod_wsgi i apacha2, więcej na ten temat można odnaleźć aws eb docs
W sekcji static files definiujemy ReWrity na pliki statyczne (html,js,css). Jest to potrzebne, ponieważ domyślnie cały ruch będzie szedł do aplikacji, która nie została przygotowana na serwowanie plików statycznych.
W sekcji python podajemy ścieżkę do naszego programu w polu WSGIPath. Ważne – nie możemy używać WSGIAlias.
3.3 Przygotowanie środowiska elastic beanstalk.
Posiadając już stworzoną instancje AWS elasticbeanstlk contact, ostatnim krokiem jest stworzenie dla niej środowiska. Środowisko to nic jak stary podział aplikacji na etapy wdrożenia aplikacji (TEST, PREPROD, PRODUKCJA). Główne cechy środowiska to platforma (Python2.7) i typ (Czy to aplikacja frontowa czy backendowa).
Chcemy na razie stworzyć jedno środowisko, które będzie przeznaczone dla produkcji frontowej.
Wszystkie potrzebne elementy dla środowiska zostały automatycznie stworzone za jednym poleceniem (domyślnie usługa dąży do wysokiej dostępności) :
- S3 – zasób na pliki dla środowiska, tutaj będą trzymane wrzucane paczki.
- security group – firewall na poziomie interfejsu ec2, reguła do wpuszczania ruchu wchodzącego na porcie 80.
- Load balancer – element do balansowania ruchu http/s pomiędzy n instancji naszej aplikacji i terminowania SSL.
- Auto Scaling Group – Według niej definiujemy ilość instancji aktywnych, z czego mają się budować i możliwość zwiększania/zmniejszania ilości instancji. Jest ona wymagana w elbv2.
- CloudWatch alarm – są tworzone dwa alarmy (czujki), które na podstawie średniego użycia cpu wszystkich instancji, alarmują Auto scaling group żeby zwiększył lub zmniejszył ilości instancji aplikacji.
Jedynym problemem jak się pojawił to WSGIPatch, ponieważ jeszcze nie ma naszej aplikacji, bo nie skonfigurowaliśmy pliku ~/.elasticbeanstalk/config.yml 🙂
3.4 Przygotowanie paczki do deployu.
Do wrzucenia aplikacji do elastic beanstalk możemy podejść na dwa sposoby:
- wykorzystać gita podając nazwę gałęzi do wrzucenia nowej wersji.
- wrzucając aplikacje jako spakowane archiwum w zip.
W naszym przypadku nie posiadamy repozytorium gita dla aplikacji, więc posłużymy się wrzuceniem archiwum zip. Zatem musimy spakować nasze pliki do jednej paczki i przygotować konfiguracje elastic beanstalk do deployu.
Plik ~/.elasticbeanstalk/config.yml :
Plik musi się znajdować w home użytkownika, definiujemy w nim nazwę paczki i jego wersje.
Pakowanie plików aplikacji do jednego archiwum zip:
4. Uruchomienie aplikacji
No i nadszedł wielki czas! Czas na pierwszy deploy!
Status green, aplikacja uruchomiona bez błędów, gotowa do przyjmowania ruchu, poniżej printscreeny jak to wygląda z web consoli 🙂
Wyznaczony cel został spełniony, przy niewielkim nakładzie pracy stworzyliśmy wysoką dostępną architekturę aplikacji.