Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ path = "examples/serverless.rs"
name = "finops"
path = "examples/finops.rs"

[[example]]
name = "finops_nivel_1"
path = "examples/soluciones/finops_nivel_1.rs"

[[example]]
name = "finops_nivel_2"
path = "examples/soluciones/finops_nivel_2.rs"

[[example]]
name = "finops_nivel_3"
path = "examples/soluciones/finops_nivel_3.rs"

[[example]]
name = "serverless_nivel_1"
path = "examples/soluciones/serverless_nivel_1.rs"
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,6 @@ esperada es:

## Siguiente paso natural

Completar el milestone `08. Costos y FinOps` con ejercicios graduados,
soluciones compilables y análisis de costos sin precios vivos de proveedor.
Continuar con el milestone `09. AWS en la práctica`, manteniendo la regla del
curso: primero conceptos transferibles, después aterrizaje por proveedor sin
convertir el capítulo en catálogo de consola.
13 changes: 12 additions & 1 deletion docs/08-costos-y-finops.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
- **Semestre:** 5
- **Estado:** implemented
- **Milestone:** 08. Costos y FinOps
- **Issues:** #29, #30, #31
- **Issues:** #29, #30, #31, #32
- **Módulo Rust:** `src/finops.rs`
- **Diagrama:** `diagrams/08-costos-y-finops.mmd`
- **Ejemplo:** `examples/finops.rs`
- **Ejercicios:** `docs/ejercicios/08-costos-y-finops.md`
- **Costos:** `docs/costos/08-costos-y-finops.md`

## Concepto

Expand Down Expand Up @@ -272,6 +274,15 @@ permite tomar.
- `FinOpsFinding` hace visibles costos sin dueño, propósito, unidad económica,
presupuesto, límite o visibilidad suficiente.

## Ejercicios y costos

Los ejercicios viven en `docs/ejercicios/08-costos-y-finops.md` y tienen
soluciones compilables en `examples/soluciones/finops_nivel_*.rs`.

El análisis de costos vive en `docs/costos/08-costos-y-finops.md`. No usa
precios de proveedor ni agrega benchmarks: compara atribución, unidad
económica, elasticidad, observabilidad, presupuestos, ambientes y desperdicio.

## Práctica sugerida

Antes de optimizar una arquitectura cloud, escribe:
Expand Down
2 changes: 2 additions & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@
- [Ejercicios: serverless](./ejercicios/07-serverless.md)
- [Costos: serverless](./costos/07-serverless.md)
- [Costos y FinOps](./08-costos-y-finops.md)
- [Ejercicios: costos y FinOps](./ejercicios/08-costos-y-finops.md)
- [Costos: costos y FinOps](./costos/08-costos-y-finops.md)
- [AWS en la práctica](./09-aws-en-la-practica.md)
- [GCP en la práctica](./10-gcp-en-la-practica.md)
67 changes: 67 additions & 0 deletions docs/costos/08-costos-y-finops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Costos: costos y FinOps

- **Curso:** rust-cloud
- **Capítulo:** 08. Costos y FinOps
- **Estado:** implemented
- **Issue:** #32

Este capítulo no usa precios de proveedor. FinOps cambia con región, descuentos,
volumen, soporte, arquitectura, patrón de uso y fecha de consulta. Aquí el costo
se expresa como señales estables: atribución, unidad económica, límite,
visibilidad, presupuesto, desperdicio, inversión y riesgo.

## Costos que sí se pueden comparar aquí

| Decisión | Costo visible | Riesgo si se ignora |
|----------|---------------|---------------------|
| Cómputo constante | Capacidad encendida | Pagar por ociosidad o sobredimensionamiento |
| Cómputo elástico | Crecimiento por demanda | Escalar gasto sin límite operativo |
| Almacenamiento retenido | Datos, backups e índices | Guardar información sin ciclo de vida |
| Tráfico de red | Transferencia entre zonas, regiones o internet | Diseñar flujos caros por ubicación |
| Observabilidad | Logs, métricas, trazas y retención | Diagnóstico caro o insuficiente |
| Ambientes no productivos | Recursos duplicados | Previews o staging sin apagado |
| Servicios manejados | Delegación operativa | Pagar comodidad sin entender responsabilidad |
| Operación humana | Tiempo de investigación y corrección | Optimizar recursos y olvidar trabajo manual |

## Decisión sobre benchmarks

No se agrega `criterion` ni otro benchmark en este issue.

**Concepto:** el capítulo compara señales económicas, no rendimiento local.

**Problema:** medir `FinOpsProfile::evaluate` solo mediría operaciones triviales
en memoria. Ese número no enseña costos cloud reales: consumo, región, tráfico,
retención, descuentos, soporte, cuotas, hábitos del equipo y volumen.

**Alternativas:** agregar un benchmark local, simular una factura falsa o
documentar costos educativos sin dependencia externa.

**Justificación:** se documentan costos educativos porque el aprendizaje correcto
es distinguir gasto atribuible, desperdicio, inversión y riesgo aceptado. Un
benchmark será útil cuando el curso tenga simulaciones de uso, escenarios de
facturación sintética o datos fechados revisados por una persona.

## Checklist FinOps antes de optimizar

- ¿Qué unidad económica explica el costo?
- ¿Qué dueño puede interpretar la señal?
- ¿Qué propósito humano o de producto compra el gasto?
- ¿Qué parte del costo es desperdicio y cuál es inversión deliberada?
- ¿Qué límite evita que la elasticidad crezca sin control?
- ¿Qué ambiente puede apagarse, reducirse o expirar?
- ¿Qué retención de logs, métricas, backups o datos sigue siendo necesaria?
- ¿Qué riesgo aparece si se reduce capacidad, redundancia u observabilidad?
- ¿Qué precio real debe consultarse con fecha antes de publicar una recomendación?

## Señales estables para revisar una factura

1. **Atribución:** cada gasto debe poder mapearse a producto, equipo, ambiente o
iniciativa.
2. **Unidad económica:** cada gasto importante debe tener una unidad de valor:
estudiante, curso, petición, documento, evento, transacción o minuto.
3. **Límite:** cada recurso elástico debe declarar hasta dónde puede crecer.
4. **Ciclo de vida:** cada recurso no productivo debe tener regla de expiración.
5. **Retención:** cada dato, backup, log o métrica debe justificar cuánto tiempo
vive.
6. **Tradeoff:** cada ahorro debe declarar qué riesgo, latencia, confiabilidad o
trabajo humano cambia.
115 changes: 115 additions & 0 deletions docs/ejercicios/08-costos-y-finops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Ejercicios: costos y FinOps

- **Curso:** rust-cloud
- **Capítulo:** 08. Costos y FinOps
- **Estado:** implemented
- **Issue:** #32

Estos ejercicios practican costo como señal de diseño. La meta no es calcular
precios reales, sino declarar unidad económica, dueño, propósito, visibilidad,
presupuesto, elasticidad y tradeoffs antes de optimizar.

## Ejercicio 1: costo de producción gobernable `[Nivel 1]`

Construye un `FinOpsProfile` para una API de la academia:

- categoría `CostCategory::Compute`;
- ambiente `Environment::Production`;
- patrón `UsagePattern::Steady`;
- criticidad alta;
- elasticidad acotada;
- visibilidad por unidad económica;
- presupuesto con forecast y revisión;
- intención de reducir desperdicio;
- dueño, propósito y unidad económica explícitos.

**Entrada/Salida esperada:** la evaluación debe ser de bajo riesgo educativo.

<details>
<summary>Pista</summary>
Un costo sano no es necesariamente bajo. Es atribuible, explicable y gobernable.
</details>

Solución compilable: `examples/soluciones/finops_nivel_1.rs`.

## Ejercicio 2: detectar costo sin atribución `[Nivel 2]`

Modela workers de previews en desarrollo con:

- categoría de invocaciones;
- patrón de uso creciente;
- elasticidad sin límite;
- visibilidad agregada;
- sin presupuesto;
- sin dueño;
- sin unidad económica.

**Entrada/Salida esperada:** la evaluación debe reportar dueño ausente, unidad
económica ausente, presupuesto ausente, elasticidad sin límite y baja
visibilidad.

<details>
<summary>Pista</summary>
La elasticidad ayuda cuando existe límite y señal. Sin eso, solo hace que el
problema pueda crecer más rápido.
</details>

Solución compilable: `examples/soluciones/finops_nivel_2.rs`.

## Ejercicio 3: comparar inversión, desperdicio y riesgo `[Nivel 3]`

Construye tres perfiles:

- observabilidad de producción que compra confiabilidad;
- índice heredado casi sin uso en producción;
- ambiente efímero de experimentación con límite explícito.

Compara sus evaluaciones y explica cuál gasto es inversión, cuál parece
desperdicio y cuál es riesgo aceptado.

**Entrada/Salida esperada:** la observabilidad con intención y visibilidad debe
ser de bajo riesgo; el índice heredado debe revelar recurso ocioso en
producción; el ambiente efímero acotado debe quedar gobernable.

<details>
<summary>Pista</summary>
FinOps no consiste en apagar todo. A veces gastar más compra resiliencia,
aprendizaje o velocidad de entrega.
</details>

Solución compilable: `examples/soluciones/finops_nivel_3.rs`.

## Ejercicio 4: matriz FinOps de una plataforma educativa `[Nivel 4]`

Diseña una matriz para `academy-web` con:

- API pública;
- procesamiento de eventos;
- almacenamiento de assets;
- logs y métricas;
- base de datos manejada;
- ambientes de preview;
- jobs programados;
- tráfico entre regiones.

Para cada fila, declara unidad económica, dueño, propósito, ambiente,
visibilidad, presupuesto, elasticidad, riesgo y acción sugerida.

**Entrada/Salida esperada:** una tabla que distinga inversión, desperdicio,
riesgo aceptado y decisiones que requieren más información.

<details>
<summary>Pista</summary>
La pregunta más importante no es "¿qué apagamos?", sino "¿qué consumo ya no
compra valor, quién puede corregirlo y qué se rompe si lo tocamos?".
</details>

Discusión sugerida:

- Un costo sin dueño debe tratarse como deuda operativa.
- Un ambiente efímero necesita ciclo de vida, no solo una etiqueta.
- La observabilidad excesiva puede costar, pero observabilidad insuficiente
también encarece incidentes.
- Una unidad económica buena conecta consumo técnico con valor humano.
- Los precios reales deben fecharse y revisarse; el criterio arquitectónico debe
permanecer.
6 changes: 6 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ Los ejemplos progresivos de cada capítulo vivirán aquí:
- `finops.rs`: compara un costo de producción atribuido contra invocaciones de
desarrollo sin dueño, presupuesto ni unidad económica y un recurso productivo
casi sin uso.
- `soluciones/finops_nivel_1.rs`: solución del ejercicio básico de costo
gobernable.
- `soluciones/finops_nivel_2.rs`: solución del ejercicio intermedio de
elasticidad sin límite.
- `soluciones/finops_nivel_3.rs`: solución del ejercicio avanzado de
observabilidad, idle y tradeoffs.
- `soluciones/serverless_nivel_1.rs`: solución del ejercicio básico de handler
de cola acotado.
- `soluciones/serverless_nivel_2.rs`: solución del ejercicio intermedio de
Expand Down
26 changes: 26 additions & 0 deletions examples/soluciones/finops_nivel_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use rust_cloud::finops::{
BudgetControl, CostCategory, CostVisibility, ElasticityLimit, Environment, FinOpsCriticality,
FinOpsProfile, FinOpsRequirements, OptimizationIntent, UsagePattern,
};

fn main() {
let profile = FinOpsProfile::new(
"academy-api",
FinOpsRequirements {
category: CostCategory::Compute,
environment: Environment::Production,
usage_pattern: UsagePattern::Steady,
criticality: FinOpsCriticality::High,
elasticity: ElasticityLimit::Bounded { max_units: 20 },
visibility: CostVisibility::UnitEconomics,
budget_control: BudgetControl::ForecastAndReview,
optimization_intent: OptimizationIntent::ReduceWaste,
owner: "equipo academy",
purpose: "servir rutas de aprendizaje a estudiantes",
unit_economics: "costo por estudiante activo",
},
)
.unwrap();

assert!(profile.evaluate().is_low_risk());
}
51 changes: 51 additions & 0 deletions examples/soluciones/finops_nivel_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use rust_cloud::finops::{
BudgetControl, CostCategory, CostVisibility, ElasticityLimit, Environment, FinOpsCriticality,
FinOpsFinding, FinOpsProfile, FinOpsRequirements, OptimizationIntent, UsagePattern,
};

fn main() {
let profile = FinOpsProfile::new(
"preview-workers",
FinOpsRequirements {
category: CostCategory::Invocations,
environment: Environment::Development,
usage_pattern: UsagePattern::Growing,
criticality: FinOpsCriticality::Medium,
elasticity: ElasticityLimit::Unbounded,
visibility: CostVisibility::Aggregate,
budget_control: BudgetControl::None,
optimization_intent: OptimizationIntent::None,
owner: "",
purpose: "ejecutar previews automáticos",
unit_economics: "",
},
)
.unwrap();
let findings = profile.evaluate();

assert!(
findings
.findings()
.contains(&FinOpsFinding::MissingOwner("preview-workers"))
);
assert!(
findings
.findings()
.contains(&FinOpsFinding::MissingUnitEconomics("preview-workers"))
);
assert!(
findings
.findings()
.contains(&FinOpsFinding::MissingBudgetControl("preview-workers"))
);
assert!(
findings
.findings()
.contains(&FinOpsFinding::UnboundedElasticity("preview-workers"))
);
assert!(
findings
.findings()
.contains(&FinOpsFinding::LowVisibility("preview-workers"))
);
}
Loading
Loading