Tancàvem la lliçó anterior dient que ja tenies clúster, CLI i llenguatge de manifests, i que només faltava el pacient. Aquí el tens. Aquesta lliçó presenta a fons Rutas Norte S.L., l'empresa fictícia la plataforma de venda de bitllets d'autobús de la qual desplegarem i operarem sobre Kubernetes durant els onze mòduls restants. No és un exemple decoratiu: cada concepte que aprenguis a partir d'ara entrarà en escena perquè Rutas Norte el necessita, i al final del curs tindràs una plataforma completa, segura, observable i autoescalada, construïda peça a peça. Veuràs la situació de partida de l'empresa, cadascun dels seus sis components, l'arquitectura objectiu, el mapa de quin mòdul aporta què, i les convencions que seguirem sempre. I acabaràs amb el primer desplegament real: botiga-web corrent al teu clúster i responent al teu navegador.

Contingut

  1. L'empresa i el seu problema actual
  2. Els sis components de la plataforma
  3. Arquitectura objectiu sobre Kubernetes
  4. Full de ruta: què aporta cada mòdul
  5. Convencions del projecte
  6. Primer desplegament: botiga-web a rutas-norte-dev
  7. Per què aquest pod és fràgil

  1. L'empresa i el seu problema actual

Rutas Norte S.L. és un operador d'autobusos interurbans que ven els seus bitllets per internet a través de la plataforma Rutas Norte. Tretze persones al departament tècnic, unes 4.000 reserves diàries de mitjana i 25.000 els dies punta.

La seva infraestructura actual:

  • Dues màquines llogades amb Docker Compose. Una serveix el web i l'API; l'altra, la base de dades.
  • Desplegaments manuals: algú es connecta per SSH, executa docker compose pull && docker compose up -d i creua els dits. Hi ha un tall de servei d'entre un i dos minuts, així que només es desplega els dimarts de matinada.
  • Sense autoreparació: al març, el contenidor de l'API va morir a les 02:40 per una fuita de memòria i ningú no se'n va adonar fins a les 07:15. Quatre hores i mitja sense vendre bitllets.
  • Sense elasticitat: en els pics de ponts i vacances el trànsit es multiplica per sis. La resposta ha estat contractar una màquina dimensionada per a l'agost i pagar-la els dotze mesos.
  • Secrets per tot arreu: la contrasenya de PostgreSQL viu en un fitxer .env que s'ha compartit per correu. Aquesta base de dades conté nom, DNI, telèfon i correu de cada client.
  • Sense observabilitat: els logs són en fitxers dins de cada contenidor. Diagnosticar un problema implica entrar per SSH i buscar amb grep.

La direcció tècnica ha aprovat la migració a Kubernetes amb quatre objectius mesurables: zero talls als desplegaments, recuperació automàtica de caigudes, capacitat elàstica als pics i traçabilitat i control d'accés sobre les dades personals. Aquests quatre objectius són, un a un, el temari que tens al davant.

  1. Els sis components de la plataforma

Aquests noms t'acompanyaran durant tot el curs. Conserva'ls exactament així.

2.1. botiga-web

  • Què és: el frontal públic. Una SPA servida per nginx amb els resultats de cerca, el selector de seients i el procés de pagament.
  • Estat: sense estat. Qualsevol rèplica serveix qualsevol petició.
  • Imatge: registry.rutasnorte.example/botiga-web:1.8.0
  • Domini: www.rutasnorte.example
  • Què necessita del clúster: diverses rèpliques, exposició HTTP/HTTPS a l'exterior, configuració injectada (la URL de l'API varia per entorn) i actualització sense tall.

2.2. api-reserves

  • Què és: l'API REST en Node.js. Consulta disponibilitat de places, calcula preus, crea reserves i emet bitllets. És el cor del negoci.
  • Estat: sense estat. Tota la persistència és a PostgreSQL i a Redis.
  • Imatge: registry.rutasnorte.example/api-reserves:2.4.0
  • Domini: api.rutasnorte.example
  • Què necessita del clúster: rèpliques, autoescalat per càrrega, credencials de base de dades com a secret, sondes de salut, límits de recursos i accés restringit a la base de dades.

2.3. postgres-reserves

  • Què és: PostgreSQL 16 amb les taules de reserves, clients, rutes i expedicions.
  • Estat: amb estat. És el component crític del sistema.
  • Imatge: postgres:16
  • Què necessita del clúster: emmagatzematge persistent que sobrevisqui a la recreació del pod, identitat de xarxa estable, credencials gestionades com a secret, còpies de seguretat i una política de xarxa que impedeixi que s'hi connecti qualsevol.

2.4. redis-cache

  • Què és: memòria cau en memòria de la disponibilitat de places per expedició i data. Absorbeix la majoria de les consultes de cerca i evita saturar PostgreSQL.
  • Estat: amb estat, però prescindible. Si es perd, es repobla des de la base de dades; només es degrada el rendiment durant uns minuts.
  • Imatge: redis:7.2-alpine
  • Què necessita del clúster: un nom estable, límits de memòria estrictes i configuració de política d'expulsió.

2.5. worker-notificacions

  • Què és: procés en segon pla que consumeix una cua i envia els correus de confirmació de reserva i els recordatoris de viatge.
  • Estat: sense estat, però no rep trànsit entrant: no cal que sigui accessible des de fora.
  • Imatge: registry.rutasnorte.example/worker-notificacions:1.2.0
  • Què necessita del clúster: rèpliques escalades per longitud de cua i no per CPU, credencials SMTP com a secret, i aturada ordenada per no perdre un enviament a mig fer.

2.6. informes-ocupacio

  • Què és: tasca programada que cada nit a les 02:30 calcula l'ocupació per línia i expedició del dia anterior i deixa un informe per al departament comercial.
  • Estat: sense estat, d'execució finita: arrenca, treballa uns minuts i acaba.
  • Imatge: registry.rutasnorte.example/informes-ocupacio:1.0.3
  • Què necessita del clúster: execució programada, control de reintents, límit d'execucions simultànies i historial de resultats.

Resum comparatiu

Component Estat Trànsit entrant Objecte de Kubernetes que el governarà Mòdul
botiga-web Sense estat Públic (HTTP) Deployment + Service + Ingress 2, 4
api-reserves Sense estat Públic (HTTP) i intern Deployment + Service + Ingress + HPA 2, 4, 9
postgres-reserves Amb estat Només intern, restringit StatefulSet + PVC + Service headless 5, 6
redis-cache Amb estat prescindible Només intern Deployment o StatefulSet + Service 2, 5
worker-notificacions Sense estat Cap Deployment (sense Service) + KEDA 2, 9
informes-ocupacio Sense estat, finit Cap CronJob 6

Aquesta taula conté ja una lliçó de disseny: el tipus d'objecte de Kubernetes que necessites es dedueix de dues preguntes —té estat? i rep trànsit?— abans d'escriure una sola línia de YAML.

  1. Arquitectura objectiu sobre Kubernetes

Aquesta és la destinació a la qual arribarem al final del mòdul 11.

flowchart TB
    U["Clients<br/>navegador i mòbil"]
    DNS["DNS<br/>www / api .rutasnorte.example"]
    U --> DNS

    subgraph CL["Clúster de Kubernetes"]
        ING["Ingress Controller<br/>TLS amb cert-manager"]

        subgraph NS["namespace rutas-norte-pro"]
            SVCW["Service botiga-web"]
            SVCA["Service api-reserves"]
            TW1["Pod botiga-web"]
            TW2["Pod botiga-web"]
            API1["Pod api-reserves"]
            API2["Pod api-reserves"]
            API3["Pod api-reserves"]
            SVCR["Service redis-cache"]
            RED["Pod redis-cache"]
            SVCP["Service postgres-reserves"]
            PG["StatefulSet<br/>postgres-reserves-0"]
            PVC[("PVC 20 GiB")]
            WK1["Pod worker-notificacions"]
            WK2["Pod worker-notificacions"]
            CJ["CronJob<br/>informes-ocupacio"]
        end
    end

    DNS --> ING
    ING --> SVCW
    ING --> SVCA
    SVCW --> TW1
    SVCW --> TW2
    SVCA --> API1
    SVCA --> API2
    SVCA --> API3
    API1 --> SVCR
    API2 --> SVCR
    API3 --> SVCP
    SVCR --> RED
    SVCP --> PG
    PG --- PVC
    WK1 --> SVCP
    WK2 --> SVCP
    CJ --> SVCP

Punts que convé llegir al diagrama:

  • Una sola porta d'entrada: l'Ingress Controller termina el TLS i encamina per domini cap al Service corresponent.
  • Cap component no coneix IP: tot es comunica pel nom del Service, resolt pel DNS intern del clúster.
  • postgres-reserves és l'únic amb disc persistent, i només ha de ser abastable des d'api-reserves, el worker i el CronJob. Això es garantirà amb una NetworkPolicy al mòdul 4.
  • worker-notificacions no té Service: ningú no li parla, ell consumeix feina i surt a parlar amb altres.

  1. Full de ruta: què aporta cada mòdul

Aquesta taula és el contracte del curs: diu quina peça de Rutas Norte afegim o millorem a cada mòdul.

Mòdul Què s'afegeix o es millora a Rutas Norte
1. Introducció Clúster de pràctiques, convencions, namespace rutas-norte-dev i primer pod de botiga-web
2. Components principals botiga-web i api-reserves com a Deployments amb rèpliques; Services interns; actualització de versió sense tall i rollback; separació en namespaces per entorn
3. Configuració i secrets Configuració de la botiga i l'API en ConfigMaps; contrasenya de PostgreSQL i credencials SMTP en Secrets; requests i limits a tots els components; quotes per entorn; ServiceAccounts pròpies
4. Xarxes Publicació de www.rutasnorte.example i api.rutasnorte.example amb Ingress i TLS; DNS intern entre components; NetworkPolicy que aïlla postgres-reserves
5. Emmagatzematge Volum persistent per a la base de dades via PVC i StorageClass; expansió del volum; còpies de seguretat i restauració de les reserves
6. Conceptes avançats postgres-reserves migrat a StatefulSet; informes-ocupacio com a CronJob; init container que espera la base de dades; sidecar de mètriques; agent de logs com a DaemonSet
7. Monitoratge i registre Sondes de vida i disponibilitat a tots els components; kubectl top; Prometheus i Grafana amb panell de reserves per minut; logs centralitzats; depuració d'incidències
8. Seguretat RBAC per equip i entorn; contenidors sense privilegis i amb sistema de fitxers de només lectura; Pod Security Standards; enduriment de xarxa; signatura i escaneig d'imatges
9. Escalat i rendiment HPA sobre api-reserves per als pics de ponts; VPA per dimensionar; autoescalat de nodes; escalat de worker-notificacions per longitud de cua amb KEDA; PodDisruptionBudgets
10. Ecosistema Empaquetat de la plataforma amb Helm; variants per entorn amb Kustomize; desplegament continu amb GitOps; trasllat a un clúster gestionat
11. Casos reals Posada en producció completa; canalització de CI/CD; desplegament canari d'una versió de l'API; operació diària, runbooks i control de costos
12. Certificació Repàs transversal orientat a CKA, CKAD i CKS fent servir la plataforma com a banc de proves

  1. Convencions del projecte

Aquestes regles s'apliquen a totes les lliçons. Adopta-les des d'ara; són també bones pràctiques del món real.

5.1. Namespaces per entorn

Namespace Ús Qui hi desplega
rutas-norte-dev Desenvolupament. Dades fictícies, recursos reduïts Qualsevol persona de l'equip
rutas-norte-pre Preproducció. Rèplica fidel de producció per validar Canalització automàtica
rutas-norte-pro Producció. Dades reals de clients Només la canalització, amb aprovació

Durant el mòdul 1 i bona part del 2 treballarem només a rutas-norte-dev.

5.2. Esquema d'etiquetes

Tots els objectes porten aquestes tres etiquetes com a mínim:

metadata:
  labels:
    app: botiga-web                          # el component
    app.kubernetes.io/part-of: rutas-norte   # la plataforma completa
    entorn: dev                              # l'entorn

Això permet consultes com aquestes, que valen or quan el clúster creix:

kubectl get all -l app.kubernetes.io/part-of=rutas-norte -n rutas-norte-dev
kubectl get pods -l entorn=pro -A
kubectl logs -l app=api-reserves -n rutas-norte-dev --tail=50

5.3. Registre i imatges: etiquetes immutables

El registre d'imatges de l'empresa és registry.rutasnorte.example. La regla més important del projecte quant a imatges:

Cada versió es publica amb una etiqueta única i immutable, que no es reutilitza mai. Prohibit latest en qualsevol entorn.

Referència És vàlida? Per què
registry.rutasnorte.example/api-reserves:2.4.0 Versió semàntica, immutable
registry.rutasnorte.example/api-reserves:2.4.0-a3f9c1b Sí, millor Inclou el commit: traçabilitat total
registry.rutasnorte.example/api-reserves@sha256:9f3a1c... Sí, la més estricta Digest: impossible de suplantar
registry.rutasnorte.example/api-reserves:latest No Dues rèpliques del mateix Deployment poden acabar executant codi diferent; el rollback deixa de ser fiable i no saps què hi ha a producció

5.4. Estructura del repositori

La que vam definir a la lliçó Objectes, Manifests YAML i el Model Declaratiu:

rutas-norte/
└── k8s/
    ├── base/                # definició comuna
    ├── entorns/
    │   ├── dev/
    │   ├── pre/
    │   └── pro/
    ├── entorn-local/
    └── README.md

I la regla d'or que l'acompanya: si un canvi no és a Git, no existeix. Res de kubectl edit com a mètode de desplegament.

  1. Primer desplegament: botiga-web a rutas-norte-dev

Prou teoria. Desplegarem el primer tros real de Rutas Norte.

Pas 1: comprovar el clúster

minikube status --profile=rutas-norte
kubectl config current-context
rutas-norte
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

rutas-norte

Pas 2: crear el namespace de manera declarativa

# k8s/base/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: rutas-norte-dev
  labels:
    app.kubernetes.io/part-of: rutas-norte
    entorn: dev
kubectl apply -f k8s/base/namespace.yaml
kubectl get namespace rutas-norte-dev
namespace/rutas-norte-dev created

NAME              STATUS   AGE
rutas-norte-dev   Active   3s

Fixa't que l'hem creat amb un manifest, no amb kubectl create namespace. És una decisió deliberada: el namespace forma part de la definició del projecte i ha de ser a Git com tota la resta.

I ara, el consell de productivitat de la lliçó 01-05, que t'estalviarà escriure -n rutas-norte-dev centenars de vegades:

kubectl config set-context --current --namespace=rutas-norte-dev

Pas 3: escriure el manifest del pod

# k8s/base/botiga-web-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: botiga-web
  namespace: rutas-norte-dev
  labels:
    app: botiga-web
    app.kubernetes.io/part-of: rutas-norte
    entorn: dev
  annotations:
    rutasnorte.example/responsable: [email protected]
spec:
  containers:
    - name: nginx
      image: nginx:1.27-alpine
      ports:
        - name: http
          containerPort: 80
      resources:
        requests:
          cpu: "50m"
          memory: "64Mi"
        limits:
          cpu: "200m"
          memory: "128Mi"

Repàs camp a camp, recolzant-nos en el que hem après:

  • apiVersion: v1 i kind: Pod: el Pod pertany al grup core, per això no porta prefix de grup.
  • metadata.name: nom únic dins del namespace.
  • metadata.labels: les tres etiquetes del projecte. Al mòdul 2 seran les que faci servir el Service per trobar els seus pods.
  • metadata.annotations: metadada informativa, no consultable.
  • spec.containers: una llista. Aquí un sol element, com serà habitual.
  • image: nginx:1.27-alpine: fem servir la imatge pública nginx perquè registry.rutasnorte.example és un registre fictici i no existeix. A tot el curs, quan aparegui una imatge de registry.rutasnorte.example, substitueix-la mentalment —i al teu clúster— pel seu equivalent públic. Etiqueta explícita, mai latest, segons la convenció del projecte.
  • ports: és documentació informativa; no obre res per si sol. L'exposició real vindrà amb el Service (mòdul 2).
  • resources: requests és el que el scheduler reserva per decidir en quin node hi cap; limits és el sostre que el kubelet imposa. Els estudiarem a fons al mòdul 3, però convé posar-los des del primer dia.

Pas 4: validar i aplicar

kubectl apply -f k8s/base/botiga-web-pod.yaml --dry-run=client
kubectl apply -f k8s/base/botiga-web-pod.yaml
pod/botiga-web created (dry run)
pod/botiga-web created

Pas 5: observar l'arrencada

kubectl get pods -w
NAME         READY   STATUS              RESTARTS   AGE
botiga-web   0/1     Pending             0          0s
botiga-web   0/1     ContainerCreating   0          1s
botiga-web   1/1     Running             0          4s

Estàs veient, en directe, el recorregut de la lliçó Arquitectura de Kubernetes: Pending mentre el scheduler tria node, ContainerCreating mentre el kubelet descarrega la imatge i prepara la xarxa, Running quan el contenidor és viu. Talla amb Ctrl+C.

Pas 6: inspeccionar

kubectl get pod botiga-web -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE
botiga-web   1/1     Running   0          45s   10.244.0.21  rutas-norte   <none>
kubectl describe pod botiga-web
Name:         botiga-web
Namespace:    rutas-norte-dev
Node:         rutas-norte/192.168.49.2
Labels:       app=botiga-web
              app.kubernetes.io/part-of=rutas-norte
              entorn=dev
Status:       Running
IP:           10.244.0.21
Containers:
  nginx:
    Image:          nginx:1.27-alpine
    Port:           80/TCP
    State:          Running
    Ready:          True
    Restart Count:  0
    Limits:         cpu: 200m, memory: 128Mi
    Requests:       cpu: 50m, memory: 64Mi
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  50s   default-scheduler  Successfully assigned rutas-norte-dev/botiga-web to rutas-norte
  Normal  Pulled     49s   kubelet            Container image "nginx:1.27-alpine" already present on machine
  Normal  Created    49s   kubelet            Created container nginx
  Normal  Started    49s   kubelet            Started container nginx

Els quatre esdeveniments expliquen la història completa: el scheduler va assignar node, i després el kubelet va obtenir la imatge, va crear el contenidor i el va arrencar. Exactament el repartiment de responsabilitats que vam estudiar.

kubectl logs botiga-web --tail=5
/docker-entrypoint.sh: Configuration complete; ready for start up
2026/08/05 10:22:14 [notice] 1#1: nginx/1.27.0
2026/08/05 10:22:14 [notice] 1#1: start worker processes

Pas 7: veure-ho al navegador

El pod té IP 10.244.0.21, però aquesta IP només existeix dins del clúster. Per arribar-hi des de la teva màquina fem servir port-forward:

kubectl port-forward pod/botiga-web 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

Obre http://localhost:8080 al navegador: veuràs la pàgina de benvinguda de nginx. A Rutas Norte, aquella seria la portada de la botiga de bitllets. Deixa l'ordre corrent mentre proves i talla-la amb Ctrl+C.

Des d'un altre terminal també ho pots comprovar sense navegador:

curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080
200

Enhorabona: acabes de desplegar el primer component de Rutas Norte a Kubernetes.

  1. Per què aquest pod és fràgil

Abans de celebrar-ho gaire, fem l'experiment que dona sentit al mòdul 2.

kubectl delete pod botiga-web
kubectl get pods
pod "botiga-web" deleted

No resources found in rutas-norte-dev namespace.

Ha desaparegut i no torna. Compara-ho amb el que vam dir a la lliçó de conceptes: un pod solt no té cap controlador que el vigili. Ningú no executa un bucle de reconciliació sobre ell, perquè l'estat desitjat que vas declarar era literalment "que existeixi aquest pod", i en esborrar-lo també vas esborrar aquella declaració.

Els quatre problemes d'un pod solt:

Problema Conseqüència per a Rutas Norte
No es recrea si mor Reprodueix exactament la caiguda nocturna de quatre hores i mitja que va patir l'empresa al març
No es pot escalar Per tenir tres còpies caldria escriure tres manifests amb tres noms diferents
No es pot actualitzar sense tall Canviar d'imatge exigeix esborrar i recrear: hi ha un interval sense servei
No té adreça estable Cada recreació canvia la IP, i ningú no sap on connectar-se

La solució és la jerarquia que ja coneixes del mapa conceptual: Deployment → ReplicaSet → Pod. Un Deployment declara "vull 3 rèpliques d'aquesta imatge", el ReplicaSet les manté contra vent i marea, i un Service els dona un nom estable.

Torna a crear el pod per deixar el clúster com estava i tancar el mòdul amb la plataforma en marxa:

kubectl apply -f k8s/base/botiga-web-pod.yaml
kubectl get pods
pod/botiga-web created

NAME         READY   STATUS    RESTARTS   AGE
botiga-web   1/1     Running   0          5s

Errors Comuns i Consells

  • Aplicar al namespace equivocat. Si kubectl get pods no mostra res, comprova el namespace amb kubectl config view --minify | grep namespace o fes servir -A. Declarar metadata.namespace explícitament a cada manifest, com fem aquí, elimina el problema d'arrel.
  • Fer servir registry.rutasnorte.example literalment. És un registre fictici: no existeix. El pod es quedaria en ImagePullBackOff. Als exercicis pràctics fes servir sempre la imatge pública equivalent (nginx, postgres, redis, node).
  • Creure que ports.containerPort exposa el pod. No fa res per si sol: és documentació. L'accés real arriba amb port-forward (per a proves), Service (mòdul 2) o Ingress (mòdul 4).
  • Deixar port-forward com a solució. És una eina de depuració d'un sol usuari, lligada al teu terminal. No és mai una forma d'exposar un servei.
  • Crear pods solts i acostumar-s'hi. Aquest ha estat un exercici deliberat per entendre la fragilitat. A partir del mòdul 2, tot va en Deployments.
  • Oblidar resources. Sense requests, el scheduler no pot planificar bé; sense limits, un contenidor descontrolat pot tombar els seus veïns. Posa'ls des del principi encara que els ajustos vinguin després.
  • Consell: crea ja el repositori amb l'estructura k8s/ i fes un commit amb namespace.yaml i botiga-web-pod.yaml. Treballar així des de la primera lliçó és la diferència entre acabar el curs amb una plataforma reproduïble i acabar amb un clúster ple de coses que ningú no sap com es van crear.

Exercicis

Exercici 1: Dissenyar la plataforma sobre el paper

Sense escriure cap manifest, completa una taula amb els sis components de Rutas Norte i, per a cadascun, respon: (a) té estat?, (b) rep trànsit entrant i d'on?, (c) quin objecte de Kubernetes el governarà?, i (d) què passaria avui, amb Docker Compose, si la màquina que l'allotja s'apagués? Després, justifica en tres línies per què redis-cache i postgres-reserves, essent tots dos "amb estat", reben tractaments molt diferents.

Exercici 2: Desplegar i explorar redis-cache

Seguint totes les convencions del projecte, crea el manifest k8s/base/redis-cache-pod.yaml per a un pod redis-cache a rutas-norte-dev amb la imatge pública redis:7.2-alpine, el port 6379, les tres etiquetes del projecte i requests de 50m de CPU i 64Mi de memòria. Després:

  1. Valida'l sense tocar el clúster i aplica'l.
  2. Comprova que està Running i esbrina la seva IP i el seu node.
  3. Entra al contenidor i comprova que Redis respon executant redis-cli ping.
  4. Mostra únicament els pods de la plataforma Rutas Norte fent servir l'etiqueta comuna.

Exercici 3: Demostrar la fragilitat i anticipar la solució

  1. Simula una caiguda de l'aplicació matant el procés principal del contenidor de botiga-web amb kubectl exec, i observa amb --watch què passa. Torna el contenidor? Canvia el comptador RESTARTS? Canvia la IP del pod?
  2. Ara esborra el pod sencer amb kubectl delete pod i observa de nou. Torna?
  3. Explica la diferència entre els dos casos indicant quin component actua en cada un.
  4. Escriu en dues frases quin objecte necessitaries perquè el segon cas també es recuperés sol.

Solucions

Solució 1

Component (a) Estat (b) Trànsit entrant (c) Objecte (d) Si cau la màquina avui
botiga-web No Públic, des d'internet Deployment + Service + Ingress El web deixa de respondre del tot
api-reserves No Públic i intern Deployment + Service + Ingress + HPA No es poden consultar ni crear reserves
postgres-reserves Intern, restringit StatefulSet + PVC Aturada total i risc de pèrdua de dades si el disc no està replicat
redis-cache Sí, prescindible Intern Deployment o StatefulSet + Service Degradació de rendiment; el servei continua amb consultes directes a la base de dades
worker-notificacions No Cap Deployment (sense Service) Els correus de confirmació s'acumulen sense enviar-se
informes-ocupacio No, finit Cap CronJob L'informe nocturn no es genera

redis-cache i postgres-reserves reben tractaments diferents perquè l'estat de Redis és reconstruïble: si es perd, es repobla des de la base de dades i només es degrada el rendiment. L'estat de PostgreSQL és la font de veritat del negoci: perdre'l significa perdre reserves i dades personals de clients. Per això PostgreSQL exigeix emmagatzematge persistent, identitat estable, còpies de seguretat i aïllament de xarxa, mentre que Redis només necessita un límit de memòria i una política d'expulsió.

Solució 2

# k8s/base/redis-cache-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-cache
  namespace: rutas-norte-dev
  labels:
    app: redis-cache
    app.kubernetes.io/part-of: rutas-norte
    entorn: dev
spec:
  containers:
    - name: redis
      image: redis:7.2-alpine
      ports:
        - name: redis
          containerPort: 6379
      resources:
        requests:
          cpu: "50m"
          memory: "64Mi"
        limits:
          cpu: "200m"
          memory: "256Mi"
kubectl apply -f k8s/base/redis-cache-pod.yaml --dry-run=client
kubectl apply -f k8s/base/redis-cache-pod.yaml
kubectl get pod redis-cache -o wide
kubectl exec -it redis-cache -- redis-cli ping
kubectl get pods -l app.kubernetes.io/part-of=rutas-norte
PONG

NAME          READY   STATUS    RESTARTS   AGE
redis-cache   1/1     Running   0          32s
botiga-web    1/1     Running   0          14m

Solució 3

# 1. Matar el procés dins del contenidor
kubectl get pods -w &
kubectl exec botiga-web -- kill 1
botiga-web   1/1   Running   0          15m
botiga-web   0/1   Error     0          15m
botiga-web   1/1   Running   1 (2s ago) 15m

El contenidor sí que torna: RESTARTS passa de 0 a 1 i la IP del pod no canvia, perquè és el mateix pod. Qui el recupera és el kubelet, aplicant la restartPolicy: Always que un pod té per defecte. El kubelet reinicia contenidors dins d'un pod existent.

# 2. Esborrar el pod sencer
kubectl delete pod botiga-web
kubectl get pods
No resources found in rutas-norte-dev namespace.

El pod no torna. No hi ha cap controlador que vigili la seva existència.

  1. La diferència és en qui actua i sobre què: el kubelet vigila els contenidors dins dels pods que té assignats i els reinicia si moren, però no pot recrear un pod que ja no existeix com a objecte a l'API. Recrear pods és feina d'un controlador del kube-controller-manager, i un pod solt no en té cap d'associat: en esborrar-lo, vas esborrar el mateix estat desitjat.

  2. Necessites un Deployment, que crea un ReplicaSet el controlador del qual manté permanentment el nombre de rèpliques declarat. Amb ell, l'estat desitjat deixa de ser "que existeixi aquest pod concret" i passa a ser "que existeixin N pods amb aquestes característiques", de manera que esborrar-ne un provoca immediatament la creació d'un altre.

Conclusió

Ja coneixes el projecte que dona sentit a tot el curs. Rutas Norte S.L. és una empresa amb problemes absolutament reals —caigudes nocturnes sense resposta, pics de demanda en ponts i vacances, desplegaments amb tall de servei i dades personals de clients mal protegides— i la seva plataforma es compon de sis peces amb necessitats ben diferenciades: dos frontals sense estat, una base de dades crítica amb estat, una memòria cau prescindible, un worker sense trànsit entrant i una tasca nocturna programada. Tens l'arquitectura objectiu, el mapa de quin mòdul aporta què, i les convencions —namespaces per entorn, esquema d'etiquetes, etiquetes d'imatge immutables i estructura k8s/ versionada a Git— que aplicarem sense excepció.

I, sobretot, ja has desplegat el teu primer component: botiga-web corrent a rutas-norte-dev, inspeccionat amb get, describe i logs, i visible al teu navegador mitjançant port-forward. També has comprovat en primera persona el seu punt feble: un pod solt que, en esborrar-se, no torna mai.

Amb això tanques el mòdul 1. Saps què és Kubernetes, com està construït, què significa cada terme, tens un clúster funcionant, domines kubectl i entens el model declaratiu. El mòdul 2, Components Principals de Kubernetes, arrenca just on acaba aquesta lliçó: convertirem aquell pod fràgil en un Deployment amb diverses rèpliques que es recupera sol, aprendrem primer què és exactament un Pod per dins i com un ReplicaSet el manté amb vida, i donarem a botiga-web i a api-reserves una adreça estable amb Serveis. La plataforma Rutas Norte comença a prendre forma de debò.

Curs de Kubernetes

Mòdul 1: Introducció a Kubernetes

Mòdul 2: Components Principals de Kubernetes

Mòdul 3: Gestió de Configuració i Secrets

Mòdul 4: Xarxes a Kubernetes

Mòdul 5: Emmagatzematge a Kubernetes

Mòdul 6: Conceptes Avançats de Kubernetes

Mòdul 7: Monitoratge i Registre

Mòdul 8: Seguretat a Kubernetes

Mòdul 9: Escalat i Rendiment

Mòdul 10: Ecosistema i Eines de Kubernetes

Mòdul 11: Estudis de Cas i Aplicacions del Món Real

Mòdul 12: Preparació per a la Certificació de Kubernetes

© Copyright 2026. Tots els drets reservats