Reemplaza los placeholders "TODO (fase 2+)" por narrativa completa, grounded en el codigo/manifiestos/incidentes reales del lab (no generico): - ADR 0001 (por que k3d) y ADR 0002 (por que Argo CD): pasan de template vacio a Contexto/Opciones/Decision/Consecuencias reales, apoyados en known-issues.md (blackhole MTU) y en la config real de ecommerce-app.yaml. - vision-general.md: el "por que" de cada frontera de confianza del diagrama. - gitops-flujo.md: ejemplo real con hashes de commit (Fase 3b de ADR 0006, v1.0.171 -> hotfix -> v1.0.172), selfHeal explicado con el syncPolicy real del repo. - red-y-exposicion.md: diagrama de terminacion TLS real, por que todo va "proxied", patron de diagnostico "interno sano, publico roto". - glosario.md: 9 terminos nuevos, cada uno con ejemplo real y verificado del repo (Namespace, ResourceQuota, LimitRange, NetworkPolicy, Deployment, Service, Ingress, StatefulSet, Init container). - notas-sueltas.md: MinIO/S3, limites reales del subscriber revalidate-storefront.ts, que se automatizaria desde cero. Validado con `docker build --target build` (mkdocs build --strict, mismo paso que el pipeline real) -- cero links rotos, cero warnings.
207 lines
8.3 KiB
Markdown
207 lines
8.3 KiB
Markdown
# Glosario
|
|
|
|
> Pensado para alguien que ve estos términos por primera vez. Definiciones
|
|
> cortas primero, detalle técnico después. Se irá expandiendo en fases
|
|
> siguientes — por ahora cubre los términos que ya aparecen en el resto
|
|
> del sitio.
|
|
|
|
## GitOps
|
|
|
|
**En una frase:** el estado deseado del sistema vive en Git, y un
|
|
proceso automático (no una persona con `kubectl`) se encarga de que el
|
|
cluster real coincida con lo que dice Git.
|
|
|
|
**Detalle:** en vez de ejecutar comandos contra el cluster a mano, se
|
|
edita un archivo YAML, se hace commit, y una herramienta (aquí, Argo CD)
|
|
detecta el cambio y lo aplica. Si alguien cambia algo directo en el
|
|
cluster sin pasar por Git, GitOps lo revierte (`selfHeal`) — Git es la
|
|
única fuente de verdad.
|
|
|
|
## Tunnel (Cloudflare Tunnel)
|
|
|
|
**En una frase:** una forma de exponer un servicio interno a internet
|
|
sin abrir puertos en el router/firewall.
|
|
|
|
**Detalle:** un proceso (`cloudflared`) corre dentro de la red local y
|
|
abre una conexión saliente hacia Cloudflare. El tráfico público llega a
|
|
Cloudflare y viaja hacia adentro por esa misma conexión — no hace falta
|
|
port-forwarding ni IP pública propia.
|
|
|
|
## Argo CD
|
|
|
|
**En una frase:** el "robot" que sincroniza el cluster Kubernetes con
|
|
lo que está escrito en Git.
|
|
|
|
**Detalle:** vigila uno o más repos Git, compara el estado declarado
|
|
(manifiestos YAML/Kustomize) contra el estado real del cluster, y
|
|
aplica la diferencia. Ver [flujo GitOps](gitops-flujo.md).
|
|
|
|
## Manifest (manifiesto)
|
|
|
|
**En una frase:** un archivo YAML que describe qué quieres que exista
|
|
en Kubernetes (un Deployment, un Service, un Ingress...).
|
|
|
|
**Detalle:** Kubernetes no se controla escribiendo código imperativo
|
|
("crea un pod"), sino declarando el resultado deseado ("quiero 2
|
|
réplicas de esta imagen corriendo"). El manifiesto es ese documento.
|
|
|
|
## App of Apps
|
|
|
|
**En una frase:** un patrón donde una Application de Argo CD no
|
|
despliega una app directamente, sino que despliega *otras*
|
|
Applications.
|
|
|
|
**Detalle:** en este lab, `application.yaml` (raíz) vigila la carpeta
|
|
`apps/` de `apps-registry`; cada archivo ahí dentro es una Application
|
|
hija que a su vez apunta a un workload real. Permite agregar una app
|
|
nueva con un solo archivo YAML nuevo.
|
|
|
|
## Kustomize
|
|
|
|
**En una frase:** una forma de componer manifiestos de Kubernetes sin
|
|
plantillas (a diferencia de Helm).
|
|
|
|
**Detalle:** un archivo `kustomization.yaml` lista qué recursos YAML
|
|
incluir y qué parches aplicarles, sin necesidad de un lenguaje de
|
|
templating separado.
|
|
|
|
## Namespace
|
|
|
|
**En una frase:** una partición lógica dentro del mismo cluster físico
|
|
— agrupa recursos relacionados y les pone un límite alrededor.
|
|
|
|
**Detalle:** este lab tiene un namespace por dominio de negocio
|
|
(`ecommerce`, `docs-portal`) más `argocd` para el propio Argo CD. Todo
|
|
lo que gobierna a un namespace (cuotas, políticas de red) vive en
|
|
`platform-infra`, separado de los manifiestos de la app — así una app
|
|
nueva no puede "olvidarse" de traer su propia gobernanza.
|
|
|
|
## ResourceQuota
|
|
|
|
**En una frase:** el techo total de recursos que un namespace entero
|
|
puede consumir, sumando todos sus pods.
|
|
|
|
**Detalle:** la cuota real de `ecommerce`
|
|
(`platform-infra/ecommerce-governance/resourcequota.yaml`):
|
|
|
|
```yaml
|
|
hard:
|
|
requests.cpu: "3"
|
|
requests.memory: 4Gi
|
|
limits.cpu: "8"
|
|
limits.memory: 8Gi
|
|
pods: "12"
|
|
persistentvolumeclaims: "6"
|
|
requests.storage: 80Gi
|
|
```
|
|
|
|
Si un Deployment nuevo pidiera más `requests.memory` del que queda
|
|
disponible bajo ese techo, Kubernetes rechaza el pod directamente — no
|
|
lo deja arrancar y luego fallar.
|
|
|
|
## LimitRange
|
|
|
|
**En una frase:** los valores por defecto (y los mínimos/máximos) que
|
|
aplican a un contenedor *individual* dentro de un namespace, para
|
|
cuando el manifiesto no los declara explícitos.
|
|
|
|
**Detalle:** complementa a `ResourceQuota` (que mira el namespace
|
|
entero) a nivel de un solo contenedor. La de `ecommerce`
|
|
(`limitrange.yaml`) pone `defaultRequest: 100m/128Mi`,
|
|
`default: 500m/512Mi` (límites si el contenedor no los declara), y un
|
|
rango permitido de `10m/16Mi` a `2 CPU/1Gi` por contenedor — evita
|
|
tanto el contenedor que no pide nada y termina compitiendo mal por
|
|
recursos, como el que pide de más y se come la cuota del namespace
|
|
entero él solo.
|
|
|
|
## NetworkPolicy
|
|
|
|
**En una frase:** un firewall a nivel de Kubernetes — qué tráfico de
|
|
red se permite entrar (o salir) de un pod.
|
|
|
|
**Detalle:** sin ninguna `NetworkPolicy`, todos los pods de un cluster
|
|
pueden hablarse entre sí libremente. La de `ecommerce`
|
|
(`networkpolicy.yaml`) usa `podSelector: {}` (aplica a todos los pods
|
|
del namespace) y permite ingress solo desde `namespaceSelector: {}`
|
|
(cualquier namespace del cluster, típicamente Traefik llegando desde
|
|
`kube-system` o el namespace de ingress) — bloquea tráfico externo al
|
|
cluster que intentara saltarse Traefik y pegarle directo a un Service
|
|
interno.
|
|
|
|
## Deployment
|
|
|
|
**En una frase:** el controlador para cargas de trabajo **sin
|
|
estado** — réplicas intercambiables entre sí, ninguna con identidad
|
|
propia.
|
|
|
|
**Detalle:** `frontend-deploy` es un Deployment de 2 réplicas: no
|
|
importa cuál de las dos atienda una petición, ambas sirven exactamente
|
|
lo mismo y ninguna guarda datos propios en disco. Si un pod muere,
|
|
Kubernetes crea otro cualquiera para reemplazarlo — no hay "el pod
|
|
original" que recuperar. Contrastar con **StatefulSet** abajo.
|
|
|
|
## Service
|
|
|
|
**En una frase:** un nombre de red estable que apunta a un grupo de
|
|
pods, aunque esos pods cambien.
|
|
|
|
**Detalle:** los pods son efímeros (mueren y se recrean con IP nueva
|
|
cada vez); un Service (ej. `frontend-svc`, `postgres-svc`) les da un
|
|
nombre DNS interno fijo (`frontend-svc.ecommerce.svc.cluster.local`,
|
|
o simplemente `frontend-svc` desde dentro del mismo namespace) que no
|
|
cambia aunque los pods de atrás sí. `postgres-svc` en este lab es
|
|
además un Service `clusterIP: None` ("headless") — necesario porque
|
|
`commerce-postgres` es un StatefulSet y cada pod necesita su propia
|
|
identidad de red estable, no una IP compartida balanceada entre
|
|
réplicas.
|
|
|
|
## Ingress
|
|
|
|
**En una frase:** la regla que dice "las peticiones a este dominio y
|
|
esta ruta van a este Service", para tráfico HTTP que entra al cluster.
|
|
|
|
**Detalle:** `ecommerce-ingress` enruta por *path*, no solo por
|
|
dominio: `shop.cruzcloud.net/api/catalog` va a `catalog-api-svc`, y
|
|
todo lo demás (`/`) va a `frontend-svc` — un solo objeto Ingress con
|
|
dos backends distintos según el prefijo de la URL. Es Traefik (el
|
|
Ingress Controller del cluster) quien lee estos objetos y hace el
|
|
enrutamiento real; el Ingress en sí es solo la declaración de la
|
|
regla, no el componente que la ejecuta.
|
|
|
|
## StatefulSet
|
|
|
|
**En una frase:** el controlador para cargas de trabajo **con
|
|
estado** — cada réplica tiene identidad propia y almacenamiento propio
|
|
que sobrevive a que el pod se reinicie.
|
|
|
|
**Detalle:** `commerce-postgres` es un StatefulSet, no un Deployment,
|
|
porque el frontend puede tener 2 réplicas idénticas sin datos propios,
|
|
pero Postgres no — sus datos tienen que vivir en un disco específico
|
|
que sobreviva un reinicio del pod y sepa exactamente cuál pod es
|
|
"el suyo". Cada pod de un StatefulSet obtiene su propio
|
|
`PersistentVolumeClaim` vía `volumeClaimTemplates` (acá,
|
|
`postgres-data`, 10Gi en `local-path`) y un nombre de red estable y
|
|
numerado (`commerce-postgres-0`), a diferencia de los nombres
|
|
aleatorios de un Deployment. Meilisearch, Redis y MinIO en este lab
|
|
siguen el mismo patrón por la misma razón — todos guardan datos en
|
|
disco que tienen que sobrevivir al pod.
|
|
|
|
## Init container
|
|
|
|
**En una frase:** un contenedor que corre **antes** que los
|
|
contenedores principales de un pod, y tiene que terminar bien (exit
|
|
0) para que el resto arranque.
|
|
|
|
**Detalle:** `medusa-deploy` usa dos, y a propósito están separados en
|
|
vez de ser uno solo: `wait-for-postgres` (`pg_isready` en loop, solo
|
|
espera a que Postgres acepte conexiones) y `migrations`
|
|
(`db:migrate`, corre las migraciones de verdad). Un incidente real
|
|
mostró por qué separarlos importa: cuando el chequeo de disponibilidad
|
|
reusaba la misma `DATABASE_URL` completa de la app (con
|
|
`?sslmode=disable` incluido), el parser de `pg_isready` no la entendía
|
|
y el pod quedaba atascado en `Init` — reportado como si fuera
|
|
`CrashLoopBackOff`, sin serlo. El fix fue que el chequeo de
|
|
disponibilidad use el mínimo de parámetros posible
|
|
(host/puerto/usuario/db), nunca la URI completa pensada para la app.
|
|
Ver el [playbook del crashloop de Medusa](../playbooks/incidente-crashloop-medusa.md).
|