Arribem al moment que el curs porta prometent des del mòdul 1: publicar Rutas Norte a internet. Tenim cinc components desplegats, tots amb Services ClusterIP que només existeixen dins del clúster, i cap client no pot comprar un bitllet. A 04-02 vam veure que LoadBalancer resoldria el problema al preu d'un balancejador i una IP pública per servei, sense encaminament per domini ni per ruta. Aquesta lliçó presenta la resposta correcta: un únic punt d'entrada HTTP que reparteix el trànsit segons el domini i la ruta demanats. En acabar, www.rutasnorte.example servirà la botiga i api.rutasnorte.example servirà l'API, tots dos des del mateix balancejador, i sabràs distingir amb claredat entre el recurs Ingress —una regla que no fa res per si sola— i el controlador d'Ingress, el programa que la converteix en configuració real.

Contingut

  1. El problema: diversos serveis HTTP, un sol punt d'entrada
  2. Recurs davant de controlador: la distinció essencial
  3. Panorama de controladors
  4. IngressClass i l'anotació heretada
  5. Anatomia d'un Ingress
  6. pathType: els tres valors i els casos que confonen
  7. Cas pràctic: publicar la botiga i l'API
  8. Encaminament per host davant d'encaminament per ruta i reescriptura
  9. Anotacions del dia a dia
  10. Depuració
  11. Gateway API: la successora

  1. El problema: diversos serveis HTTP, un sol punt d'entrada

Rutas Norte necessita publicar, com a mínim:

Destinació pública Component Notes
www.rutasnorte.example botiga-web Trànsit massiu als ponts
api.rutasnorte.example api-reserves Consumida per la SPA i per agències
www.rutasnorte.example/api api-reserves Alternativa sense domini a part
admin.rutasnorte.example Panell intern Només des de la xarxa d'oficina

Amb type: LoadBalancer serien quatre balancejadors, quatre IP públiques i quatre certificats TLS gestionats per separat, multiplicat pels tres entorns. I tot i així faltaria l'essencial: un balancejador L4 no entén HTTP. No pot llegir la capçalera Host per decidir a quin servei va la petició, ni mirar la ruta, ni reescriure-la, ni afegir capçaleres. L'Ingress trasllada la decisió a capa 7:

flowchart TB
    C1["Client<br/>www.rutasnorte.example"] --> LB
    C2["Client<br/>api.rutasnorte.example"] --> LB
    LB["UN Service LoadBalancer<br/>IP publica unica"] --> IC["Controlador d'Ingress<br/>(pods nginx al cluster)"]
    IC -->|"Host: www.rutasnorte.example"| S1["Service botiga-web<br/>ClusterIP"]
    IC -->|"Host: api.rutasnorte.example"| S2["Service api-reserves<br/>ClusterIP"]
    IC -->|"/admin"| S3["Service panell-admin<br/>ClusterIP"]
    S1 --> P1["Pods botiga-web"]
    S2 --> P2["Pods api-reserves"]

Un balancejador, una IP, un lloc on acabar el TLS (04-05), i tots els serveis interns continuen sent ClusterIP.

  1. Recurs davant de controlador: la distinció essencial

Aquesta és la confusió número u de la lliçó i cal fixar-la abans d'escriure res.

Recurs Ingress Controlador d'Ingress
Què és Un objecte de l'API, networking.k8s.io/v1 Un programa que s'executa en pods del clúster
Què fa Res. Declara una intenció Observa els Ingress i encamina el trànsit real
Qui el crea Tu, amb kubectl apply L'administrador, un cop per clúster
Analogia El senyal de trànsit dibuixat en un plànol L'asfalt, els carrils i el guàrdia
Si falta l'altre Es crea sense error i no passa res No sap on enviar res

El símptoma de crear un Ingress sense controlador enganya: kubectl apply respon created, kubectl get ingress el llista i el domini no respon. La pista és a la columna ADDRESS, buida per sempre.

NAME          CLASS   HOSTS                          ADDRESS   PORTS   AGE
rutas-norte   nginx   www.rutasnorte.example,api...             80      12m

Un controlador és, per dins, un bucle idèntic al del mòdul 1: observa l'API, llegeix els Ingress, Services i EndpointSlices, genera un fitxer de configuració (un nginx.conf, a ingress-nginx) i recarrega el seu proxy, fent servir una ServiceAccount amb permisos (03-06).

  1. Panorama de controladors

Controlador Base Punts forts A tenir en compte
ingress-nginx NGINX El més estès; mantingut pel projecte Kubernetes; enorme catàleg d'anotacions Recarrega la configuració en canviar; moltes funcions viuen en anotacions no estandarditzades
Traefik Go, propi Configuració dinàmica sense recàrregues; integració nativa amb ACME; bon panell Les seves funcions avançades fan servir CRD propis (IngressRoute)
HAProxy Ingress HAProxy Rendiment i estabilitat en L4/L7; excel·lent per a càrrega alta Comunitat més petita
AWS ALB / GKE / AGIC Balancejador del núvol El trànsit ni tan sols entra en un pod; s'integra amb WAF i certificats gestionats Lligat al proveïdor; menys control fi
Istio Gateway / Cilium Malla / eBPF mTLS, polítiques L7, telemetria profunda Complexitat notable; sol venir amb una malla completa

Compte amb un detall històric: existeixen dos controladors basats en NGINX. ingress-nginx és el del projecte Kubernetes; "NGINX Ingress Controller" és el de F5/NGINX Inc. Les seves anotacions no són compatibles, i moltes hores s'han perdut copiant la del controlador equivocat. Aquí fem servir ingress-nginx, el de l'addon de minikube.

minikube -p rutas-norte addons enable ingress
kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-9k2lm        0/1     Completed   0          70s
ingress-nginx-admission-patch-x4dpq         0/1     Completed   0          70s
ingress-nginx-controller-7d4b8f6c8d-2vq7z   1/1     Running     0          70s

Els dos Completed són Jobs (06-03) que instal·len el webhook de validació: gràcies a ell, un Ingress amb sintaxi invàlida es rebutja a l'apply en lloc de trencar la configuració del proxy.

  1. IngressClass i l'anotació heretada

Un clúster pot tenir diversos controladors: un de públic per a botiga-web i api-reserves, un altre d'intern per al panell d'administració. IngressClass diu quin controlador atén quin Ingress.

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"   # aten els Ingress sense classe
spec:
  controller: k8s.io/ingress-nginx

A l'Ingress es referencia amb el camp spec.ingressClassName: nginx. Abans de Kubernetes 1.18 això es feia amb l'anotació kubernetes.io/ingress.class: "nginx", que continua funcionant en molts controladors per compatibilitat però està desaconsellada i desapareixerà. Veuràs moltíssims exemples a internet amb ella: són antics. Fes servir ingressClassName.

Si no indiques classe i cap no està marcada com a predeterminada, cap controlador no recull l'Ingress: ADDRESS buit i silenci.

  1. Anatomia d'un Ingress

apiVersion: networking.k8s.io/v1     # COMPTE: v1, no les obsoletes extensions/v1beta1
kind: Ingress
metadata:
  name: rutas-norte
  namespace: rutas-norte-pro         # ha de ser el MATEIX que el dels Services
spec:
  ingressClassName: nginx            # quin controlador l'aten

  defaultBackend:                    # opcional: on va allo que no casa cap regla
    service:
      name: botiga-web
      port:
        number: 80

  rules:
    - host: www.rutasnorte.example   # opcional: sense host, la regla casa qualsevol domini
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: botiga-web     # nom d'un Service del MATEIX namespace
                port:
                  number: 80         # o name: http, si el port te nom

Restriccions que provoquen la majoria de les fallades:

  • L'Ingress i els Services han de ser al mateix namespace. Un Ingress de rutas-norte-pro no pot apuntar a un Service de rutas-norte-dev: és disseny de seguretat, no limitació tècnica.
  • El port pot ser number o name, però no tots dos. Referenciar-lo per nom sobreviu a un canvi de número.
  • host accepta un comodí al primer nivell (*.rutasnorte.example), que casa api.rutasnorte.example però no www.api.rutasnorte.example ni el domini nu. Les regles sense host casen qualsevol domini: útil per a proves per IP, perillós en producció.

defaultBackend és la destinació d'allò que no casa res: sense ell, el controlador retorna el seu 404 genèric; amb ell, un client que escrigui malament el subdomini acaba a la botiga.

  1. pathType: els tres valors i els casos que confonen

pathType és obligatori des de networking.k8s.io/v1 i la seva semàntica sorprèn gairebé tothom.

Valor Com compara Recomanació
Exact Coincidència literal exacta, sensible a majúscules Rutes concretes, sense descendents
Prefix Per segments de ruta separats per /, no per caràcters El valor per defecte de facto
ImplementationSpecific Ho decideix el controlador; a ingress-nginx habilita expressions regulars Només quan necessitis regex, i sabent que no és portable

La clau de Prefix és a les tres paraules "per segments de ruta". /api no és un prefix de caràcters: casa /api i /api/elquesigui, però no casa /apificat.

Regla Petició Casa? Per què
/api Prefix /api Exacte
/api Prefix /api/ Segment complet
/api/ Prefix /api La barra final s'ignora en comparar
/api Prefix /api/reserves/33 Descendent per segments
/api Prefix /apificat No apificat és un altre segment diferent
/api Exact /api
/api Exact /api/ No La barra final la fa diferent
/api Exact /api/reserves No No hi ha descendents
/API Exact /api No Distingeix majúscules

Regla de desempat quan diverses casen: guanya la ruta més llarga, sense importar el pathType.

paths:
  - path: /              # casa tot
    pathType: Prefix
    backend: { service: { name: botiga-web,   port: { number: 80 } } }
  - path: /api           # mes llarga: guanya per a /api/*
    pathType: Prefix
    backend: { service: { name: api-reserves, port: { number: 3000 } } }

Una petició a /api/reserves casa les dues regles, i va a api-reserves perquè /api és més llarga que /. Aquest ordre per longitud, i no per posició al YAML, evita l'error de "he posat la regla més específica a dalt i no funciona".

  1. Cas pràctic: publicar la botiga i l'API

Un sol Ingress publica els dos dominis de Rutas Norte.

# k8s/entorns/pro/ingress-rutas-norte.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rutas-norte
  namespace: rutas-norte-pro
  labels:
    app.kubernetes.io/part-of: rutas-norte
    entorn: pro
  annotations:
    # Mida de cos: els justificants en PDF que puja atencio al client
    nginx.ingress.kubernetes.io/proxy-body-size: "8m"
    # La passarel-la de pagaments pot trigar; donem marge
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
  ingressClassName: nginx
  rules:
    - host: www.rutasnorte.example
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: botiga-web
                port:
                  name: http           # referencia per nom de port
    - host: api.rutasnorte.example
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-reserves
                port:
                  name: http

Fixa't en el que no cal fer: no es canvien els Services a NodePort ni a LoadBalancer. Continuen sent ClusterIP, perquè qui els parla és el controlador, que és dins del clúster.

Aplicació i comprovació:

kubectl apply -f k8s/entorns/pro/ingress-rutas-norte.yaml
kubectl get ingress -n rutas-norte-pro

# Els dominis .example no existeixen al DNS public: es resolen a ma
echo "$(minikube -p rutas-norte ip) www.rutasnorte.example api.rutasnorte.example" \
  | sudo tee -a /etc/hosts

curl -s -o /dev/null -w 'botiga: %{http_code}\n' http://www.rutasnorte.example/
curl -s -w '\n' http://api.rutasnorte.example/salut
NAME          CLASS   HOSTS                                          ADDRESS        PORTS   AGE
rutas-norte   nginx   www.rutasnorte.example,api.rutasnorte.example   192.168.49.2   80      40s

botiga: 200
{"estat":"ok","versio":"2.4.1","entorn":"pro"}

ADDRESS amb la IP del node significa que el controlador ha recollit l'Ingress. Aquest camp triga entre uns segons i un parell de minuts a aparèixer; si continua buit passats cinc, alguna cosa va malament (apartat 10).

Els clients de Rutas Norte ja poden arribar a la plataforma: és la primera vegada al curs que el trànsit entra de debò des de fora del clúster. Que l'encaminament es fa per la capçalera Host i no per la IP ho comprovarem a l'exercici 1: mateixa IP, mateix port, resultats diferents segons el Host. Això és encaminament L7.

  1. Encaminament per host davant d'encaminament per ruta i reescriptura

L'alternativa als dos dominis és servir l'API sota /api del domini principal.

Per host (api.rutasnorte.example) Per ruta (www.rutasnorte.example/api)
Certificats TLS Un per domini (o comodí) Un de sol
Registres DNS Un per subdomini Un
CORS a la SPA Sí: origen diferent No: mateix origen
Galetes No es comparteixen entre subdominis (tret de configuració) Compartides
Reescriptura de ruta No necessària Gairebé sempre necessària
Escalar per separat Molt fàcil Fàcil

Rutas Norte fa servir totes dues: api.rutasnorte.example per a les agències externes, i www.rutasnorte.example/api perquè la SPA no hagi de lidiar amb CORS.

Reescriptura de rutes

El problema: la SPA demana /api/reserves però api-reserves espera /reserves; sense reescriptura rebria /api/reserves i retornaria 404.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rutas-norte-api-per-ruta
  namespace: rutas-norte-pro
  annotations:
    # $2 = segon grup de captura de l'expressio regular del path
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: nginx
  rules:
    - host: www.rutasnorte.example
      http:
        paths:
          - path: /api(/|$)(.*)          # grup 1: /(o fi), grup 2: la resta
            pathType: ImplementationSpecific
            backend:
              service:
                name: api-reserves
                port:
                  name: http

Com llegir aquesta expressió: /api casa el prefix literal; (/|$) és el grup 1 (una barra o el final de la cadena, perquè casin tant /api com /api/...); (.*) és el grup 2, tot el que vingui després; i rewrite-target: /$2 reconstrueix la ruta amb només el grup 2.

Petició del navegador Grup 2 El que rep api-reserves
/api/reserves reserves /reserves
/api/reserves/33 reserves/33 /reserves/33
/api (buit) /
/api/salut?v=2 salut /salut?v=2 (la query es conserva)

I l'avís: pathType passa a ImplementationSpecific perquè estem fent servir una expressió regular, cosa que Prefix no contempla. Aquell Ingress no és portable a Traefik ni a l'ALB d'AWS. És un compromís conscient.

Advertència molt repetida: la reescriptura afecta la ruta de la petició, no les URL que l'aplicació genera al seu HTML o a les seves redireccions. Si api-reserves respon Location: /reserves/33, el navegador hi anirà i no a /api/reserves/33. Les aplicacions servides sota un prefix l'han de conèixer (típicament amb una variable BASE_PATH).

  1. Anotacions del dia a dia

Les anotacions són el mecanisme pel qual cada controlador exposa les seves funcions; aquestes són les d'ingress-nginx que es fan servir en qualsevol plataforma real.

Anotació Per a què Valor típic a Rutas Norte
proxy-body-size Mida màxima del cos. 413 Request Entity Too Large si se supera 8m
proxy-read-timeout / proxy-send-timeout Segons d'espera cap al backend. 504 en esgotar-se 60
proxy-connect-timeout Espera per establir connexió 5
limit-rps / limit-connections Limitació de peticions i connexions per IP de client 20 rps
limit-whitelist IP exemptes del límit Rang de l'oficina
whitelist-source-range Només aquestes IP hi poden accedir Panell d'administració
configuration-snippet Fragment de configuració NGINX a mida Capçaleres de seguretat
enable-cors / cors-allow-origin Capçaleres CORS gestionades pel proxy Per a les agències externes
backend-protocol HTTP, HTTPS, GRPC HTTP

Exemple aplicat als pics de trànsit de ponts i vacances:

metadata:
  annotations:
    # Limitacio: 20 peticions per segon i client, amb marge de rafega
    nginx.ingress.kubernetes.io/limit-rps: "20"
    nginx.ingress.kubernetes.io/limit-burst-multiplier: "3"
    # La xarxa de l'oficina no es limita mai
    nginx.ingress.kubernetes.io/limit-whitelist: "10.20.30.0/24"
    # Capceleres de seguretat cap al client
    nginx.ingress.kubernetes.io/configuration-snippet: |
      more_set_headers "X-Content-Type-Options: nosniff";
      more_set_headers "X-Frame-Options: SAMEORIGIN";

Dues advertències importants:

  • configuration-snippet està desactivat per defecte a les versions recents d'ingress-nginx per seguretat (permetia injectar configuració arbitrària del proxy des de qualsevol namespace). Cal habilitar-lo al ConfigMap del controlador, i convé pensar-s'ho dues vegades.
  • La limitació s'aplica per rèplica del controlador. Amb tres rèpliques, un límit de 20 rps és a la pràctica 60.

Els ajustos globals (capçaleres per defecte, mides de memòria intermèdia, format de log) no van en anotacions sinó al ConfigMap del controlador, ingress-nginx-controller del namespace ingress-nginx.

  1. Depuració

kubectl describe ingress

La primera parada sempre:

kubectl describe ingress rutas-norte -n rutas-norte-pro
Name:             rutas-norte
Namespace:        rutas-norte-pro
Address:          192.168.49.2
Ingress Class:    nginx
Rules:
  Host                      Path  Backends
  ----                      ----  --------
  www.rutasnorte.example
                            /     botiga-web:http (10.244.0.22:8080,10.244.0.29:8080)
  api.rutasnorte.example
                            /     api-reserves:http (10.244.0.31:3000)
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ------------------------  -------
  Normal  Sync    35s   nginx-ingress-controller  Scheduled for sync

El que cal mirar, en aquest ordre: Address emplenat (algú ha recollit l'Ingress); Ingress Class correcta; els backends amb IP de pod entre parèntesis —si posa <error: endpoints "botiga-web" not found> o una llista buida, el problema no és de l'Ingress, és el Service, i tornes al diagnòstic de 02-05—; i Events amb Sync, que confirma que el controlador va aplicar la configuració.

Logs del controlador

kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller -f
192.168.49.1 - - [05/Aug/2026:11:20:14 +0000] "GET /reserves/33 HTTP/1.1" 200 812
  "-" "curl/8.5.0" 141 0.043 [rutas-norte-pro-api-reserves-http] [] 10.244.0.31:3000 812 0.042 200

Els camps entre claudàtors són or: [rutas-norte-pro-api-reserves-http] és l'upstream triat, i 10.244.0.31:3000 el pod concret. Si l'upstream apareix buit, cap regla no ha casat.

Quadre de fallades

Símptoma Causa probable Comprovació
ADDRESS buit després de 5 min No hi ha controlador, o ingressClassName no casa kubectl get pods -n ingress-nginx; kubectl get ingressclass
404 del controlador (nginx) Cap regla no casa: Host o path malament curl -H 'Host: ...'; revisa pathType
503 Service Temporarily Unavailable El Service no té endpoints kubectl get endpointslices -n <ns>
502 Bad Gateway El pod rebutja la connexió o el targetPort és incorrecte kubectl exec i curl al pod directament
504 Gateway Time-out El backend triga més que proxy-read-timeout Puja el temps d'espera o arregla la lentitud
413 Cos més gran que proxy-body-size Ajusta l'anotació
Funciona per IP i no per domini /etc/hosts o DNS malament getent hosts www.rutasnorte.example
L'Ingress no es crea El webhook de validació el rebutja Llegeix el missatge: sol ser regex invàlida o ruta mal formada

La distinció mereix memoritzar-se: 503 és que no hi ha a qui enviar (endpoints buits) i 502 és que hi ha a qui enviar però no respon bé. Capes diferents.

La verificació definitiva: la configuració generada

Veure el nginx.conf que el controlador ha generat a partir del teu Ingress tanca qualsevol discussió sobre què està passant: kubectl exec -n ingress-nginx deploy/ingress-nginx-controller -- cat /etc/nginx/nginx.conf | grep -A5 "server_name api.rutasnorte.example".

  1. Gateway API: la successora

L'Ingress ha envellit malament. La seva especificació és tan mínima que tot allò interessant va acabar en anotacions propietàries: reescriptura, CORS, limitació, capçaleres... Res d'això no és portable. A més barreja responsabilitats: qui administra la infraestructura i qui publica una aplicació editen el mateix objecte.

La Gateway API (gateway.networking.k8s.io) és la resposta oficial, ja estable per als seus recursos principals.

Concepte Recurs Qui el gestiona
Quina implementació es fa servir GatewayClass Administrador del clúster
El punt d'entrada: ports, TLS, dominis Gateway Equip de plataforma
Les regles HTTP: hosts, rutes, filtres, pesos HTTPRoute Equip d'aplicació
Altres protocols TCPRoute, GRPCRoute, TLSRoute Equip d'aplicació

Avantatges concrets davant d'Ingress: separació de rols (l'equip de Rutas Norte crea el seu HTTPRoute sense tocar el punt d'entrada); funcions al model, no en anotacions —reescriptura, redirecció, capçaleres i repartiment per pesos són camps de l'API, així que el canari de 11-04 deixa de necessitar anotacions específiques—; rutes entre namespaces amb permís explícit del propietari del Gateway; i portabilitat real entre implementacions.

L'Ingress no està obsolet i continuarà funcionant molts anys: hi ha massa desplegat. Però per a una plataforma nova el 2026 val la pena avaluar la Gateway API, sobretot si ja es fa servir Istio, Cilium o Traefik. Aquí continuem amb Ingress perquè és el que et trobaràs i el que avaluen les certificacions del mòdul 12.

Errors Comuns i Consells

  • Crear l'Ingress sense controlador. L'apply va bé i res no funciona. Comprova kubectl get pods -n ingress-nginx abans.
  • Apuntar a un Service d'un altre namespace. No és possible. L'Ingress viu al namespace dels seus Services.
  • Copiar anotacions del controlador equivocat. nginx.ingress.kubernetes.io/* és d'ingress-nginx; el de F5 fa servir nginx.org/*. No són intercanviables.
  • Fer servir kubernetes.io/ingress.class. Obsoleta. Fes servir ingressClassName.
  • Esperar que Prefix compari caràcters. /api no casa /apificat. Compara segments.
  • Confondre 503 amb 502. El primer és "no hi ha endpoints"; el segon, "el pod no respon bé". Diagnòstics diferents.
  • Reescriure rutes sense que l'aplicació ho sàpiga. Els enllaços i redireccions que generi continuaran sense el prefix. Configura el BASE_PATH de l'aplicació.
  • Oblidar que l'encaminament depèn de la capçalera Host. Provar amb curl http://IP/ sense -H 'Host: ...' donarà 404 encara que tot estigui bé.
  • Consell: un Ingress per aplicació, no un de gegant per clúster. Es despleguen i es reverteixen de manera independent.
  • Consell: les anotacions de temps d'espera i mida de cos són de les primeres que es necessiten en producció. Posa-les des del principi amb valors raonables en lloc d'esperar al primer 413 en un pont.

Exercicis

Exercici 1: Publicar els dos dominis de Rutas Norte

Activa l'addon ingress de minikube, crea l'Ingress que publica www.rutasnorte.example contra botiga-web i api.rutasnorte.example contra api-reserves, resol els dominis a /etc/hosts i comprova les dues rutes. Demostra a més que l'encaminament es fa per capçalera Host.

Exercici 2: Servir l'API sota /api amb reescriptura

Afegeix al domini www.rutasnorte.example una ruta /api que arribi a api-reserves sense el prefix. Verifica als logs del controlador quina ruta rep realment el backend i què passa amb /apificat.

Exercici 3: Diagnosticar tres Ingress trencats

Reprodueix i diagnostica: (A) un Ingress amb ingressClassName: traefik en un clúster amb només ingress-nginx; (B) un Ingress correcte el Service del qual apunta a un selector que no casa; (C) un Ingress el backend.service.port.number del qual és 8080 quan el Service exposa el 80. Indica el símptoma exacte de cadascun i l'ordre que l'identifica.

Solucions

Exercici 1

minikube -p rutas-norte addons enable ingress
kubectl wait --for=condition=ready pod \
  -l app.kubernetes.io/component=controller -n ingress-nginx --timeout=120s
kubectl apply -f k8s/entorns/pro/ingress-rutas-norte.yaml
kubectl get ingress -n rutas-norte-pro -w      # esperar que aparegui ADDRESS

# Encaminament per Host: mateixa IP, tres resultats
IP=$(minikube -p rutas-norte ip)
for H in www.rutasnorte.example api.rutasnorte.example inventat.example; do
  printf '%-28s %s\n' "$H" "$(curl -s -o /dev/null -w '%{http_code}' -H "Host: $H" http://$IP/)"
done
www.rutasnorte.example       200
api.rutasnorte.example       200
inventat.example             404

El 404 del tercer prova que la decisió es pren llegint la capçalera Host, no la IP de destinació.

Exercici 2

# k8s/entorns/pro/ingress-api-per-ruta.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rutas-norte-api-per-ruta
  namespace: rutas-norte-pro
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: nginx
  rules:
    - host: www.rutasnorte.example
      http:
        paths:
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: api-reserves
                port:
                  name: http
kubectl apply -f k8s/entorns/pro/ingress-api-per-ruta.yaml
curl -s http://www.rutasnorte.example/api/salut
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=3
"GET /api/salut HTTP/1.1" 200 ... [rutas-norte-pro-api-reserves-http] 10.244.0.31:3000

El client va demanar /api/salut; el backend va rebre /salut. Amb /apificat, la regex /api(/|$)(.*) que casaria (perquè use-regex compara caràcters, no segments) i el backend rebria /ficat — un motiu més per preferir Prefix tret que la reescriptura sigui imprescindible, i per ancorar millor l'expressió si és un problema.

Exercici 3

Cas Símptoma Ordre que l'identifica
A classe inexistent ADDRESS permanentment buit; cap esdeveniment Sync; el domini no respon kubectl get ingressclass (només existeix nginx) i kubectl describe ingress sense esdeveniments
B selector que no casa L'Ingress està bé i amb ADDRESS, però retorna 503 kubectl describe ingress mostra el backend sense IP; kubectl get endpointslices buit
C port inexistent 503 i un error explícit a describe <error: endpoints "api-reserves" not found> o backend sense resoldre; el port de l'Ingress ha de coincidir amb el port del Service, no amb el del contenidor
kubectl describe ingress <nom> -n rutas-norte-pro | sed -n '/Rules/,/Annotations/p'
kubectl get endpointslices -n rutas-norte-pro -l kubernetes.io/service-name=api-reserves

L'error de C és especialment freqüent: el port de l'Ingress és el del Service (port), no el del contenidor (targetPort). Confondre'ls produeix un Ingress que sembla correcte i retorna 503.

Conclusió

Rutas Norte ja està publicada. Entens la distinció que ordena tota la resta: el recurs Ingress és una declaració d'intencions que per si sola no fa absolutament res, i el controlador d'Ingress és el programa que l'observa, genera configuració de proxy i encamina el trànsit de debò; si falta el segon, el primer es crea sense errors i l'ADDRESS es queda buit per sempre. Coneixes el panorama de controladors, el perill de confondre ingress-nginx amb el controlador homònim de F5, i saps seleccionar el teu amb ingressClassName en lloc de l'anotació obsoleta kubernetes.io/ingress.class.

Domines l'anatomia de l'objecte: rules amb host i http.paths, backend.service.name amb el port del Service (no el del contenidor), i el defaultBackend per a allò que no casa res. Tens clar que pathType: Prefix compara segments de ruta i no caràcters —/api no casa /apificat— que Exact distingeix la barra final i les majúscules, que ImplementationSpecific és la porta a les expressions regulars al preu de la portabilitat, i que quan diverses regles casen guanya la més llarga.

Sobretot, has fet la feina: vas activar l'addon ingress, vas publicar www.rutasnorte.example contra botiga-web i api.rutasnorte.example contra api-reserves amb un sol Ingress i un sol punt d'entrada, vas resoldre els dominis amb /etc/hosts i vas demostrar que el repartiment es fa llegint la capçalera Host. Vas afegir la ruta /api amb rewrite-target entenent grup a grup l'expressió regular, i coneixes les anotacions que es necessiten en producció des del primer dia: mida de cos, temps d'espera, limitació de peticions i capçaleres de seguretat. Saps depurar amb describe, amb els logs del controlador i, en últim extrem, llegint el nginx.conf generat, i distingeixes sense dubtar un 503 (sense endpoints) d'un 502 (backend que no respon). I saps que la Gateway API és la successora, amb separació de rols i funcions al model en lloc d'en anotacions.

Queda un problema greu, i és dels que no admeten demora: tot això va per HTTP en clar. Les dades personals que els clients escriuen per reservar —nom, DNI, telèfon, correu— i les dades que viatgen cap a la passarel·la de pagaments estan recorrent internet sense xifrar. A 04-05 posarem HTTPS als dos dominis: primer amb un certificat autosignat per a desenvolupament, i després amb cert-manager emetent i renovant automàticament certificats de Let's Encrypt mitjançant els desafiaments ACME HTTP-01 i DNS-01.

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