A la lliçó anterior vam publicar www.rutasnorte.example i api.rutasnorte.example amb un únic Ingress, i vam tancar assenyalant el problema que no admet demora: tot viatja en HTTP en clar. El nom, el DNI, el telèfon i el correu que un client escriu per reservar un bitllet, i les dades que van cap a la passarel·la de pagaments, estan creuant internet sense xifrar. Aquesta lliçó posa HTTPS als dos dominis: primer a mà amb un certificat autosignat per entendre les peces, i després de manera automàtica amb cert-manager, que emetrà i renovarà certificats de Let's Encrypt sense que ningú hagi de recordar res.
Advertiment de seguretat. Aquesta lliçó ensenya la mecànica de Kubernetes per gestionar certificats. La configuració criptogràfica real d'una plataforma en producció —conjunts de xifratge, versions de TLS permeses, polítiques d'HSTS, custòdia de claus privades, requisits de compliment normatiu— l'ha de revisar i aprovar un professional de seguretat. Els valors que apareixen aquí són didàctics i raonables el 2026, però envelleixen: no els copiïs a producció sense validar-los amb qui correspongui a la teva organització.
Contingut
- Per què HTTPS és obligatori a Rutas Norte
- On acaba el TLS en un clúster
- El Secret
kubernetes.io/tlsi el bloctls:de l'Ingress - Certificat autosignat per a desenvolupament
- cert-manager: quin problema resol i instal·lació
- Els objectes de cert-manager i el flux d'emissió
- ACME amb Let's Encrypt:
HTTP-01davant deDNS-01 - Emissió automàtica des de l'Ingress
- L'entorn de staging i els límits d'emissió
- Renovació automàtica i comprovació de l'estat
- Redirecció a HTTPS i HSTS
- Més enllà: mTLS i malles de servei
- Per què HTTPS és obligatori a Rutas Norte
No és una bona pràctica: és un requisit.
| Motiu | Què passa sense TLS |
|---|---|
| Dades personals | Nom, DNI, telèfon i correu viatgen llegibles per qualsevol xarxa intermèdia. Al RGPD, el xifratge en trànsit és una mesura tècnica esperable |
| Pagaments | PCI DSS exigeix xifratge del canal. Cap passarel·la seriosa no accepta integrar-se per HTTP |
| Sessions | Un JWT o una galeta interceptada en una wifi pública és un compte robat |
| Integritat | Un intermediari pot modificar la resposta: injectar scripts, canviar l'import |
| Navegadors i SEO | Marquen "No segur", bloquegen API (geolocalització, service workers) i els cercadors penalitzen HTTP. La botiga semblaria fraudulenta |
I una precisió: TLS no només xifra, també autentica. El certificat demostra que qui respon a www.rutasnorte.example és realment Rutas Norte i no algú que ha segrestat el DNS. Sense aquella part, el xifratge seria amb un desconegut.
- On acaba el TLS en un clúster
"Acabar el TLS" significa desxifrar: el punt on el trànsit deixa d'estar xifrat. Hi ha tres opcions.
flowchart LR
CA["Client"] -->|HTTPS| IA["A. Ingress:<br/>desxifra aqui"]
IA -->|"HTTP en clar"| SA["Pods"]
CB["Client"] -->|HTTPS| IB["B. Ingress: desxifra<br/>i torna a xifrar"]
IB -->|HTTPS| SB["Pods amb certificat propi"]
CC["Client"] -->|HTTPS| IC["C. Ingress: NO desxifra,<br/>reenvia per SNI"]
IC -->|HTTPS| SC["El pod acaba el TLS"]
| Model | Avantatges | Inconvenients | Quan |
|---|---|---|---|
| A. Terminació a l'Ingress | Un sol lloc amb certificats; les aplicacions no saben de TLS; el controlador pot encaminar per ruta i capçaleres | El trànsit intern va en clar dins del clúster | Per defecte, i el que fa servir Rutas Norte |
| B. Rexifratge | Xifrat també dins del clúster | Cada aplicació gestiona el seu certificat | Entorns regulats, xarxes no fiables |
| C. Passthrough | El certificat no surt mai de l'aplicació | L'Ingress no veu HTTP: sense encaminament per ruta, sense reescriptura | mTLS estricte, protocols opacs |
Rutas Norte fa servir A. El trànsit intern en clar es compensa amb les polítiques de xarxa de 04-06, i si calgués xifratge dins del clúster, la resposta seria una malla de servei (08-04).
- El Secret
kubernetes.io/tls i el bloc tls: de l'Ingress
kubernetes.io/tls i el bloc tls: de l'IngressUn certificat a Kubernetes és un Secret de tipus kubernetes.io/tls amb exactament dues claus: tls.crt, la cadena de certificats en PEM (el del servidor primer, després els intermedis), i tls.key, la clau privada en PEM. El tipus obliga que totes dues existeixin.
Recorda de 03-02: això és base64, no xifratge, i qualsevol amb permís de lectura sobre Secrets en aquell namespace té la clau privada de la plataforma; és l'argument més contundent per al RBAC de 08-01 i per al xifratge en repòs d'etcd. L'Ingress el consumeix amb el bloc tls::
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rutas-norte
namespace: rutas-norte-pro
spec:
ingressClassName: nginx
tls:
- hosts:
- www.rutasnorte.example
- api.rutasnorte.example
secretName: rutasnorte-tls # Secret del MATEIX namespace que l'Ingress
rules:
# ... les mateixes regles de 04-04, sense canvisTres regles que trenquen això si no es compleixen: el Secret ha de ser al mateix namespace que l'Ingress (no hi ha referències entre namespaces, així que publicar els tres entorns exigeix el certificat als tres, i cert-manager el pot emetre a cadascun); els hosts del bloc tls han de coincidir amb els del certificat, o el navegador donarà ERR_CERT_COMMON_NAME_INVALID; i es poden posar diverses entrades tls, cadascuna amb el seu Secret, triant el controlador per SNI, el nom que el client anuncia en iniciar la salutació TLS.
- Certificat autosignat per a desenvolupament
Per a rutas-norte-dev no demanem certificats a una autoritat pública: el domini no existeix i el clúster és local. En generem un de propi.
# Clau privada de 2048 bits i certificat autosignat a 365 dies
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout /tmp/rutasnorte-dev.key \
-out /tmp/rutasnorte-dev.crt \
-subj "/C=ES/ST=Cantabria/L=Santander/O=Rutas Norte S.L./CN=www.rutasnorte.example" \
-addext "subjectAltName=DNS:www.rutasnorte.example,DNS:api.rutasnorte.example"Desglossament: -x509 genera un certificat directament en lloc d'una sol·licitud (CSR); -nodes deixa la clau privada sense contrasenya, imprescindible perquè ningú no la teclejarà en arrencar; -newkey rsa:2048 crea clau i certificat en un pas; -subj dona les dades del titular sense preguntar; i -addext subjectAltName afegeix el camp que de debò importa.
Sobre subjectAltName (SAN): els navegadors fa anys que ignoren el CN i validen exclusivament les SAN, de manera que un certificat sense SAN es rebutja encara que el CN sigui perfecte —és l'error número u en generar certificats a mà—. Aquí en necessitem dues, una per domini, perquè el mateix certificat serveixi la botiga i l'API.
kubectl create secret tls rutasnorte-tls \
--cert=/tmp/rutasnorte-dev.crt --key=/tmp/rutasnorte-dev.key -n rutas-norte-dev
# Verificar que les SAN son les esperades
kubectl get secret rutasnorte-tls -n rutas-norte-dev \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -text \
| grep -A1 "Subject Alternative Name"
curl -k -s -o /dev/null -w '%{http_code}\n' https://www.rutasnorte.example/
curl -s https://www.rutasnorte.example/ 2>&1 | head -1X509v3 Subject Alternative Name:
DNS:www.rutasnorte.example, DNS:api.rutasnorte.example
200
curl: (60) SSL certificate problem: self-signed certificatekubectl create secret tls posa el tipus correcte i les dues claus amb els noms correctes.
Amb -k funciona; sense -k, falla. Això és correcte i és la lliçó: el certificat xifra igual de bé, però ningú no pot verificar qui el va emetre, i el navegador mostrarà "La connexió no és privada" amb NET::ERR_CERT_AUTHORITY_INVALID. Un client que veiés aquell avís no compraria. Per això els autosignats serveixen per a desenvolupament i proves internes, mai per a producció.
- cert-manager: quin problema resol i instal·lació
Amb certificats d'una autoritat pública, el procés manual és: generar clau i CSR, demostrar que controles el domini, rebre el certificat, crear el Secret, i repetir-ho cada 90 dies, que és el que duren els de Let's Encrypt. El resultat previsible és l'incident clàssic: un dissabte a la nit caduca el certificat, la botiga deixa de funcionar en ple pont, i ningú no recorda com es renovava perquè ho va fer una persona que ja no hi és.
cert-manager converteix això en un bucle de reconciliació com qualsevol altre: declares que vols un certificat i ell l'obté, el desa en un Secret i el renova abans que caduqui, indefinidament.
# Instal-lacio amb els CRD inclosos
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml
kubectl get pods -n cert-manager
kubectl get crds | grep cert-manager.iocert-manager-6d8b9c7f4d-jk29p 1/1 Running 0 60s
cert-manager-cainjector-5f9b7d8c6-w4xr2 1/1 Running 0 60s
cert-manager-webhook-7c4d9f8b5-mn6vt 1/1 Running 0 60s
certificaterequests.cert-manager.io certificates.cert-manager.io
challenges.acme.cert-manager.io clusterissuers.cert-manager.io
issuers.cert-manager.io orders.acme.cert-manager.ioTres components: cert-manager és el controlador que observa els Certificate i executa el flux d'emissió; cainjector injecta paquets de CA en webhooks i APIServices; i webhook valida i aplica valors per defecte als recursos propis.
Sis CRD (06-06): cert-manager estén l'API de Kubernetes amb tipus propis i un controlador que els reconcilia. És el patró operador de 06-07 en estat pur, i probablement l'exemple més útil que trobaràs.
- Els objectes de cert-manager i el flux d'emissió
| Objecte | Àmbit | Qui el crea | Què és |
|---|---|---|---|
Issuer |
Namespace | Tu | Font de certificats vàlida només en aquell namespace |
ClusterIssuer |
Clúster | Tu (administrador) | Font utilitzable des de qualsevol namespace |
Certificate |
Namespace | Tu, o l'Ingress amb l'anotació | "Vull un certificat per a aquests dominis, en aquest Secret" |
CertificateRequest / Order / Challenge |
Namespace | cert-manager | La petició amb el seu CSR, la comanda ACME i cada desafiament a superar |
Els tres últims són interns: no s'escriuen a mà, però són on es llegeix què està fallant, seguint la cadena Certificate → CertificateRequest → Order → Challenge.
sequenceDiagram
participant U as Tu (o l'Ingress)
participant CM as cert-manager
participant LE as Let's Encrypt (ACME)
participant K8S as API de Kubernetes
U->>K8S: crea Certificate (dominis + secretName)
CM->>K8S: observa el Certificate
CM->>CM: genera clau privada i CSR
CM->>K8S: crea CertificateRequest
CM->>K8S: crea Order
CM->>LE: sol-licita la comanda per als dominis
LE-->>CM: desafiaments pendents (HTTP-01 o DNS-01)
CM->>K8S: crea Challenge
CM->>K8S: publica la prova (Ingress temporal o registre TXT)
CM->>LE: "ja pots validar"
LE->>LE: comprova la prova des d'internet
LE-->>CM: validat; aqui tens el certificat
CM->>K8S: crea/actualitza el Secret kubernetes.io/tls
CM->>K8S: Certificate amb Ready=True
Note over CM: i programa la renovacio als 60 dies
- ACME amb Let's Encrypt:
HTTP-01 davant de DNS-01
HTTP-01 davant de DNS-01ACME (Automatic Certificate Management Environment) és el protocol que automatitza l'emissió. El seu nucli és una pregunta: demostres que controles el domini?
Desafiament HTTP-01
Let's Encrypt demana publicar un fitxer amb un contingut concret a http://<domini>/.well-known/acme-challenge/<token>; cert-manager crea un pod i un Ingress temporal per servir-lo, i l'esborra en acabar.
# k8s/base/clusterissuer-letsencrypt-http01.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-produccio
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected] # avisos de caducitat i problemes
privateKeySecretRef:
name: letsencrypt-produccio-compte # clau del COMPTE ACME, no del certificat
solvers:
- http01:
ingress:
ingressClassName: nginxRequisit imprescindible: el domini ha de resoldre al teu Ingress i ser accessible des d'internet al port 80. Conseqüències directes: no funciona a minikube amb dominis .example resolts per /etc/hosts (per això a dev fem servir autosignats); no funciona per a serveis interns sense exposició pública; no pot emetre certificats comodí; i si redirigeixes tot l'HTTP a HTTPS has d'excloure /.well-known/acme-challenge/ —els controladors moderns ho gestionen sols, però amb regles pròpies és una fallada habitual.
Desafiament DNS-01
Let's Encrypt demana un registre TXT a _acme-challenge.<domini>. cert-manager el crea fent servir l'API del proveïdor de DNS i l'esborra després.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-dns-compte
solvers:
- dns01:
cloudflare:
email: [email protected]
apiTokenSecretRef:
name: cloudflare-token # Secret amb el token de l'API del DNS
key: token
selector:
dnsZones:
- rutasnorte.example # aquest solver nomes per a aquesta zonaHTTP-01 |
DNS-01 |
|
|---|---|---|
| Què es publica | Un fitxer a /.well-known/acme-challenge/ |
Un registre TXT |
| Requereix port 80 públic | Sí | No |
| Funciona amb serveis interns | No | Sí |
| Certificats comodí | No | Sí, obligatori |
| Credencials necessàries | Cap | Token de l'API del DNS |
| Velocitat | Segons | Minuts (propagació del DNS) |
| Risc | Cap d'especial | Un token amb permís per editar la teva zona DNS |
Regla pràctica: HTTP-01 per defecte, i DNS-01 quan necessitis comodins o el servei no sigui públic. Rutas Norte faria servir HTTP-01 per als seus dos dominis; si demà volgués *.rutasnorte.example per donar un subdomini a cada agència, hauria de passar a DNS-01.
- Emissió automàtica des de l'Ingress
Es pot crear un Certificate explícit, útil quan es volen controlar la durada, l'algorisme de clau o la rotació:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: rutasnorte-tls
namespace: rutas-norte-pro
spec:
secretName: rutasnorte-tls # el Secret que es crearà
duration: 2160h # 90 dies
renewBefore: 720h # renovar 30 dies abans de caducar
privateKey:
algorithm: ECDSA
size: 256
rotationPolicy: Always # clau nova a cada renovació
dnsNames: [www.rutasnorte.example, api.rutasnorte.example]
issuerRef:
name: letsencrypt-produccio
kind: ClusterIssuerPerò el còmode és l'anotació a l'Ingress: cert-manager la detecta i genera el Certificate per tu a partir del bloc tls:.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rutas-norte
namespace: rutas-norte-pro
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-produccio"
# per a un Issuer de namespace seria: cert-manager.io/issuer
spec:
ingressClassName: nginx
tls:
- hosts:
- www.rutasnorte.example
- api.rutasnorte.example
secretName: rutasnorte-tls # cert-manager crearà aquest Secret
rules:
# ... les mateixes regles de 04-04Tota la gestió de certificats de Rutas Norte es redueix a una anotació: els dominis surten de tls.hosts i la destinació, de tls.secretName.
kubectl apply -f k8s/entorns/pro/ingress-rutas-norte.yaml
kubectl get certificate,order,challenge -n rutas-norte-procertificate.cert-manager.io/rutasnorte-tls False rutasnorte-tls 12s
order.acme.cert-manager.io/rutasnorte-tls-1-2894732 pending 11s
challenge.acme.cert-manager.io/rutasnorte-tls-1-...-0 pending www.rutasnorte.example 10s
# ... uns segons despres
certificate.cert-manager.io/rutasnorte-tls True rutasnorte-tls 47sREADY: True i els Order/Challenge desapareguts: el certificat és al Secret i el controlador d'Ingress ja l'està servint.
- L'entorn de staging i els límits d'emissió
Let's Encrypt imposa límits estrictes: 50 certificats per domini registrat i setmana, 5 fallades de validació per compte, domini i hora, 5 duplicats exactes per setmana (mateix conjunt de dominis) i 100 noms per certificat.
El de duplicats és el que mossega: cinc intents amb el mateix conjunt de dominis i quedes bloquejat una setmana; depurant una configuració nova es consumeixen en deu minuts i no hi ha manera d'accelerar-ho. Per això existeix l'entorn de staging, amb els mateixos límits multiplicats per molt i certificats emesos per una CA de proves que els navegadors no reconeixen.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory # l'unica diferencia
email: [email protected]
privateKeySecretRef:
name: letsencrypt-staging-compte
solvers:
- http01:
ingress:
ingressClassName: nginxEl procediment correcte, sense excepcions: (1) configurar l'Ingress amb cert-manager.io/cluster-issuer: letsencrypt-staging; (2) comprovar kubectl get certificate fins a READY: True; (3) verificar amb curl -k que el TLS funciona i que l'emissor és (STAGING) Let's Encrypt; i (4) només llavors passar a producció:
kubectl annotate ingress rutas-norte -n rutas-norte-pro \
cert-manager.io/cluster-issuer=letsencrypt-produccio --overwrite
kubectl delete secret rutasnorte-tls -n rutas-norte-pro
kubectl get certificate -n rutas-norte-pro -wAquell kubectl delete secret és necessari: sense ell, cert-manager veu un certificat vàlid i no el reemplaça fins que toqui renovar.
- Renovació automàtica i comprovació de l'estat
cert-manager renova quan queda menys de renewBefore per caducar (per defecte un terç de la vida; amb 90 dies, als 60). El procés és idèntic al d'emissió i el Secret s'actualitza al seu lloc, sense canviar de nom. Cal reiniciar els pods? No. El controlador d'Ingress observa el Secret i recarrega sol. Si un pod muntés el certificat com a volum, el kubelet propaga el canvi en aproximadament un minut, encara que l'aplicació l'hauria de rellegir.
Comprovacions
Status:
Conditions:
Type: Ready
Status: True
Message: Certificate is up to date and has not expired
Not Before: 2026-07-30T09:14:23Z
Not After: 2026-10-28T09:14:22Z
Renewal Time: 2026-09-28T09:14:22Z
Events:
Normal Issued 21d cert-manager-certificates-issuing The certificate has been successfully issuedNot After i Renewal Time són els dos camps que cal vigilar. I el certificat servit de debò:
echo | openssl s_client -connect www.rutasnorte.example:443 \
-servername www.rutasnorte.example 2>/dev/null \
| openssl x509 -noout -issuer -subject -datesissuer=C=US, O=Let's Encrypt, CN=R11
subject=CN=www.rutasnorte.example
notBefore=Jul 30 09:14:23 2026 GMT
notAfter=Oct 28 09:14:22 2026 GMTEl -servername és imprescindible: sense SNI, el controlador retornaria el seu certificat per defecte i en veuries un d'equivocat.
Diagnòstic quan READY és False
Segueix la cadena cap avall fins al Challenge, amb kubectl describe sobre certificate, certificaterequest, order i challenge, i finalment kubectl logs -n cert-manager -l app=cert-manager.
Missatge al Challenge |
Causa |
|---|---|
Waiting for HTTP-01 challenge propagation: wrong status code '404' |
L'Ingress temporal no és accessible, o el DNS públic no apunta al teu clúster |
connection refused / timeout |
El port 80 no està obert des d'internet |
NXDOMAIN |
El domini no existeix al DNS públic |
too many certificates already issued |
Límit setmanal assolit. Espera o fes servir staging |
Issuer not found |
Confusió entre Issuer i ClusterIssuer, o nom mal escrit |
Aquell últim mereix atenció: cert-manager.io/issuer busca un Issuer al namespace de l'Ingress; cert-manager.io/cluster-issuer busca un ClusterIssuer global. Fer servir l'anotació equivocada dona un error que sembla de nom i és de tipus.
- Redirecció a HTTPS i HSTS
Publicar HTTPS no n'hi ha prou: cal impedir l'HTTP, perquè un client que escrigui el domini sense esquema anirà per HTTP. A ingress-nginx la redirecció està activada per defecte tan bon punt l'Ingress té bloc tls, i es controla amb les anotacions ssl-redirect (HTTP → HTTPS) i force-ssl-redirect (fins i tot darrere d'un altre proxy):
Però la redirecció deixa una finestra: la primera petició viatja en clar i pot ser interceptada. HSTS (HTTP Strict Transport Security) la tanca: una capçalera que ordena al navegador fer servir HTTPS per a aquell domini durant un temps, sense preguntar i sense permetre saltar-se l'avís.
metadata:
annotations:
nginx.ingress.kubernetes.io/hsts: "true"
nginx.ingress.kubernetes.io/hsts-max-age: "31536000" # 1 any
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
nginx.ingress.kubernetes.io/hsts-preload: "false"Advertiments seriosos sobre HSTS, perquè és de les poques coses d'aquesta lliçó que et poden deixar fora del teu propi domini:
- No es pot revocar ràpidament. Els navegadors recorden la directiva fins que expiri
max-age. Si el teu certificat falla, els usuaris no poden entrar, ni acceptant el risc. includeSubDomainsafecta TOTS els subdominis, inclosos els que encara no tenen HTTPS: unadmin.rutasnorte.exampleintern per HTTP deixaria de ser accessible.preloadés pràcticament irreversible: entrar a la llista precarregada dels navegadors és fàcil, sortir-ne triga mesos. Comença ambmax-agebaix (300) i puja'l progressivament.
I aquí toca recordar l'advertiment inicial: la política d'HSTS, les versions de TLS acceptades (ssl-protocols: "TLSv1.2 TLSv1.3") i els conjunts de xifratge (ssl-ciphers), que són ajustos globals del ConfigMap del controlador i no anotacions per Ingress, han de ser revisats per un professional de seguretat abans d'aplicar-se en producció.
- Més enllà: mTLS i malles de servei
El que hem muntat protegeix el tram client ↔ Ingress; dins del clúster, el trànsit entre el controlador i botiga-web, o entre api-reserves i postgres-reserves, continua en clar. Dos mecanismes van més lluny. mTLS (TLS mutu): a més del servidor, el client presenta certificat, de manera que api-reserves no només verifica amb qui parla sinó que demostra qui és; és la base de la identitat criptogràfica entre serveis i substitueix la confiança basada en adreces IP. I les malles de servei (Istio, Linkerd, Cilium Service Mesh), que injecten un proxy al costat de cada pod —o l'integren al kernel amb eBPF— i estableixen mTLS automàticament entre tots els components, amb certificats de curta vida i sense tocar el codi.
Per a Rutas Norte avui és exagerat: cinc components en un clúster propi, amb les polítiques de xarxa de 04-06 limitant qui pot parlar amb qui. Es replantejaria si la plataforma creixés a desenes de serveis o si un requisit normatiu exigís xifratge extrem a extrem. L'anàlisi completa és a 08-04.
Errors Comuns i Consells
- Començar directament a producció de Let's Encrypt. Cinc fallades i una setmana bloquejat. Sempre staging primer.
- Certificat sense
subjectAltName. Els navegadors ignoren elCN. Sense SAN, el certificat és inútil. - Secret TLS en un altre namespace. No hi ha referències creuades: el Secret viu on viu l'Ingress.
- Confondre
IssuerambClusterIssuera l'anotació. L'error diu "no trobat" i és de tipus. - Canviar l'issuer sense esborrar el Secret. cert-manager veu un certificat vàlid i no reemplaça res.
- Redirigir a HTTPS bloquejant
/.well-known/acme-challenge/. El desafiamentHTTP-01deixa de funcionar i la renovació falla en silenci fins que caduca. - Activar HSTS amb
preloaddes del primer dia. Pràcticament irreversible. Pujamax-ageper etapes. - Intentar
HTTP-01a minikube amb dominis d'/etc/hosts, o demanar un comodí ambHTTP-01: el primer no és accessible des de Let's Encrypt i el segon és impossible per disseny (exigeixDNS-01). - Consell: vigila
certmanager_certificate_expiration_timestamp_secondsa Prometheus (07-03) i alerta amb 21 dies de marge. L'automatització també falla. - Consell: un
Certificateper domini en lloc d'un amb molts SAN limita el dany: una fallada de validació en un domini no impedeix renovar els altres. - Consell: desa el
ClusterIssuera Git, però mai el Secret amb la clau privada del compte ACME ni el token del DNS. Aplica allò de 03-02: Sealed Secrets, ESO o Vault.
Exercicis
Exercici 1: HTTPS en desenvolupament amb certificat autosignat
Genera amb openssl un certificat vàlid per a www.rutasnorte.example i api.rutasnorte.example, crea'l com a Secret TLS a rutas-norte-dev, afegeix-lo a l'Ingress i comprova que HTTPS funciona amb -k i falla sense. Explica exactament quina garantia falta.
Exercici 2: Instal·lar cert-manager i crear els dos ClusterIssuers
Instal·la cert-manager, crea letsencrypt-staging i letsencrypt-produccio amb desafiament HTTP-01, i anota l'Ingress de producció amb el de staging. Segueix la cadena Certificate → Order → Challenge i explica per què a minikube el desafiament no es completarà.
Exercici 3: Diagnosticar un certificat que no s'emet
Un Certificate porta 20 minuts en READY: False. Dissenya el procediment de diagnòstic complet, indicant quina ordre fer servir a cada nivell i quin missatge esperaries per a tres causes diferents: domini que no resol des d'internet, port 80 tancat i límit d'emissió assolit.
Solucions
Exercici 1
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout /tmp/dev.key -out /tmp/dev.crt \
-subj "/C=ES/O=Rutas Norte S.L./CN=www.rutasnorte.example" \
-addext "subjectAltName=DNS:www.rutasnorte.example,DNS:api.rutasnorte.example"
kubectl create secret tls rutasnorte-tls \
--cert=/tmp/dev.crt --key=/tmp/dev.key -n rutas-norte-dev
kubectl patch ingress rutas-norte -n rutas-norte-dev --type=merge -p '
spec:
tls:
- hosts: ["www.rutasnorte.example","api.rutasnorte.example"]
secretName: rutasnorte-tls'
curl -k -s -o /dev/null -w 'amb -k: %{http_code}\n' https://www.rutasnorte.example/
curl -s -o /dev/null https://www.rutasnorte.example/ || echo "sense -k: fallada (esperat)"El que falta és l'autenticació, no el xifratge. El canal està igual de xifrat, però ningú de confiança no avala que aquell certificat pertanyi a Rutas Norte: un atacant que segrestés el DNS podria presentar el seu propi autosignat i el client no notaria la diferència. La cadena de confiança és el que aporta una CA pública.
Exercici 2
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml
kubectl wait --for=condition=Available deploy --all -n cert-manager --timeout=180s
kubectl apply -f k8s/base/clusterissuer-letsencrypt-staging.yaml
kubectl apply -f k8s/base/clusterissuer-letsencrypt-produccio.yaml
kubectl get clusterissuer # tots dos han d'apareixer amb READY True
kubectl annotate ingress rutas-norte -n rutas-norte-pro \
cert-manager.io/cluster-issuer=letsencrypt-staging --overwrite
kubectl describe challenge -n rutas-norte-pro | tail -12Reason: Waiting for HTTP-01 challenge propagation: failed to perform self check
GET request: Get "http://www.rutasnorte.example/.well-known/acme-challenge/xY3...":
dial tcp: lookup www.rutasnorte.example: no such hostA minikube el domini només existeix al teu /etc/hosts. Els servidors de Let's Encrypt no el resolen ni poden arribar al teu clúster, així que HTTP-01 no es pot completar per disseny. És exactament el motiu pel qual en desenvolupament es fan servir certificats autosignats.
Exercici 3
NS=rutas-norte-pro
kubectl describe certificate rutasnorte-tls -n $NS | sed -n '/Status/,$p' # nivell 1
kubectl describe certificaterequest -n $NS | grep -A3 "Conditions" # nivell 2
kubectl describe order -n $NS | grep -A5 "Status" # nivell 3
kubectl describe challenge -n $NS | grep -A5 "Reason" # nivell 4: el missatge util
kubectl logs -n cert-manager -l app=cert-manager --tail=80 | grep -i error # nivell 5| Causa | Missatge esperat | On apareix |
|---|---|---|
| Domini que no resol | dial tcp: lookup www.rutasnorte.example: no such host |
Challenge |
| Port 80 tancat | connection refused o context deadline exceeded després del self check |
Challenge |
| Límit assolit | 429 urn:ietf:params:acme:error:rateLimited: too many certificates already issued |
Order i logs de cert-manager |
Per als dos primers s'arregla la infraestructura (DNS públic, tallafocs). Per al tercer no hi ha arreglament tècnic: s'espera que passi la setmana o es treballa en staging.
Conclusió
Rutas Norte ja xifra el seu trànsit. Saps per què HTTPS no és opcional en una plataforma que gestiona DNI, telèfons i pagaments, i que TLS aporta dues coses diferents: xifratge i identitat. Coneixes els tres models de terminació —a l'Ingress, rexifratge i passthrough— i per què la terminació a l'Ingress és l'elecció correcta aquí. Domines la peça bàsica, el Secret de tipus kubernetes.io/tls amb les seves claus tls.crt i tls.key, i les tres regles que el governen: mateix namespace que l'Ingress, coincidència entre els hosts del bloc tls i les SAN del certificat, i selecció per SNI quan n'hi ha diversos.
Has generat un certificat autosignat amb openssl per a desenvolupament, amb el detall decisiu del subjectAltName que els navegadors validen ignorant el CN, i has comprovat al teu propi terminal la diferència entre "xifrat" i "verificable": funciona amb -k, falla sense, i aquella diferència és la raó que els autosignats no arribin mai a producció.
Després has automatitzat el problema amb cert-manager, que és el patró operador aplicat a certificats: sis CRD, un controlador i un bucle de reconciliació. Saps què és un Issuer i en què es diferencia d'un ClusterIssuer, i com cert-manager encadena per sota Certificate → CertificateRequest → Order → Challenge, que és també l'ordre en què es diagnostica qualsevol fallada. Entens ACME i els seus dos desafiaments: HTTP-01, senzill però amb el requisit de ser accessible des d'internet al port 80 i sense poder emetre comodins, i DNS-01, imprescindible per a comodins i per a serveis interns a canvi de confiar un token de l'API del DNS. I has reduït tota la gestió a una anotació a l'Ingress, amb la disciplina irrenunciable de començar sempre en staging per no consumir els cinc intents setmanals de Let's Encrypt.
Saps comprovar l'estat amb kubectl get certificate i openssl s_client -servername, que la renovació passa 30 dies abans de caducar sense reiniciar res, i com tancar la porta a l'HTTP amb la redirecció i amb HSTS, mesurant-ne bé els riscos perquè no es revoca a voluntat. I saps què queda fora: el trànsit dins del clúster continua en clar, i això són mTLS i malles de servei, matèria de 08-04.
Ens queda un forat dels grans, el mateix que arrosseguem des del mòdul 3: qualsevol pod del clúster es pot connectar a postgres-reserves:5432. Un pod compromès, una imatge amb una dependència maliciosa o un simple error de desplegament a rutas-norte-dev tenen accés directe a la base de dades amb les dades personals de tots els clients. A 04-06, l'última lliçó del mòdul, construirem el model d'aïllament de la plataforma: denegar-ho tot per defecte, obrir el DNS —la fallada clàssica que tomba el clúster sencer—, i autoritzar una a una únicament les converses que Rutas Norte necessita.
Curs de Kubernetes
Mòdul 1: Introducció a Kubernetes
- Què és Kubernetes?
- Arquitectura de Kubernetes
- Conceptes i Terminologia Clau
- Configuració d'un Clúster de Kubernetes
- La CLI de Kubernetes: kubectl
- Objectes, Manifests YAML i el Model Declaratiu
- El Projecte del Curs: la Plataforma Rutas Norte
Mòdul 2: Components Principals de Kubernetes
- Pods
- ReplicaSets
- Deployments
- Actualitzacions, Rollbacks i Estratègies de Desplegament
- Serveis
- Namespaces
- Etiquetes, Selectors i Anotacions
Mòdul 3: Gestió de Configuració i Secrets
- ConfigMaps
- Secrets
- Variables d'Entorn
- Quotes i Límits de Recursos
- LimitRanges i Classes de Qualitat de Servei (QoS)
- ServiceAccounts i Accés a l'API des dels Pods
Mòdul 4: Xarxes a Kubernetes
- Xarxes de Clúster
- Tipus de Serveis
- DNS Intern i Descobriment de Serveis
- Controladors d'Ingress
- TLS i Gestió de Certificats amb cert-manager
- Polítiques de Xarxa
Mòdul 5: Emmagatzematge a Kubernetes
- Volums
- Volums Persistents
- Reclamacions de Volums Persistents
- Classes d'Emmagatzematge
- Aprovisionament Dinàmic, Expansió i Snapshots
- Còpies de Seguretat i Restauració de Dades
Mòdul 6: Conceptes Avançats de Kubernetes
- StatefulSets
- DaemonSets
- Treballs i CronJobs
- Init Containers, Sidecars i Patrons Multicontenidor
- Planificació: Afinitat, Taints i Toleracions
- Definicions de Recursos Personalitzats (CRDs)
- Operadors i el Patró Controlador
Mòdul 7: Monitoratge i Registre
- Verificacions de Salut i Sondes
- Servidor de Mètriques i kubectl top
- Monitoratge amb Prometheus
- Visualització i Alertes amb Grafana i Alertmanager
- Registre Centralitzat amb Elasticsearch, Fluentd i Kibana (EFK)
- Depuració d'Aplicacions i Esdeveniments del Clúster
Mòdul 8: Seguretat a Kubernetes
- Control d'Accés Basat en Rols (RBAC)
- Contextos de Seguretat i Enduriment del Contenidor
- Polítiques de Seguretat de Pods i Pod Security Standards
- Seguretat de Xarxa
- Seguretat d'Imatges
- Auditoria, Escaneig i Gestió de Vulnerabilitats
Mòdul 9: Escalat i Rendiment
- Autoescalat Horitzontal de Pods
- Autoescalat Vertical de Pods
- Autoescalat de Clúster
- Escalat per Esdeveniments i Mètriques Personalitzades amb KEDA
- Alta Disponibilitat: PodDisruptionBudgets i Topologia
- Ajust de Rendiment
Mòdul 10: Ecosistema i Eines de Kubernetes
- Minikube i Entorns Locals amb kind
- Kubeadm
- Helm
- Kustomize
- GitOps amb Argo CD i Flux
- Kubernetes Gestionat: EKS, AKS i GKE
Mòdul 11: Estudis de Cas i Aplicacions del Món Real
- Desplegament d'una Aplicació Web
- Execució d'Aplicacions amb Estat
- CI/CD amb Kubernetes
- Estratègies de Desplegament: Blue-Green i Canary
- Gestió Multi-Clúster
- Operació en Producció: Incidències, Runbooks i Costos
