feat(lab-03): complete Phase 4 - Compute & EC2 lab
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>
This commit is contained in:
210
labs/lab-03-compute/reference/compose-resources-syntax.md
Normal file
210
labs/lab-03-compute/reference/compose-resources-syntax.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Reference: Docker Compose Resources Syntax
|
||||
|
||||
Riferimento completo per la configurazione delle risorse in Docker Compose.
|
||||
|
||||
## Sezione deploy.resources
|
||||
|
||||
### Struttura Completa
|
||||
|
||||
```yaml
|
||||
services:
|
||||
service_name:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: 'VALUE'
|
||||
memory: 'VALUE'
|
||||
reservations:
|
||||
cpus: 'VALUE'
|
||||
memory: 'VALUE'
|
||||
```
|
||||
|
||||
## Parametri Limits
|
||||
|
||||
### cpus
|
||||
|
||||
**Formato:** Stringa con numero decimale
|
||||
|
||||
```yaml
|
||||
cpus: '0.5' # 50% di 1 CPU
|
||||
cpus: '1' # 1 CPU completa
|
||||
cpus: '2' # 2 CPU complete
|
||||
cpus: '1.5' # 1.5 CPU
|
||||
cpus: '0.25' # 25% di 1 CPU
|
||||
```
|
||||
|
||||
**Validità:**
|
||||
- Minimo: `0.001` (1 millesimo di CPU)
|
||||
- Massimo: Numero di CPU host (es. 8 su host con 8 core)
|
||||
- Default: Nessun limite (tutte le CPU disponibili)
|
||||
|
||||
### memory
|
||||
|
||||
**Formato:** Stringa con unità
|
||||
|
||||
```yaml
|
||||
memory: '512M' # 512 Megabyte
|
||||
memory: '1G' # 1 Gigabyte
|
||||
memory: '128M' # 128 Megabyte
|
||||
memory: '4G' # 4 Gigabyte
|
||||
memory: '1024M' # 1024 Megabyte (equivale a 1G)
|
||||
```
|
||||
|
||||
**Unità Supportate:**
|
||||
- `B` - Byte
|
||||
- `K` / `KB` - Kilobyte (1024 bytes)
|
||||
- `M` / `MB` - Megabyte (1024 KB)
|
||||
- `G` / `GB` - Gigabyte (1024 MB)
|
||||
|
||||
**Validità:**
|
||||
- Minimo: `4M` (4 Megabyte)
|
||||
- Massico: Memoria host disponibile
|
||||
- Default: Nessun limite (tutta la memoria disponibile)
|
||||
|
||||
## Parametri Reservations
|
||||
|
||||
### Scopo
|
||||
|
||||
Le **reservations** garantiscono risorse minime disponibili:
|
||||
- Docker riserva queste risorse per il container
|
||||
- Usato per pianificazione capacity (Kubernetes)
|
||||
- Meno comune in Docker Compose locale
|
||||
|
||||
### Esempio
|
||||
|
||||
```yaml
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2' # Massimo 2 CPU
|
||||
memory: '4G' # Massimo 4 GB
|
||||
reservations:
|
||||
cpus: '1' # Garantite 1 CPU
|
||||
memory: '2G' # Garantiti 2 GB
|
||||
```
|
||||
|
||||
**Uso tipico:**
|
||||
- `limits` - Definisce il tetto massimo (enforcement)
|
||||
- `reservations` - Definisce il pavimento minimo (garanzia)
|
||||
|
||||
## Esempi Completi per Servizi
|
||||
|
||||
### Web Server (t2.micro)
|
||||
|
||||
```yaml
|
||||
web:
|
||||
image: nginx:alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 1G
|
||||
```
|
||||
|
||||
### Application Server (t2.small)
|
||||
|
||||
```yaml
|
||||
app:
|
||||
image: node:alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 2G
|
||||
```
|
||||
|
||||
### Database (t2.medium)
|
||||
|
||||
```yaml
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 4G
|
||||
reservations:
|
||||
cpus: '1'
|
||||
memory: 2G
|
||||
```
|
||||
|
||||
### Worker CPU-Intensive (c5.xlarge)
|
||||
|
||||
```yaml
|
||||
worker:
|
||||
image: python:alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '4'
|
||||
memory: 4G
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
### Verifica con docker compose config
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
```
|
||||
|
||||
Output per servizio con limits:
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 1073741824 # 1G in byte
|
||||
```
|
||||
|
||||
### Verifica con docker inspect
|
||||
|
||||
```bash
|
||||
docker inspect lab03-web --format '{{.HostConfig}}'
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
map[NanoCpus:1000000000 Memory:1073741824]
|
||||
```
|
||||
|
||||
Conversione:
|
||||
- `NanoCpus: 1000000000` = 1 CPU (1e9 nanocpus)
|
||||
- `Memory: 1073741824` = 1 GB (in byte)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Errore: "no matching resources"
|
||||
|
||||
**Causa:** Host non ha abbastanza risorse
|
||||
|
||||
**Soluzione:**
|
||||
```yaml
|
||||
# Riduci i limits
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5' # Era '2'
|
||||
memory: 512M # Era '2G'
|
||||
```
|
||||
|
||||
### Errore: "invalid memory format"
|
||||
|
||||
**Causa:** Formato non valido
|
||||
|
||||
**Soluzione:**
|
||||
```yaml
|
||||
# ✗ WRONG
|
||||
memory: 1024 # Manca unità
|
||||
memory: "1GB" # "GB" non valido (usa G)
|
||||
|
||||
# ✓ CORRECT
|
||||
memory: 1G
|
||||
memory: 1024M
|
||||
```
|
||||
|
||||
## Vedi Anche
|
||||
- Tutorial: Configurare Limiti delle Risorse
|
||||
- Reference: EC2 Instance Mapping
|
||||
159
labs/lab-03-compute/reference/ec2-instance-mapping.md
Normal file
159
labs/lab-03-compute/reference/ec2-instance-mapping.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Reference: EC2 Instance Type Mapping
|
||||
|
||||
Tabella completa di mapping tra Docker resource limits e EC2 instance types.
|
||||
|
||||
## Tabella di Mapping Completa
|
||||
|
||||
| Docker Compose | EC2 Instance | vCPUs | Memory | Costo/ora* | Use Case |
|
||||
|----------------|--------------|-------|--------|------------|----------|
|
||||
| `cpus: '0.5'`<br>`memory: 512M` | t2.nano | 0.5 | 512 MB | $0.006 | Microservizi minimi |
|
||||
| `cpus: '1'`<br>`memory: 1G` | t2.micro | 1 | 1 GB | $0.012 | Dev/Test |
|
||||
| `cpus: '1'`<br>`memory: 2G` | t2.small | 1 | 2 GB | $0.024 | Web server |
|
||||
| `cpus: '2'`<br>`memory: 4G` | t2.medium | 2 | 4 GB | $0.048 | Application |
|
||||
| `cpus: '2'`<br>`memory: 8G` | m5.large | 2 | 8 GB | $0.096 | Production |
|
||||
| `cpus: '4'`<br>`memory: 16G` | m5.xlarge | 4 | 16 GB | $0.192 | High traffic |
|
||||
| `cpus: '8'`<br>`memory: 32G` | m5.2xlarge | 8 | 32 GB | $0.384 | Scalabile |
|
||||
| `cpus: '16'`<br>`memory: 64G` | m5.4xlarge | 16 | 64 GB | $0.768 | Enterprise |
|
||||
|
||||
\*Costi indicativi per regione us-east-1
|
||||
|
||||
## Famiglie Instance Types
|
||||
|
||||
### General Purpose (m5, m6)
|
||||
|
||||
Equilibrato tra CPU, memoria, rete.
|
||||
|
||||
```yaml
|
||||
# m5.large - 2 vCPUs, 8 GB
|
||||
cpus: '2'
|
||||
memory: 8G
|
||||
```
|
||||
|
||||
**Use case:** Web server, application server
|
||||
|
||||
### Burstable (t2, t3)
|
||||
|
||||
Credit-based CPU, basso costo.
|
||||
|
||||
```yaml
|
||||
# t2.micro - 1 vCPU, 1 GB
|
||||
cpus: '1'
|
||||
memory: 1G
|
||||
```
|
||||
|
||||
**Use case:** Dev, test, microservizi
|
||||
|
||||
### Compute Optimized (c5, c6)
|
||||
|
||||
Alto ratio CPU/memoria.
|
||||
|
||||
```yaml
|
||||
# c5.xlarge - 4 vCPUs, 8 GB
|
||||
cpus: '4'
|
||||
memory: 8G
|
||||
```
|
||||
|
||||
**Use case:** Batch processing, encoding
|
||||
|
||||
### Memory Optimized (r5, r6)
|
||||
|
||||
Alto ratio memoria/CPU.
|
||||
|
||||
```yaml
|
||||
# r5.large - 2 vCPUs, 16 GB
|
||||
cpus: '2'
|
||||
memory: 16G
|
||||
```
|
||||
|
||||
**Use case:** Database, caching
|
||||
|
||||
## Docker Compose Examples
|
||||
|
||||
### T2 Nano (Micro)
|
||||
|
||||
```yaml
|
||||
micro:
|
||||
image: alpine:3.19
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
```
|
||||
|
||||
### T2 Micro (Dev/Test)
|
||||
|
||||
```yaml
|
||||
dev:
|
||||
image: node:alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 1G
|
||||
```
|
||||
|
||||
### T2 Small (Web)
|
||||
|
||||
```yaml
|
||||
web:
|
||||
image: nginx:alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 2G
|
||||
```
|
||||
|
||||
### T2 Medium (Application)
|
||||
|
||||
```yaml
|
||||
app:
|
||||
image: python:alpine
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 4G
|
||||
```
|
||||
|
||||
### M5 Large (Production)
|
||||
|
||||
```yaml
|
||||
production:
|
||||
image: myapp:latest
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 8G
|
||||
```
|
||||
|
||||
## Shortcut Reference
|
||||
|
||||
### Quick Copy-Paste
|
||||
|
||||
```yaml
|
||||
# T2 Nano
|
||||
cpus: '0.5'; memory: 512M
|
||||
|
||||
# T2 Micro
|
||||
cpus: '1'; memory: 1G
|
||||
|
||||
# T2 Small
|
||||
cpus: '1'; memory: 2G
|
||||
|
||||
# T2 Medium
|
||||
cpus: '2'; memory: 4G
|
||||
|
||||
# M5 Large
|
||||
cpus: '2'; memory: 8G
|
||||
|
||||
# M5 XLarge
|
||||
cpus: '4'; memory: 16G
|
||||
```
|
||||
|
||||
## Vedi Anche
|
||||
- Tutorial: Configurare Limiti delle Risorse
|
||||
- How-to: Selezionare Instance Type
|
||||
- Explanation: Compute-EC2 Parallels
|
||||
193
labs/lab-03-compute/reference/healthcheck-syntax.md
Normal file
193
labs/lab-03-compute/reference/healthcheck-syntax.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Reference: Docker Compose Healthcheck Syntax
|
||||
|
||||
Riferimento completo per la configurazione degli healthchecks.
|
||||
|
||||
## Sezione healthcheck
|
||||
|
||||
### Struttura Completa
|
||||
|
||||
```yaml
|
||||
services:
|
||||
service_name:
|
||||
healthcheck:
|
||||
test: ["CMD", "command", "arg1", "arg2"]
|
||||
interval: 30s
|
||||
timeout: 30s
|
||||
retries: 3
|
||||
start_period: 0s
|
||||
```
|
||||
|
||||
## Parametri
|
||||
|
||||
### test (Required)
|
||||
|
||||
Comando da eseguire per verificare la salute.
|
||||
|
||||
**Formato CMD:**
|
||||
```yaml
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost/health"]
|
||||
```
|
||||
|
||||
**Formato CMD-SHELL:**
|
||||
```yaml
|
||||
test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"]
|
||||
```
|
||||
|
||||
**Formato NONE:**
|
||||
```yaml
|
||||
test: ["NONE"]
|
||||
```
|
||||
Disabilita healthcheck ereditato dall'immagine.
|
||||
|
||||
### interval
|
||||
|
||||
Frequenza di esecuzione del test.
|
||||
|
||||
```yaml
|
||||
interval: 5s # Ogni 5 secondi
|
||||
interval: 10s # Ogni 10 secondi
|
||||
interval: 30s # Ogni 30 secondi (default)
|
||||
interval: 1m # Ogni minuto
|
||||
```
|
||||
|
||||
**Validità:**
|
||||
- Minimo: `1s` (1 secondo)
|
||||
- Massimo: Nessuno
|
||||
- Default: `30s`
|
||||
|
||||
### timeout
|
||||
|
||||
Tempo massimo per completare il test.
|
||||
|
||||
```yaml
|
||||
timeout: 2s # 2 secondi
|
||||
timeout: 5s # 5 secondi (default)
|
||||
timeout: 30s # 30 secondi
|
||||
```
|
||||
|
||||
**Nota:** Se il test supera il timeout, conta come fallimento.
|
||||
|
||||
### retries
|
||||
|
||||
Numero di fallimenti consecutivi prima di marcare unhealthy.
|
||||
|
||||
```yaml
|
||||
retries: 1 # 1 fallimento = unhealthy
|
||||
retries: 3 # 3 fallimenti = unhealthy (default)
|
||||
retries: 5 # 5 fallimenti = unhealthy
|
||||
```
|
||||
|
||||
**Calcolo del tempo unhealthy:**
|
||||
```
|
||||
tempo_totale = (interval + timeout) × retries
|
||||
```
|
||||
|
||||
Esempio con `interval: 10s, timeout: 5s, retries: 3`:
|
||||
- Check 1: 0s - 5s
|
||||
- Check 2: 10s - 15s
|
||||
- Check 3: 20s - 25s
|
||||
- Unhealthy dopo: 25s
|
||||
|
||||
### start_period
|
||||
|
||||
Grace period prima di contare retries verso unhealthy.
|
||||
|
||||
```yaml
|
||||
start_period: 0s # Nessun grace period (default)
|
||||
start_period: 5s # 5 secondi di grace
|
||||
start_period: 10s # 10 secondi di grace
|
||||
start_period: 30s # 30 secondi di grace
|
||||
```
|
||||
|
||||
**Comportamento:**
|
||||
- Durante `start_period`: Fallimenti non contano
|
||||
- Dopo `start_period`: `retries` inizi a contare
|
||||
|
||||
## Esempi per Tipo di Servizio
|
||||
|
||||
### HTTP Service (Nginx)
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
```
|
||||
|
||||
### Database (PostgreSQL)
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
```
|
||||
|
||||
### Cache (Redis)
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
### TCP Connection
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "nc -z localhost 8080 || exit 1"]
|
||||
interval: 15s
|
||||
timeout: 2s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
### File Check
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "test -f /tmp/ready || exit 1"]
|
||||
interval: 5s
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
```
|
||||
|
||||
## Stati di Salute
|
||||
|
||||
### Ciclo di Vita
|
||||
|
||||
```
|
||||
created → starting → healthy
|
||||
↓
|
||||
unhealthy
|
||||
```
|
||||
|
||||
**Transizioni:**
|
||||
|
||||
| Da | A | Condizione |
|
||||
|----|---|------------|
|
||||
| created | starting | Container avviato con healthcheck |
|
||||
| starting | healthy | `retries` consecutivi passano |
|
||||
| starting | unhealthy | `retries` consecutivi falliscono (dopo start_period) |
|
||||
| healthy | unhealthy | `retries` consecutivi falliscono |
|
||||
| unhealthy | healthy | 1 check passa |
|
||||
|
||||
### Ispezionare Stato
|
||||
|
||||
```bash
|
||||
# Stato corrente
|
||||
docker inspect lab03-web --format '{{.State.Health.Status}}'
|
||||
# Output: healthy / unhealthy / starting
|
||||
|
||||
# Exit code dell'ultimo check
|
||||
docker inspect lab03-web --format '{{.State.Health.ExitCode}}'
|
||||
# Output: 0 (success) o !0 (failure)
|
||||
|
||||
### Vedi Anche
|
||||
- Tutorial: Implementare Healthchecks
|
||||
- How-to: Custom Healthcheck
|
||||
Reference in New Issue
Block a user