Tancàvem la lliçó anterior assenyalant un fil solt que ha recorregut tot el mòdul. El selector d'un ReplicaSet que adopta pods, el selector d'un Service que troba els seus destins, l'etiqueta entorn amb què les polítiques de xarxa seleccionaran namespaces, l'anotació kubernetes.io/change-cause que documenta cada revisió, el pod-template-hash que el Deployment afegeix pel seu compte, i totes les consultes amb -l que fem servir des de la primera lliçó: tot això són etiquetes i anotacions. Les hem anat fent servir per necessitat, sense sistematitzar. Aquesta lliçó hi posa ordre, i no és un afer menor: en un clúster amb sis components per tres entorns, l'esquema d'etiquetatge és el que separa una plataforma navegable d'un caos d'objectes anònims. Veuràs la diferència exacta entre etiqueta i anotació, la sintaxi i les restriccions de claus i valors, les etiquetes recomanades per Kubernetes i com es concreten a l'esquema oficial de Rutas Norte, els selectors d'igualtat i de conjunt en totes les seves formes, qui els consumeix, per què el selector d'un Deployment és immutable, l'ús real de les anotacions i les consultes del dia a dia que et faran productiu.
Contingut
- Etiquetes enfront d'anotacions
- Sintaxi i restriccions de claus i valors
- Les etiquetes recomanades per Kubernetes
- L'esquema d'etiquetatge de Rutas Norte
- Selectors d'igualtat
- Selectors de conjunt
- Selectors en manifests:
matchLabelsimatchExpressions - Qui consumeix selectors
- La regla d'or: el selector d'un Deployment és immutable
- Anotacions a la pràctica
kubectl labelikubectl annotate- Consultes útils del dia a dia
- Etiquetes enfront d'anotacions
Totes dues viuen a metadata i totes dues són parells clau-valor. Aquí s'acaba la semblança.
metadata:
name: api-reserves
labels: # per IDENTIFICAR i SELECCIONAR
app.kubernetes.io/name: api-reserves
entorn: pro
annotations: # per ADJUNTAR INFORMACIÓ
kubernetes.io/change-cause: "v2.5.0 - cache de disponibilitat (RN-482)"
rutasnorte.example/responsable: [email protected]| Aspecte | Etiquetes (labels) |
Anotacions (annotations) |
|---|---|---|
| Propòsit | Identificar i seleccionar objectes | Adjuntar metadades no identificatives |
| Es poden consultar? | Sí: kubectl get -l, selectors |
No: no existeix --annotation-selector |
| Estan indexades? | Sí, etcd les indexa | No |
| Mida del valor | Màxim 63 caràcters | Fins a 256 KiB en total |
| Caràcters del valor | Alfanumèrics, -, _, . |
Qualsevol: JSON, text llarg, URLs, salts de línia |
| Qui les fa servir | Controladors, Services, el planificador, tu | Eines, kubectl, controladors d'Ingress, humans |
| Cost de tenir-ne moltes | Impacte en el rendiment de les consultes | Pràcticament nul |
| Exemple | app: api-reserves |
kubernetes.io/change-cause: "..." |
La regla de decisió, que resol el 100 % dels dubtes:
Voldràs buscar objectes per aquesta dada, o servirà a un selector? És una etiqueta. És informació que es llegeix però no es busca? És una anotació.
Exemples aplicats a Rutas Norte:
| Dada | Tipus | Per què |
|---|---|---|
Component (api-reserves) |
Etiqueta | Els Services i els ReplicaSets hi seleccionen |
Entorn (pro) |
Etiqueta | Es consulta constantment i les NetworkPolicies la faran servir |
Versió (2.5.0) |
Etiqueta | Útil per consultar quina versió corre on |
| Correu de l'equip responsable | Anotació | Es llegeix en un incident, no s'hi busca |
| Motiu de l'últim desplegament | Anotació | Text lliure i llarg |
| URL del quadre de comandament | Anotació | Conté : i /, prohibits en valors d'etiqueta |
| Hash del commit desplegat | Anotació (o etiqueta curta) | Sol ser informatiu |
| Contrasenya de la base de dades | Cap de les dues | Mai. Va en un Secret (03-02) |
- Sintaxi i restriccions de claus i valors
Kubernetes és estricte amb el format, i conèixer les regles evita rebutjos incomprensibles.
Estructura d'una clau
Una clau té un nom i, opcionalment, un prefix separat per /:
Regles del nom (la part obligatòria):
- Màxim 63 caràcters.
- Ha de començar i acabar per caràcter alfanumèric.
- Pot contenir
-,_,.i alfanumèrics enmig.
Regles del prefix (opcional):
- Ha de ser un subdomini DNS vàlid:
rutasnorte.example,app.kubernetes.io. - Màxim 253 caràcters.
- Se separa del nom amb
/. - Reservats: els prefixos
kubernetes.io/ik8s.io/estan reservats per al mateix Kubernetes i els seus components principals. No els facis servir per a les teves etiquetes.
Regles del valor d'una etiqueta
- Màxim 63 caràcters (o buit, que és vàlid).
- Si no és buit, ha de començar i acabar per alfanumèric.
- Només alfanumèrics,
-,_i.enmig. - Prohibits: espais,
/,:,@, accents,ç, emojis.
Exemples vàlids i invàlids:
| Etiqueta | Vàlida? | Motiu |
|---|---|---|
app: api-reserves |
Sí | Format canònic |
app.kubernetes.io/version: 2.5.0 |
Sí | Prefix estàndard, valor amb punts |
rutasnorte.example/linia: BIL-SAN |
Sí | Prefix propi de l'empresa |
entorn: pro |
Sí | Sense prefix, perfectament vàlid |
equip: backend_reserves |
Sí | El guió baix està permès |
responsable: [email protected] |
No | L'@ està prohibida en valors |
panell: https://grafana.example/d/abc |
No | : i / prohibits. Fes servir una anotació |
descripcio: API de reserves |
No | Els espais estan prohibits |
regió: nord |
No | Els accents estan prohibits |
kubernetes.io/la-meva-etiqueta: x |
No (desaconsellat) | Prefix reservat |
Comprova el rebuig tu mateix:
kubectl label pod --all [email protected] -n rutas-norte-deverror: '[email protected]' is not a valid label value:
a valid label must be an empty string or consist of alphanumeric characters,
'-', '_' or '.', and must start and end with an alphanumeric characterLa versió correcta fa servir una anotació:
kubectl annotate deployment api-reserves \
rutasnorte.example/[email protected] -n rutas-norte-devRegles de les anotacions
Les claus segueixen les mateixes regles que les de les etiquetes. Els valors, en canvi, són gairebé lliures: qualsevol cadena, inclosos JSON, salts de línia i caràcters especials, amb un límit conjunt de 256 KiB per a totes les anotacions d'un objecte.
Aquell límit generós és el que permet que kubectl apply desi el manifest complet a kubectl.kubernetes.io/last-applied-configuration, com vam veure a Objectes i Manifests.
- Les etiquetes recomanades per Kubernetes
Kubernetes defineix un conjunt d'etiquetes comunes sota el prefix app.kubernetes.io/. No són obligatòries ni les imposa res, però són el vocabulari compartit que entenen Helm, Kustomize, Argo CD, Prometheus i pràcticament qualsevol eina de l'ecosistema.
| Etiqueta | Significat | Exemple a Rutas Norte |
|---|---|---|
app.kubernetes.io/name |
Nom de l'aplicació | api-reserves |
app.kubernetes.io/instance |
Identifica una instal·lació concreta d'aquella aplicació | api-reserves-pro |
app.kubernetes.io/version |
Versió actual | 2.5.0 |
app.kubernetes.io/component |
Paper que juga dins de l'arquitectura | api, frontend, cache, base-dades, worker |
app.kubernetes.io/part-of |
Aplicació de nivell superior a la qual pertany | rutas-norte |
app.kubernetes.io/managed-by |
Eina que gestiona l'objecte | kubectl, helm, argocd |
La diferència entre name i instance és la que més costa:
nameés què és:postgres. La mateixa en totes les instal·lacions.instanceés quin és:postgres-reserves-pro. Distingeix dues instal·lacions del mateix.
Si Rutas Norte tingués dues bases de dades PostgreSQL —una de reserves i una altra de facturació—, totes dues portarien name: postgres però instance: postgres-reserves i instance: postgres-facturacio.
Un exemple complet amb les sis:
metadata:
name: api-reserves
labels:
app.kubernetes.io/name: api-reserves
app.kubernetes.io/instance: api-reserves-pro
app.kubernetes.io/version: "2.5.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: rutas-norte
app.kubernetes.io/managed-by: kubectlNota pràctica: version: "2.5.0" va entre cometes. Sense elles, YAML podria interpretar valors com 1.0 com a número i provocar un error de tipus, ja que els valors d'etiqueta han de ser cadenes.
Un advertiment important que enllaça amb l'apartat 9: app.kubernetes.io/version no ha d'anar al selector. Si hi fos, en canviar de versió el selector deixaria d'encaixar amb els seus propis pods, i com que el selector és immutable, hauries de recrear el Deployment a cada desplegament. La versió és informativa; la identitat la donen name i instance.
- L'esquema d'etiquetatge de Rutas Norte
Ha arribat el moment de fixar l'esquema definitiu del projecte. Fins ara hem fet servir tres etiquetes mínimes (app, app.kubernetes.io/part-of i entorn); les consolidem i les ampliem.
Les etiquetes del projecte
| Etiqueta | Obligatòria | Valors possibles | Per a què |
|---|---|---|---|
app |
Sí | botiga-web, api-reserves, postgres-reserves, redis-cache, worker-notificacions, informes-ocupacio |
Identificador curt del component. Va als selectors |
entorn |
Sí | dev, pre, pro |
Entorn. Va als selectors i a les NetworkPolicies |
app.kubernetes.io/name |
Sí | Igual que app |
Compatibilitat amb l'ecosistema |
app.kubernetes.io/part-of |
Sí | rutas-norte |
Agrupa tota la plataforma. Mai en un selector |
app.kubernetes.io/component |
Sí | frontend, api, base-dades, cache, worker, informes |
Paper arquitectònic |
app.kubernetes.io/version |
Sí | 1.8.0, 2.5.0... |
Versió desplegada. Mai en un selector |
app.kubernetes.io/managed-by |
Recomanada | kubectl, argocd |
Qui gestiona l'objecte |
rutasnorte.example/criticitat |
Recomanada | critica, alta, mitjana, baixa |
Prioritza la resposta davant d'incidents |
La regla d'or de l'esquema, que es deriva de tot el que hem après al mòdul:
Només
appientornentren als selectors. Són les dues úniques etiquetes que identifiquen el component de forma inequívoca i que no canvien mai.
Tota la resta —versió, component, criticitat, gestor— és informativa i pot canviar sense recrear res.
La taula mestra: sis components
| Component | app |
component |
version |
criticitat |
Porta Service? |
|---|---|---|---|---|---|
botiga-web |
botiga-web |
frontend |
1.8.0 |
alta |
Sí |
api-reserves |
api-reserves |
api |
2.4.0 |
critica |
Sí |
postgres-reserves |
postgres-reserves |
base-dades |
16.2 |
critica |
Sí (headless al mòdul 6) |
redis-cache |
redis-cache |
cache |
7.2 |
mitjana |
Sí |
worker-notificacions |
worker-notificacions |
worker |
1.2.0 |
alta |
No |
informes-ocupacio |
informes-ocupacio |
informes |
1.0.3 |
baixa |
No |
El manifest resultant
Així queda api-reserves amb l'esquema complet aplicat:
# k8s/base/api-reserves-deployment.yaml (metadades completes)
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-reserves
namespace: rutas-norte-dev
labels:
app: api-reserves
entorn: dev
app.kubernetes.io/name: api-reserves
app.kubernetes.io/instance: api-reserves-dev
app.kubernetes.io/version: "2.4.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: rutas-norte
app.kubernetes.io/managed-by: kubectl
rutasnorte.example/criticitat: critica
annotations:
kubernetes.io/change-cause: "v2.4.0 - desplegament inicial"
rutasnorte.example/responsable: [email protected]
rutasnorte.example/panell: "https://grafana.rutasnorte.example/d/api-reserves"
rutasnorte.example/runbook: "https://wiki.rutasnorte.example/runbooks/api-reserves"
spec:
replicas: 2
selector:
matchLabels:
app: api-reserves # NOMES aquestes dues.
entorn: dev # Immutables.
template:
metadata:
labels:
app: api-reserves
entorn: dev
app.kubernetes.io/name: api-reserves
app.kubernetes.io/instance: api-reserves-dev
app.kubernetes.io/version: "2.4.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: rutas-norte
app.kubernetes.io/managed-by: kubectl
rutasnorte.example/criticitat: critica
spec:
containers:
- name: api
image: node:20-alpine
# ...Fixa't en l'asimetria, que és exactament la que vam aprendre amb els ReplicaSets: el template porta nou etiquetes i el selector només n'exigeix dues. Està permès i és el correcte: el selector ha de ser un subconjunt mínim i estable; la resta d'etiquetes viatgen amb els pods per poder-los consultar.
Aplica'l i observa la potència immediata:
kubectl apply -f k8s/base/api-reserves-deployment.yaml
kubectl get pods -l app.kubernetes.io/component=api --show-labelsNAME READY STATUS LABELS
api-reserves-9c4d7e831-j2wsk 1/1 Running app=api-reserves,app.kubernetes.io/component=api,app.kubernetes.io/instance=api-reserves-dev,app.kubernetes.io/managed-by=kubectl,app.kubernetes.io/name=api-reserves,app.kubernetes.io/part-of=rutas-norte,app.kubernetes.io/version=2.4.0,entorn=dev,pod-template-hash=9c4d7e831,rutasnorte.example/criticitat=critica
- Selectors d'igualtat
Un selector és una consulta sobre etiquetes. El tipus més simple compara valors.
| Operador | Significat | Exemple |
|---|---|---|
= |
Igual | app=api-reserves |
== |
Igual (sinònim exacte de =) |
app==api-reserves |
!= |
Diferent | entorn!=pro |
Es fan servir amb -l (o --selector), i diverses condicions separades per comes es combinen amb I lògic:
# Els pods d'api-reserves
kubectl get pods -l app=api-reserves
# Els pods d'api-reserves A desenvolupament (I logic)
kubectl get pods -l app=api-reserves,entorn=dev
# Tots els pods de la plataforma que NO son a produccio
kubectl get pods -A -l app.kubernetes.io/part-of=rutas-norte,entorn!=proNAMESPACE NAME READY STATUS AGE
rutas-norte-dev api-reserves-9c4d7e831-j2wsk 1/1 Running 5m
rutas-norte-dev botiga-web-6f9c4b8d7-42kxr 1/1 Running 1h
rutas-norte-dev redis-cache-6c8f9d745-w2mtb 1/1 Running 1h
rutas-norte-pre api-reserves-7f1d3e942-c9plk 1/1 Running 45m
rutas-norte-pre botiga-web-6f9c4b8d7-d3jbx 1/1 Running 45mUn detall sobre != que convé conèixer: també selecciona els objectes que no tenen aquella etiqueta en absolut. entorn!=pro retorna tant els de dev i pre com els que no tenen l'etiqueta entorn.
No existeix l'O lògic als selectors d'igualtat. Per a això hi ha els de conjunt.
- Selectors de conjunt
Més expressius. Operen sobre conjunts de valors i sobre l'existència de la clau.
| Operador | Significat | Exemple |
|---|---|---|
in |
El valor és a la llista | entorn in (pre,pro) |
notin |
El valor no és a la llista | entorn notin (dev) |
<clau> |
L'etiqueta existeix, amb qualsevol valor | rutasnorte.example/criticitat |
!<clau> |
L'etiqueta no existeix | !rutasnorte.example/criticitat |
Exemples aplicats:
# Els components dels entorns "seriosos" (O logic)
kubectl get pods -A -l 'entorn in (pre,pro)'
# Tot el que NO es de desenvolupament
kubectl get deploy -A -l 'entorn notin (dev)'
# Objectes als quals s'ha oblidat la criticitat: auditoria de l'esquema
kubectl get deploy -A -l 'app.kubernetes.io/part-of=rutas-norte,!rutasnorte.example/criticitat'
# Components critics o d'alta criticitat, en qualsevol entorn
kubectl get pods -A -l 'rutasnorte.example/criticitat in (critica,alta)'NAMESPACE NAME READY STATUS AGE
rutas-norte-dev api-reserves-9c4d7e831-j2wsk 1/1 Running 12m
rutas-norte-dev api-reserves-9c4d7e831-p7xtr 1/1 Running 12m
rutas-norte-dev botiga-web-6f9c4b8d7-42kxr 1/1 Running 1h
rutas-norte-dev worker-notificacions-8c7b5d94f-k2xrt 1/1 Running 1hNota sobre les cometes: els selectors de conjunt porten parèntesis i espais, que la shell interpretaria. Tanca'ls sempre entre cometes simples.
I es poden combinar amb els d'igualtat, separant per comes:
kubectl get pods -A -l 'app.kubernetes.io/part-of=rutas-norte,entorn in (pre,pro),app.kubernetes.io/component!=cache'
- Selectors en manifests:
matchLabels i matchExpressions
matchLabels i matchExpressionsDins d'un YAML, els selectors tenen dues formes equivalents a les dues famílies que acabes de veure.
matchLabels: igualtat
És un mapa: totes les claus han de coincidir (I lògic). És el que hem fet servir a tot el mòdul.
matchExpressions: conjunts
selector:
matchExpressions:
- key: app
operator: In
values: [api-reserves]
- key: entorn
operator: In
values: [pre, pro]
- key: rutasnorte.example/obsolet
operator: DoesNotExistoperator |
Equival a | Requereix values? |
|---|---|---|
In |
in (…) |
Sí |
NotIn |
notin (…) |
Sí |
Exists |
<clau> |
No |
DoesNotExist |
!<clau> |
No |
Combinar-los
Es poden fer servir tots dos alhora; totes les condicions es combinen amb I lògic:
selector:
matchLabels:
app: api-reserves
matchExpressions:
- key: entorn
operator: In
values: [pre, pro]Traducció: "pods amb app=api-reserves i amb entorn igual a pre o a pro".
Quin fer servir
| Cas | Recomanació |
|---|---|
| Selector d'un Deployment, ReplicaSet o StatefulSet | matchLabels: simple, llegible, i el selector ha de ser mínim |
| Selector d'un Service | Obligatòriament mapa pla: no admet cap de les dues formes, només selector: directe |
| NetworkPolicy que abasta diversos entorns o n'exclou alguna cosa | matchExpressions |
| Afinitat de pods | matchExpressions |
Atenció a l'excepció del Service, que ja vam veure a la seva lliçó i convé recordar aquí perquè és una asimetria real de l'API:
# Deployment: AMB matchLabels
kind: Deployment
spec:
selector:
matchLabels:
app: api-reserves
entorn: devEl motiu és històric: els Services són del grup core v1, anterior al selector enriquit, i només admeten igualtat.
- Qui consumeix selectors
Els selectors no són només per a consultes manuals. Són el mecanisme d'acoblament de tot Kubernetes: la manera com uns objectes en troben uns altres sense conèixer-ne els noms.
| Qui | Què selecciona | Lliçó |
|---|---|---|
| ReplicaSet | Els pods que ha de mantenir i comptar | 02-02 |
| Deployment | Els pods dels seus ReplicaSets (amb pod-template-hash afegit) |
02-03 |
| Service | Els pods als quals enruta el trànsit | 02-05 |
| StatefulSet i DaemonSet | Els seus pods | 06-01, 06-02 |
| Job i CronJob | Els pods de les seves execucions | 06-03 |
| NetworkPolicy | Quins pods protegeix i de qui accepta trànsit | 04-06 |
| Afinitat i antiafinitat de pods | Al costat de quins pods col·locar-se o no | 06-05 |
| PodDisruptionBudget | Quins pods protegeix dels desallotjaments voluntaris | 09-05 |
| HorizontalPodAutoscaler | Indirectament, via l'objecte que escala | 09-01 |
| Prometheus (ServiceMonitor) | De quins pods recollir mètriques | 07-03 |
kubectl -l |
El que tu vulguis | 01-05 |
flowchart TB
POD["Pods amb etiquetes<br/>app=api-reserves<br/>entorn=dev"]
RS["ReplicaSet<br/>els mante"]
SVC["Service<br/>els enruta transit"]
NP["NetworkPolicy<br/>els protegeix"]
PDB["PodDisruptionBudget<br/>evita desallotjar-los tots"]
MON["ServiceMonitor<br/>recull les seves metriques"]
RS -->|selector| POD
SVC -->|selector| POD
NP -->|podSelector| POD
PDB -->|selector| POD
MON -->|selector| POD
La lliçó de fons: les etiquetes d'un pod no són decoració, són la seva interfície amb la resta del sistema. Canviar una etiqueta d'un pod el pot treure d'un Service, deixar-lo fora d'una política de xarxa o fer-lo invisible per al seu ReplicaSet. Ho veurem a l'exercici 3.
- La regla d'or: el selector d'un Deployment és immutable
Comprova-ho:
kubectl patch deployment api-reserves --type=merge \
-p '{"spec":{"selector":{"matchLabels":{"app":"api-reserves","entorn":"dev","nou":"si"}}}}'El mateix passa amb ReplicaSets, StatefulSets i DaemonSets. Els Services són l'excepció: el seu selector sí que es pot modificar, i això els converteix en l'eina de les estratègies blue-green del mòdul 11.
Per què és immutable
La raó és la seguretat de les dades... dels pods. Imagina que es permetés canviar-lo:
- El Deployment té
selector: app=api-reservesi governa 4 pods amb aquella etiqueta. - Canvies el selector a
app=api-reserves-v2. - Instantàniament, els 4 pods deixen d'encaixar. Es converteixen en orfes, exactament com els de l'experiment
--cascade=orphande la lliçó de ReplicaSets. - El Deployment compta 0 pods propis i en crea 4 de nous.
- Resultat: 8 pods corrent, 4 d'ells sense controlador, invisibles per al Deployment, consumint recursos i sense ningú que els actualitzi ni els recuperi si cauen.
Pitjor encara: si el Service continuava apuntant a app=api-reserves, aquells 4 orfes continuarien rebent trànsit de producció sense que cap controlador els vigili.
Kubernetes prefereix fallar en aplicar abans que deixar-te arribar a aquell estat.
Com canviar un selector quan de debò cal
Hi ha dos camins, i el primer és el bo:
Camí A: substituir el controlador sense tallar el servei.
# 1. Esborrar el Deployment deixant vius els pods
kubectl delete deployment api-reserves --cascade=orphan
# 2. Aplicar el manifest nou, amb el selector corregit
kubectl apply -f k8s/base/api-reserves-deployment.yaml
# 3. Comprovar. Si el selector nou encaixa amb els pods vells, els adopta;
# si no, crea els seus i despres cal netejar els orfes
kubectl get pods -l app.kubernetes.io/part-of=rutas-norte -n rutas-norte-devCamí B: nom nou i transició pel Service. Es crea un Deployment amb un altre nom i el selector correcte, s'espera que estigui llest i es canvia el selector del Service perquè apunti als pods nous. És, en essència, un desplegament blue-green (11-04).
La conseqüència pràctica
Pensa bé el selector abans del primer
apply. És la decisió menys reversible d'un manifest.
I d'aquí la regla del projecte que ja coneixes: al selector, només app i entorn. Mai la versió, mai el gestor, mai la criticitat, mai part-of. Tot el que pugui canviar amb el temps es queda fora.
- Anotacions a la pràctica
Les anotacions semblen menys importants que les etiquetes fins que descobreixes quantes coses funcionen gràcies a elles.
Anotacions que ja has fet servir
{
"deployment.kubernetes.io/revision": "3",
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",...}",
"kubernetes.io/change-cause": "v2.4.0 - desplegament inicial",
"rutasnorte.example/responsable": "[email protected]"
}| Anotació | Qui la posa | Per a què |
|---|---|---|
kubernetes.io/change-cause |
Tu o el teu CI/CD | Apareix a kubectl rollout history (02-04) |
deployment.kubernetes.io/revision |
El controlador de Deployment | Número de revisió de cada ReplicaSet |
kubectl.kubernetes.io/last-applied-configuration |
kubectl apply |
Base de la fusió de tres vies (01-06) |
kubectl.kubernetes.io/restartedAt |
kubectl rollout restart |
Força un canvi al template per recrear els pods |
Anotacions que configuren comportament
Aquest és l'ús més potent: molts controladors es configuren mitjançant anotacions, no mitjançant camps del spec. El cas paradigmàtic és el controlador d'Ingress:
# Avancament del modul 4: NO ho apliquis encara
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rutas-norte
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "8m"
nginx.ingress.kubernetes.io/rate-limit-rps: "50"
cert-manager.io/cluster-issuer: "letsencrypt-produccio"Cap d'aquelles línies és a l'esquema de l'Ingress: són instruccions que el controlador d'NGINX i cert-manager llegeixen i apliquen. El motiu d'aquest disseny és que cada implementació d'Ingress té capacitats diferents, i l'API estàndard no les pot cobrir totes. S'estudien a Controladors d'Ingress i TLS i Certificats.
Anotacions per a humans
I l'ús més simple i més rendible: informació que salva una guàrdia nocturna.
metadata:
annotations:
rutasnorte.example/responsable: "[email protected]"
rutasnorte.example/guardia: "+34 600 000 000"
rutasnorte.example/panell: "https://grafana.rutasnorte.example/d/api-reserves"
rutasnorte.example/runbook: "https://wiki.rutasnorte.example/runbooks/api-reserves"
rutasnorte.example/repositori: "https://git.rutasnorte.example/rutas-norte/api-reserves"
rutasnorte.example/commit: "a3f9c1b4e7d2"
rutasnorte.example/descripcio: |
API REST de reserves. Consulta disponibilitat a redis-cache i
persisteix a postgres-reserves. Dependencies critiques: totes dues.
Davant de 5xx sostinguts, revisar primer la connexio a postgres-reserves.Fixa't en dues coses impossibles amb etiquetes: valors amb @, : i /, i un valor multilínia. Aquesta és la raó que existeixin les anotacions.
A les tres de la matinada, això val el seu pes en or:
kubectl get deploy api-reserves -o jsonpath='{.metadata.annotations.rutasnorte\.example/runbook}{"\n"}'La regla innegociable: mai secrets a les anotacions
Mai no guardis contrasenyes, tokens, claus d'API ni certificats privats a les anotacions.
Els motius:
- Es llegeixen en clar amb
kubectl get -o yamlokubectl describe, que solen ser permisos àmpliament concedits. - Apareixen als logs: qualsevol bolcat d'un objecte les inclou.
- Es copien a
last-applied-configuration, i queden duplicades. - Se'n van als backups i a les eines de GitOps, propagant-se arreu.
- No es xifren en repòs dins d'etcd tret que el clúster ho tingui configurat, i tot i així el mecanisme està pensat per a Secrets.
El mateix val per a les etiquetes, amb l'agreujant que a més són indexades i consultables.
Per a això hi ha els Secrets, a la lliçó 03-02, i la seva gestió segura al mòdul 8. Aquell POSTGRES_PASSWORD en clar que vam deixar al Deployment provisional de postgres-reserves és exactament el deute que pagarem al mòdul següent.
kubectl label i kubectl annotate
kubectl label i kubectl annotateTotes dues ordres comparteixen sintaxi.
Afegir
kubectl label deployment api-reserves rutasnorte.example/criticitat=critica
kubectl annotate deployment api-reserves rutasnorte.example/guardia="+34 600 000 000"Sobreescriure: --overwrite
Si la clau ja existeix, l'ordre falla tret que ho indiquis:
És una protecció deliberada contra trepitjar sense voler una etiqueta que algun selector estigui fent servir.
Esborrar: el sufix -
kubectl label deployment api-reserves rutasnorte.example/criticitat-
kubectl annotate deployment api-reserves rutasnorte.example/guardia-Aquell guió final és fàcil de passar per alt en llegir un script. Recorda-ho: clau amb guió al final significa esborrar.
Operacions massives
# A diversos objectes pel nom
kubectl label pods pod-a pod-b prova=si
# A TOTS els objectes d'un tipus al namespace
kubectl label pods --all revisat=2026-08-05
# Filtrant per un altre selector
kubectl label deploy -l app.kubernetes.io/part-of=rutas-norte \
app.kubernetes.io/managed-by=kubectl --overwrite
# A tots els namespaces
kubectl label ns -l app.kubernetes.io/part-of=rutas-norte auditat=siAdvertiment de seguretat: --all combinat amb --overwrite sobre una etiqueta que apareix en algun selector pot treure pods del seu Service o del seu ReplicaSet a l'acte. Prova sempre primer amb --dry-run=server:
Un advertiment sobre les etiquetes posades a mà
Canviar una etiqueta amb kubectl label sobre un pod gestionat per un Deployment no sobreviu: al pròxim desplegament, els pods es recreen a partir del template i el canvi desapareix. Perquè perduri, edita spec.template.metadata.labels al manifest.
I hi ha un efecte secundari molt més greu, que explorarem a l'exercici 3: si canvies una etiqueta que és al selector del ReplicaSet, el pod queda orfe a l'instant i el ReplicaSet en crea un altre per substituir-lo.
- Consultes útils del dia a dia
Aquí és on l'esquema d'etiquetatge deixa de ser burocràcia i es converteix en productivitat. Les consultes més rendibles combinen -l amb els formats de sortida que vam veure a La CLI de Kubernetes.
Inventari de la plataforma
kubectl get pods -A -l app.kubernetes.io/part-of=rutas-norte \
-o custom-columns='ENTORN:.metadata.labels.entorn,COMPONENT:.metadata.labels.app,VERSIO:.metadata\.labels.app\.kubernetes\.io/version,POD:.metadata.name,ESTAT:.status.phase'ENTORN COMPONENT VERSIO POD ESTAT
dev api-reserves 2.4.0 api-reserves-9c4d7e831-j2wsk Running
dev api-reserves 2.4.0 api-reserves-9c4d7e831-p7xtr Running
dev botiga-web 1.8.0 botiga-web-6f9c4b8d7-42kxr Running
dev redis-cache 7.2 redis-cache-6c8f9d745-w2mtb Running
pre api-reserves 2.4.0 api-reserves-7f1d3e942-c9plk Running
pro botiga-web 1.8.0 botiga-web-6f9c4b8d7-x4nbc RunningTruc de sintaxi important: a custom-columns, els punts que formen part de la clau de l'etiqueta cal escapar-los amb \.. Si no, kubectl els interpreta com a separadors de ruta JSONPath i no troba res.
Quina versió corre a cada entorn
La consulta que més vegades et demanaran:
kubectl get deploy -A -l app=api-reserves \
-o custom-columns='NS:.metadata.namespace,DEPLOY:.metadata.name,IMATGE:.spec.template.spec.containers[0].image,REPLIQUES:.spec.replicas'NS DEPLOY IMATGE REPLIQUES
rutas-norte-dev api-reserves node:20-alpine 2
rutas-norte-pre api-reserves node:20-alpine 2Auditoria de l'esquema d'etiquetatge
Trobar el que incompleix la convenció del projecte:
# Deployments sense l'etiqueta part-of: s'han escapat de l'esquema
kubectl get deploy -A -l '!app.kubernetes.io/part-of'
# Objectes de la plataforma sense criticitat assignada
kubectl get deploy,sts,ds -A -l 'app.kubernetes.io/part-of=rutas-norte,!rutasnorte.example/criticitat'
# Pods sense l'etiqueta d'entorn: no els abastaria cap NetworkPolicy
kubectl get pods -A -l 'app.kubernetes.io/part-of=rutas-norte,!entorn'Consultes d'incident
# Tot el que es critic i NO esta corrent
kubectl get pods -A -l 'rutasnorte.example/criticitat=critica' \
--field-selector status.phase!=Running
# Logs agregats de totes les repliques d'un component, amb prefix de pod
kubectl logs -l app=api-reserves -n rutas-norte-pro --tail=50 --prefix
# Ordenar per reinicis: qui esta patint
kubectl get pods -A -l app.kubernetes.io/part-of=rutas-norte \
--sort-by=.status.containerStatuses[0].restartCount
# Els esdeveniments recents del namespace, el primer que cal mirar
kubectl get events -n rutas-norte-pro --sort-by=.lastTimestamp | tail -20Operacions en bloc
# Reiniciar tots els components sense estat d'un entorn
kubectl rollout restart deploy -l 'app.kubernetes.io/part-of=rutas-norte' -n rutas-norte-dev
# Esborrar TOT un entorn de proves (amb compte)
kubectl delete all -l 'app.kubernetes.io/part-of=rutas-norte' -n rutas-norte-dev --dry-run=clientAquell --dry-run=client abans d'un delete massiu és un hàbit que convé adquirir.
Combinacions amb -o wide i --show-labels
# Veure on es cada cosa
kubectl get pods -A -l entorn=pro -o wide
# Veure totes les etiquetes d'un objecte
kubectl get deploy api-reserves --show-labels
# Agrupar visualment per una etiqueta
kubectl get pods -A -L entorn,app.kubernetes.io/componentEl flag -L (ela majúscula) és un petit tresor: afegeix columnes amb el valor de les etiquetes indicades, sense filtrar res.
NAMESPACE NAME READY STATUS AGE ENTORN COMPONENT
rutas-norte-dev api-reserves-9c4d7e831-j2wsk 1/1 Running 30m dev api
rutas-norte-dev botiga-web-6f9c4b8d7-42kxr 1/1 Running 2h dev frontend
rutas-norte-dev redis-cache-6c8f9d745-w2mtb 1/1 Running 2h dev cache
rutas-norte-pre api-reserves-7f1d3e942-c9plk 1/1 Running 1h pre apiErrors Comuns i Consells
- Ficar la versió al selector. En desplegar una versió nova el selector deixa d'encaixar, i com que és immutable, t'obliga a recrear el Deployment. El selector només porta
appientorn. - Selectors massa amplis. Un
app.kubernetes.io/part-of: rutas-nortecom a selector adopta i pot esborrar pods d'altres components, com vam veure a ReplicaSets. - Fer servir caràcters prohibits en valors d'etiqueta. Res d'
@,:,/, espais ni accents. Si la dada els necessita, és una anotació. - Fer servir el prefix
kubernetes.io/per a etiquetes pròpies. Està reservat. Fes servir el domini de la teva organització:rutasnorte.example/. - Guardar secrets a les anotacions o les etiquetes. Es llegeixen en clar amb
describe, viatgen als backups i acaben a Git. Van en Secrets. - Posar les etiquetes només a
metadatai no aspec.template.metadata. Els pods hereten les del template, no les del Deployment. És l'error que trenca els Services. - Oblidar
--overwritei pensar que l'ordre ha funcionat.kubectl labelfalla si la clau existeix. Llegeix sempre la sortida. - Canviar amb
kubectl labeluna etiqueta que és en un selector. El pod queda orfe i el controlador en crea un altre. Pot duplicar capacitat sense que te n'adonis. - Esperar que un canvi amb
kubectl labelsobre un pod perduri. Es perd al pròxim desplegament. Edita eltemplate. - Oblidar les cometes simples als selectors de conjunt. Els parèntesis i els espais els interpreta la shell.
- No escapar els punts de les claus a
custom-columns.app.kubernetes.io/versions'ha d'escriureapp\.kubernetes\.io/version. - Consell: defineix l'esquema d'etiquetatge abans de desplegar res. Afegir-lo després implica editar tots els manifests i, si toca selectors, recrear objectes.
- Consell:
kubectl get pods -A -L entorn,appet dona una vista tabulada de tota la plataforma sense filtrar. És la consulta amb què començar qualsevol revisió. - Consell: documenta l'esquema a
k8s/README.mddel repositori. Un esquema que només coneix qui el va dissenyar no és un esquema.
Exercicis
Exercici 1: Aplicar l'esquema complet a botiga-web
- Actualitza
k8s/base/botiga-web-deployment.yamlperquè el Deployment i el seutemplateportin les vuit etiquetes de l'esquema de Rutas Norte (app,entorn, les cinc d'app.kubernetes.io/icriticitat), i quatre anotacions: responsable, panell, runbook ichange-cause. - Assegura't que el selector continua tenint només
appientorn, i explica en dues línies per què. - Aplica'l i demostra amb una ordre que els pods porten les vuit etiquetes.
- Recupera l'URL del runbook amb una sola ordre.
Exercici 2: Consultes sobre la plataforma
Amb els tres entorns desplegats, escriu l'ordre exacta per a cada pregunta:
- Tots els pods de la plataforma a
preopro, en qualsevol namespace. - Tots els Deployments de la plataforma que no són de desenvolupament.
- Els pods de components amb criticitat
criticaoaltaque no estan en estatRunning. - Una taula amb entorn, component, versió i node de tots els pods de la plataforma.
- Els Deployments als quals els falta l'etiqueta
rutasnorte.example/criticitat(auditoria de l'esquema). - Tots els pods, sense filtrar, mostrant
entorniapp.kubernetes.io/componentcom a columnes addicionals.
Exercici 3: L'experiment del pod orfe
Aquest exercici demostra per què les etiquetes són la interfície d'un pod amb la resta del sistema. Treballa a rutas-norte-dev amb el Deployment de botiga-web (3 rèpliques) i el seu Service.
- Apunta quants pods hi ha i quants endpoints té el Service.
- Tria un pod i canvia-li l'etiqueta
appabotiga-web-aillatambkubectl label --overwrite. - Observa immediatament: quants pods hi ha ara? Què ha fet el ReplicaSet? Continua viu el pod modificat? Qui n'és el propietari?
- Comprova quants endpoints té ara el Service i explica per què.
- Explica per a què serveix aquesta tècnica al món real i quin perill té.
- Deixa el clúster com estava.
Solucions
Solució 1
# k8s/base/botiga-web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: botiga-web
namespace: rutas-norte-dev
labels:
app: botiga-web
entorn: dev
app.kubernetes.io/name: botiga-web
app.kubernetes.io/instance: botiga-web-dev
app.kubernetes.io/version: "1.8.0"
app.kubernetes.io/component: frontend
app.kubernetes.io/part-of: rutas-norte
app.kubernetes.io/managed-by: kubectl
rutasnorte.example/criticitat: alta
annotations:
kubernetes.io/change-cause: "v1.8.0 - esquema d'etiquetatge complet (RN-495)"
rutasnorte.example/responsable: "[email protected]"
rutasnorte.example/panell: "https://grafana.rutasnorte.example/d/botiga-web"
rutasnorte.example/runbook: "https://wiki.rutasnorte.example/runbooks/botiga-web"
spec:
replicas: 3
revisionHistoryLimit: 5
minReadySeconds: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: botiga-web
entorn: dev
template:
metadata:
labels:
app: botiga-web
entorn: dev
app.kubernetes.io/name: botiga-web
app.kubernetes.io/instance: botiga-web-dev
app.kubernetes.io/version: "1.8.0"
app.kubernetes.io/component: frontend
app.kubernetes.io/part-of: rutas-norte
app.kubernetes.io/managed-by: kubectl
rutasnorte.example/criticitat: alta
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"- El selector porta només
appientornperquè és immutable i ha d'identificar el component de forma estable. Si incloguésapp.kubernetes.io/version, en desplegar la 1.9.0 el selector deixaria d'encaixar amb els pods nous, i com que no es pot modificar, caldria esborrar i recrear el Deployment a cada desplegament. A més, un selector mínim evita el risc d'adopcions indegudes si un altre objecte comparteix etiquetes informatives.
kubectl apply -f k8s/base/botiga-web-deployment.yaml
kubectl get pods -l app=botiga-web -o jsonpath='{.items[0].metadata.labels}' | python3 -m json.tool{
"app": "botiga-web",
"app.kubernetes.io/component": "frontend",
"app.kubernetes.io/instance": "botiga-web-dev",
"app.kubernetes.io/managed-by": "kubectl",
"app.kubernetes.io/name": "botiga-web",
"app.kubernetes.io/part-of": "rutas-norte",
"app.kubernetes.io/version": "1.8.0",
"entorn": "dev",
"pod-template-hash": "5b7c9f4d8",
"rutasnorte.example/criticitat": "alta"
}Les vuit de l'esquema, més el pod-template-hash que hi afegeix el Deployment.
kubectl get deploy botiga-web -o jsonpath='{.metadata.annotations.rutasnorte\.example/runbook}{"\n"}'Solució 2
# 1. Pods de la plataforma a pre o pro
kubectl get pods -A -l 'app.kubernetes.io/part-of=rutas-norte,entorn in (pre,pro)'
# 2. Deployments que no son de desenvolupament
kubectl get deploy -A -l 'app.kubernetes.io/part-of=rutas-norte,entorn notin (dev)'
# 3. Critics o alts que no estan Running
kubectl get pods -A -l 'rutasnorte.example/criticitat in (critica,alta)' \
--field-selector status.phase!=Running
# 4. Taula d'inventari
kubectl get pods -A -l app.kubernetes.io/part-of=rutas-norte \
-o custom-columns='ENTORN:.metadata.labels.entorn,COMPONENT:.metadata.labels.app,VERSIO:.metadata.labels.app\.kubernetes\.io/version,NODE:.spec.nodeName'
# 5. Auditoria: sense criticitat
kubectl get deploy -A -l 'app.kubernetes.io/part-of=rutas-norte,!rutasnorte.example/criticitat'
# 6. Columnes addicionals sense filtrar
kubectl get pods -A -L entorn,app.kubernetes.io/component# Sortida de la 4
ENTORN COMPONENT VERSIO NODE
dev api-reserves 2.4.0 rutas-norte
dev api-reserves 2.4.0 rutas-norte
dev botiga-web 1.8.0 rutas-norte
dev redis-cache 7.2 rutas-norte
pre api-reserves 2.4.0 rutas-norte
pro botiga-web 1.8.0 rutas-norteNota sobre la pregunta 3: -l filtra per etiquetes i --field-selector per camps de l'objecte. Són mecanismes diferents i complementaris; els camps disponibles per a --field-selector són limitats (status.phase, spec.nodeName, metadata.name, metadata.namespace i poca cosa més).
Solució 3
# 1. Situacio de partida
kubectl get pods -l app=botiga-web -n rutas-norte-dev
kubectl get endpoints botiga-web -n rutas-norte-devNAME READY STATUS RESTARTS AGE
botiga-web-5b7c9f4d8-6kdnp 1/1 Running 0 10m
botiga-web-5b7c9f4d8-q3xwt 1/1 Running 0 10m
botiga-web-5b7c9f4d8-z8mrv 1/1 Running 0 10m
NAME ENDPOINTS AGE
botiga-web 10.244.0.81:80,10.244.0.82:80,10.244.0.83:80 2h3 pods, 3 endpoints.
# 2. Canviar l'etiqueta del selector en un pod
kubectl label pod botiga-web-5b7c9f4d8-6kdnp app=botiga-web-aillat --overwrite -n rutas-norte-dev
# 3. Observar
kubectl get pods -n rutas-norte-dev -l app.kubernetes.io/part-of=rutas-norte,app.kubernetes.io/component=frontendpod/botiga-web-5b7c9f4d8-6kdnp labeled
NAME READY STATUS RESTARTS AGE
botiga-web-5b7c9f4d8-6kdnp 1/1 Running 0 11m
botiga-web-5b7c9f4d8-h7pnk 1/1 Running 0 4s
botiga-web-5b7c9f4d8-q3xwt 1/1 Running 0 11m
botiga-web-5b7c9f4d8-z8mrv 1/1 Running 0 11mAra hi ha 4 pods. El que ha passat, pas a pas:
- En canviar
appdebotiga-webabotiga-web-aillat, el pod va deixar d'encaixar amb el selector del ReplicaSet. - A la volta següent del seu bucle de reconciliació, el ReplicaSet va comptar 2 pods propis on n'hi havia d'haver 3 i en va crear un de nou (
h7pnk, amb 4 segons d'edat). - El pod modificat continua viu, però ha quedat orfe: cap controlador no el vigila.
kubectl get pod botiga-web-5b7c9f4d8-6kdnp -n rutas-norte-dev \
-o jsonpath='{.metadata.ownerReferences}{"\n"}'Sortida buida: no té propietari. Kubernetes li va retirar les ownerReferences en deixar d'encaixar amb el selector.
Continuen sent 3, però un ha canviat. El pod aïllat (10.244.0.81) ha sortit del Service perquè el seu selector també exigeix app=botiga-web; al seu lloc hi ha entrat el pod nou (10.244.0.87). El pod orfe ja no rep trànsit encara que continuï perfectament viu i sa.
-
Per a què serveix al món real: és la tècnica clàssica d'aïllament per depurar en producció. Si un de cinc pods presenta un comportament anòmal —una fuita de memòria, respostes erràtiques, un log sospitós—, canviar-li una etiqueta del selector el treu del Service i del ReplicaSet en un instant. Deixa de rebre trànsit de clients reals, el ReplicaSet crea un substitut per no perdre capacitat, i tu conserves el pod intacte, amb la seva memòria i el seu estat, per inspeccionar-lo amb calma:
kubectl exec,kubectl logs, bolcats, perfilat. No cal reproduir el problema en un entorn de proves: tens el pacient viu sobre la taula.El perill és doble. Primer, aquell pod ja no el gestiona ningú: si el node cau o algú el desallotja, desapareix sense substitut, i sobretot és fàcil oblidar-se'n, consumint CPU i memòria indefinidament. Segon, si el canvi d'etiqueta es fa per error o en sentit contrari —donar a un pod solt les etiquetes d'un component governat—, provoques l'adopció i el possible esborrat immediat que vam veure a la lliçó de ReplicaSets. La disciplina obligatòria és etiquetar el pod aïllat amb la data i el motiu, i esborrar-lo en acabar:
kubectl label pod botiga-web-5b7c9f4d8-6kdnp \
rutasnorte.example/aillat-el=2026-08-05 \
rutasnorte.example/incident=RN-501 -n rutas-norte-dev# 6. Neteja
kubectl delete pod botiga-web-5b7c9f4d8-6kdnp -n rutas-norte-dev
kubectl get pods -l app=botiga-web -n rutas-norte-dev
kubectl get endpoints botiga-web -n rutas-norte-devpod "botiga-web-5b7c9f4d8-6kdnp" deleted
NAME READY STATUS RESTARTS AGE
botiga-web-5b7c9f4d8-h7pnk 1/1 Running 0 6m
botiga-web-5b7c9f4d8-q3xwt 1/1 Running 0 17m
botiga-web-5b7c9f4d8-z8mrv 1/1 Running 0 17m
NAME ENDPOINTS AGE
botiga-web 10.244.0.82:80,10.244.0.83:80,10.244.0.87:80 2hTres pods, tres endpoints, tot en ordre. I adona't que en esborrar l'orfe no va aparèixer cap substitut: el ReplicaSet ja tenia els seus tres pods i aquell no era seu.
Conclusió
Tanques el mòdul 2 amb el fil que el recorria sencer convertit en sistema. Saps distingir sense dubtar una etiqueta d'una anotació: les primeres identifiquen i es consulten, estan indexades, tenen 63 caràcters i un joc de caràcters restringit; les segones adjunten informació que es llegeix però no es busca, admeten fins a 256 KiB i qualsevol contingut, inclosos JSON i text multilínia. Coneixes la sintaxi completa de claus i valors, saps que kubernetes.io/ és un prefix reservat i que el domini de la teva organització és el lloc correcte per al que és propi, i domines les sis etiquetes recomanades per Kubernetes, inclosa la distinció entre name (què és) i instance (quin és).
Has fixat l'esquema d'etiquetatge definitiu de Rutas Norte per als seus sis components i els seus tres entorns, amb la seva regla d'or: només app i entorn entren als selectors, perquè el selector d'un Deployment és immutable i ficar-hi la versió et condemnaria a recrear l'objecte a cada desplegament. Fas servir les dues famílies de selectors —igualtat amb =, == i !=; conjunts amb in, notin, exists i la seva negació— tant a la línia d'ordres amb -l com als manifests amb matchLabels i matchExpressions, sense oblidar l'asimetria dels Services, que només admeten mapa pla. Saps qui consumeix selectors, que són gairebé tots: ReplicaSets, Deployments, Services, NetworkPolicies, PodDisruptionBudgets, afinitat i les eines de monitoratge. Fas servir les anotacions per al que serveixen —documentar el canvi, configurar controladors d'Ingress, deixar el runbook i el telèfon de guàrdia a mà— sense cometre mai l'error de guardar-hi un secret. I tens al cinturó kubectl label i kubectl annotate amb --overwrite i l'esborrat amb guió final, més el repertori de consultes que converteix un clúster gran en una cosa navegable.
Amb això tanques el mòdul 2 i la plataforma Rutas Norte ja és viva. botiga-web va passar de ser aquell pod fràgil del mòdul 1 a un Deployment de tres rèpliques que es recupera sol; api-reserves, redis-cache i worker-notificacions tenen els seus; els quatre components que reben connexions tenen una adreça estable amb balanceig entre rèpliques; saps desplegar sense tall de servei i desfer un desplegament trencat en menys d'un minut; tens tres entorns separats en namespaces amb el mateix manifest desplegat en diversos d'ells; i tot està etiquetat amb un esquema coherent que les lliçons següents explotaran.
Però hi ha deutes pendents molt visibles. La contrasenya de PostgreSQL continua escrita en clar dins d'un manifest que és a Git, i aquella base de dades guarda el nom, el DNI, el telèfon i el correu de cada client de Rutas Norte. L'URL de l'API va incrustada a la imatge en lloc d'injectar-se segons l'entorn. Cap namespace no té quota, així que un error a desenvolupament pot deixar sense recursos la producció. I tots els nostres pods declaren requests i limits a ull, sense criteri. El mòdul 3, Gestió de Configuració i Secrets, ataca exactament això: separarem la configuració del codi amb ConfigMaps, traurem les credencials dels manifests amb Secrets, injectarem tots dos com a variables d'entorn, posarem quotes i límits a cada entorn, entendrem les classes de qualitat de servei que decideixen quin pod mor primer quan falta memòria, i donarem a cada component la seva pròpia identitat davant de l'API amb ServiceAccounts.
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
