Od VM do PaaS
Usługi chmurowe, laboratorium 3
Agenda
- Stan startowy i Resource Group projektu
- App Service Plan i Web App
- App Settings
- Paczka ZIP i wdrożenie
- Test przez HTTPS
- Log stream
- Konfiguracja, restart, stop: co z danymi?
- Porównanie VM i PaaS, koszt
- Raport i sprzątanie
Architektura: przed i po
przed (po cleanup L02):
Azure: brak zasobów kursu
L02 dla porównania:
Internet -> Public IP -> NSG -> VM -> systemd -> gunicorn :8000 -> CloudNotes
po L03:
Client -> HTTPS -> App Service (app-cloudnotes-<SUFFIX>, plan F1)
-> gunicorn -> CloudNotes (SQLite i pliki w /tmp instancji)
App Service: dwa zasoby
| Zasób | Rola | Odpowiednik z L02 |
|---|---|---|
| App Service Plan | compute: system, poziom, liczba instancji, cena | VM i jej rozmiar |
| Web App | aplikacja: kod, runtime, konfiguracja, adres | aplikacja i unit systemd |
Płacisz za plan, nie za aplikację.
Kategoria: Application Platform (PaaS) Azure App Service / AWS Elastic Beanstalk / Google App Engine
Zasoby projektu zostają
| Rodzaj | Gdzie | Cykl życia |
|---|---|---|
| tymczasowe | rg-labNN | usuwane na końcu zajęć |
| projekt CloudNotes | rg-cloudnotes | zostają, jeśli są tanie |
| drogie elementy projektu | rg-cloudnotes | usuwane, odtwarzane z checkpointu |
Od dziś potrzebny jest <SUFFIX>: adres app-cloudnotes-<SUFFIX>.azurewebsites.net musi być globalnie unikalny.
Koszt
| Plan | Cena | Uwagi |
|---|---|---|
| F1 Free, Linux | 0 USD | współdzielone compute, limit CPU na dobę, 1 instancja, brak Always On, brak SLA |
| B1 Basic, Linux | około 0,018 USD/h, około 13 USD/miesiąc | tylko wariant awaryjny |
- F1: grupa
rg-cloudnoteszostaje do L04 - B1: usuwasz grupę na końcu zajęć
Krok 1, 3: start i Resource Group
az provider register --namespace Microsoft.Web --wait
az group create --name rg-cloudnotes --location <REGION>
Krok 4: App Service Plan
az webapp list-runtimes --os linux --output tsv | grep PYTHON
az appservice plan create --resource-group rg-cloudnotes --name plan-cloudnotes-<SUFFIX> \
--location <REGION> --is-linux --sku F1
| L02 (IaaS) | L03 (PaaS) |
|---|---|
rozmiar Standard_B2ats_v2 | poziom F1 |
| obraz Ubuntu | --is-linux |
| VNet, subnet, NSG, IP, dysk | — |
Krok 5: Web App
az webapp create --resource-group rg-cloudnotes --plan plan-cloudnotes-<SUFFIX> \
--name app-cloudnotes-<SUFFIX> --runtime "PYTHON:3.12" --https-only true
az resource list --resource-group rg-cloudnotes \
--query "[].{name:name, type:type}" --output table
https://app-cloudnotes-<SUFFIX>.azurewebsites.net: strona domyślna, z HTTPS- 2 zasoby (na L02: 6)
- Bez kodu mamy już: system, Python, DNS, certyfikat, load balancer
Krok 6: App Settings
az webapp config appsettings set --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX> \
--settings APP_ENVIRONMENT=app-service SCM_DO_BUILD_DURING_DEPLOYMENT=true
def setting(name, default=None):
return os.environ.get(name) or default
- App Settings -> zmienne środowiskowe procesu
APP_ENVIRONMENT: czyta aplikacjaSCM_DO_BUILD_DURING_DEPLOYMENT: czyta mechanizm wdrożenia (build,pip install)- L02:
Environment=w unicie. Kod ten sam.
Krok 7: paczka ZIP
git archive HEAD:project/src --format=zip --output=cloudnotes-app.zip
unzip -l ~/cloudnotes-app.zip
app.pyirequirements.txtw korzeniu paczki- Bez
.venv/i__pycache__/ - Paczka = artefakt wdrożeniowy, powtarzalny dla commita
Krok 8: wdrożenie
time az webapp deploy --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX> \
--src-path ~/cloudnotes-app.zip --type zip
ZIP -> Kudu -> Oryx build (venv, pip install)
-> kontener Python 3.12 -> gunicorn --bind=0.0.0.0 --timeout 600 app:app
Portal: Deployment Center -> Logs -> Running oryx build
Plan Free: kilka minut cierpliwości.
Krok 9: test przez HTTPS
curl -s https://app-cloudnotes-<SUFFIX>.azurewebsites.net/health | jq
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" \
http://app-cloudnotes-<SUFFIX>.azurewebsites.net/health
healthy,environment: app-service- HTTP ->
301-> HTTPS - Dodaj notatki (jedna z załącznikiem), wygeneruj raport
- Backendy:
sqlite,local,sync. Dane nadal na instancji.
Krok 10: log stream
az webapp log config --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX> \
--docker-container-logging filesystem
az webapp log tail --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX>
Drugi terminal:
curl -s -o /dev/null -w "%{http_code}\n" https://app-cloudnotes-<SUFFIX>.azurewebsites.net/debug/error
- Aplikacja pisze na stdout, platforma zbiera
- L02:
journalctlpo SSH. L03: API, CLI, portal. 500= aplikacja działa i ma błąd -> logi
Krok 11: zmiana konfiguracji
az webapp config appsettings set --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX> \
--settings APP_ENVIRONMENT=app-service-test
curl -s https://app-cloudnotes-<SUFFIX>.azurewebsites.net/health | jq "{environment, instance, started_at}"
curl -s https://app-cloudnotes-<SUFFIX>.azurewebsites.net/api/notes | jq ".notes | length"
| przed | po | |
|---|---|---|
environment | app-service | app-service-test |
started_at | stary | nowy |
| notatki | 4 | 0 |
Na koniec przywróć APP_ENVIRONMENT=app-service.
Krok 12: restart
az webapp restart --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX>
| Ścieżka w kontenerze | Cykl życia |
|---|---|
/tmp, system kontenera | znika przy restarcie |
/home (m.in. /home/site/wwwroot) | trwały udział sieciowy planu |
- CloudNotes trzyma dane w
/tmp/cloudnotes-> restart kasuje stan - PaaS zdjął z nas serwer, nie rozwiązał problemu stanu
- SQLite w
/home? Udział sieciowy, wiele instancji: zły pomysł
Rozwiązanie: Object Storage (L04), Managed Database (L05)
Krok 13: stop
az webapp stop --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX>
curl -s -o /dev/null -w "%{http_code}\n" https://app-cloudnotes-<SUFFIX>.azurewebsites.net/health
az webapp start --resource-group rg-cloudnotes --name app-cloudnotes-<SUFFIX>
| Akcja | Koszt płatnego planu |
|---|---|
az webapp stop | nadal naliczany |
| zmiana planu na F1 | 0 |
| usunięcie planu | 0 |
403 - This web app is stopped odpowiada platforma, nie CloudNotes.
Krok 14: VM a PaaS
| Zadanie | L02: VM | L03: App Service |
|---|---|---|
| sieć, reguły, publiczny IP | ja | ? |
| HTTPS i certyfikat | brak | ? |
| system i aktualizacje | ja | ? |
| Python, zależności, Gunicorn | ja | ? |
| konfiguracja | Environment= | ? |
| logi | journalctl po SSH | ? |
| stan po restarcie | znika | ? |
Ceny B1 szukasz w cenniku (pełne polecenie w instrukcji). Sweden Central: około 13,14 USD/miesiąc.
Kompromisy PaaS
Zyskujemy:
- brak zarządzania systemem, runtime i serwerem aplikacji
- HTTPS, DNS, logi, restart procesu: od platformy
- powtarzalne wdrożenie artefaktu
Tracimy:
- wybór systemu i dowolnych pakietów systemowych
- tylko obsługiwane wersje runtime i sposób uruchamiania
- limity planu, mechanizmy specyficzne dla dostawcy
Weryfikacja
Raport ~/l03-report.txt (polecenie w instrukcji):
- plan
F1(lubB1), Linux - aplikacja
Running,httpsOnly,PYTHON|3.12 - dokładnie 2 zasoby w
rg-cloudnotes - App Settings:
APP_ENVIRONMENT=app-service,SCM_DO_BUILD_DURING_DEPLOYMENT=true /healthprzez HTTPS:healthy- HTTP ->
301 - cena B1 z cennika
Sprzątanie
Wariant F1: grupa zostaje.
az appservice plan show --resource-group rg-cloudnotes --name plan-cloudnotes-<SUFFIX> --query "sku.name" --output tsv
rm ~/cloudnotes-app.zip
az group list --tag course=cloud-services --query "[].{name:name, lab:tags.lab}" --output table
Wariant B1: usuń grupę.
az group delete --name rg-cloudnotes --yes --no-wait
az group wait --name rg-cloudnotes --deleted
az group exists --name rg-cloudnotes
Odtworzenie na L04: sekcja „Odtworzenie stanu cp03-app-service”.
Podsumowanie
- Plan = compute i koszt, Web App = aplikacja
- Dostarczam kod i konfigurację, platforma resztę
- Paczka ZIP to artefakt, build robi platforma
- App Settings = zmienne środowiskowe; zmiana restartuje aplikację
- Logi: stdout, zbiera platforma
stopaplikacji nie zatrzymuje kosztu planu- Restart kasuje stan lokalny, także w PaaS
Następnie: L04, pliki poza instancją (Blob Storage).