Salta el contingut

Introducció a Kubernetes


Què és Kubernetes i per què l'hem d'aprendre?

Quan parlem de Kubernetes (que veureu escrit sovint com K8s, on el 8 representa les 8 lletres entre la K i la s), estem parlant d'una de les eines més importants en el món del desenvolupament i desplegament d'aplicacions modernes. Però anem a començar des del principi per entendre per què aquesta tecnologia s'ha convertit en un estàndard de la indústria.

Imagineu que teniu una aplicació web, per exemple una botiga online. Aquesta aplicació funciona molt bé quan teniu pocs usuaris, però què passa quan de sobte teniu un pic de trànsit? Potser per Black Friday, o perquè heu sortit a les notícies i tothom vol veure la vostra aplicació. El vostre servidor comença a saturar-se, l'aplicació va lenta, i alguns usuaris fins i tot reben errors. Aquest és un problema clàssic d'escalabilitat.

Tradicionalment, la solució passaria per tenir diversos servidors, configurar un balancejador de càrrega, assegurar que tots els servidors tenen la mateixa versió de l'aplicació, i gestionar què passa si un servidor falla. Tot això de forma manual pot ser un malson. Aquí és on entra Kubernetes.

Kubernetes és una plataforma de codi obert que automatitza el desplegament, l'escalat i la gestió d'aplicacions que funcionen dins de contenidors (com Docker). Va ser creat originalment per Google basant-se en la seva experiència interna gestionant milers de milions de contenidors, i actualment està mantingut per la Cloud Native Computing Foundation (CNCF), una organització que agrupa empreses com Google, Microsoft, Amazon i moltes altres.

El que fa especial Kubernetes és que et permet declarar com vols que sigui el teu sistema (per exemple, "vull que sempre hi hagi 3 instàncies de la meva aplicació funcionant"), i Kubernetes s'encarrega de fer que això sigui una realitat constantment. Si una instància falla, Kubernetes en crea una de nova automàticament. Si necessites més capacitat, només has de dir-li que vols 10 instàncies en lloc de 3, i ell ho gestiona.

Versions i suport de Kubernetes

És important entendre com funciona el cicle de versions de Kubernetes perquè en un entorn professional haureu de mantenir els vostres clústers actualitzats. Al moment d'escriure aquest document, a l'octubre de 2025, la versió més recent i estable de Kubernetes és la v1.34, que es va llançar l'agost de 2025. Aquesta versió va introduir 58 millores noves, de les quals 23 van passar a ser funcionalitats estables.

Kubernetes segueix el que s'anomena una política de suport N-2. Això significa que sempre mantenen amb suport les tres versions més recents. Actualment, aquestes són la v1.34, v1.33 i v1.32. Cada versió rep suport durant 14 mesos en total, que es divideixen en 12 mesos de suport actiu més 2 mesos addicionals de perióde d'actualització. Això vol dir que teniu temps suficient per planificar i executar les actualitzacions sense pressa, però també vol dir que no podeu ignorar les actualitzacions indefinidament, per no arribar al end of life de la versió.

Kubernetes llança una nova versió menor aproximadament cada quatre mesos. La propera versió, la v1.35, està prevista per desembre de 2025. Cada versió porta un nom temàtic, com les distribucions de linux Ubuntu/Debian. Per exemple, la v1.33 es deia "Octarine", i la v1.34 es diu "Of Wind & Will".


Com funciona l'arquitectura de Kubernetes per dins

Per entendre bé Kubernetes, hem de comprendre com està organitzat internament. Kubernetes funciona amb una arquitectura que tradicionalment s'anomena mestre-esclau, però que actualment es coneix amb els termes més moderns de "control plane" (pla de control) i "worker nodes" (nodes de treball). Penseu en això com una empresa: teniu un equip directiu que pren decisions i planifica, i teniu els treballadors que executen el treball real.

Arquitectura Kubernetes

El Control Plane: el cervell del clúster

El control plane és el cervell de Kubernetes. És el conjunt de components que prenen totes les decisions sobre què passa al clúster. Per exemple, decideix on col·locar cada aplicació, quan escalar-les, i què fer quan alguna cosa va malament. El control plane no executa les vostres aplicacions, només les gestiona.

Dins del control plane trobem diversos components, cadascun amb una responsabilitat específica. El primer i més important és el kube-apiserver, que és literalment la porta d'entrada a tot el sistema. Cada vegada que voleu fer alguna cosa amb Kubernetes, ja sigui desplegar una aplicació, veure l'estat del clúster, o eliminar recursos, ho feu parlant amb l'API server. Aquest component exposa una API REST sobre HTTPS, i absolutament tot al clúster passa per ell. Tant vosaltres com a usuaris, com la resta de components de Kubernetes, parlen amb l'API server per saber què està passant i per demanar canvis.

El següent component fonamental és etcd, que és la memòria del clúster. Etcd és una base de dades distribuïda de tipus clau-valor que guarda tota la informació sobre l'estat del clúster. Aquí s'emmagatzema quins pods s'estan executant, quines configuracions teniu definides, quin és l'estat de cada node, i bàsicament tot el que Kubernetes necessita recordar. És extremadament important, i per això en entorns de producció sempre es fa servir amb replicació per assegurar que no es perdi mai aquesta informació.

El kube-scheduler és el component responsable de decidir on executar cada pod. Quan creeu un pod nou, el scheduler mira tots els nodes disponibles al clúster i decideix quin és el millor lloc per col·locar-lo. Té en compte moltes coses: quants recursos CPU i memòria necessita el pod, quants recursos té disponibles cada node, si hi ha requisits especials com "ha d'executar-se al mateix node que un altre pod" o "no pot executar-se en nodes de determinat tipus". És com un gestor de recursos humans que decideix quin treballador és el més adequat per a cada tasca.

El kube-controller-manager és en realitat un conjunt de controladors diferents que s'executen junts. Cada controlador té una feina específica: hi ha un controlador que vigila els nodes i detecta quan un node deixa de funcionar, un altre que s'assegura que sempre tingueu el nombre correcte de rèpliques dels vostres pods, un altre que gestiona els serveis, etc. Els controladors segueixen un patró molt simple però molt potent: observen constantment l'estat actual del clúster, el comparen amb l'estat desitjat que heu definit, i prenen accions per fer que l'estat actual s'assembli a l'estat desitjat.

Finalment, hi ha el cloud-controller-manager, que és opcional i només cal si esteu executant Kubernetes en un proveïdor de núvol com AWS, Google Cloud o Azure. Aquest component s'encarrega d'integrar Kubernetes amb els serveis del núvol, per exemple creant balancejadors de càrrega del proveïdor quan els necessiteu, o gestionant els volums d'emmagatzematge.

Els Worker Nodes: on realment s'executen les aplicacions

Mentre que el control plane pren totes les decisions, els worker nodes són on realment s'executen les vostres aplicacions. Cada node és un servidor (físic o virtual) que forma part del clúster. Podeu tenir tres nodes, deu nodes, o mil nodes, depenent de les vostres necessitats.

Cada worker node té tres components principals. El primer és el kubelet, que és com l'agent de Kubernetes al node. El kubelet s'executa com un daemon al sistema operatiu (no com un contenidor) i és el responsable d'assegurar que els contenidors que se suposa que han d'executar-se al node realment s'estan executant. Parla amb l'API server per rebre instruccions sobre quins pods ha d'executar, i després treballa amb el container runtime per posar en marxa aquests contenidors. També monitoritza constantment la salut dels pods i reporta l'estat a l'API server.

El kube-proxy és el component responsable de la xarxa dins del clúster. Gestiona les regles de xarxa que permeten que els pods es puguin comunicar entre ells i amb el món exterior. Quan definiu un Service a Kubernetes (que veurem més endavant), kube-proxy és el que fa la màgia de fer que aquest servei funcioni, redirigint el trànsit de xarxa als pods correctes i fent balanceig de càrrega entre ells.

Finalment, necessitem un container runtime, que és el motor que realment executa els contenidors. Docker va ser el més popular durant molt de temps, però actualment containerd (la part de Docker que realment executa contenidors) és l'opció més comuna, i també es fa servir CRI-O. Aquest component és el que agafa una imatge de contenidor, la descarrega si cal, i la posa en marxa.

Tota aquesta arquitectura està documentada en detall a:

Cluster Kubernetes


Els conceptes fonamentals que heu de dominar

Ara que ja entenem l'arquitectura general, anem a aprofundir en els conceptes que utilitzareu dia a dia quan treballeu amb Kubernetes. Aquests són els blocs de construcció bàsics que necessiteu conèixer per poder desplegar i gestionar aplicacions.

Pods: la unitat bàsica d'execució

Quan parleu amb algú que treballa amb Kubernetes, la primera cosa que us dirà és que el Pod és la unitat més petita i bàsica que podeu desplegar. Però què vol dir això exactament?

Un pod és com una capsa que encapsula un o més contenidors que treballen junts. Penseu en un pod com una petita "màquina virtual lleugera" que agrupa contenidors que necessiten compartir recursos. Tots els contenidors dins d'un mateix pod comparteixen la mateixa adreça IP, poden comunicar-se entre ells usant localhost, i poden compartir volums d'emmagatzematge.

Ara bé, tot i que un pod pot contenir múltiples contenidors, la pràctica més habitual i recomanada és tenir un sol contenidor per pod. Per què? Doncs perquè això fa que sigui més fàcil escalar i gestionar les aplicacions. Si teniu una aplicació web i voleu escalar-la, simplement creeu més pods amb aquesta aplicació. Si poseu múltiples coses diferents dins d'un mateix pod, aleshores no podeu escalar-les independentment.

Hi ha excepcions a aquesta regla, però. De vegades té sentit tenir múltiples contenidors en un pod quan un contenidor és l'aplicació principal i els altres són helpers. Per exemple, podríeu tenir un pod amb el vostre servidor web com a contenidor principal, i un segon contenidor que s'encarrega de recolectar els logs i enviar-los a un sistema centralitzat. Aquest patró s'anomena "sidecar pattern".

Una cosa molt important d'entendre sobre els pods és que són efímers, és a dir, temporals. Kubernetes pot crear i destruir pods en qualsevol moment. Si un node falla, tots els pods d'aquell node es consideren perduts i Kubernetes en crea de nous en altres nodes. Si actualitzeu una aplicació, els pods vells es destrueixen i es creen de nous amb la nova versió. Per això, mai no hauríeu de pensar en un pod específic com alguna cosa permanent. Les dades importants s'han de guardar fora dels pods, en volums persistents.

Un exemple bàsic d'un pod seria aquest, que executa un servidor web NGINX amb la versió 1.27:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.27
    ports:
    - containerPort: 80

Aquest fitxer YAML (que és el format estàndard per definir recursos a Kubernetes) diu molt simplement: "Vull un pod que es digui nginx-pod, que tingui un contenidor amb la imatge de Docker nginx:1.27, i que aquest contenidor exposi el port 80". Fixeu-vos que especifiquem la versió 1.27 de NGINX, no usem latest. Això és una bona pràctica perquè així sabem exactament quina versió estem executant.

Podeu trobar tota la documentació sobre pods a https://kubernetes.io/docs/concepts/workloads/pods/

Deployments: gestió intel·ligent dels vostres pods

Acabem de veure què són els pods, però hi ha un problema: normalment no creeu pods directament. Per què? Doncs perquè els pods són efímers i necessiteu alguna cosa que els gestioni de forma intel·ligent. Aquí és on entren els Deployments.

Un Deployment és com un gestor que s'encarrega de mantenir els vostres pods funcionant correctament. Quan creeu un Deployment, li esteu dient a Kubernetes: "Vull que sempre hi hagi X rèpliques d'aquesta aplicació funcionant, i si alguna falla, crea'n una de nova automàticament". Però els Deployments fan molt més que això.

La gran potència dels Deployments està en com gestionen les actualitzacions. Imagineu que teniu la vostra aplicació web funcionant amb 5 rèpliques (5 pods), i voleu actualitzar-la a una nova versió. Si destruíssiu tots els pods vells i crééssiu els nous d'un cop, tindríeu un downtime, un perióde de temps on l'aplicació no estaria disponible. Això no és acceptable en un entorn de producció.

Els Deployments tenen una funcionalitat anomenada "rolling update" (actualització rodant) que resol aquest problema de forma elegant. El que fa és anar actualitzant els pods progressivament: crea un pod nou amb la nova versió, espera que estigui funcionant correctament, i només llavors destrueix un pod vell. Després repeteix el procés fins que tots els pods estan actualitzats. D'aquesta manera, sempre teniu algunes rèpliques funcionant i mai hi ha downtime.

I encara hi ha més: si després d'actualitzar us adoneu que la nova versió té un error, podeu fer un rollback (revertir) a la versió anterior amb una sola comanda. Kubernetes recorda les versions anteriors i pot tornar enrere de forma automàtica.

Els Deployments també permeten escalar les vostres aplicacions molt fàcilment. Si veieu que necessiteu més capacitat, només heu de canviar el nombre de rèpliques i Kubernetes crea o destrueix pods automàticament per arribar al nombre desitjat.

Aquí teniu un exemple complet d'un Deployment que crea tres rèpliques d'un servidor web NGINX:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        ports:
        - containerPort: 80

Analitzem aquest fitxer per entendre què fa cada part. A la secció de metadata donem un nom al deployment. Després, a spec, diem que volem 3 rèpliques. El selector amb matchLabels indica quins pods gestiona aquest Deployment (els que tenen l'etiqueta app: nginx). Finalment, template defineix com seran els pods que crearà: contindran un contenidor NGINX amb la versió 1.27.

La documentació oficial sobre Deployments es pot trobar a https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

Services: fent que les vostres aplicacions siguin accessibles

Ara que entenem els Deployments i sabem que tenim múltiples rèpliques dels nostres pods funcionant, ens trobem amb un problema: com accedim a aquests pods? Recordeu que els pods són efímers i tenen adreces IP que poden canviar. Si un pod falla i se'n crea un de nou, tindrà una IP diferent. I si tenim 5 rèpliques, quina IP fem servir? Com balancem la càrrega entre elles?

Aquest és exactament el problema que resolen els Services. Un Service a Kubernetes és una abstracció que defineix un conjunt lògic de pods i una política per accedir-hi. Penseu en un Service com un nom DNS estable i una IP fixa que apunta als vostres pods, independentment de quantes rèpliques hi hagi o de si els pods canvien.

Quan creeu un Service, li doneu un selector que coincideix amb les etiquetes dels vostres pods. Per exemple, si els vostres pods tenen l'etiqueta "app: nginx", el Service amb selector "app: nginx" automàticament trobarà aquests pods i dirigirà el trànsit cap a ells. Si teniu 5 rèpliques, el Service distribuirà les peticions entre els 5 pods automàticament. Si un pod falla i se'n crea un de nou, el Service ho detecta automàticament i comença a enviar-li trànsit.

Kubernetes ofereix diferents tipus de Services depenent de com voleu exposar la vostra aplicació. El tipus més bàsic és ClusterIP, que és el tipus per defecte. Aquest tipus crea una IP interna al clúster que només és accessible des de dins del clúster. És perfecte per a comunicacions internes entre diferents aplicacions del vostre clúster.

El tipus NodePort és útil quan voleu que l'aplicació sigui accessible des de fora del clúster. Amb NodePort, Kubernetes obre un port específic en tots els nodes del clúster, i qualsevol trànsit que arribi a qualsevol node en aquest port es redirigeix automàticament als vostres pods. Els ports que podeu utilitzar van del 30000 al 32767.

El tipus LoadBalancer és utilitzat principalment en entorns de núvol (AWS, Google Cloud, Azure). Aquest tipus crea automàticament un balancejador de càrrega del proveïdor de núvol que distribueix el trànsit entre els nodes del vostre clúster.

Finalment, hi ha ExternalName, que és una mica diferent: aquest tipus mapeja el vostre Service a un nom DNS extern. És útil quan voleu que els vostres pods puguin accedir a un servei extern usant un nom intern del clúster.

Aquí teniu un exemple pràctic d'un Service de tipus NodePort que exposa la nostra aplicació NGINX:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080

En aquest exemple, estem creant un Service anomenat nginx-service. El selector "app: nginx" indica que aquest Service enviarà trànsit als pods que tinguin aquesta etiqueta. Definim tres ports: port 80 és el port en què el Service escolta dins del clúster, targetPort 80 és el port on els pods escolten, i nodePort 30080 és el port que s'obrirà en tots els nodes per accedir des de fora.

Podeu trobar tots els detalls sobre Services a la documentació oficial: https://kubernetes.io/docs/concepts/services-networking/service/

Ingress: el proxy invers i balancejador de càrrega de Kubernetes

Fins ara hem vist com exposar aplicacions amb Services, però hi ha una limitació important: si tenim múltiples aplicacions i fem servir NodePort per a cadascuna, acabarem amb molts ports diferents oberts (30080, 30081, 30082...), i això no és gens pràctic. El que realment volem és poder accedir a totes les nostres aplicacions web pel port 80 o 443 estàndard, i que alguna cosa intel·ligent s'encarregui de dirigir cada petició a l'aplicació correcta segons el domini o el path de la URL.

Això és exactament el que fa un Ingress. Un Ingress és un recurs de Kubernetes que gestiona l'accés extern als serveis del vostre clúster, normalment HTTP i HTTPS. Funciona de manera similar a un servidor web com NGINX o Apache quan actuen com a proxy invers: rep les peticions externes i les redirigeix al servei intern adequat segons regles que definiu.

Però atenció, hi ha una cosa important d'entendre: un recurs Ingress per si sol no fa res. Necessiteu també un Ingress Controller, que és el component que realment implementa la funcionalitat d'Ingress. És com si l'Ingress fos la configuració (les regles que voleu aplicar) i l'Ingress Controller fos el programari que aplica aquestes regles. El més popular és el NGINX Ingress Controller, que al 2025 va per la versió 1.11 o superior.

Amb un Ingress podeu fer coses molt útils. Per exemple, podeu tenir múltiples aplicacions web diferents al vostre clúster, i que totes es puguin accedir pel port 80, però cadascuna amb un path diferent. Imagineu que teniu una API REST a "/api", un panell d'administració a "/admin", i l'aplicació principal a "/". L'Ingress pot dirigir cada petició al servei correcte segons el path.

També podeu fer enrutament basat en el nom de domini (virtual hosts). Per exemple, podríeu tenir "api.example.com" que apunta a la vostra API, "admin.example.com" que apunta al panell d'administració, i "www.example.com" que apunta a l'aplicació principal. Tot això amb un sol Ingress Controller que escolta al port 80.

Una altra funcionalitat molt important dels Ingress és la terminació SSL/TLS. Això vol dir que podeu posar certificats HTTPS al vostre Ingress, i ell s'encarregarà de desxifrar el trànsit HTTPS abans d'enviar-lo als vostres serveis interns. Així, els vostres serveis poden funcionar simplement amb HTTP internament, i l'Ingress s'encarrega de la complexitat de HTTPS.

Els Ingress també poden fer redireccionaments, modificar capçaleres HTTP, aplicar autenticació bàsica, i moltes altres coses. La flexibilitat és immensa, especialment amb NGINX Ingress Controller que permet injectar configuració NGINX personalitzada mitjançant anotacions.

Per utilitzar Ingress al vostre clúster, primer heu d'instal·lar un Ingress Controller. Si esteu fent servir Minikube per practicar, això és tan senzill com executar la comanda "minikube addons enable ingress". En un clúster real, hauríeu d'instal·lar NGINX Ingress Controller seguint les instruccions oficials a https://kubernetes.github.io/ingress-nginx/


Preparant el nostre entorn de treball: instal·lació pas a pas

Abans de començar a treballar amb Kubernetes, necessitem tenir un entorn on practicar. La bona notícia és que no necessiteu un clúster de producció amb desenes de servidors per aprendre. Hi ha eines que us permeten executar un clúster complet de Kubernetes al vostre propi ordinador.

Minikube: el vostre clúster Kubernetes personal

La millor opció per aprendre Kubernetes és Minikube. Minikube és una eina que crea un clúster Kubernetes d'un sol node al vostre ordinador local. Tot funciona igual que en un clúster real, però en un entorn petit i controlat perfecte per aprendre i experimentar. Podeu instal·lar i desinstal·lar coses, fer proves, fins i tot trencar el clúster si cal, tot sense cap risc.

Per instal·lar Minikube en un sistema Ubuntu o Debian, primer haureu de descarregar l'executable. Obriu un terminal i executeu aquestes comandes:

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

La primera comanda descarrega Minikube, i la segona el instal·la al sistema de manera que podeu executar-lo des de qualsevol lloc. Un cop instal·lat, podeu iniciar el vostre clúster Kubernetes amb una sola comanda:

minikube start

Aquest procés pot trigar uns minuts la primera vegada perquè ha de descarregar la imatge del clúster Kubernetes. Quan acabi, tindreu un clúster Kubernetes complet funcionant al vostre ordinador. Podeu verificar que tot funciona executant:

minikube status

Això us mostrarà l'estat del clúster i hauria de dir que tot està "Running". Minikube també ve amb addons molt útils que podeu activar fàcilment. Per exemple, per activar l'Ingress Controller (que necessitarem més endavant), només cal executar:

minikube addons enable ingress

kubectl: la vostra eina de comandament

Minikube us crea el clúster, però per interactuar amb ell necessiteu kubectl (que es pronuncia "kube-control" o "kube-c-t-l"). Kubectl és la interfície de línia de comandes oficial de Kubernetes. És l'eina que utilitzareu per crear, modificar, eliminar i inspeccionar recursos al vostre clúster.

Per instal·lar kubectl, primer descarregueu l'executable de la versió que vulgueu. És important que la versió de kubectl sigui compatible amb la versió del vostre clúster. Com a regla general, kubectl pot estar una versió menor per sobre o per sota del vostre clúster. Si el vostre clúster és la versió 1.34, kubectl pot ser 1.33, 1.34 o 1.35.

curl -LO "https://dl.k8s.io/release/v1.34.0/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Un cop instal·lat, podeu verificar que funciona correctament:

kubectl version --client

Això us mostrarà la versió de kubectl que heu instal·lat. Per veure si pot connectar amb el vostre clúster, proveu:

kubectl get nodes

Aquesta comanda llista tots els nodes del vostre clúster. Amb Minikube només en tindreu un, que es dirà "minikube". Si veieu aquesta informació, vol dir que tot està configurat correctament i ja podeu començar a treballar.

La documentació oficial sobre com començar amb Minikube la trobareu a https://kubernetes.io/docs/tutorials/kubernetes-basics/ i les instruccions d'instal·lació de kubectl a https://kubernetes.io/docs/tasks/tools/


Posant en pràctica tot el que hem après: exemples pas a pas

Ara que ja tenim una comprensió sòlida dels conceptes bàsics i tenim el nostre entorn configurat, és hora de posar les mans a l'obra i veure com funciona tot això en la pràctica. Anem a començar amb un exemple senzill però complet: desplegar un servidor web NGINX.

Primer exemple pràctic: desplegant un servidor web NGINX

L'objectiu d'aquest exercici és desplegar un servidor web NGINX que tingui alta disponibilitat, és a dir, que estigui funcionant en múltiples rèpliques perquè si una falla, les altres continuïn servint. També volem que sigui accessible des de fora del clúster i que tingui monitoratge de salut automàtic.

Creant el Deployment

El primer pas és crear el Deployment que gestionarà els nostres pods. Creeu un fitxer nou anomenat nginx-deployment.yaml i obriu-lo amb el vostre editor de text preferit. Anem a construir aquest fitxer pas a pas, entenent cada part.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webserver-nginx
  labels:
    app: webserver
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webserver
  template:
    metadata:
      labels:
        app: webserver
    spec:
      containers:
      - name: nginx
        image: nginx:1.27-alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 15
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5

Analitzem aquest fitxer secció per secció. A dalt de tot indiquem que estem creant un recurs de tipus Deployment de la API apps/v1. Li donem el nom "webserver-nginx" i una etiqueta "app: webserver" que ens servirà per identificar-lo.

A la secció spec és on definim com volem que sigui aquest Deployment. Primer de tot, diem que volem 3 rèpliques. Això significa que Kubernetes crearà i mantindrà sempre 3 pods idèntics funcionant. Per què tres? És un bon nombre per començar: tens redundància (si un falla tens dos més), però no estàs gastant massa recursos.

El selector amb matchLabels és molt important. Diu: "aquest Deployment gestiona tots els pods que tinguin l'etiqueta app: webserver". Això és el que permet al Deployment saber quins pods ha de controlar.

La secció template defineix com seran els pods que el Deployment crearà. Primer els donem l'etiqueta "app: webserver" (que coincideix amb el selector que hem definit abans). Després especifiquem que cada pod tindrà un contenidor anomenat nginx que usa la imatge nginx:1.27-alpine. Hem triat la variant alpine perquè és més lleugera que la versió estàndard (ocupa menys espai i s'inicia més ràpid), però funciona exactament igual.

La secció de resources és crucial per a un entorn de producció. Aquí estem dient dues coses diferents: requests és la quantitat mínima de recursos que el pod necessita per funcionar (64Mi de memòria i 100m de CPU, on 100m és un dècim d'un core de CPU). Limits és el màxim que pot fer servir (128Mi de memòria i 200m de CPU). Kubernetes utilitza aquests valors per decidir on col·locar els pods i per assegurar que cap pod monopolitzi els recursos del node.

Les proves de salut són molt importants. livenessProbe comprova si el contenidor està viu. Si aquesta prova falla diverses vegades, Kubernetes reiniciarà el pod automàticament. En el nostre cas, estem dient: "fes una petició HTTP GET a la ruta / del port 80. Espera 15 segons després d'iniciar el contenidor abans de començar a comprovar, i després comprova cada 10 segons".

readinessProbe és similar, però serveix per saber si el pod està llest per rebre trànsit. Si aquesta prova falla, Kubernetes deixa d'enviar trànsit a aquest pod (però no el reinicia). Això és útil quan un pod necessita temps per inicialitzar-se o per carregar dades. En el nostre cas, començem a comprovar als 5 segons i ho fem cada 5 segons.

Podeu trobar més informació sobre com crear Deployments a https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/

Creant el Service per exposar l'aplicació

Ara que tenim el Deployment definit, necessitem una manera d'accedir als nostres pods. Aquí és on entra el Service. Creeu un segon fitxer anomenat nginx-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: webserver-service
spec:
  type: NodePort
  selector:
    app: webserver
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080

Aquest Service és més senzill que el Deployment. Li donem el nom "webserver-service" i especifiquem que serà de tipus NodePort, que com recordeu, obre un port en tots els nodes del clúster per permetre l'accés extern.

El selector "app: webserver" és la clau: aquest Service trobarà automàticament tots els pods que tinguin aquesta etiqueta i els enviarà trànsit. No hem hagut d'especificar IPs ni noms de pods, només l'etiqueta. Això és molt potent perquè significa que si escale el Deployment a 10 rèpliques, el Service automàticament començarà a enviar trànsit a totes les 10 sense que haguem de canviar res.

La secció de ports defineix tres valors diferents. El port 80 és el port en què el Service escolta dins del clúster. Altres aplicacions del clúster poden accedir al nostre servidor web fent una petició a "webserver-service:80". El targetPort 80 indica el port on els nostres pods escolten, que coincideix amb el containerPort que vam definir al Deployment. Finalment, nodePort 30080 és el port que s'obrirà en tots els nodes del clúster per permetre l'accés des de fora.

Desplegant tot al clúster

Ara que tenim els dos fitxers YAML preparats, és hora de desplegar-los al clúster. Obriu un terminal a la carpeta on heu guardat els fitxers i executeu aquestes comandes:

kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml

La comanda apply és molt versàtil: si el recurs no existeix, el crea, i si ja existeix, l'actualitza amb els canvis que hi hagueu fet. Hauríeu de veure missatges confirmant que el deployment i el service s'han creat.

Ara podem verificar que tot funciona correctament. Primer, mirem l'estat del Deployment:

kubectl get deployments

Això us mostrarà una llista dels deployments que teniu. Hauríeu de veure "webserver-nginx" amb 3/3 en la columna READY, que indica que les tres rèpliques estan funcionant correctament.

Per veure els pods individuals que s'han creat, executeu:

kubectl get pods -l app=webserver

L'opció -l app=webserver filtra els pods per etiqueta, així només veureu els pods del vostre servidor web. Hauríeu de veure tres pods amb noms com "webserver-nginx-xxxxxxxxxx-xxxxx". Els nombres del final són generats automàticament per Kubernetes.

Per veure el Service, executeu:

kubectl get services

Això us mostrarà el vostre service "webserver-service" amb el tipus NodePort i els ports configurats.

Accedint al servidor web

Ara ve la part emocionant: accedir al nostre servidor web. Si esteu usant Minikube, la manera més senzilla és executar:

minikube service webserver-service --url

Aquesta comanda us donarà una URL que podeu obrir al navegador per veure la pàgina de bienvenida de NGINX. El que fa Minikube per sota és crear un túnel des del vostre ordinador fins al clúster perquè pugueu accedir fàcilment.

Alternativament, podeu obtenir l'IP de Minikube amb "minikube ip" i després accedir directament a http://[IP_DE_MINIKUBE]:30080

Provant l'escalabilitat i l'auto-recuperació

Un dels grans avantatges de Kubernetes és la facilitat per escalar. Provem d'augmentar el nombre de rèpliques del nostre servidor web:

kubectl scale deployment webserver-nginx --replicas=5

Aquesta comanda li diu a Kubernetes que volem 5 rèpliques en lloc de 3. Si executeu immediatament "kubectl get pods -l app=webserver", veureu com Kubernetes està creant dos nous pods. Al cap de pocs segons, tindreu 5 pods funcionant, i el Service automàticament començarà a distribuir el trànsit entre els cinc.

També podem provar l'auto-recuperació. Seleccioneu el nom d'un dels pods (el podeu veure amb kubectl get pods) i elimine'l:

kubectl delete pod [nom-del-pod]

Si immediatament torneu a executar "kubectl get pods -l app=webserver", veureu alguna cosa interessant: un pod estarà en estat "Terminating" (s'està eliminant), però ja hi haurà un nou pod en estat "ContainerCreating" o "Running". Kubernetes ha detectat que un pod ha desaparegut i automàticament n'ha creat un de nou per mantenir les 5 rèpliques que hem demanat. Això és l'auto-recuperació en acció.


Segon exemple pràctic: configurant un proxy invers amb NGINX Ingress

Aquest exemple és especialment interessant perquè mostra com Kubernetes pot gestionar múltiples aplicacions web diferents accedint-hi totes pel mateix port però amb paths o dominis diferents. És exactament el que faríeu amb un servidor NGINX o Apache tradicional actuant com a proxy invers, però amb tota la potència i flexibilitat de Kubernetes.

Entenent què farem

L'objectiu és desplegar dues aplicacions web diferents al nostre clúster. Cada aplicació mostrarà una pàgina diferent per poder distingir-les fàcilment. Després configurarem un Ingress perquè puguin accedir a les dues aplicacions des del mateix domini però amb paths diferents. Per exemple, http://myapp.local/app1 mostrarà la primera aplicació i http://myapp.local/app2 mostrarà la segona.

Instal·lant l'NGINX Ingress Controller

Abans de poder utilitzar Ingress, necessitem instal·lar l'Ingress Controller. Recordeu que l'Ingress (el recurs que definirem després) és només la configuració, però necessitem el Controller que implementi aquesta configuració.

Si esteu usant Minikube, la instal·lació és extremadament senzilla:

minikube addons enable ingress

Això instal·la i configura automàticament l'NGINX Ingress Controller versió 1.11 o superior. Podeu verificar que s'ha instal·lat correctament executant:

kubectl get pods -n ingress-nginx

Hauríeu de veure diversos pods en el namespace "ingress-nginx", incloent el "ingress-nginx-controller". Quan aquest pod estigui en estat "Running", vol dir que l'Ingress Controller està llest per rebre trànsit.

Si no esteu usant Minikube, sinó un clúster real (baremet o al núvol), haureu d'instal·lar l'NGINX Ingress Controller manualment. La forma més directa és executar:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.2/deploy/static/provider/baremetal/deploy.yaml

Aquesta comanda descarrega i aplica tots els recursos necessaris per executar l'Ingress Controller. Trobareu tota la documentació oficial a https://kubernetes.github.io/ingress-nginx/

Desplegant la primera aplicació

Ara crearem la primera aplicació. Per fer-ho més interessant i visual, utilitzarem un ConfigMap per definir un HTML personalitzat. Creeu un fitxer anomenat app1-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: nginx
        image: nginx:1.27-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        configMap:
          name: app1-html
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app1-html
data:
  index.html: |
    <html>
      <head>
        <title>App 1</title>
        <style>
          body { font-family: Arial; text-align: center; padding: 50px; background-color: #e3f2fd; }
          h1 { color: #1976d2; }
        </style>
      </head>
      <body>
        <h1>Benvingut a l'Aplicació 1</h1>
        <p>Aquesta és la primera aplicació del nostre clúster Kubernetes</p>
      </body>
    </html>
---
apiVersion: v1
kind: Service
metadata:
  name: app1-service
spec:
  selector:
    app: app1
  ports:
  - port: 80
    targetPort: 80

Aquest fitxer defineix tres recursos alhora (separats per ---). Primer tenim el Deployment, que crea 2 rèpliques d'NGINX. La part interessant és el volumeMounts: estem muntant un volum anomenat "html" a la ruta /usr/share/nginx/html, que és on NGINX busca els fitxers HTML per defecte.

Aquest volum ve d'un ConfigMap anomenat "app1-html", que és el segon recurs que definim. Un ConfigMap és un recurs de Kubernetes que permet emmagatzemar dades de configuració, en aquest cas, el contingut del fitxer index.html. D'aquesta manera, podem canviar el contingut del nostre servidor web sense haver de crear una nova imatge de Docker.

Finalment, definim un Service de tipus ClusterIP (el tipus per defecte) que exposa els pods internament al clúster. Fixeu-vos que no especifiquem NodePort perquè no volem accedir directament a aquest servei des de fora, sinó a través de l'Ingress.

Desplegant la segona aplicació

Ara crearem la segona aplicació seguint el mateix patró. Creeu un fitxer app2-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app2-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app2
  template:
    metadata:
      labels:
        app: app2
    spec:
      containers:
      - name: nginx
        image: nginx:1.27-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        configMap:
          name: app2-html
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app2-html
data:
  index.html: |
    <html>
      <head>
        <title>App 2</title>
        <style>
          body { font-family: Arial; text-align: center; padding: 50px; background-color: #f3e5f5; }
          h1 { color: #7b1fa2; }
        </style>
      </head>
      <body>
        <h1>Benvingut a l'Aplicació 2</h1>
        <p>Aquesta és la segona aplicació del nostre clúster Kubernetes</p>
      </body>
    </html>
---
apiVersion: v1
kind: Service
metadata:
  name: app2-service
spec:
  selector:
    app: app2
  ports:
  - port: 80
    targetPort: 80

És pràcticament idèntic a l'aplicació 1, però amb etiquetes diferents (app: app2) i un HTML diferent amb altres colors perquè puguem distingir fàcilment quina aplicació estem veient.

Configurant l'Ingress: el cor del proxy invers

Ara ve la part més interessant: configurar l'Ingress que actuarà com a proxy invers. L'Ingress és el que rebrà totes les peticions HTTP externes i les redirigirà a l'aplicació corresponent segons el path de la URL. Creeu un fitxer anomenat ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.local
    http:
      paths:
      - path: /app1
        pathType: Prefix
        backend:
          service:
            name: app1-service
            port:
              number: 80
      - path: /app2
        pathType: Prefix
        backend:
          service:
            name: app2-service
            port:
              number: 80

Aquest Ingress és el cervell de la nostra configuració de proxy invers. Anem a entendre cada part detalladament.

A la secció de metadata, li donem el nom "multi-app-ingress" i afegim dues anotacions importants. L'anotació nginx.ingress.kubernetes.io/rewrite-target: / és crucial: diu a l'Ingress que quan redirigeix la petició al servei, ha de reescriure el path a /. Això significa que una petició a /app1/index.html es converteix en /index.html quan arriba al nostre servei. Sense això, NGINX buscaria el fitxer a /app1/index.html dins del contenidor, que no existeix.

L'anotació nginx.ingress.kubernetes.io/ssl-redirect: "false" desactiva la redirecció automàtica de HTTP a HTTPS. Per defecte, NGINX Ingress Controller intenta forçar HTTPS, però com que estem fent proves locals sense certificats SSL, desactivem aquesta funcionalitat.

L'ingressClassName: nginx especifica quin Ingress Controller ha de processar aquest Ingress. Això és important si teniu múltiples Ingress Controllers instal·lats al clúster.

La secció rules és on definim les regles d'enrutament. Primer especifiquem un host: "myapp.local". Això significa que l'Ingress només processarà peticions que tinguin aquest host en la capçalera HTTP. Després definim els paths: qualsevol petició a /app1 (i tot el que comenci per aquest path, gràcies a pathType: Prefix) s'enviarà al servei "app1-service" al port 80. Igualment, les peticions a /app2 s'enviaran a "app2-service".

Desplegant tots els components

Ara que tenim tots els fitxers preparats, és hora de desplegar-ho tot al clúster. Executeu aquestes comandes en ordre:

kubectl apply -f app1-deployment.yaml
kubectl apply -f app2-deployment.yaml
kubectl apply -f ingress.yaml

Cadascuna d'aquestes comandes crearà múltiples recursos (Deployment, ConfigMap i Service per a cada aplicació, i l'Ingress). Podeu verificar que tot s'ha creat correctament:

kubectl get deployments
kubectl get services
kubectl get ingress

Quan executeu "kubectl get ingress", veureu el vostre Ingress "multi-app-ingress". A la columna ADDRESS hauria d'aparèixer una IP (pot trigar uns segons). Això vol dir que l'Ingress Controller ha processat el recurs i està llest per rebre trànsit.

Per veure més detalls sobre l'Ingress, executeu:

kubectl describe ingress multi-app-ingress

Això us mostrarà tota la configuració, incloent les regles d'enrutament que hem definit. És molt útil per depurar si alguna cosa no funciona com s'esperava.

Configurant l'accés local

Perquè puguem accedir a les nostres aplicacions usant el domini "myapp.local", hem de configurar el nostre ordinador perquè sàpiga que aquest domini apunta al nostre clúster Kubernetes. Això es fa editant el fitxer /etc/hosts (en Linux i Mac) o C:\Windows\System32\drivers\etc\hosts (en Windows).

Primer, necessitem saber quina IP té el nostre clúster. Si esteu usant Minikube, obteniu-la amb:

minikube ip

Això us donarà una IP com ara 192.168.49.2 (la vostra pot ser diferent). Ara heu d'editar el fitxer hosts. En Linux o Mac, obriu un terminal i executeu:

sudo nano /etc/hosts

Afegiu una línia al final del fitxer:

192.168.49.2 myapp.local

Recordeu substituir la IP per la que us hagi donat "minikube ip". Guardeu el fitxer i sortiu de l'editor (a nano, Ctrl+O per guardar, Ctrl+X per sortir).

Provant el nostre proxy invers

Ara ve el moment de la veritat: comprovar que tot funciona correctament. Obriu un navegador web i aneu a:

http://myapp.local/app1

Hauríeu de veure la pàgina amb fons blau que diu "Benvingut a l'Aplicació 1". Ara aneu a:

http://myapp.local/app2

I hauríeu de veure una pàgina amb fons lila que diu "Benvingut a l'Aplicació 2".

El que està passant per sota és fascinant: el vostre navegador fa una petició HTTP al domini "myapp.local", que el vostre fitxer hosts redirigeix a la IP del clúster Minikube. L'Ingress Controller d'NGINX rep aquesta petició, mira el host i el path, i segons les regles que hem definit a l'Ingress, redirigeix la petició al servei corresponent (app1-service o app2-service). Aquest servei distribueix la petició entre les rèpliques disponibles (en tenim 2 de cada), i finalment un dels pods processa la petició i retorna el HTML que veieu al navegador.

També podeu provar les aplicacions des de la línia de comandes amb curl:

curl http://myapp.local/app1
curl http://myapp.local/app2

Hauríeu de veure el codi HTML de cada aplicació.

Podeu trobar tota la documentació sobre Ingress a https://kubernetes.io/docs/concepts/services-networking/ingress/ i sobre NGINX Ingress Controller a https://kubernetes.github.io/ingress-nginx/


Tercer exemple: enrutament basat en dominis (Virtual Hosts)

L'exemple anterior ens ha mostrat com enrutar segons el path de la URL, però hi ha una altra manera molt potent d'organitzar les vostres aplicacions: usant dominis diferents per a cada aplicació. Això és el que tradicionalment s'anomena virtual hosts en servidors web com Apache o NGINX.

La idea és senzilla: en lloc de tenir /app1 i /app2 al mateix domini, tindríem app1.local i app2.local, cada un apuntant a la seva aplicació. Això té avantatges: cada aplicació pot tenir la seva pròpia configuració SSL, les URLs són més netes (no cal el prefix), i és més fàcil de gestionar si teniu moltes aplicacions diferents.

Podem reutilitzar els mateixos deployments i services que vam crear a l'exemple anterior. L'únic que canviarà és la configuració de l'Ingress. Creeu un fitxer anomenat ingress-vhosts.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: virtual-host-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  ingressClassName: nginx
  rules:
  - host: app1.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app1-service
            port:
              number: 80
  - host: app2.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app2-service
            port:
              number: 80

La diferència clau és que ara tenim dues regles diferents, una per a cada host. La primera regla diu: "quan rebi una petició per al host app1.local, independentment del path, envia-la a app1-service". La segona regla fa el mateix per a app2.local i app2-service.

Fixeu-vos que el path ara és simplement /, que vol dir "qualsevol path". També hem eliminat l'anotació de rewrite-target perquè ja no és necessària: les peticions arriben directament amb el path que han de tenir.

Per utilitzar aquesta configuració, primer elimineu l'Ingress anterior si encara el teniu:

kubectl delete ingress multi-app-ingress

I després despleg

ueu el nou:

kubectl apply -f ingress-vhosts.yaml

Ara heu d'actualitzar el vostre fitxer /etc/hosts per incloure els dos nous dominis:

192.168.49.2 app1.local
192.168.49.2 app2.local

Podeu provar-ho ara visitant http://app1.local i http://app2.local al vostre navegador. Veureu que cada domini mostra la seva aplicació corresponent, i no cal especificar cap path.


Quart exemple: afegint HTTPS amb certificats SSL/TLS

Fins ara hem estat treballant només amb HTTP, però en un entorn de producció segurament voldreu HTTPS. L'Ingress de Kubernetes fa que afegir HTTPS sigui relativament senzill. El que farem és crear un certificat SSL (en aquest cas autosignat, només per a proves), emmagatzemar-lo en un Secret de Kubernetes, i configurar l'Ingress per utilitzar-lo.

Creant el certificat SSL

Primer, generarem un certificat autosignat usant OpenSSL. Aquest certificat només és vàlid per a proves locals, en producció hauríeu d'usar un certificat real d'una autoritat de certificació com Let's Encrypt. Executeu aquesta comanda:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=myapp.local/O=myapp"

Aquesta comanda crea dos fitxers: tls.key (la clau privada) i tls.crt (el certificat). Els paràmetres indiquen que volem un certificat X.509 autosignat (-x509), sense contrasenya (-nodes), vàlid durant 365 dies, amb una clau RSA de 2048 bits, i per al domini myapp.local.

Ara hem de crear un Secret de Kubernetes que contingui aquests fitxers. Un Secret és un recurs especial que emmagatzema dades sensibles de forma segura:

kubectl create secret tls myapp-tls --cert=tls.crt --key=tls.key

El tipus de secret tls és específic per a certificats SSL/TLS. Podeu verificar que s'ha creat correctament amb:

kubectl get secrets

Configurant l'Ingress amb TLS

Ara crearem un nou Ingress que utilitzi aquest certificat. Creeu un fitxer ingress-tls.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.local
    secretName: myapp-tls
  rules:
  - host: myapp.local
    http:
      paths:
      - path: /app1
        pathType: Prefix
        backend:
          service:
            name: app1-service
            port:
              number: 80
      - path: /app2
        pathType: Prefix
        backend:
          service:
            name: app2-service
            port:
              number: 80

La secció tls és la novetat aquí. Indica que per als hosts llistats (en aquest cas myapp.local), l'Ingress ha d'utilitzar el certificat SSL emmagatzemat al Secret "myapp-tls". També hem afegit l'anotació force-ssl-redirect: "true", que fa que qualsevol petició HTTP es redirigeixi automàticament a HTTPS.

Desplegeu aquest Ingress:

kubectl delete ingress virtual-host-ingress  # Si el teniu del pas anterior
kubectl apply -f ingress-tls.yaml

Ara podeu accedir a les vostres aplicacions via HTTPS:

curl -k https://myapp.local/app1

L'opció -k indica a curl que ignori els errors de certificat (necessària perquè estem usant un certificat autosignat que el navegador no confia). Si obriu https://myapp.local/app1 al navegador, probablement veureu un avís de seguretat dient que el certificat no és de confiança. Això és normal amb certificats autosignats; en producció usaríeu un certificat real i aquest avís no apareixeria.

Podeu veure tota la documentació sobre TLS a Ingress a https://kubernetes.io/docs/concepts/services-networking/ingress/#tls


Comandes essencials de kubectl que utilitzareu dia a dia

Quan treballeu amb Kubernetes, passareu molt de temps utilitzant kubectl. És la vostra eina per interactuar amb el clúster, i conèixer bé les comandes més comunes us farà molt més eficients. Anem a repassar les comandes que utilitzareu constantment.

Consultant l'estat dels recursos

La comanda més bàsica i que probablement executareu més vegades és kubectl get. Aquesta comanda us mostra una llista de recursos del tipus que especifiqueu. Per exemple, per veure tots els pods del vostre clúster, simplement executeu kubectl get pods. Això us dona una vista de tots els pods, amb el seu nom, si estan en estat Running o no, quantes vegades s'han reiniciat, i quant de temps fa que estan funcionant.

De vegades voldreu més informació sobre els pods. En aquests casos, podeu afegir l'opció -o wide que us mostra detalls addicionals com la IP del pod i en quin node s'està executant. També podeu filtrar els resultats per etiquetes, cosa que és molt útil quan teniu molts recursos. Per exemple, kubectl get pods -l app=nginx només us mostrarà els pods que tinguin l'etiqueta "app=nginx".

També podeu consultar altres tipus de recursos canviant "pods" per "deployments", "services", "ingress", o qualsevol altre tipus de recurs. Fins i tot podeu usar "all" per veure pods, services i deployments alhora.

Obtenint informació detallada

Quan veieu que alguna cosa no funciona correctament, la comanda kubectl describe és la vostra millor amiga. Aquesta comanda us dona una descripció completa d'un recurs específic, incloent tots els seus detalls de configuració, el seu estat actual, i molt important, els esdeveniments recents relacionats amb aquest recurs.

Per exemple, si teniu un pod que no s'inicia correctament, podeu executar kubectl describe pod [nom-del-pod] i obtindreu molta informació valuosa. Veureu per què el pod no pot iniciar-se, si hi ha problemes descarregant la imatge, si no hi ha prou recursos al node, si hi ha errors en la configuració, etc. Els esdeveniments al final de la sortida solen ser especialment útils perquè mostren què ha estat passant amb el recurs en ordre cronològic.

Consultant els logs

Els logs són fonamentals per entendre què està passant dins dels vostres contenidors. La comanda kubectl logs [nom-del-pod] us mostra tots els logs que el contenidor ha escrit a la sortida estàndard. Si el pod té múltiples contenidors, haureu d'especificar quin contenidor voleu amb l'opció -c [nom-del-contenidor].

Una opció molt útil és -f (follow), que funciona com la comanda tail -f de Linux: mostra els logs en temps real a mesura que es generen. Això és perfecte quan esteu depurant un problema i voleu veure exactament què està fent l'aplicació en cada moment. Executeu kubectl logs -f [nom-del-pod] i veureu els logs actualitzant-se en directe.

Executant comandes dins dels pods

De vegades necessiteu entrar dins d'un pod per inspeccionar-lo, executar comandes, o simplement explorar què hi ha. La comanda kubectl exec us ho permet. Per exemple, kubectl exec -it [nom-del-pod] -- /bin/bash us dona una shell interactiva dins del contenidor. L'opció -i fa la sessió interactiva, i -t assigna un terminal.

Un cop dins, podeu executar qualsevol comanda que estigui disponible al contenidor. Això és molt útil per depurar problemes, comprovar configuracions, o fins i tot provar coses manualment abans d'automatitzar-les.

Copiant fitxers

Amb kubectl cp podeu copiar fitxers des del vostre ordinador local cap a un pod o viceversa. Per copiar un fitxer local al pod, executeu kubectl cp fitxer-local [nom-del-pod]:/path/dins/pod. Per copiar del pod al vostre ordinador, invertiu l'ordre: kubectl cp [nom-del-pod]:/path/dins/pod fitxer-local. Això és molt útil per extreure logs, bases de dades de desenvolupament, o pujar fitxers de configuració.

Accedint directament a un pod

Si voleu accedir a un servei que està executant-se dins d'un pod sense haver de configurar un Service o un Ingress, podeu usar port forwarding. La comanda kubectl port-forward pod/[nom-del-pod] 8080:80 redirigeix el port 8080 del vostre ordinador local al port 80 del pod. Després podeu obrir http://localhost:8080 al vostre navegador i accedir directament al servei que corre dins del pod. Això és especialment útil per a debugging.

Eliminant recursos

Quan voleu eliminar recursos, teniu diverses opcions. Podeu eliminar un recurs específic amb kubectl delete pod [nom-del-pod], o podeu eliminar tots els recursos definits en un fitxer YAML amb kubectl delete -f fitxer.yaml. També podeu eliminar per etiqueta, per exemple kubectl delete pods -l app=test eliminaria tots els pods amb l'etiqueta "app=test".

Informació del clúster

Per veure informació general sobre el vostre clúster, podeu usar kubectl cluster-info, que us mostra les URLs dels serveis principals del clúster. Per veure els nodes que formen part del clúster, executeu kubectl get nodes, que us mostrarà tots els nodes amb el seu estat, versió de Kubernetes, i altres detalls bàsics.


Bones pràctiques per treballar amb Kubernetes

A mesura que aneu treballant amb Kubernetes, us adonareu que hi ha maneres millors i pitjors de fer les coses. Aquí us explico algunes pràctiques recomanades que us estalviaran molts problemes a llarg termini.

Especificant versions concretes de les imatges

Quan definiu un contenidor, podeu sentir-vos temptats a usar l'etiqueta "latest" per la imatge, pensant que així sempre tindreu la versió més recent. Però això és una mala idea en la majoria de casos. El problema és que "latest" pot canviar en qualsevol moment, i això pot fer que el vostre Deployment es trenqui sense que hagueu canviat res al vostre codi.

Imagineu que desplegeu avui amb nginx:latest i tot funciona perfectament. Demà, els desenvolupadors de NGINX llancen una nova versió amb canvis importants. Si Kubernetes necessita recrear un pod (per exemple, perquè un node ha fallat), descarregarà aquesta nova versió i el vostre pod pot deixar de funcionar correctament. Com que vosaltres no heu canviat res, serà molt difícil de depurar.

Per això, és molt millor especificar versions concretes, com nginx:1.27. D'aquesta manera, sabeu exactament quina versió esteu executant, i els pods es recreen sempre amb la mateixa versió. Quan volgueu actualitzar, ho feu conscientemente, canviant el número de versió i testejant els canvis.

Definint límits de recursos

Cada pod hauria de tenir definits els seus límits de CPU i memòria. Això pot semblar una complicació innecessària quan comenceu, però és crucial per a la estabilitat del clúster. Sense límits, un pod defectuós podria monopolitzar tots els recursos d'un node i afectar altres aplicacions.

Hi ha dos tipus de valors que podeu definir: requests i limits. Els requests són els recursos mínims que el pod necessita per funcionar correctament. Kubernetes usa aquests valors per decidir on col·locar el pod. Si cap node té prou recursos disponibles per satisfer els requests, el pod no es desplegarà fins que s'alliberin recursos.

Els limits són el màxim que el pod pot utilitzar. Si un pod intenta utilitzar més CPU del límit, Kubernetes l'estrangularà (el farà anar més lent). Si intenta utilitzar més memòria del límit, Kubernetes matarà el contenidor i el reiniciarà. Això pot semblar dur, però és millor que permetre que un sol pod es mengi tota la memòria del node.

Utilitzant health checks

Els health checks són proves que Kubernetes executa periòdicament per saber si els vostres pods estan funcionant correctament. Hi ha dos tipus principals: liveness probes i readiness probes.

La liveness probe (prova de vida) comprova si el contenidor està viu. Si aquesta prova falla repetidament, Kubernetes assumeix que el contenidor s'ha penjat i el reinicia. Això és útil per recuperar-se de situacions on l'aplicació entra en un estat corrupte del qual no pot sortir sola.

La readiness probe (prova de preparació) comprova si el pod està llest per rebre trànsit. És important perquè algunes aplicacions necessiten temps per inicialitzar-se: poden necessitar carregar dades de la base de dades, escalfar cachés, o fer altres tasques abans d'estar llestes per servir peticions. Durant aquest temps, el pod està funcionant (passa la liveness probe) però no hauria de rebre trànsit encara. Si la readiness probe falla, Kubernetes temporalment deixa d'enviar trànsit a aquest pod, però no el reinicia.

Organitzant amb namespaces

Els namespaces són una manera de dividir el vostre clúster en entorns virtuals separats. Per defecte, tots els recursos es creen al namespace "default", però podeu crear els vostres propis namespaces per organitzar millor les coses.

Per exemple, podríeu tenir un namespace "development" per a proves, un "staging" per a testing pre-producció, i un "production" per a l'entorn real. Dins de cada namespace, podeu tenir policies de xarxa diferents, límits de recursos diferents, i permisos d'accés diferents. Això ajuda a mantenir les coses organitzades i evitar accidents com esborrar accidentalment recursos de producció quan pensàveu que estàveu a development.

Gestionant secrets de forma segura

Mai, mai, mai poseu contrasenyes o altres dades sensibles directament als fitxers YAML del vostre codi. És una pràctica de seguretat terrible que pot tenir conseqüències greus. En comptes d'això, utilitzeu els Secrets de Kubernetes, que són recursos específics per emmagatzemar informació sensible.

Els Secrets es poden crear des de fitxers o amb la línia de comandes, i després els vostres pods hi poden accedir muntant-los com a volums o com a variables d'entorn. Kubernetes emmagatzema els Secrets de forma xifrada (en versions recents) i només els proporciona als pods que realment els necessiten.

Usant etiquetes consistents

Les etiquetes són la manera principal d'organitzar i seleccionar recursos a Kubernetes. És important usar-les de forma consistent. Per exemple, podríeu tenir sempre una etiqueta "app" que identifica l'aplicació, una etiqueta "environment" que diu si és dev, staging o production, i una etiqueta "version" per indicar la versió.

Amb etiquetes ben definides, podeu fer consultes molt potents com "mostra'm tots els pods de l'aplicació web que estiguin en l'entorn de producció", o "elimina tots els recursos de la versió antiga que ja no necessitem".

Documentant els fitxers YAML

Els fitxers YAML admeten comentaris, i hauríeu d'usar-los generosament. Quan torneu a mirar un fitxer després de sis mesos, us agraireu haver escrit comentaris explicant per què vau configurar alguna cosa d'una manera particular. És especialment important documentar decisions que poden no ser òbvies, com valors específics de recursos o anotacions especials.

Separant configuració i codi

Les bones pràctiques de desenvolupament modernes diuen que la configuració hauria d'estar separada del codi. A Kubernetes, això es fa amb ConfigMaps. En lloc de codificar en dur valors de configuració a la vostra imatge de Docker, els poseu en un ConfigMap que podeu canviar fàcilment sense haver de reconstruir la imatge.

Per exemple, si la vostra aplicació necessita saber la URL de la base de dades, poseu aquesta URL en un ConfigMap. D'aquesta manera, podeu tenir el mateix codi funcionant en diferents entorns només canviant el ConfigMap.


Recursos addicionals per aprofundir

Documentació oficial

Eines i ecosistema

  • Helm: Gestor de paquets per Kubernetes
  • Kustomize: Personalització de configuracions YAML
  • Lens: IDE gràfic per treballar amb Kubernetes
  • K9s: Terminal UI per gestionar clústers

Monitoratge i observabilitat

  • Prometheus: Sistema de monitoratge
  • Grafana: Visualització de mètriques
  • ELK Stack: Agregació de logs (Elasticsearch, Logstash, Kibana)

Certificacions

  • Certified Kubernetes Administrator (CKA)
  • Certified Kubernetes Application Developer (CKAD)

Referències

Tota la informació d'aquest document ha estat extreta i verificada de les següents fonts oficials:

  1. Kubernetes Official Blog:
  2. https://kubernetes.io/blog/2025/08/27/kubernetes-v1-34-release/
  3. https://kubernetes.io/blog/2025/04/23/kubernetes-v1-33-release/

  4. Kubernetes Official Documentation:

  5. https://kubernetes.io/docs/concepts/
  6. https://kubernetes.io/docs/concepts/workloads/pods/
  7. https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
  8. https://kubernetes.io/docs/concepts/services-networking/service/
  9. https://kubernetes.io/docs/concepts/services-networking/ingress/

  10. Kubernetes Release Information:

  11. https://kubernetes.io/releases/
  12. https://endoflife.date/kubernetes

  13. Arquitectura i tutorials:

  14. https://devopscube.com/kubernetes-architecture-explained/
  15. https://kubernetes.io/docs/tutorials/kubernetes-basics/

  16. NGINX Ingress Controller:

  17. https://kubernetes.github.io/ingress-nginx/
  18. https://github.com/kubernetes/ingress-nginx

Exercicis proposats per a pràctiques

Exercici 1: Bàsic

  1. Desplega un servidor web NGINX amb 2 rèpliques
  2. Exposa'l mitjançant un Service de tipus NodePort
  3. Accedeix al servei des del navegador
  4. Escala el deployment a 4 rèpliques

Exercici 2: Intermedi

  1. Crea dues aplicacions web diferents
  2. Configura un Ingress per enrutar tràfic segons el path (/app1, /app2)
  3. Configura health checks per a ambdues aplicacions
  4. Simula una caiguda d'un pod i observa com Kubernetes el recupera

Exercici 3: Avançat

  1. Desplega una aplicació web amb base de dades
  2. Configura Persistent Volumes per a la base de dades
  3. Implementa Ingress amb TLS
  4. Configura límits de recursos i monitoritza l'ús
  5. Implementa una estrategia de rolling update