KK - 12 Factor App
Π‘ΡΡ ΠΎΠΉ ΠΊΠΎΠ½ΡΠΏΠ΅ΠΊΡ ΠΈ Π»Π°Π±ΠΎΡΠ°ΡΠΎΡΠ½Π°Ρ ΡΠ°Π±ΠΎΡΠ° ΠΏΠΎ ΠΊΡΡΡΡ 12 Factor App ΠΎΡ KodeKloud, Π½Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΠΎΠ΅ ΠΌΡΡΠ»ΡΠΌΠΈ Π°Π²ΡΠΎΡΠ°
Intro
- ΠΡΠ΅Π·Π΅Π½ΡΠ°ΡΠΈΡ ΠΎΡ KK, ΡΠΎΡΠΊ Π½Π° y.disk
- https://12factor.net/ - ΠΌΠ°Π½ΠΈΡΠ΅ΡΡ
- https://videos.itrevolution.com/watch/432442730/ -
12 factor terraform
12-ΡΠ°ΠΊΡΠΎΡΠ½ΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ - ΡΡΠΎ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ»ΠΎΠ³ΠΈΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΡΠ΄ ΠΏΡΠΈΠ½ΡΠΈΠΏΠΎΠ² Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌΡΡ , ΡΡΡΠΎΠΉΡΠΈΠ²ΡΡ ΠΈ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π² ΠΎΠ±Π»Π°ΡΠ½ΡΡ ΡΡΠ΅Π΄Π°Ρ .
ΠΠΎΡ 12 ΠΏΡΠΈΠ½ΡΠΈΠΏΠΎΠ², ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠΏΠΈΡΡΠ²Π°ΡΡ, ΠΊΠ°ΠΊ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ 12-ΡΠ°ΠΊΡΠΎΡΠ½ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ (ΠΏΠΎ Π²Π΅ΡΡΠΈΠΈ chat-gpt):
- ΠΠΎΠ΄ Π±Π°Π·ΠΈΡΡΠ΅ΡΡΡ Π½Π° ΠΊΠΎΠ½ΡΡΠΎΠ»ΠΈΡΡΠ΅ΠΌΡΡ Π²Π΅ΡΡΠΈΡΡ , ΠΊΠΎΡΠΎΡΡΠ΅ Ρ ΡΠ°Π½ΡΡΡΡ Π² ΡΠΈΡΡΠ΅ΠΌΠ΅ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ Π²Π΅ΡΡΠΈΠΉ.
- ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΡΠΎΡΠΎΠ½Π½ΠΈΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ ΠΈ ΡΠ΅ΡΠ²ΠΈΡΠΎΠ² ΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ ΡΠ²Π½ΠΎ ΠΈ ΡΠ°Π·Π΄Π΅Π»ΡΡΡΡΡ.
- ΠΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡΡΡ ΡΠ°Π·ΠΌΠ΅ΡΠ΅Π½Π° Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ.
- Backing ΡΠ΅ΡΠ²ΠΈΡΡ (Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ , ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΠΈ Ρ.Π΄.) Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡΡΡ ΠΊΠ°ΠΊ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅ΠΌΡΠ΅ ΡΠ΅ΡΡΡΡΡ.
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π·Π°ΠΏΡΡΠΊΠ°ΡΡΡΡ ΠΊΠ°ΠΊ ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ², ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠ³ΡΡ Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°ΡΡΡΡ.
- ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΎ ΠΊΠ°ΠΊ ΠΏΠΎΡΠΎΠΊ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ²ΠΎΠ΄Π° ΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π·Π°Π²ΠΈΡΠ΅ΡΡ ΠΎΡ ΡΠ°ΠΉΠ»ΠΎΠ²ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΡ.
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡΠΌΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΊΠΎΠ΄ΠΎΠ² Π²ΠΎΠ·Π²ΡΠ°ΡΠ°.
- ΠΡΠΎΡΠ΅ΡΡΡ Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡ Π±Π΅Π· ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ ΠΈ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ Π»Π΅Π³ΠΊΠΎ ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΠ΅Π½Ρ ΠΈΠ»ΠΈ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΡΡΠ΅Π½Ρ.
- Π Π°Π·ΡΠ°Π±ΠΎΡΠΊΠ°, ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡΠ²ΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΡ ΡΡΠ΅Π΄Ρ.
- Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π·Π°ΠΏΡΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π° Π΄Π²Π΅ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ.
- ΠΠ΄ΠΌΠΈΠ½ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ ΡΠ΅ΡΠ΅Π· Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ.
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π±ΡΡΡΡΠΎΠ³ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π½Π°Π³ΡΡΠ·ΠΊΠΈ.
Π‘ΠΎΠ±Π»ΡΠ΄Π΅Π½ΠΈΠ΅ ΡΡΠΈΡ ΠΏΡΠΈΠ½ΡΠΈΠΏΠΎΠ² ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ, ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°ΡΡ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡΡ Π² ΠΎΠ±Π»Π°ΡΠ½ΡΡ ΡΡΠ΅Π΄Π°Ρ .
1. Codebase (32) - (VCS)
- ΠΠΎΠ΄ Ρ ΡΠ°Π½ΠΈΡΡΡ Π² VCS, Π΄Π»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ Ρ Π½ΠΈΠΌ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ
- Π‘ΡΡΠ½ΠΎΡΡΠΈ ΡΠ»Π΅Π΄ΡΠ΅Ρ Π΄ΡΠΎΠ±ΠΈΡΡ ΠΏΠΎ ΠΌΠ΅ΡΠ΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π° ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΡ
- βΠΠ°ΠΊ ΡΠΎΡ
ΡΠ°Π½ΡΡΡ Π±Π°Π»Π°Π½Ρ Π² IaC-Π΅? ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ Π΅ΡΡΡ Π₯ ΠΊΠΎΠΌΠ°Π½Π΄, Π΄Π»Ρ ΠΊΠΎΡΠΎΡΡΡ
Π½ΡΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ ΠΈΠ½ΡΡΡ: ΡΠ΅ΡΡ, ΡΠ΅ΡΠ²Π΅ΡΠ°
- Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π² ΠΎΠ΄Π½ΠΎΠΌ tf ΠΏΡΠΎΠ΅ΠΊΡΠ΅ ΠΌΠ΅Π½Π΅Π΄ΠΆΠΈΡΡ ΠΈ ΡΠ΅ΡΡ, ΠΈ ΡΠ΅ΡΠ²Π΅ΡΠ°
- ΡΠ΅Π½ΡΡΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½ΠΎ ΡΠΏΡΠ°Π²Π»ΡΡΡ ΡΠ΅ΡΡΠΌΠΈ Π΄Π»Ρ Π²ΡΠ΅Ρ ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ² ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΌΠ΅ΡΡΠ°
- Π΅ΡΠ»ΠΈ Ρ Π½Π°Ρ Π΄ΠΎΠ±Π°Π²ΠΈΡΡΡΡ Π΅ΡΠ΅ ΠΊΡΡΠ° ΡΠ΅ΡΡΡΡΠΎΠ², ΡΠΈΠΏΠ° bd, s3, X, ΡΠΎ ΠΏΡΠΎΡΡΠΎ ΠΏΠΎΠ΄ΡΠΎΠ±ΠΈΡΡ ΡΡΠΎ ΡΠ»Π΅Π³ΠΊΠ° Π² ΡΠ°ΠΌΠΊΠ°Ρ
ΠΏΡΠΎΠ΅ΠΊΡΠ°?
tf-modules?
2. Dependencies (43) - (Dockerfile | .lock )
- ΠΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΡΠ°ΡΡΡΠΈΡΡΠ²Π°ΡΡ Π½Π° Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ Π²Π΅ΡΡΠΈΠΈ, Π²ΡΠ΅ Π²Π½Π΅ΡΠ½ΠΈΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΠΆΠ΅ΡΡΠΊΠΎ Π·Π°ΠΏΠΈΠ½Π΅Π½Ρ (Ρ Π΄ΡΠΌΠ°Ρ ΡΠ»Π΅Π΄ΡΠ΅Ρ Π΄ΠΎΠΏΡΡΠΊΠ°ΡΡ Π»Π΅Π³ΠΊΠΈΠΉ ΡΠ»Π΅ΠΊΡ ΡΠ΅ΡΠ΅Π· version-constraints, ΡΠΈΠΏΠ° 0.1.X, Π½ΠΎ ΡΡΠΎ ΡΠΈΡΠΊ)
3. Config (71) - (env)
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ
ΡΠ°Π½ΠΈΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ (Π½ΠΎ Ρ Π±Ρ ΡΠΊΠ°Π·Π°Π», ΡΡΠΎ ΡΡΠΎ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΠΎΡ ΠΌΠ΅Π»ΠΊΠΈΡ
ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π³ΠΎΠ΄ΠΈΡΡΡ,
Ρ ΠΎΡΠΎΡΠΈΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠ»Π΅ΠΊΡΠ° - traefik
, ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ Π² config.toml, env_vars, Π° ΡΠ°ΠΊ ΠΆΠ΅ ΡΠ»Π°Π³ΠΈ ΠΏΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅ - Ρ Π²ΡΠ΅Π³ΠΎ ΡΡΠΎ ΡΡΡΡ-ΡΡΡΡ ΡΠ°Π·Π½ΡΠΉ ΠΏΡΠΈΠΎΡΠΈΡΠ΅Ρ) - βΒ ΠΡΠ»ΠΈ Π³ΠΎΠ²ΠΎΡΠΈΡΡ ΠΎΠ± ΠΈΠ½ΡΡΠ΅, ΡΠΎ ΠΊΠ°ΠΊ ΡΡΡ ΡΠΎΡ ΡΠ°Π½ΡΡΡ Π±Π°Π»Π°Π½Ρ ΡΠ΅ΠΌΠΏΠ»Π΅ΠΉΡΠΎΠ² ΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π² ΡΠ΅ΠΌΠΏΠ»Π΅ΠΉΡΡ?
4. Backing Services (67) - (DB | cache)
- Backing ΡΠ΅ΡΠ²ΠΈΡΡ (Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ , ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΠΈ Ρ.Π΄.) Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡΡΡ ΠΊΠ°ΠΊ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅ΠΌΡΠ΅ ΡΠ΅ΡΡΡΡΡ.
- βΒ - ΡΠ²Π»ΡΠ΅ΡΡΡ Π»ΠΈ PVC ΡΠ°ΠΊΠΈΠΌ ΡΠ΅ΡΠ²ΠΈΡΠΎΠΌ? π€£
- βΒ - Π΅ΡΠ»ΠΈ ΠΌΡ Π² infra-e, ΡΠΎ Π΄Π»Ρ Π½Π°Ρ Π°ΡΡΠ΅ΡΠ°ΠΊΡΠΎΠΌ ΡΠ²Π»ΡΠ΅ΡΡΡ helm chart, Π° ΠΊΠ°ΠΊ ΠΌΡ ΠΈΡ Π±ΡΠ΄Π΅ΠΌ Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡ Π½Π΅ ΡΠ°ΠΊ Π²Π°ΠΆΠ½ΠΎ? (helm install / argocd / flux ) - Π·Π²ΡΡΠΈΡ ΠΎΡ Π½Π°ΡΡΠ½ΡΡΠΎ π
5. Build, release, run (77) - (DevOps | CI/CD/CD -> SRE)
- ΠΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΡΠ°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ:
- ΡΠ±ΠΎΡΠΊΠΎΠΉ Π°ΡΡΠ΅ΡΠ°ΠΊΡΠ°
- ΡΠ΅Π»ΠΈΠ·ΠΎΠΌ (Π΄ΠΎΡΡΠ°Π²ΠΊΠ° + Π΄Π΅ΠΏΠ»ΠΎΠΉΠΌΠ΅Π½Ρ ΠΎΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ CD/CD)
- ΠΎΠΏΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ
6. Processes (57) - (SIGTERM | SIGKILL)
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΡΡΠ΅ΠΉΡΠ»Π΅ΡΡ, Π±ΡΡΡΡΠΎ ΡΠ±ΠΈΠ²Π°ΡΡΡΡ, ΠΈ Π±ΡΡΡ Π³ΠΎΡΠΎΠ²ΡΠΌ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΠΊΠΎΠ΄Ρ Π²ΡΡ ΠΎΠ΄Π° ΠΎΡ CRI, ΡΡΠΎΠ±Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ Π·Π°Π²Π΅ΡΡΠ°ΡΡΡΡ Π² ΠΎΠ±Π»Π°ΡΠ½ΠΎΠΉ ΡΡΠ΅Π΄Π΅
7. Port Binding (85) - (port-mapping)
- ΠΌΠ°Π»ΠΎ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΠΌΠΎ Π² ΠΊΡΠ±Π΅ΡΠ΅, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΡΡ ΠΏΠΎΡΡ ΠΊΠ°ΠΊ ENV, Π½Π° ΡΠ»ΡΡΠ°ΠΉ Π΅ΡΠ»ΠΈ ΠΌΡ Π·Π°Π΄ΡΠΌΠ°Π΅ΠΌ Π·Π°ΠΏΠΈΡ Π°ΡΡ Π²ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π² ΠΎΠ΄ΠΈΠ½ Pod / docker-compose service?
8. Concurrency (55) - (HPA)
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΌΠ΅ΡΡ
Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°ΡΡΡΡ
, ΠΏΠΎΡΡΠΎΠΌΡ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡΡΡΠ΅ΠΉΡΠ»Π΅ΡΡ
9. Disposability (90) - (GC)
- ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡΡΠΎ ΠΏΠΎΠ΄Π½ΠΈΠΌΠ°ΡΡΡΡ ΠΈ Π±ΡΡΡΡΠΎ ΡΠ±ΠΈΠ²Π°ΡΡΡΡ
10. Dev/prod parity (95) - (tools | CI/CD)
- dev ΠΈ prod ΠΏΠΎ ΡΡΠ»Π°ΠΌ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ ΠΏΠΎΡ ΠΎΠΆΠΈΠΌ Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±Π°
11. Logs (101)
- ΠΠΎΠ³ΠΈ ΠΏΠΈΡΡΡΡΡ Π² stdout ΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡΡΡΡΡ Π°Π³Π΅Π½ΡΠΎΠΌ, ΠΆΠ΅Π»Π°ΡΠ΅Π»ΡΠ½ΠΎ Π² json
12. Admin Processes (107) - (declarative)
- ΠΠ΄ΠΌΠΈΠ½ΡΠΊΠΈΠ΅ ΡΠ°ΡΠΊΠΈ ΡΠΈΠΏΠ° ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ ΠΠ, Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΡΠΌΠΈ, IaC
ΠΡΠΈΠΌΠ΅Ρ: fastapi-12-factor
ΠΡΠΈΠΌΠ΅Ρ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ΠΊΠΎΠ½ΡΠΏΠ΅ΠΊΡ ΠΎΡ KK
ΠΠΎΠ΄ - https://github.com/karma-git/fastapi-12-factor
1. Codebase
Π‘ΠΏΠΈΡΠΎΠΊ ΠΈ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²
---
version: '3'
services:
api:
container_name: "fastapi-12f"
image: karmawow/fastapi-12f:latest
build:
context: ./
dockerfile: Dockerfile
volumes:
- ./:/home/app
env_file:
- .env
restart: always
ports:
# machine:container
- "8000:8080"
redis-db:
image: redis
container_name: redis
command: redis-server /usr/local/etc/redis/redis.conf
ports:
- "6379:6379"
volumes:
- ./data:/data
- ./redis.conf:/usr/local/etc/redis/redis.conf
FROM python:3.10.0-alpine3.14
COPY ./requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
RUN addgroup --gid 10001 app \
&& adduser \
--uid 10001 \
--home /home/app \
--shell /bin/ash \
--ingroup app \
--disabled-password \
app
WORKDIR /home/app
USER app
COPY ./ /home/app
# default, can be overrided
ENV UVICORN_PORT 8000
EXPOSE 8000
ENTRYPOINT ["/usr/local/bin/uvicorn"]
CMD ["main:app", "--reload", "--host=0.0.0.0", "--no-access-log"]
import os
import logging
from fastapi import FastAPI
from pydantic import BaseSettings
import redis
import json_log_formatter
class Settings(BaseSettings):
app_name: str = "Awesome API"
app_log_level: str = os.environ.get('APP_LOGLEVEL', 'INFO').upper()
port: int = os.environ.get("UVICORN_PORT", 8000)
redis_host: str = os.environ.get("REDIS_HOST", "redis-db")
redis_port: int = os.environ.get("REDIS_PORT", 6380)
settings = Settings()
logger = logging.getLogger(__name__)
stdout = logging.StreamHandler()
stdout.setLevel(level=settings.app_log_level)
formatter = json_log_formatter.VerboseJSONFormatter()
stdout.setFormatter(formatter)
logger.addHandler(stdout)
app = FastAPI()
redis_db = redis.Redis(host=settings.redis_host, port=settings.redis_port)
@app.get("/")
async def welcomeToKodeKloud():
try:
redis_db.incr('visitorCount')
visitCount = str(redis_db.get('visitorCount'), 'utf-8')
except redis.exceptions.ConnectionError as e:
logger.critical(e)
return {"message": "Welcome to KODEKLOUD!"}
else:
logger.debug(visitCount)
return {"message": "Welcome to KODEKLOUD!", "request_count": visitCount}
@app.get("/info")
async def info():
return {
"app_name": settings.app_name,
"app_log_level": settings.app_log_level,
"app_port": settings.port,
"redis_host": settings.redis_host,
"redis_port": settings.redis_port,
}
2. Dependencies
Π₯ΡΠ°Π½ΠΈΠΌ Π²ΡΠ΅ Π½Π΅ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠ΅ python Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π² ΡΠ°ΠΉΠ»Π΅, Π° ΡΠ°ΠΌΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌ Π² Π°ΡΡΠ΅ΡΠ°ΠΊΡ Dockerfile:
3. Config; Backend; Port-Binding; Logs
# ΠΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΡΡΠΎΠ²Π΅Π½Ρ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ
APP_LOGLEVEL = WARNING
# ΠΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΠΏΠΎΡΡ, Π½Π° ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅Ρ server
# ΠΡΠΈ ΡΠΌΠ΅Π½Π΅, ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎ ΡΡΠΎΡΠΎΠ½Ρ Infrastructure ΡΠ°ΠΊΠΆΠ΅ Π΅Π³ΠΎ ΠΏΠΎΠΌΠ΅Π½ΡΡΡ
UVICORN_PORT = 8080
# ΠΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ hostname redis
# ΠΡΠΈ ΡΠΌΠ΅Π½Π΅, ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎ ΡΡΠΎΡΠΎΠ½Ρ Infrastructure ΡΠ°ΠΊΠΆΠ΅ Π΅Π³ΠΎ ΠΏΠΎΠΌΠ΅Π½ΡΡΡ
REDIS_HOST = redis-db
# ΠΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΠΏΠΎΡΡ, Π½Π° ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅Ρ redis
# ΠΡΠΈ ΡΠΌΠ΅Π½Π΅, ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎ ΡΡΠΎΡΠΎΠ½Ρ Infrastructure ΡΠ°ΠΊΠΆΠ΅ Π΅Π³ΠΎ ΠΏΠΎΠΌΠ΅Π½ΡΡΡ
REDIS_PORT = 6379
...
# ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΠΏΠΎΡΡ uvicorn
ENV UVICORN_PORT 8000
EXPOSE 8000
# Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π±ΠΎΠ»Π΅Π΅ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ, ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ uvicorn Π² main.py
# ΠΈ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ python, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ argparse
# Π½ΠΎ ΡΠΎ ΡΡΠΎΡΠΎΠ½Ρ infra ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ ENTRYPOINT ΠΈ CMD
ENTRYPOINT ["/usr/local/bin/uvicorn"]
CMD ["main:app", "--reload", "--host=0.0.0.0", "--no-access-log"]
---
...
services:
api:
...
# ΠΏΡΠΎΠΊΠΈΠ΄ΡΠ²Π°Π΅ΠΌ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ ΠΈΠ· ΡΠ°ΠΉΠ»Π° Π² ΡΠ°Π½ΡΠ°ΠΉΠΌ
env_file:
- .env
ports:
# ΠΌΠ°ΠΏΠΈΠ½Π³ ΠΏΠΎΡΡΠΎΠ²
# docker-host:container, Π³Π΄Π΅ ΠΏΠΎΡΡ Π² container Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡ Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ UVICORN_PORT ΠΈΠ· env
- "8000:8080"
# Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ REDIS_HOST ΠΈΠ· env Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡ
redis-db:
# docker-host:container, Π³Π΄Π΅ ΠΏΠΎΡΡ Π² container Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡ Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ REDIS_PORT ΠΈΠ· env
ports:
- "6379:6379"
import os
import logging
from fastapi import FastAPI
from pydantic import BaseSettings
import redis
import json_log_formatter
# ΠΠ»Π°ΡΡ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ ΠΈ ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΡ Π½Π°ΡΡΡΠΎΠ΅ΠΊ ΡΠ΅ΡΠ΅Π· pydantic
class Settings(BaseSettings):
app_name: str = "Awesome API"
app_log_level: str = os.environ.get('APP_LOGLEVEL', 'INFO').upper()
port: int = os.environ.get("UVICORN_PORT", 8000)
redis_host: str = os.environ.get("REDIS_HOST", "redis-db")
redis_port: int = os.environ.get("REDIS_PORT", 6380)
# ΠΠ±ΡΠ΅ΠΊΡ dict, Ρ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΠΌΠΈ
settings = Settings()
...
# ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅
# ΠΠΎΠ»ΡΡΠ°Π΅ΠΌ Π»ΠΎΠ³Π³Π΅Ρ ΠΈΠ· ΡΠ°ΠΉΠ»Π°
logger = logging.getLogger(__name__)
# ΡΠΎΠ·Π΄Π°Π΅ΠΌ log Ρ
ΡΠ½Π΄Π»Π΅Ρ
stdout = logging.StreamHandler()
# Π·Π°Π΄Π°Π΅ΠΌ ΡΡΠΎΠ²Π΅Π½Ρ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ, TODO: Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ
stdout.setLevel(level=settings.app_log_level)
# ΡΠΎΠ·Π΄Π°Π΅ΠΌ json ΡΠΎΡΠΌΠ°ΡΡΠ΅Ρ
formatter = json_log_formatter.VerboseJSONFormatter()
# Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΡΠΎΡΠΌΠ°ΡΡΠ΅Ρ ΠΊ Ρ
ΡΠ½Π΄Π»Π΅ΡΡ
stdout.setFormatter(formatter)
# Π²Π΅ΡΠ°Π΅ΠΌ Ρ
ΡΠ½Π΄Π»Π΅Ρ Π½Π° Π»ΠΎΠ³Π³Π΅Ρ
logger.addHandler(stdout)
# ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ°Π΅ΠΌ ΠΊ redis Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ ΠΈΠ· Π½Π°ΡΡΡΠΎΠ΅ΠΊ
redis_db = redis.Redis(host=settings.redis_host, port=settings.redis_port)
@app.get("/")
async def welcomeToKodeKloud():
try:
redis_db.incr('visitorCount')
visitCount = str(redis_db.get('visitorCount'), 'utf-8')
# ΠΡΠ»Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΈΠ½ΡΡΡ ΠΈ Π»ΠΎΠ³ΠΈΡΡΠ΅ΠΌ ΠΈΡ
except redis.exceptions.ConnectionError as e:
logger.critical(e)
return {"message": "Welcome to KODEKLOUD!"}
else:
logger.debug(visitCount)
return {"message": "Welcome to KODEKLOUD!", "request_count": visitCount}