Infraštruktúra postavená na kontajneroch
o kontajneroch, o (mikro) službách spustených v kontajneroch, o metodológii The Twelve-Factor App
Motivácia
- (slide) doteraz sme sa pohybovali na nižších vrstvách, dnes sa porozprávame o tom, ako to vyzerá v cloud-e a akým spôsobom tam budem nasadzovať naše riešenia/služby
- urobíme to na príklade jednoduchej webovej služby (tzv. microservice) a porozprávame si o tom, ako ju pripraviť pre produkčné nasadenie, na čo si dávať pozor
The Microservice
(slide) urobíme jednoduchú mikroslužbu na získanie info o počasí
zacneme tym, ze vytvorime náš projekt. v ňom vytvoríme priečinok
app/
a v nom vytvorime subormain.py
s tymto obsahom:
from fastapi import FastAPI
import pendulum
= FastAPI()
app
@app.get('/api/weather/{query}')
def get_weather(query: str):
= 'http://api.openweathermap.org/data/2.5/weather'
url = {
params 'q': query,
'units': 'metric',
'appid': '98113cc2ea891cc2246900c7dc6a8038'
}= httpx.get(url, params=params)
response return response.json()
if __name__ == '__main__':
'main:app', reload=True, host='0.0.0.0', port=8000) uvicorn.run(
Nasadenie aplikácie
starý spôsob
- na čistom stroji/virtuálnom stroji
- ručné nasadenie (nemusí byť)
- aktualizácia môže dať zabrať vzhľadom na to, čo je nainštalované na samotnom stroji. môže byť výhodnejšie (aj ked zdlhavejšie vytvorenie nového virtuálneho stroja a nahradiť s ním predchádzajúcu verziu)
pomocou kontajnerov
našim cieľom bude nasadiť túto aplikáciu pomocou Docker kontajneru
Virtuálne stroje vs kontajnery
Čo je to Docker?
Ak sa pozrieme priamo do dokumentácie Docker-a, nájdeme ako odpoveď na túto otázku toto:
Docker je otvorená platforma pre vývoj, nasadzovanie a spúšťanie aplikácií.
Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code, you can significantly reduce the delay between writing code and running it in production.
Čo je to kontajner?
Kontajner je inštanciou obrazu. Pre jednoduchosť sa zatiaľ môžeme na obraz pozerať ako na zip balík, v ktorom je zabalená aplikácia. Spustením obrazu vznikne kontajner, pričom z jedného obrazu je možné spustiť viacero kontajnerov.
proces spustený v izolovanom prostredí nad jadrom lokálneho OS
Čo je to obraz?
Obrazy sú nemenné!
Ak by sme hľadali nejakú paralelu, tak sa môžeme pozrieť na súbory uložené na disku:
- (spustiteľný) súbor reprezentuje obraz
- súbor je nemenný (je určený na čítanie)
- spustením súboru vzniká proces, ktorý reprezentuje kontajner
- z jedného súboru viem spustiť ľubovoľný počet procesov
- každý spustený proces je jednoznačne identifikovaný svojim PID
Vytvorenie obrazu pre aplikáciu
# zakladny obraz
FROM python:3.12-slim
# nainstalujem potrebne softverove vybanie
RUN pip install httpx fastapi[standard]
# prekopirujem svoj zdrojovy kod
COPY app/ /app
# poviem, co sa ma spustit pri spusteni kontajnera
EXPOSE 8000
WORKDIR /app
#CMD [ "fastapi", "dev", "main.py" ]
CMD [ "uvicorn", "main:app", "--reload", "--host=0.0.0.0" ]
Obraz zostavíte príkazom:
$ docker image build --tag pocko .
Best Practices
The Twelve-Factor app
(slide) The Twelve-Factor App je methodológia pre tvorbu aplikácií typu softvér ako služba (z angl. software-as-a-service). :
- Use declarative formats for setup automation, to minimize time and cost for new developers joining the project;
- Have a clean contract with the underlying operating system, offering maximum portability between execution environments;
- Are suitable for deployment on modern cloud platforms, obviating the need for servers and systems administration;
- Minimize divergence between development and production, enabling continuous deployment for maximum agility;
- And can scale up without significant changes to tooling, architecture, or development practices.
Konfigurácia pomocou premenných prostredia
Aby sme mohli komunikovať so službou OpenWeather, potrebujeme do každého dopytu vložiť aj API token. Ten získame po registrácii do služby a prípadne aj zaplatením poplatku. Tento token je však súkromný a každý používateľ aj našej služby by mal používať ten svoj.
Aktuálne je súčasťou kódu našej aplikácie aj token pre prístup k API služby OpenWeather. Tento prístup je porušením metodológie The Twelve-Factor App, ktorá vyžaduje striktné oddelenie konfigurácie od kódu aplikácie. Odporúčaním metodológie je miesto toho umiestniť konfiguráciu do tzv. premenných prostredia.
Premenné prostredia
(slide) Premenné prostredia (z angl. environment variables) sú premenné nastavené používateľom v operačnom systéme, pomocou ktorých je možné ovplyvňovať správanie spustených aplikácií.
Premenné prostredia sú nastavené mimo zdrojového kódu aplikácie a aj mimo konfiguračných súborov aplikácie. Používajú sa na nastavenie tých hodnôt, ktoré sa menia medzi nasadeniami aplikácie, ako napríklad:
- umiestnenie databázového serveru a prístup k nemu
- prihlasovacie údaje a umiestnenie vzdialenej služby, od ktorej závisí tá naša
- port, na ktorom bude aplikácia spustená
Operačný systém samotný obsahuje množstvo premenných prostredia. Ich
zoznam si viete zobraziť príkazom printenv
. Od ostatných
premenných ich odlíšite najmä tým, že používajú tzv.
SCREAMING_SNAKE_CASE notáciu pre pomenovávanie premenných.
Ak však budete chcieť premenné prostredia vytvoriť z príkazového riadku systému Linux, musíte ich exportovať. Napríklad:
$ export DB_URI=postgresql+psycopg2://scott:tiger@localhost:5432/mydatabase
Premenné prostredia vo forme konfigurácie aplikácie sa často ukladajú
do súboru .env
alebo do súborov s príponou
.env
, ako napríklad local.env
. Tento súbor
obsahuje zoznam premenných spolu s ich hodnotami vo formáte
kľúč=hodnota
. Vyzerať môže napr. takto:
DB_HOST=localhost
DB_USER=scott
DB_PASSWORD=tiger
DB_NAME=mydatabase
Upozornenie
Súbor .env
NIKDY!!! neposielajte do repozitára s vašimi
zdrojovými kódmi, pretože obsahuje citlivé informácie častokrát pre
prístup k vzdialeným službám alebo databázam! Ak sa takýto súbor do
repozitára dostane, je to považované za únik citlivých informácií. Preto
si do súboru .gitignore
vždy pridajte záznam, ktorý zamedzí
odosielaniu týchto súborov do repozitára.
Kolízia mien sa rieši prefixom.
Konfigurácia aplikácie pomocou premenných prostredia
V jazyku Python na prácu s premennými môžeme použiť priamo balík
os
a v ňom slovník environ
. Obsahuje premenné
prostredia pre spustenú aplikáciu.
Miesto toho však použijeme balík pydantic-settings
,
ktorý je rozšírením modulu pydantic
a je možné vytvárať
modely pre potreby nastavenia. Výhodou je, že automaticky model
zvaliduje a dokáže rovno načítať údaje zo súboru .env
, ak
sa taký v priečinku, z ktorého sa aplikácia spúšťa, nachádza.
class Settings(BaseSettings):
str = 'bar'
token: int = 1
apple:
= SettingsConfigDict(
model_config ='POCKO_',
env_prefix='utf-8',
env_file_encoding='.env',
env_file )
Následne upravíme hlavný kod tak, aby konfiguráciu použil:
@app.get('/api/weather/{query}')
def get_weather(query: str):
= 'http://api.openweathermap.org/data/2.5/weather'
url = {
params 'q': query,
'units': settings.units,
'appid': settings.token
}= httpx.get(url, params=params)
response return response.json()
Tým sme vyriešili konfiguráciu služby podľa metodológie The Twelve-Factor App.
Healthcheck
Problém
spravovať distribuované systémy je náročné. skladajú sa totiž z veľkého množstva súčastí, ktoré potrebujú pracovať (a spolupracovať), aby systém mohol ako celok fungovať.
ak sa niektorá jeho súčasť pokazí, systém ju musí:
- detegovať, napr. vytvorením alertu,
- obísť ju, napr. load balancer nebude posielať požiadavky na nefungujúcu službu, a
- opraviť ju, resp. zotaviť sa z nej.
a to všetko sa musí udiať automagicky.
ako teda detegovať, že bežiaca služba nedokáže spracovávať požiadavky?
Čo je to Healthcheck?
Health check poskytuje jednoduchý mechanizmus,
pomocou ktorého je možné overiť, či daná služba pracuje správne.
obyčajne má služba vytvorené Health Check API pomocou protokolu HTTP
(napr. /health
), ktorá pomocou HTTP stavových kódov hovorí
o stave služby. Je možné sa však stretnúť aj s prípadmi, kedy sa
kontrola stavu služby vykonáva pomocou metódy HEAD nad niektorým
existujúcim endpointom.
okrem stavového kódu sa môže vo výsledku HTTP požiadavky nachádzať aj krátky JSON dokument, ako napr.:
{
"status" : "UP"
}
What to Check in Health Check API
v rámci kontroly zdravia služby sa môže overovať napr.:
- stav spojenia s ostatnými službami,
- stav stroja, napr. jeho diskový priestor, využitie pamäte a pod.,
- špecifická logika aplikácie,
- stav databázy,
- a iné.
Z-Pages
(slide) Ako endpoint pre Health
Check API sa dá stretnut s názvom /healthz
, ktorý používa
napr. Grafana S týmto konceptom prišiel Google a endpoint-y, ktoré
končia s písmenom Z sa nazývajú Z-Pages. Ide o to, aby nedošlo k
zameneniu názvov mnozneho cisla endpointov REST API, aby bolo jasne, ze
toto tu je specialny endpoint
Jednoduchý healthcheck
@app.head('/api/healthz')
@app.get('/api/healthz')
def check_health():
return {
'status': 'up'
}
Health Check in Containers
okrem toho však s kontrolou stavu súvisí aj kontrola stavu kontajnera, v ktorom je aplikácia spustená. kontajnery totiž bežia 24/7 a aj tu môže dôjsť k niektorým situáciám:
- stav kontajneru
- aktualizácia aplikácie v kontajneri
takže ak aplikácia beží v kontajneri a ten je spustený, nemusí to hneď znamenať, že aplikácia vo vnútri kontajneru pracuje správne. kontrolu teda treba vykonávať ako na úrovni aplikácie, tak aj na úrovni kontajnera.
na urovni kontajnerov mame podporu priamo pri definicii obrazu v
súbore Dockerfile
. k dispozícii je klucove slovo
HEALTHCHECK
a kontrola moze vyzerat napriklad takto:
HEALTHCHECK \
--interval=30s \
--timeout=3s \
--retries=3 \
--start-period=0 \
CMD curl --fail http://localhost:8000/api/health || exit 1
Vyznam jednotlivych volieb klucoveho slova HEALTHCHECK
je nasledovny:
--interval=<interval>
- Interval medzi dvoma kontrolami, predvolena hodnota je30
sekúnd.--timeout=<time length>
- Prikaz na kontrolu sa bude vykonavat zadany cas. Ak tento cas uplynie, kontrola zdravia bude považovaná za neuspesnu. Predvolena hodnota je30
sekúnd.--retries=<number>
- Ak dany pocet krat po sebe kontrola zdravia zlyhá, kontajner bude považovaný za nezdravy. Predvolena hodnota su3
pokusy.--start-period=<duration>
- Po akom čase sa má kontrola spustiť. Tento čas je určený pre naštartovanie samotnej aplikácie.
Kompozícia
db + app + klient do db
services:
Záver
Ďalšie zdroje
- The Twelve-Factor App methodology
- Containers (Docker) vs Virtual Machines (VM): Pros, Cons, and Use Cases
- microservices.io Pattern: Health Check API