Phase Plans (5 files): - 04-RESEARCH.md: Domain research on Docker limits, healthchecks, EC2 parallels - 04-VALIDATION.md: Success criteria and validation strategy - 04-01-PLAN.md: Test infrastructure (RED phase) - 04-02-PLAN.md: Diátxis documentation - 04-03-PLAN.md: Infrastructure implementation (GREEN phase) Test Scripts (6 files, 1300+ lines): - 01-resource-limits-test.sh: Validate INF-03 compliance - 02-healthcheck-test.sh: Validate healthcheck configuration - 03-enforcement-test.sh: Verify resource limits with docker stats - 04-verify-infrastructure.sh: Infrastructure verification - 99-final-verification.sh: End-to-end student verification - run-all-tests.sh: Test orchestration with fail-fast - quick-test.sh: Fast validation (<30s) Documentation (11 files, 2500+ lines): Tutorials (3): - 01-set-resource-limits.md: EC2 instance types, Docker limits syntax - 02-implement-healthchecks.md: ELB health check parallels - 03-dependencies-with-health.md: depends_on with service_healthy How-to Guides (4): - check-resource-usage.md: docker stats monitoring - test-limits-enforcement.md: Stress testing CPU/memory - custom-healthcheck.md: HTTP, TCP, database healthchecks - instance-type-mapping.md: Docker limits → EC2 mapping Reference (3): - compose-resources-syntax.md: Complete deploy.resources reference - healthcheck-syntax.md: All healthcheck parameters - ec2-instance-mapping.md: Instance type mapping table Explanation (1): - compute-ec2-parallels.md: Container=EC2, Limits=Instance Type, Healthcheck=ELB Infrastructure: - docker-compose.yml: 5 services (web, app, worker, db, stress-test) All services: INF-03 compliant (cpus + memory limits) All services: healthcheck configured EC2 parallels: t2.nano, t2.micro, t2.small, t2.medium, m5.large - Dockerfile: Alpine 3.19 + stress tools + non-root user Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
411 lines
8.2 KiB
Markdown
411 lines
8.2 KiB
Markdown
# Tutorial 3: Dipendenze tra Servizi con Healthchecks
|
|
|
|
In questo tutorial imparerai a configurare dipendenze tra servizi usando `depends_on`, assicurando che i servizi partano nell'ordine corretto.
|
|
|
|
## Obiettivi di Apprendimento
|
|
|
|
Al termine di questo tutorial sarai in grado di:
|
|
- Comprendere le dipendenze tra servizi in applicazioni multi-tier
|
|
- Configurare `depends_on` con conditions
|
|
- Implementare startup ordinato con healthchecks
|
|
- Verificare l'ordine di avvio dei servizi
|
|
|
|
---
|
|
|
|
## Prerequisiti
|
|
|
|
- Completamento di Tutorial 1 e 2
|
|
- Servizi configurati con resource limits e healthchecks
|
|
- Comprensione base di architetture multi-tier
|
|
|
|
---
|
|
|
|
## Parte 1: Dipendenze tra Servizi
|
|
|
|
### Cos'è una Dipendenza?
|
|
|
|
In un'applicazione multi-tier, i servizi dipendono l'uno dall'altro:
|
|
|
|
```
|
|
Web → App → Database
|
|
```
|
|
|
|
- Il **Web** server ha bisogno dell'**App** server
|
|
- L'**App** server ha bisogno del **Database**
|
|
- Il **Database** non dipende da nessuno (parte prima)
|
|
|
|
### Perché sono Importanti?
|
|
|
|
1. **Prevenzione Errori:** Evita connection error a servizi non pronti
|
|
2. **Startup Affidabile:** Ogni servizio aspetta che le sue dipendenze siano pronte
|
|
3. **Zero-Downtime:** Durante deployment, i nuovi servizi aspettano i vecchi
|
|
4. **Debugging:** Problemi di connessione sono più facili da diagnosticare
|
|
|
|
---
|
|
|
|
## Parte 2: Tipi di Dipendenze
|
|
|
|
### depends_on: service_started (Default)
|
|
|
|
```yaml
|
|
services:
|
|
app:
|
|
depends_on:
|
|
- db
|
|
```
|
|
|
|
**Comportamento:** `app` parte quando `db` è **avviato** (non necessariamente healthy)
|
|
|
|
**Problema:** Il database potrebbe ancora essere inizializzando → connection errors
|
|
|
|
### depends_on: service_healthy (Raccomandato)
|
|
|
|
```yaml
|
|
services:
|
|
app:
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
```
|
|
|
|
**Comportamento:** `app` parte quando `db` è **healthy** (dopo healthcheck pass)
|
|
|
|
**Vantaggio:** Il database è completamente pronto → nessun connection error
|
|
|
|
---
|
|
|
|
## Parte 3: Pratica - Architettura Multi-Tier
|
|
|
|
Creiamo un'applicazione a 3 tier con dipendenze:
|
|
|
|
```
|
|
Web (t2.micro) → App (t2.small) → DB (t2.medium)
|
|
```
|
|
|
|
### Step 1: Configurare il Database (Primo)
|
|
|
|
```yaml
|
|
version: "3.8"
|
|
|
|
services:
|
|
# Tier 3: Database - nessuna dipendenza
|
|
db:
|
|
image: postgres:16-alpine
|
|
container_name: lab03-db
|
|
hostname: db
|
|
|
|
environment:
|
|
POSTGRES_DB: lab03_db
|
|
POSTGRES_USER: lab03_user
|
|
POSTGRES_PASSWORD: lab03_password
|
|
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2'
|
|
memory: 4G
|
|
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U lab03_user -d lab03_db || exit 1"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 10s
|
|
|
|
volumes:
|
|
- db-data:/var/lib/postgresql/data
|
|
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
db-data:
|
|
```
|
|
|
|
**Nota:** Il database non ha `depends_on` - è il primo a partire.
|
|
|
|
### Step 2: Configurare l'App Server
|
|
|
|
```yaml
|
|
# Tier 2: Application - dipende dal database
|
|
app:
|
|
image: nginx:alpine
|
|
container_name: lab03-app
|
|
hostname: app
|
|
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1'
|
|
memory: 2G
|
|
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 5s
|
|
|
|
ports:
|
|
- "127.0.0.1:8081:80"
|
|
|
|
# Dipende dal database healthy
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Nota:** `app` parte SOLO quando `db` è `healthy`.
|
|
|
|
### Step 3: Configurare il Web Server
|
|
|
|
```yaml
|
|
# Tier 1: Web - dipende dall'app
|
|
web:
|
|
image: nginx:alpine
|
|
container_name: lab03-web
|
|
hostname: web
|
|
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1'
|
|
memory: 1G
|
|
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 5s
|
|
|
|
ports:
|
|
- "127.0.0.1:8080:80"
|
|
|
|
# Dipende dall'app healthy
|
|
depends_on:
|
|
app:
|
|
condition: service_healthy
|
|
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Nota:** `web` parte SOLO quando `db` → `app` sono entrambi `healthy`.
|
|
|
|
---
|
|
|
|
## Parte 4: Avvio e Verifica
|
|
|
|
### Step 1: Avviare tutti i servizi
|
|
|
|
```bash
|
|
cd labs/lab-03-compute
|
|
docker compose up -d
|
|
```
|
|
|
|
### Step 2: Osservare l'ordine di avvio
|
|
|
|
```bash
|
|
# Monitora lo stato in tempo reale
|
|
watch -n 2 'docker ps --format "table {{.Names}}\t{{.Status}}"'
|
|
```
|
|
|
|
**Sequenza prevista:**
|
|
|
|
1. `lab03-db` parte → `starting` → `(healthy)` dopo ~10-20s
|
|
2. `lab03-app` parte → `starting` → `(healthy)` dopo che `db` è healthy
|
|
3. `lab03-web` parte → `starting` → `(healthy)` dopo che `app` è healthy
|
|
|
|
### Step 3: Verificare l'ordine nei log
|
|
|
|
```bash
|
|
docker compose logs --tail=50
|
|
```
|
|
|
|
Cerca messaggi tipo:
|
|
```
|
|
lab03-db | database system is ready to accept connections
|
|
lab03-app | Waiting for db to be healthy...
|
|
lab03-web | Waiting for app to be healthy...
|
|
```
|
|
|
|
---
|
|
|
|
## Parte 5: Testare le Dipendenze
|
|
|
|
### Test 1: Riavviare il database
|
|
|
|
```bash
|
|
# Ferma il database
|
|
docker compose stop db
|
|
|
|
# Guarda lo stato di app e web
|
|
docker ps
|
|
```
|
|
|
|
**Risultato:** `app` e `web` rimangono in esecuzione (non dipendono dal runtime di db, solo dall'avvio iniziale)
|
|
|
|
### Test 2: Ferma e riavvia l'app
|
|
|
|
```bash
|
|
# Ferma l'app
|
|
docker compose stop app
|
|
|
|
# Guarda lo stato del web
|
|
docker ps
|
|
```
|
|
|
|
**Risultato:** `web` continua a funzionare (stessa logica)
|
|
|
|
### Test 3: Riavvio completo
|
|
|
|
```bash
|
|
# Ferma tutto
|
|
docker compose down
|
|
|
|
# Riavvia
|
|
docker compose up -d
|
|
|
|
# Osserva l'ordine di startup
|
|
docker compose up -d && docker compose logs -f
|
|
```
|
|
|
|
Vedrai: `db` → `app` → `web` in ordine.
|
|
|
|
---
|
|
|
|
## Parte 6: Parallelismo AWS
|
|
|
|
### ECS Task Definitions
|
|
|
|
In AWS ECS, le dipendenze si configurano nel Task Definition:
|
|
|
|
```json
|
|
{
|
|
"containerDefinitions": [
|
|
{
|
|
"name": "db",
|
|
"essential": true,
|
|
"healthCheck": {
|
|
"command": ["CMD-SHELL", "pg_isready -U postgres"],
|
|
"interval": 10,
|
|
"timeout": 5,
|
|
"retries": 5
|
|
}
|
|
},
|
|
{
|
|
"name": "app",
|
|
"essential": true,
|
|
"dependsOn": [
|
|
{
|
|
"containerName": "db",
|
|
"condition": "HEALTHY"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "web",
|
|
"essential": true,
|
|
"dependsOn": [
|
|
{
|
|
"containerName": "app",
|
|
"condition": "HEALTHY"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Condizioni di Dipendenza ECS
|
|
|
|
| Condizione | Docker Equivalente | Descrizione |
|
|
|------------|-------------------|-------------|
|
|
| START | `depends_on` (default) | Container avviato |
|
|
| HEALTHY | `condition: service_healthy` | Healthcheck passing |
|
|
| COMPLETE | - | Container exit code 0 |
|
|
| SUCCESS | - | Container exit code 0 |
|
|
|
|
---
|
|
|
|
## Parte 7: Best Practices
|
|
|
|
### 1. Usa Sempre service_healthy
|
|
|
|
```yaml
|
|
# ✓ GOOD
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
|
|
# ✗ AVOID (se possibile)
|
|
depends_on:
|
|
- db
|
|
```
|
|
|
|
### 2. Configura healthcheck appropriati
|
|
|
|
```yaml
|
|
# Database - startup più lento
|
|
healthcheck:
|
|
retries: 5
|
|
start_period: 10s
|
|
|
|
# Web server - startup veloce
|
|
healthcheck:
|
|
retries: 3
|
|
start_period: 5s
|
|
```
|
|
|
|
### 3. Previeni loop di dipendenze
|
|
|
|
```yaml
|
|
# ✗ WRONG - circular dependency
|
|
web:
|
|
depends_on:
|
|
app: {condition: service_healthy}
|
|
app:
|
|
depends_on:
|
|
web: {condition: service_healthy} # LOOP!
|
|
|
|
# ✓ GOOD - directional dependency
|
|
web:
|
|
depends_on:
|
|
app: {condition: service_healthy}
|
|
app:
|
|
depends_on:
|
|
db: {condition: service_healthy} # OK
|
|
db:
|
|
# No dependencies - base tier
|
|
```
|
|
|
|
---
|
|
|
|
## Riepilogo
|
|
|
|
In questo tutorial hai imparato:
|
|
|
|
✓ **Concetto:** Dipendenze tra servizi per startup ordinato
|
|
✓ **Sintassi:** `depends_on` con `condition: service_healthy`
|
|
✓ **Pratica:** Architettura multi-tier Web → App → DB
|
|
✓ **Verifica:** Osservare l'ordine di startup
|
|
✓ **Parallelismo:** ECS `dependsOn` con condizione HEALTHY
|
|
|
|
---
|
|
|
|
## Complimenti!
|
|
|
|
Hai completato i tutorial di Lab 03 - Compute & EC2!
|
|
|
|
**Competenze Acquisite:**
|
|
- Configurare limiti delle risorse (EC2 instance types)
|
|
- Implementare healthchecks (ELB health checks)
|
|
- Gestire dipendenze tra servizi (ECS task definitions)
|
|
|
|
**Prossimi Passi:**
|
|
- Esegui i test di verifica: `bash tests/run-all-tests.sh`
|
|
- Esplora le guide How-to per procedure specifiche
|
|
- Consulta i documenti Reference per sintassi completa
|
|
- Leggi Explanation per approfondire i parallelismi cloud
|