Lab 08: Capstone
Día: viernes · Branch de referencia: lab08-start → lab08-solution (= solution)
Objetivo
Partiendo de un namespace limpio, desplegar TaskFlow completo integrando las ocho capas trabajadas durante la semana, sin copiar manifiestos de labs anteriores uno por uno, sino ensamblando conscientemente cada pieza a partir de lo aprendido. Este lab no introduce conceptos nuevos: es integración y validación.
Contexto
Cada equipo (2-3 personas, según arme el instructor) recibe un namespace nuevo y vacío, sin nada de lo desplegado en labs anteriores. La consigna es simple de enunciar y exigente de ejecutar: dejar corriendo, de una, la versión completa de TaskFlow: la misma que resultaría de hacer los labs 01 a 07 en orden, pero armada de memoria y criterio propio, no copy-pasteada.
Namespace limpio
oc new-project taskflow-capstone-<equipo>
(o el namespace que indique el instructor, no reutilizar tu <usuario> de
los labs anteriores).
Checklist de integración
Marcar cada ítem solo cuando esté aplicado y verificado, no solo escrito:
Configuración (lab02)
-
ConfigMapcon host/puerto/nombre de base + config de OTel. -
Secretcon credenciales de Postgres, generado contra el clúster (nunca commiteado). -
Cero valores hardcodeados en
appsettings.json.
Imagen (lab01 + lab03)
-
Dockerfile multi-stage, imagen final
aspnet, non-root (chgrp 0
USER 1654). -
Imagen construida y publicada a mano con
podman build/push(igual que en lab01/lab03, no vía el pipeline) contra elImageStreamdel namespace nuevo (las imágenes no se comparten entre namespaces por defecto).
Despliegue base (lab01 + lab02)
-
Deploymentdetaskflow-dbcon el Secret/ConfigMap correctos. -
Deploymentdetaskflow-apisin sidecar de Postgres. -
Service+Routedetaskflow-api.
Salud (lab05)
-
startupProbe,livenessProbe,readinessProbecableados. -
Verificado en vivo: escalar
taskflow-dba 0 no reiniciataskflow-api(solo lo saca deEndpoints).
Observabilidad (lab06)
-
ServiceMonitoraplicado y scrapeando (Observe → Targets). -
Logs del pod son JSON válido.
Seguridad (lab03 + lab07)
-
Pod corre bajo SCC
restricted-v2(sinanyuid/privileged). -
El pod también pasa Pod Security Admission (
enforce=restricteda nivel de namespace), el equivalente portable de la SCC. -
resources.requests/limitsdefinidos. -
NetworkPolicyde segmentación (solo el router llega a la API, solo la API llega a la base). -
Role/RoleBindingde mínimo privilegio para la ServiceAccount del pipeline.
Validación final por equipo
Cada equipo hace una demo corta (5-10 min) al resto, mostrando:
-
GET /api/tasksrespondiendo a través de la Route. -
Un fallo de readiness provocado en vivo (escalar Postgres a 0) sin que el pod de la API se reinicie.
-
Un gráfico de métricas real en la consola con tráfico generado en el momento.
-
oc auth can-i delete deployments --as=system:serviceaccount:<ns>:pipelinerespondiendono.
Criterios de "hecho"
-
Los 17 ítems del checklist de integración están tildados y verificados (no solo aplicados).
-
La demo de validación se hizo sin usar
oc apply -fsobre los manifiestos ya resueltos de labs anteriores (labs/lab0*/manifests): el objetivo es reconstruir, no copiar. -
El equipo puede explicar, de punta a punta, cada decisión del checklist si el instructor pregunta "¿por qué esto así?".
Reto extra individual
Para quien termine el checklist de integración antes de tiempo: un reto individual (no de equipo), con una app nueva que nadie de la semana vio todavía. La consigna es la misma que si te entregaran cualquier repo de negocio real y te dijeran "hazlo cloud native" — no hay README de labs, no hay Dockerfile, no hay manifiestos de referencia.
Elige (o el instructor te asigna) uno de estos cinco repos, sin repetir el mismo dominio que la persona de al lado:
-
capstone-helpdesk — mesa de ayuda interna (tickets + comentarios)
-
capstone-expense-approval — aprobación de gastos (solicitudes + pasos de aprobación)
-
capstone-branch-inventory — inventario de sucursales (ítems + movimientos de stock)
-
capstone-room-booking — reserva de salas (reservas + asistentes)
-
capstone-leave-tracker — solicitudes de vacaciones (solicitudes + notas)
Cada repo trae solo la app .NET (con su propio README de cómo correrla local) y nada más: ni Dockerfile, ni carpeta de manifiestos, ni pistas de Kubernetes. El resto lo armas tú, de cero.
Namespace dedicado, distinto de tu <usuario> de toda la semana (ese ya
tiene TaskFlow desplegado, este reto arranca de cero): <usuario>-reto,
ya aprovisionado por el instructor con lo mismo que tienes en tu namespace
de siempre (cuota, admin sobre tu propio namespace, NetworkPolicy
base).
La app ya trae, de fábrica, un endpoint de carga pesada de CPU
(GET /api/carga/{n}, calcula Fibonacci de forma recursiva — sin dormir
el hilo, consume CPU real) para el HPA. Eso sí ya está en el código que
clonas — los health checks (/healthz, /readyz, /startupz) no,
esos los armas tú, igual que en el lab05.
Checklist del reto extra
-
Imagen construida y publicada a mano (
podman build/push) contra elImageStreamde tu namespace. -
Deploymentcon2réplicas. -
Endpoints de
/healthz,/readyz,/startupzagregados por ti (mismo patrón del lab05) ystartupProbe/livenessProbe/readinessProbecableados contra ellos. -
resources.requests/limitsdefinidos. -
ConfigMapcon la configuración no sensible de la base (host/puerto/nombre) leída por la app vía variables de entorno, no hardcodeada en el código que subes. -
Secret(nunca commiteado) con usuario/password de la base, generado contra el clúster, referenciado por elDeploymentvíasecretKeyRef— nunca como variable de entorno en texto plano en un manifiesto. -
Service+Routesirviendo la API. -
Pod corriendo bajo SCC
restricted-v2— no hace falta declarar nada especial a mano, si no le pides privilegios de más a tu contenedor, la SCC ya te lo da. -
RoleBindingdándoleviewde tu namespace a alguien de otro equipo — que esa persona confirme conoc get pods -n <tu-namespace>que sí puede ver tu proyecto. -
HPA (obligatorio):
HorizontalPodAutoscalersobre elDeployment, generando carga real contraGET /api/carga/{n}y mostrando el escalado en vivo conoc get hpa -w.