Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DevOps

Introducció

Tradicionalment, les empreses de programari tenien dos equips separats: els desenvolupadors (Dev), que escrivien codi i volien publicar funcionalitats noves ràpidament, i els d’operacions (Ops), que gestionaven els servidors i volien estabilitat. Aquests dos equips sovint treballaven en contra:

  • Dev llençava codi “per sobre del mur” a Ops, que havia de fer-lo funcionar en producció.
  • Ops rebutjava canvis perquè cada desplegament era un risc d’inestabilitat.
  • Els desplegaments es feien manualment, de nit, i amb por.

DevOps és la cultura i el conjunt de pràctiques que elimina aquest mur. L’objectiu és que el cicle entre escriure codi i tenir-lo funcionant en producció sigui ràpid, automatitzat i fiable.

La metodologia Twelve-Factor App defineix dotze principis per construir aplicacions preparades per a aquest model de treball:

  1. Codebase — un codi font, molts desplegaments
  2. Dependencies — declarar i aïllar les dependències
  3. Config — configuració a l’entorn
  4. Backing services — serveis com a recursos connectables
  5. Build, release, run — separar compilació, publicació i execució
  6. Processes — processos sense estat
  7. Port binding — exportar serveis per port
  8. Concurrency — escalar amb processos
  9. Disposability — inici ràpid i aturada elegant
  10. Dev/prod parity — entorns similars
  11. Logs — tractats com a fluxos d’esdeveniments
  12. Admin processes — tasques d’administració com a processos puntuals

Aquests principis s’organitzen naturalment en cinc àrees, que segueixen el cicle de vida d’una aplicació: des de com s’organitza el codi fins a com es manté en producció.

Principis de disseny

A continuació es desenvolupen els dotze factors agrupats en cinc àrees. Cada àrea representa una etapa del cicle: preparar el codi, fer-lo portable, lliurar-lo, executar-lo i operar-lo.

Codi i dependències

Factors I i II

Abans de pensar en servidors o desplegaments, cal que el codi font estigui ben organitzat. Aquests dos principis estableixen la base: un repositori clar i unes dependències que no deixin res a l’atzar.

Codebase

Cada aplicació té un únic repositori de codi font (per exemple, un repositori Git). A partir d’aquest repositori es generen múltiples desplegaments: desenvolupament, staging, producció.

Què passa si no ho fem així?

  • Si dues aplicacions comparteixen el mateix repositori, un canvi en una pot trencar l’altra.
  • Si una aplicació té múltiples repositoris, és difícil saber quina versió del codi s’està executant.
  • Si hi ha codi compartit entre aplicacions, s’ha d’extreure com a llibreria independent amb el seu propi versionat.

Dependencies

Totes les dependències s’han de declarar explícitament en un fitxer del projecte (pom.xml, package.json, requirements.txt…). Mai s’ha de dependre de paquets instal·lats globalment al sistema.

Sense dependències explícites:

  • “A la meva màquina funciona!” — però al servidor de producció falta una llibreria que tenies instal·lada sense saber-ho.
  • Un company clona el projecte i no li funciona perquè té una versió diferent de Java.
  • Actualitzes una dependència global i, de cop, tres projectes deixen de funcionar.

Amb dependències explícites, qualsevol persona (o màquina) pot reconstruir l’entorn exacte de l’aplicació des de zero.

Configuració i serveis externs

Factors III i IV

Un cop tenim el codi i les dependències controlades, el següent problema és: com fem que la mateixa aplicació funcioni en entorns diferents (la teva màquina, un servidor de proves, producció) sense haver de modificar el codi?

Config

La configuració que varia entre desplegaments s’ha d’emmagatzemar en variables d’entorn, mai dins del codi font. Exemples de configuració:

  • Credencials de base de dades (DB_HOST, DB_PASSWORD)
  • URLs de serveis externs (API_URL)
  • Claus d’API (EMAIL_API_KEY)
  • Mode de funcionament (DEBUG=true, LOG_LEVEL=info)

Un bon test: el codi font es podria fer públic en qualsevol moment sense comprometre cap credencial? Si la resposta és no, hi ha configuració que no hauria d’estar al codi.

L’alternativa — fitxers de configuració com config.prod.properties al repositori — és problemàtica: és fàcil cometre errors pujant credencials a Git, i cada entorn nou requereix un fitxer nou.

Backing services

Els serveis auxiliars (bases de dades, cues de missatges, serveis de correu, sistemes de cache) es tracten com a recursos connectables. Per a l’aplicació, no hi ha diferència entre una base de dades PostgreSQL local i una al núvol: només canvia la URL de connexió.

Això vol dir que canviar de proveïdor (per exemple, de MySQL a PostgreSQL, o d’un SMTP local a un servei extern) hauria de requerir només un canvi de configuració (una variable d’entorn), no un canvi de codi.

Aquesta idea connecta directament amb el factor anterior: si la configuració està a l’entorn, connectar un servei diferent és trivial.

Pipeline de lliurament

Factors V i X

Ara que el codi és portable (no depèn de l’entorn), necessitem un procés clar i repetible per portar-lo del repositori fins a producció. Aquí és on DevOps es diferencia més del model tradicional: en lloc de desplegaments manuals i arriscats, el lliurament és un pipeline automatitzat.

Build, release, run

El desplegament es divideix en tres etapes estrictes que mai s’han de barrejar:

  1. Build: compilar el codi i les dependències en un artefacte executable (un JAR, una imatge Docker, un bundle JavaScript…).
  2. Release: combinar l’artefacte amb la configuració de l’entorn concret. Cada release té un identificador únic (un timestamp, un hash de commit, un número de versió).
  3. Run: executar la release a l’entorn de destí.

Per què separar-les? Perquè si algú edita codi directament al servidor de producció (saltant-se el build), no hi ha manera de saber què s’està executant, ni de tornar enrere si alguna cosa falla. La separació garanteix traçabilitat i reproduïbilitat.

Dev/prod parity

Els entorns de desenvolupament, staging i producció han de ser tan semblants com sigui possible. Les diferències entre entorns són una font habitual de problemes:

  • Desenvolupes amb SQLite però producció utilitza PostgreSQL → consultes SQL que fallen.
  • A la teva màquina el sistema de fitxers no distingeix majúscules, però a Linux sí → fitxers no trobats.
  • Proves amb dades petites localment, però en producció les consultes són lentes amb milions de registres.

Docker i la infraestructura com a codi (Infrastructure as Code) permeten replicar l’entorn de producció localment, reduint aquestes sorpreses.

Execució i escalabilitat

Factors VI, VII i VIII

L’aplicació ja és al servidor. Com s’executa? I què passa quan un sol servidor no és suficient per atendre tota la demanda? Aquests principis defineixen com dissenyar aplicacions que puguin créixer.

Processes

L’aplicació s’executa com un o més processos sense estat (stateless). Això vol dir que el procés no guarda res entre peticions: qualsevol dada que hagi de persistir va a un backing service (base de dades, cache, etc.).

Per què és important? Imagina una botiga en línia on l’usuari afegeix productes al carretó. Si el carretó es guarda a la memòria del procés:

  • Si el procés es reinicia, l’usuari perd el carretó.
  • Si hi ha dos processos (per repartir la càrrega), l’usuari pot veure el carretó en un i no en l’altre.

Si el carretó es guarda a una base de dades o a Redis, qualsevol procés pot servir qualsevol petició. Això és la base de l’escalabilitat horitzontal.

Port binding

L’aplicació és autocontinguda i exposa els seus serveis a través d’un port de xarxa. No depèn d’un servidor web extern per funcionar.

En el model tradicional, desplegaves un fitxer WAR dins d’un Tomcat compartit amb altres aplicacions. Amb port binding, cada aplicació inclou el seu propi servidor HTTP (Tomcat embegut, Express, Uvicorn…) i escolta en un port. Això simplifica el desplegament i l’aïllament entre aplicacions.

Concurrency

Quan l’aplicació necessita gestionar més càrrega, hi ha dues estratègies:

  • Escalar verticalment: posar un servidor més gran (més CPU, més RAM). Té un límit físic i és car.
  • Escalar horitzontalment: executar múltiples instàncies de l’aplicació. No té límit pràctic si l’aplicació és stateless.

A més, cada tipus de treball pot escalar independentment: pots tenir 10 processos servint peticions web però només 2 processant tasques en segon pla.

Operació i robustesa

Factors IX, XI i XII

L’aplicació funciona en producció. Ara cal garantir que sigui observable (podem saber què passa), robusta (resisteix errors) i mantenible (podem fer canvis operacionals sense parar-la).

Disposability

Els processos s’han de poder iniciar en segons i aturar de forma elegant (graceful shutdown): completant les peticions en curs i alliberant recursos abans de tancar-se.

Per què importa?

  • Desplegaments: cada vegada que publiques una nova versió, els processos antics s’aturen i els nous s’inicien. Si triga minuts, el desplegament és lent i arriscat.
  • Escalat elàstic: si arriba un pic de tràfic, necessites instàncies noves ara, no d’aquí 5 minuts.
  • Robustesa: si un procés falla, el sistema el pot reiniciar immediatament sense impacte visible.

Logs

L’aplicació ha d’escriure els events com un flux i no preocupar-se de on acaben: ni gestionar fitxers, ni rotacions, ni emmagatzematge. L’entorn d’execució s’encarrega de recollir, agregar i emmagatzemar els logs.

Això no vol dir utilitzar print. Cal distingir dues decisions diferents:

  • Com escriure logs (decisió de codi): utilitzar un logger (logging en Python, java.util.logging en Java) en lloc de print. El logger dóna estructura, nivells (DEBUG, INFO, ERROR), format consistent i context (timestamp, nom del mòdul).
  • On van els logs (decisió de desplegament): el logger es pot configurar per escriure a consola, a fitxer, o a tots dos. El factor XI diu que en producció, especialment amb contenidors, la sortida hauria d’anar a stdout i deixar que l’entorn els gestioni.

Per què no escriure directament a fitxers en producció?

  • Si tens 10 instàncies de l’aplicació, tens 10 fitxers de log en 10 màquines diferents. Com els consultes de manera unificada?
  • Qui gestiona la rotació dels fitxers perquè no omplin el disc?
  • Com busques un error que va passar ahir a les 3 de la matinada?

Amb logs a stdout, eines com ELK Stack o Loki els recullen automàticament, els indexen i permeten buscar-hi. En desenvolupament local, en canvi, és perfectament raonable configurar el logger perquè escrigui també a un fitxer.

Admin processes

Les tasques d’administració (migracions de base de dades, scripts de correcció de dades, consola interactiva) s’han d’executar com a processos puntuals (one-off), utilitzant el mateix codi i la mateixa configuració que l’aplicació en producció.

Això vol dir: no connectar-se per SSH al servidor i executar SQL directament a la base de dades. En lloc d’això, escriure un script de migració que formi part del codi, estigui versionat al repositori, i s’executi com un procés més.

Aplicació dels principis

Els dotze factors són principis de disseny. Aplicar-los a la pràctica requereix eines concretes i processos ben definits. Aquesta secció segueix el cicle de vida d’una aplicació en quatre etapes: gestionar el codi amb Git, empaquetar-lo en un entorn portable amb Docker, automatitzar el seu lliurament amb pipelines de CI/CD, i operar-lo en producció amb observabilitat.

Gestió del codi

Codebase

Git implementa directament el primer factor: els diferents desplegaments (desenvolupament, staging, producció) es gestionen amb branques i etiquetes dins d’un únic repositori, no amb còpies de carpetes.

Build, release, run

Git proporciona identificadors únics per a cada release. Un commit hash (a3f8b21) o una etiqueta (v1.2.3) identifiquen exactament quin codi es va construir i desplegar:

git tag -a v1.2.3 -m "Release 1.2.3: fix login timeout" git push origin v1.2.3

Això permet saber sempre què s’executa en producció i tornar enrere si cal (git checkout v1.2.2). Sense aquest versionat, la pregunta “quin codi hi ha desplegat?” no té resposta clara.

Config

El fitxer .gitignore és la primera línia de defensa per mantenir la configuració fora del codi. Fitxers com .env, credentials.json o config.local.properties mai han d’arribar al repositori:

.env *.local.properties credentials/

Si un secret es puja accidentalment a Git, queda a l’historial per sempre (fins i tot si s’esborra al commit següent). Per això és crític ignorar-los des del principi.

Admin processes

Els scripts d’administració (migracions, correccions de dades, tasques de manteniment) han de formar part del repositori, al costat del codi de l’aplicació. Això garanteix que:

  • Estan versionats: es pot saber quina migració es va aplicar i quan.
  • Són reproduïbles: es poden executar en qualsevol entorn.
  • Són revisables: passen pel mateix procés de revisió que el codi (pull requests).
projecte/ ├── src/ ├── migrations/ │ ├── 001_create_users.sql │ ├── 002_add_email_column.sql │ └── 003_fix_duplicates.py └── scripts/ └── cleanup_old_sessions.py

Git Hooks

Git permet executar scripts automàticament en moments clau del flux de treball. Aquests scripts s’anomenen hooks i són el mecanisme bàsic per automatitzar el pipeline de lliurament (Build, release, run).

Hi ha hooks locals (s’executen a la màquina del desenvolupador) i hooks al servidor (s’executen quan el repositori remot rep codi):

  • pre-commit (local): s’executa abans de crear un commit. Pot validar el format del codi, executar un linter o verificar que no hi ha secrets al codi. Si el script retorna un error, el commit es rebutja.
  • pre-receive (servidor): s’executa quan algú fa git push al repositori remot, abans d’acceptar els canvis. Pot rebutjar el push si el codi no passa els tests o no compleix les regles del projecte. És la porta d’entrada (quality gate) al repositori compartit.
  • post-receive (servidor): s’executa després d’acceptar els canvis. És el moment natural per disparar accions automàtiques: construir la imatge Docker, executar els tests d’integració, desplegar a staging.

La idea fonamental és: un git push pot desencadenar tot el pipeline de lliurament sense intervenció manual. El desenvolupador puja codi, i la cadena build → test → deploy s’executa automàticament.

Aquesta és la base conceptual del que fan les plataformes de CI/CD (GitLab CI, Jenkins…): escoltar events de Git i executar pipelines en resposta. Però el mecanisme original són els hooks de Git, i en entorns autogestionats (amb Gitolite, per exemple) els hooks pre-receive i post-receive són tot el que cal per implementar un pipeline complet.

Empaquetament i entorn

Docker no és un requisit dels dotze factors, però és l’eina que els fa naturals. Sense contenidors, complir aquests principis requereix disciplina manual; amb contenidors, molts es compleixen per defecte.

Dependencies

Un Dockerfile és, per definició, una declaració explícita de totes les dependències. El contenidor resultant és un entorn aïllat i complet: no depèn de res instal·lat a la màquina host.

FROM python:3.12-slim COPY requirements.txt . RUN pip install -r requirements.txt COPY . .

Qualsevol persona que executi docker build obtindrà exactament el mateix entorn. El problema de “a la meva màquina funciona” desapareix.

Config

Docker utilitza variables d’entorn de forma nativa. Es poden passar al moment d’executar el contenidor, sense tocar el codi ni la imatge:

docker run -e DB_HOST=postgres -e DB_PASSWORD=secret myapp

O amb Docker Compose:

services: api: image: myapp environment: - DB_HOST=postgres - DB_PASSWORD=secret

La mateixa imatge serveix per a desenvolupament, staging i producció. Només canvien les variables.

Variables no sensibles (com LOG_LEVEL o APP_PORT) poden estar al fitxer docker-compose.yml del repositori sense cap problema. Però els secrets (contrasenyes, claus d’API, tokens) no han d’estar mai ni al codi ni a la imatge. D’on surten, doncs? De la infraestructura: en desenvolupament local, d’un fitxer .env ignorat per .gitignore; en entorns automatitzats, del magatzem de secrets de la plataforma de CI/CD (per exemple, les CI/CD Variables de GitLab), que els injecta com a variables d’entorn durant l’execució del pipeline. En tots els casos, els secrets s’injecten en el moment d’executar el contenidor — mai es graven a la imatge durant el build.

Backing services

Docker Compose permet definir backing services com a contenidors adjacents. Canviar de servei és canviar una línia de configuració:

services: api: image: myapp environment: - DATABASE_URL=postgresql://db:5432/app db: image: postgres:16

Afegir un Redis per a cache, o substituir el motor de base de dades? Només cal afegir o canviar un servei al fitxer Compose i actualitzar la variable d’entorn.

Build, release, run

Les tres etapes es mapegen directament a comandes Docker:

EtapaComandaResultat
Builddocker build -t myapp .Imatge amb codi + dependències
Releasedocker tag myapp myapp:v1.2.3Imatge etiquetada amb versió
Rundocker run myapp:v1.2.3Contenidor en execució

Cada imatge és immutable. No es pot editar codi dins d’un contenidor en producció (si es fa, els canvis es perden al reiniciar). Això força la separació d’etapes.

Processes

Els contenidors són efímers per disseny: es poden destruir i recrear en qualsevol moment. Si el contenidor guarda estat a la seva capa d’escriptura, aquest estat es perd.

Això obliga a emmagatzemar les dades persistents fora del contenidor (en volums o en backing services), que és exactament el que demana el principi de Processes.

Port binding

Cada contenidor exposa el seu servei a través d’un port, mapeig que es defineix explícitament:

docker run -p 8080:8080 myapp

No hi ha servidor web compartit. Cada contenidor és autocontingut amb el seu propi procés escoltant al port.

Concurrency

Escalar és executar més contenidors:

docker compose up --scale api=5

Cinc instàncies idèntiques del servei, cadascuna escoltant al seu port, darrere d’un balancejador de càrrega. Això només funciona si l’aplicació és stateless (Processes).

Dev/prod parity

La mateixa imatge s’executa a tot arreu: el portàtil del desenvolupador, el servidor de CI, staging i producció. Les diferències entre entorns — que al principi de Dev/prod parity hem vist que són font d’errors — es redueixen a les variables de configuració (Config).

Disposability

Els contenidors s’inicien en segons. Quan cal aturar-los, Docker envia un senyal SIGTERM al procés principal; si no respon dins d’un temps límit, envia SIGKILL. L’aplicació ha de capturar SIGTERM per fer una aturada elegant (completar peticions en curs, tancar connexions).

Logs

Per defecte, Docker captura tot el que el procés escriu a stdout i stderr. Es pot consultar amb docker logs o redirigir a sistemes d’agregació mitjançant log drivers. L’aplicació utilitza un logger per escriure amb estructura i nivells, però la configuració de producció envia la sortida a stdout — i Docker s’encarrega de la resta.

Automatització del lliurament

Fins ara hem vist com gestionar el codi (Git) i com empaquetar-lo (Docker). Però entre un git push i una aplicació funcionant en producció hi ha molts passos: compilar, executar tests, construir la imatge, desplegar-la… Si aquests passos es fan manualment, són lents, propensos a errors i difícils de reproduir. L’automatització converteix tot aquest procés en un pipeline: una seqüència de passos que s’executa automàticament cada vegada que algú puja codi.

El mecanisme que dispara el pipeline són els hooks de Git (explicats anteriorment). Les plataformes de CI/CD (GitLab CI, Jenkins…) escolten events de Git i executen els passos definits.

Integració contínua (CI)

Sense integració contínua, cada desenvolupador treballa en la seva branca durant dies o setmanes. El dia que tothom intenta fusionar els canvis — el temut merge day — apareixen conflictes, tests que fallen i funcionalitats que es trenquen mútuament.

La integració contínua evita aquest problema: cada desenvolupador integra els seus canvis freqüentment (idealment, cada dia), i el sistema verifica automàticament que tot segueix funcionant:

  1. Lint: verificar l’estil i format del codi
  2. Tests: executar els tests unitaris i d’integració
  3. Build: compilar i construir l’artefacte (imatge Docker, JAR, bundle…)

Si qualsevol pas falla, el pipeline s’atura i el desenvolupador rep un avís. El codi no avança fins que tots els passos passen. Això és una quality gate: el pipeline protegeix el repositori de codi defectuós.

La idea clau és que els problemes es detecten en minuts, no dies o setmanes després, quan ja ningú recorda què va canviar.

Lliurament continu (CD)

Un cop el codi passa la CI, el pipeline pot continuar automàticament cap als entorns de desplegament:

  1. Desplegar a staging: un entorn idèntic a producció on es poden fer proves addicionals (proves d’acceptació, proves de rendiment…)
  2. Desplegar a producció: automàticament o amb una aprovació manual

La diferència entre lliurament continu (continuous delivery) i desplegament continu (continuous deployment) és l’últim pas: en el lliurament continu, el desplegament a producció requereix una aprovació manual; en el desplegament continu, és completament automàtic. La majoria d’equips comencen amb lliurament continu i avancen cap a desplegament continu a mesura que guanyen confiança en els seus tests i pipeline.

El flux complet és:

git push → lint → test → build → staging → [aprovació] → producció

Un desplegament que abans requeria hores de treball manual i coordinació entre equips es redueix a un git push i uns minuts d’espera.

Desplegament de la infraestructura

El pipeline no només desplega codi. També pot configurar servidors, instal·lar dependències i preparar l’entorn.

Tradicionalment, configurar un servidor era un procés manual: connectar-se per SSH, instal·lar paquets, editar fitxers de configuració… Si el servidor fallava, calia repetir tot el procés de memòria (o amb sort, seguint unes notes). I si calia preparar un segon servidor idèntic, les diferències apareixien inevitablement.

Eines de gestió de configuració com Ansible permeten definir l’estat desitjat d’un servidor en fitxers versionats al repositori:

  • Quin sistema operatiu i paquets han d’estar instal·lats
  • Quins serveis han d’estar actius
  • Quines variables d’entorn s’han de configurar

Aquesta idea — que la infraestructura es defineix com a codi, es versiona i s’aplica automàticament — s’anomena Infrastructure as Code (IaC). Garanteix que tots els entorns es configuren de manera idèntica, i que qualsevol canvi d’infraestructura passa pel mateix procés de revisió que el codi de l’aplicació.

Operació en producció

L’aplicació funciona en producció. Tot va bé… o no? Sense mecanismes d’observació, l’equip només descobreix els problemes quan un usuari es queixa. I a vegades, un problema petit (una consulta SQL que es fa lenta) es converteix en un problema gran (el sistema cau) perquè ningú el va detectar a temps.

L’observabilitat és la capacitat de saber què passa dins d’un sistema des de fora, sense haver d’accedir als servidors ni depurar codi en producció. Es basa en quatre pilars:

Mètriques

Les mètriques són valors numèrics que es recullen periòdicament i permeten veure tendències. Les quatre mètriques fonamentals per a qualsevol servei web són:

  • Latència: quant triga una petició? Es mesura en percentils (p50, p95, p99) perquè la mitjana amaga els casos extrems. Si el p50 és de 100ms però el p99 és de 5s, un de cada cent usuaris té una experiència molt dolenta.
  • Throughput: quantes peticions per segon atén el sistema?
  • Errors: quin percentatge de peticions fallen? (anomenat error rate)
  • Recursos: quanta CPU, memòria i disc s’utilitzen?

Les mètriques responen la pregunta “com va el sistema ara?” i permeten detectar degradacions abans que els usuaris les notin. Per exemple, si la latència p95 ha pujat de 200ms a 800ms en les últimes dues hores, alguna cosa està canviant — encara que els usuaris no s’hagin queixat.

Logs

L’aplicació utilitza un logger que escriu a stdout i l’entorn els recull (com hem vist a Empaquetament i entorn). Però per ser útils en producció amb múltiples instàncies, els logs haurien de ser estructurats (en format JSON, per exemple), perquè les eines d’agregació els puguin indexar i buscar-hi:

{"timestamp": "2025-03-15T10:23:45Z", "level": "ERROR", "service": "api", "message": "Connection refused", "host": "db-primary"}

Amb logs estructurats, es pot buscar “tots els errors del servei api de les últimes 2 hores” en segons, fins i tot amb 10 instàncies escrivint en paral·lel. Sense estructura, els logs són text lliure difícil de filtrar i analitzar automàticament.

Health checks

Un health check és un endpoint que indica si l’aplicació està preparada per rebre peticions. Normalment és una URL simple:

GET /health → 200 OK GET /health → 503 Service Unavailable

Per què no n’hi ha prou amb saber que el procés existeix? Perquè un contenidor pot estar en execució però no funcionar correctament — per exemple, perquè ha perdut la connexió amb la base de dades, o perquè s’ha quedat sense memòria interna. El health check verifica que l’aplicació realment pot atendre peticions.

Qui consulta aquest endpoint?

  • Docker: pot reiniciar un contenidor que falla el health check
  • Balancejadors de càrrega: deixen d’enviar tràfic a instàncies no saludables
  • Pipelines de CI/CD: verifiquen que el desplegament ha funcionat abans de donar-lo per bo

Alertes

Les mètriques i els health checks generen dades contínuament, però ningú pot estar mirant gràfics les 24 hores del dia. Les alertes automàtiques defineixen condicions que, quan es compleixen, envien una notificació a l’equip:

  • La latència p99 supera els 2 segons durant més de 5 minuts
  • El percentatge d’errors supera l’1%
  • Un health check falla 3 vegades consecutives

Un bon sistema d’alertes avisa dels problemes reals sense generar fatiga d’alertes — si l’equip rep 50 alertes al dia, acabarà ignorant-les totes.

Recapitulació

DevOps connecta el desenvolupament amb les operacions a través d’un cicle continu: el codi es gestiona amb Git, s’empaqueta amb Docker, es lliura automàticament amb un pipeline de CI/CD, i s’opera amb observabilitat. Els dotze factors són els principis que guien cada etapa d’aquest cicle — i les eines que hem vist són les que els fan pràctics.