dpzc-4/03_IaaS/03_03.ipynb
nlitkowski e248075771 a
2022-01-05 01:08:54 +01:00

282 lines
18 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Zadania do realizacji w czasie zajęć\n",
"\n",
"## Założenie konta na Hetzner Cloud\n",
"\n",
"1. Wejdź na stronę <https://accounts.hetzner.com> i zarejestruj nowe konto. Możesz skorzystaj ze studenckiego adresu email, ułatwi to dodanie odpowiednich uprawnień do Twojego konta.\n",
" Proces rejestracji wymaga odebrania linku aktywacyjnego oraz podania podstawowych danych osobowych. Jako formę płatności można wybrać przelew bankowy. \n",
" \n",
"1. W ramach zajęć zostaniesz przypisany do puli zasobów, która będzie opłacana przez Wydział. Zweryfikuj dostęp do projektu o nazwie ***PZC***, którego właścicielem jest Wydział.\n",
"\n",
"## Instalacja Wordpress w środowisku Hetzner\n",
"\n",
"Celem tego zadania będzie instalacja *Wordpressa* - najpopularniejszego systemu zarządzania treścią (CMS), w infrastrukturze typu IaaS z wykorzystaniem dostępu przeglądarkowego. Proces instalacji wykonamy ręcznie krok po kroku. Na następnych zajęciach przedstawione zostanie jak zautomatyzować instalację poprzez uruchomienie skryptu.\n",
"\n",
"### Centralna baza danych\n",
"\n",
"Pierwszym krokiem przy instalacji *Wordpresa* jest zainstalowanie i skonfigurowanie bazy danych. Hetzner nie oferuje zarządzanych baz danych w modelu SaaS (patrz następne zajęcia), dlatego na tym etapie będziemy również odpowiedzialni za instalację bazy i jej późniejsze utrzymanie. Jednak aby istotnie uprościć proces i wyabstrachować zbędne szczegóły, do uruchomienia oprogramowania wykorzystamy narzędzie **Docker**. \n",
"\n",
"Docelowo dążymy do uzyskania następującej konfiguracji:\n",
"\n",
"![Diagram przedstawia pojedynczą maszynę wirtualną z uruchomionymi na niej dwoma kontenerami docker: bazą danych MySql oraz webowym interfejsem administracyjnym phpMyAdmin. Komunikacja pomiędzy kontenerami odbywa się za pośrednictwem wewnętrznej sieci zarządzanej przez dockera. PhpMyAdmin jest udostępniony na publicznym adresie IP maszyny wirtualnej na porcie 8080.](obrazy/wp-etap1.png)\n",
"\n",
"\n",
"1. Rozpoczynając pracę w interfejsem webowym [chmury obliczeniowej Hetzner](https://cloud.hetzner.com) nie dysponujemy żadnymi zasobami. W ramach zasobów dostępnych w ramach zajęć powinieneś być przydzielony do dwóch projektów: *Default* oraz *PZC*. Pamiętaj, że maszyny wirtualne utworzone w projekcie *PZC* opłącene są przez Wydział, podczas gdy za te utwożone w projekcie *Default* rachunek zostanie wystawiony na dane podane przy rejestracji konta.\n",
" <img src=\"obrazy/hetzner-pusty.png\" width=\"75%\" alt=\"\">\n",
"\n",
"1. Wybieramy opcję utworzenia nowej maszyny wirtualnej i wybieramy następujące dane:\n",
"\n",
" <img src=\"obrazy/hetzner-vm-1.png\" width=\"75%\" alt=\"\">\n",
" <img src=\"obrazy/hetzner-vm-2.png\" width=\"75%\" alt=\"\">\n",
" - lokalizacja: Helsinki (nowesze serwery, lepszy transfer do polski, niższe ceny, wsparcie w języku angielskim)\n",
" - obraz systemu: Ubuntu 20.04 lub nowsze (Ubuntu serwer jest najlepszym wyborem dla początkujących administratorów)\n",
" - typ instancji: CX11 (1 vCPU, 2GB RAM, 20GB SSD, cena na poziomie 3 groszy za godzinę)\n",
" - dyski: brak\n",
" \n",
"1. W kroku *Sieć* tworzymy nową sięć prywatną o nazwie `network-1` i puli adresów `10.10.10.0/24`.\n",
" \n",
" <img src=\"obrazy/hetzner-network.png\" width=\"75%\" alt=\"\">\n",
"\n",
"1. Pomijamy dodanie zapory sieciowej oraz dodatkowych funkcjonalności. Podajemy natomiast klucz SSH, który będzie służył do logowania się na naszą maszynę na konto `root`.\n",
"\n",
" <img src=\"obrazy/hetzner-ssh-key.png\" width=\"75%\" alt=\"\">\n",
"\n",
" > **Uwaga**: Teoretycznie Hetzner umożliwia logowanie się hasłem do utworzonych maszyn wirtualnych, jest to jednak bardzo nie rozważne. Proponuję przeprowadzić eksperyment polegający na utworzeniu maszyny wirtualnej z hasłem `admin` i zmierzeniu czasu po jakim dostęp do niej zostanie przejęty przez boty. Na szczęście zawsze możesz usunąć maszynę w interfejsie webowym Hetzner, nawet po przejęciu nad nią kontroli przez kogoś innego.\n",
"\n",
"1. Potwierdzamy chęć utworzenia maszyny wirtualnej i czekamy na jej inicjalizację. Całość powinna trwać około minuty. Po tym czasie nasza maszyna jest gotowa do użycia. Sprawdź jej dostępność logując się przez SSH na przypisany nowoutworzonej maszynie adres IP. \n",
"\n",
" <img src=\"obrazy/hetzner-po-vm.png\" width=\"75%\" alt=\"\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Teraz gdy dysponujemy nową maszyną wirtualną możemy rozpocząć instalację niezbędnego oprogramowania.\n",
"\n",
"1. Na początku musimy zainstalować oprogramowanie docker. Niestety wersje oferowane w repozytoriach Ubuntu są bardzo stare i nie jest zalecane ich używanie. Poniższy skrypt instaluje zarówno `docker`a jak i `docker-compose` zgodnie z zaleceniami twórców tych narzędzi.\n",
" ```bash\n",
" apt update && apt install apt-transport-https ca-certificates curl gnupg lsb-release\n",
" \n",
" curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg\n",
" \n",
" echo \\\n",
" \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\\n",
" $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\n",
" \n",
" apt update && apt install docker-ce docker-ce-cli containerd.io\n",
"\n",
" sudo curl -L \"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose\n",
" \n",
" chmod +x /usr/local/bin/docker-compose\n",
" ```\n",
"\n",
"1. Następnie należy stworzyć plik o nazwie `docker-compose.yml` o następującej treści. Lokalizacja pliku nie ma znaczenia.\n",
" ```docker-compose\n",
" version: '3.9'\n",
"\n",
" services:\n",
" db:\n",
" image: mysql:5.7\n",
" restart: always\n",
" environment:\n",
" MYSQL_ROOT_PASSWORD: notSecureChangeMe\n",
" volumes:\n",
" - db_data:/var/lib/mysql\n",
"\n",
" phpmyadmin:\n",
" image: phpmyadmin\n",
" restart: always\n",
" ports:\n",
" - 8080:80\n",
" volumes:\n",
" db_data: {}\n",
" ```\n",
"\n",
" W pliku tym definiujemy dwie usługi (samą bazę danych oraz webowy interfejs dostępowy). Wskazujemy też, że dostęp do bazy przez przeglądarkę będzie możliwy z portu 8080.\n",
"\n",
"1. Bazę danych uruchamiamy komendą:\n",
" ```bash\n",
" docker-compose up\n",
" ```\n",
" Aby wyłączyć bazę danych należy wcisnąć `Ctrl-C`.\n",
"\n",
" > **Wskazówka**: Jeśli chcesz usunąć utworzone kontenery wraz z zasobami dyskowymi zastosuj komendę `docker-compose down -v`. W ten sposób możesz zaczać od zera.\n",
"\n",
" > **Wskazówka**: Polecenie `docker-compose up -d` uruchamia nasze kontenery w tle.\n",
"\n",
"1. Odwiedź w przeglądarce adres: `http://<adres IP maszyny wirtualnej db>:8080` u zaloguj się używając nazwy użytkownika `root` oraz hasła podanego w pliku `docker-compose.yml`. Jest to webowy interfejs dostępowy do naszej bazy danych, który przyda się w dalszej części zajęć.\n",
"\n",
" <img src=\"obrazy/phpMyAdmin.png\" width=\"75%\" alt=\"\">\n",
"\n",
"\n",
"Udało się nam skonfigurować instancję bazy MySql. W obecnej konfiguracji nie jest ona zbytnio zabezpieczona, jednak zajmiemy się tym przy okazji instalacji Wordpress w następnym kroku."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Instalacja Wordpress\n",
"\n",
"Teraz naszym zadaniem jest zainstalować oprogramowanie Wordpress na osobnej maszynie wirtualnej. Ponownie wykorzystamy gotowe obrazy `docker` w celu otrzymania następującej konfiguracji:\n",
"\n",
"![Diagram przedstawia dwie maszyny wirtualne. Konfiguracja maszyny db została zaktualizowa tak aby baza danych była dostępna w sieci prywatnej. Nowa maszyna wirtualna wordpress-1 udostępnia CMS na porcie 8000 i komunikuje się z bazą danych wewnątrz sieci prywatnej.](obrazy/wp-etap2.png)\n",
"\n",
"1. Na maszynie wirtualnej z bazą danych (`db`) musimy dokonać pewnych zmian w konfiguracji. Przede wszystkim konieczne jest udostępnienie bazy danych na zewnątrz. Nie chcemy jednak aby była ona dostępna publicznie, a tylko w sieci prywatnej. Stąd podajemy konkretny prywatny adres IP przy udostępnianiu portów. Dodajemy też osobne konto i bazę danych dla Wordpresa. Wynikowy plik powinien wyglądać następująco.\n",
"\n",
" > **Uwaga**: Zwróć uwagę na przydzielony maszynie `db` prywatny adres IP, z reguły będzie to `10.10.10.2`. Możesz to sprawdzić w widoku szczegółów maszyny wirtualnej w interfejsie webowy w zakładce *Sieć*.\n",
"\n",
" ```docker-compose\n",
" version: '3.9'\n",
"\n",
" services:\n",
" db:\n",
" image: mysql:5.7\n",
" restart: always\n",
" ports:\n",
" - \"10.10.10.2:3306:3306\"\n",
" environment:\n",
" MYSQL_ROOT_PASSWORD: notSecureChangeMe\n",
" MYSQL_DATABASE: wordpress\n",
" MYSQL_USER: wordpress\n",
" MYSQL_PASSWORD: wordpress\n",
" volumes:\n",
" - db_data:/var/lib/mysql\n",
"\n",
" phpmyadmin:\n",
" image: phpmyadmin\n",
" restart: always\n",
" # przekierowanie portów zostawione tylko dla przykładu, nie należy tak robić na produkcji\n",
" ports:\n",
" - \"8080:80\"\n",
" volumes:\n",
" db_data: {}\n",
" ```\n",
"\n",
"1. Tworzymy drugą maszynę wirtualną o nazwie `wordpress-1`, wybierając identyczne opcje jak poprzednio.\n",
"\n",
"1. Logujemy się przez SSH na nową maszynę wirtualną i podobnie jak poprzednio tworzymy plik `docker-compose.yml` o następującej treści.\n",
"\n",
" ```docker-compose\n",
" version: '3.9'\n",
"\n",
" services:\n",
" wordpress:\n",
" image: wordpress:latest\n",
" volumes:\n",
" - wordpress_data:/var/www/html\n",
" ports:\n",
" - \"8000:80\"\n",
" restart: always\n",
" environment:\n",
" WORDPRESS_DB_HOST: \"10.10.10.2:3306\"\n",
" WORDPRESS_DB_USER: wordpress\n",
" WORDPRESS_DB_PASSWORD: wordpress\n",
" WORDPRESS_DB_NAME: wordpress\n",
" \n",
" volumes:\n",
" wordpress_data: {}\n",
" ```\n",
"\n",
" Tym razem korzystamy z oficjalnego obrazu Wordpress. Za pomocą zmiennych środowiskowych podajemy dane dostępowe do bazy danych. Zwróć uwagę na zmienną środowiskową `WORDPRESS_DB_HOST`, która wskazuje na adres prywatny serwera `db`.\n",
"\n",
"1. W przeglądarce odwiedź adres `http://<adres IP maszyny wirtualnej wordpress-1>:8000` i dokończ instalację Wordpress.\n",
"\n",
"W ten sposób zakończyła się instalacja Wordpress. Serwer web oraz baza danych znajdują się na osobnych maszynach wirtualnych, ponadto baza danych dostępna jest tylko z poziomu wirtualnej sieci prywatnej."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Mechanizm równoważenia obciążenia i migawki systemu\n",
"\n",
"W kolejnym etapie dodamy mechanim równoważenia obciążenia oraz drugą maszynę wirtualną na której działał będzie Wordpress. W tym celu wykorzystamy mechanim migawek maszyn wirtualnych. Dążymy teraz do otrzymania następującej konfiguracji:\n",
"\n",
"![Diagram przedstawia ewolucję poprzedniej konfiguracji. Dodano mechanizm równoważenia obciążenia, który teraż nasłuchuje na porcie 80 i przekazuje ruch do dwóch niezależnych maszyn wirtualnych korzystając z sieci wewnętrznej.](obrazy/wp-etap3.png)\n",
"\n",
"1. Wyłącz maszynę wirtualną `wordpress-1`. Możesz to zrobić np. wydając komendę:\n",
" ```bash\n",
" shutdown now\n",
" ```\n",
" \n",
" Zweryfikuj, że maszyna jest wyłączona w interfejsie webowym.\n",
"\n",
"1. Utworz migawkę tej maszyny. W tym celu wejdź w widok szczegółów maszyny i wybierz opcję *Migawka*. Potwierdź chęć jej utworzenia i poczekaj aż proces dobiegnie końca.\n",
"\n",
"1. Migawka pozwala na stworzenie nowej maszyny wirtualnej na bazie obecnie istniejącej. Pozwoli nam to oszczędzić czas i zapewni jednolitość obu istancji. Przejdź do tworzenia nowej maszyny wirtualnej i tym razem w sekcji *Obraz systemu* wybierz opcję *Migawka*. Pozostałe opcje ustaw tak jak poprzednio, a maszynę nazwij `wordpress-2`. W między czasie możesz też uruchomić ponownie maszynę `wordpress-1`.\n",
"\n",
"1. Możesz teraz zweryfikować, że na obu maszynach działa ten sam wordpress. Dodaj przykładowy post na jednym z nich i sprawdź czy pojawi się na drugim.\n",
"\n",
"1. Czas na stworzenie i konfigurację równoważenia obciążenia. Przechodzimy do odpowiednij opcji w interfejsie webowym i wybieramy następującą konfigurację:\n",
" - lokalizacja: Helsinki\n",
" - typ: LB11\n",
" - sieć: network-1\n",
" - cele: wybieramy obie maszyny wirtualne z wordpresem i zaznaczamy komunikacje przez prywatny adres\n",
" - usługi: http, port źródłowy 800, port docelowy 8000, \n",
" - sprawdzanie stanu maszyn: wybieramy opcję *sticky sessions* z czasem ustawionym na 60 sekund, zmieniamy port docelowy na 8000, upewniamy się że *proxy protocol* jest wyłączony\n",
"\n",
" Potwierdzamy chęć utworzenia mechanizmu równoważenia obciążenia. Jego inicjalizacja może trochę potrwać, ale w przeglądarce już można przejść pod `http://<adres IP LB>:8000/`\n",
"\n",
" <img src=\"obrazy/hetzner-lb.png\" width=\"75%\" alt=\"\">\n",
"\n",
"1. Zwróć uwagę, że przy próbie zalogowanie zostajemy automatycznie przekierowani na adres IP pierwszej maszyny wirtualnej. Wynika to z domyślnego zachowania Wordpresa. Aby to naprawić należy, wejść w interfejs webowy bazy danych i wyedytować dwa wiersze w tabeli `wp-options`: `siteurl` oraz `home`, podając tam adres IP mechanizmu równoważenia obciążenia.\n",
"\n",
" > **Uwaga**: Wordpress nie jest przystosowany do łatwego przenoszenia/zmieniania adresu URL na którym pracyje.\n",
"\n",
" > **Uwaga**: W rzeczywistych warunkach nasza strona dostępna była by za pomocą adresu domenowego i powinna zostać od samego początku skonfigurowana jako dostępna pod tym adresem. Adres ten powinien być następnie przekierowany na początku na maszynę `wordpres-1` a następnie na mechanimz równoważenia obciążenia. Niestety opóźnienia propagacji wpisów DNS uniemożliwiają przeprowadzenie tego w ramach zajęć. \n",
"\n",
"1. Sprawdźmy czy nasza strona jest teraz rzeczywiście obsługiwana jednocześnie przez dwie maszyny wirtualne. W tym celu korzystając z adresu IP mechanizmu równoważenia obciążenia, dodaj nowy post zawierający jeden obraz (wgrany na serwer, nie przez URL czy z biblioteki).Odczekaj chwilę (60 sekund) lub otwórz stronę w innej przeglądarce/trybie incognito. Czasem trzeba to powrórzyć kilka razy. Co się dzieje ?\n",
"\n",
" > **Wskazówka**: Można też uruchomić narzędzia deweloperskie przeglądarki (Crtl-I) i ręcznie usunąć ciasteczko `HCLBSTICKY`, które powoduje utrzymanie powiązania przeglądarki z kontkretną maszyną wirtualną.\n",
"\n",
"1. Zaobserwowane zjawisko pokazuje, kluczowy problem z taką instalacją Wordpress. Konieczne jest utrzymanie synchronizacji pomiędzy dyskami obu maszyn wirtualnych (to tam przechowywane są przesłane na serwer obrazy). Przykładowo jeszcze większe problemy moglibyśmy obserwować przy aktualizacji Wordpresa, gdy tylko jedna z instancji została by zaktualizowana. Rozwiązanie tego problemu wymaga ingerencji w Wordpresa i zostanie pokazane na jednych z następnych zajęć."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Problemy otwarte\n",
"\n",
"Zastanów się nad następującymi problemami:\n",
"\n",
"1. W jaki sposób moglibyśmy zabezpieczyć się przed utratą zgormadzonych na stronie danych.\n",
"1. Jaki jest koszt takiej infrastruktury (wliczając kopie zapasowe, migawki, itp). Porównaj go z kosztem zakupu hostowanego Wordpresa w modelu SaaS na <https://www.wordpress.com>.\n",
"1. Co się stanie gdy zmienimy skórkę w tak skonfigurowanym Wordpresie.\n",
"1. Jakie jeszcze problemy mogą wyniknąć przy takiej instalacji Wordpresa."
]
}
],
"metadata": {
"interpreter": {
"hash": "98b0a9b7b4eaaa670588a142fd0a9b87eaafe866f1db4228be72b4211d12040f"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}