Les dues lliçons anteriors han treballat sempre sobre una màquina: meteo-01, amb el seu RAID 1, el seu /dev/md0, el seu meteora.conf en mode 600 i el seu sistema de fitxers ext4. Hi hem virtualitzat a dins, hi hem contingut processos a dins, però continuava havent-hi una màquina física en un armari, que algú va instal·lar, que té un número de sèrie i que si s'avaria deixa el servei caigut fins que algú la vagi a arreglar.
Aquesta lliçó treu aquest supòsit. Al núvol, la màquina deixa de ser un objecte i passa a ser una crida a una API: demanes una instància i en quaranta segons la tens; l'esborres i desapareix; es mor sola a les tres de la matinada perquè l'amfitrió físic ha fallat i ningú no t'avisa. Aquest canvi no és només administratiu: canvia el que significa administrar un sistema operatiu, canvia on han de viure les dades, canvia què es pot depurar i canvia com es dissenya un servei perquè sobrevisqui.
Veuràs què canvia exactament i per què, on queda la frontera de responsabilitat del sistema operatiu en cada model de servei, com arrenca de debò una instància i com s'aprovisiona amb cloud-init, què són la infraestructura immutable i els sistemes operatius mínims, com es comporta l'emmagatzematge en xarxa davant de l'SSD local amb xifres concretes, i com un orquestrador de contenidors és literalment un sistema operatiu del clúster on reapareixen els cgroups de la lliçó anterior i el planificador de 02-02. Acabarem migrant Meteora, decisió a decisió, incloent-hi el que no convé migrar. Els sistemes mòbils i de temps real tanquen el mòdul a 06-04, i les eines de monitoratge ja són el mòdul 7.
Contingut
- Què canvia quan la màquina deixa de ser física
- Bestiar i no mascotes
- Models de servei i la frontera del sistema operatiu
- L'arrencada d'una instància, pas a pas
cloud-init: aprovisionarmeteo-01al núvol- Metadades d'instància i el seu risc de seguretat
- Infraestructura immutable davant de mutable
- Sistemes operatius mínims i immutables
- Emmagatzematge al núvol: blocs, efímer i objectes
- Xarxes definides per programari
- Orquestració: el sistema operatiu del clúster
- Funcions sense servidor, microVM i sandboxes
- Escalat automàtic i l'arrencada en fred
- Observabilitat quan la màquina desapareix
- Cost i densitat com a criteri de disseny
- Cas final: migrar Meteora
Què canvia quan la màquina deixa de ser física
Enumerem els canvis sense adorns, perquè cadascun té conseqüències tècniques concretes:
| Propietat | Servidor físic (meteo-01) |
Instància al núvol |
|---|---|---|
| Aprovisionament | Setmanes: compra, muntatge, instal·lació | Segons, per API |
| Vida esperada | 3-5 anys | Hores o dies; pot desaparèixer sense avís |
| Identitat | Nom propi, número de sèrie, inventari | Un identificador generat, llencívol |
| Fallada del maquinari | Incident: algú hi va i ho arregla | Rutina: se substitueix la instància |
| Disc | Físic, dins de la caixa | Un volum de xarxa, lligat i deslligat per API |
| Xarxa | Cables, VLAN, commutador físic | Definida per programari, creada per API |
| Escala | Fixa | Elàstica, amb cost per hora o per segon |
| Cost | Inversió inicial (CAPEX) | Despesa corrent (OPEX), proporcional a l'ús |
El que és veritablement disruptiu és la fila de la vida esperada. Un servidor físic es dissenya per durar; una instància de núvol es dissenya assumint que es morirà. Els proveïdors ho diuen obertament: el compromís de disponibilitat d'una instància individual sol ser del 99,5 % mensual —unes 3,6 hores de caiguda al mes— i només s'eleven les garanties quan reparteixes la càrrega entre diverses zones.
D'aquí surt la primera regla de disseny d'aquesta lliçó, que contradiu tot el que un aprèn administrant un servidor: no intentis que la màquina no falli; dissenya perquè la seva fallada no importi.
Bestiar i no mascotes
La metàfora és del 2012 i continua sent la millor explicació del canvi cultural:
- Una mascota té nom propi (
meteo-01), s'instal·la a mà, se li fa un seguiment afectuós, se li apliquen pedaços amb cura i, quan emmalalteix, se la cura. És única i irreemplaçable. - El bestiar es numera (
meteo-api-7f3c), s'aprovisiona automàticament i és intercanviable. Quan un emmalalteix, no es cura: se substitueix.
Les conseqüències pràctiques són incòmodes al principi i alliberadores després:
- Res de canvis manuals. Un
apt installa mà en una instància crea un estat que cap altra no té i que es perdrà en substituir-la. Si el canvi importa, va a la imatge o a l'automatització. - Cap dada important no viu al disc de la instància. Tot el que ha de sobreviure surt d'allà: a un volum persistent, a una base de dades gestionada, a emmagatzematge d'objectes.
- L'accés per SSH deixa de ser l'eina principal. No pas perquè estigui prohibit, sinó perquè si el necessites per operar, alguna cosa falta a l'automatització.
- La reinstal·lació és la resposta per defecte. El que a 05-04 era el desenllaç d'un incident greu —reconstruir des de zero— aquí és l'operació de dimarts al matí.
Un matís honest, perquè el dogma s'exagera: no tot pot ser bestiar. Una base de dades amb estat, un controlador de domini o un sistema amb llicències lligades al maquinari continuen sent mascotes, i pretendre el contrari provoca desastres. La regla útil és que l'estat es concentri en les mínimes peces possibles, i que tota la resta sigui intercanviable.
Models de servei i la frontera del sistema operatiu
La pregunta rellevant per a aquest curs no és "què és el núvol", sinó qui administra el sistema operatiu en cada model:
| Model | Tu gestiones | El proveïdor gestiona | Veus el SO? | Exemple |
|---|---|---|---|---|
| On-premise | Tot | Res | Sí, sencer | meteo-01 a l'armari |
| IaaS | SO, pedaços, temps d'execució, aplicació | Maquinari, hipervisor, xarxa física | Sí, sencer | Una instància de còmput |
| CaaS | Imatge del contenidor i la seva configuració | A més, el SO dels nodes | Parcialment (la imatge) | Un servei de contenidors gestionat |
| PaaS | Només el codi i la configuració | A més, el temps d'execució | No | Una plataforma d'aplicacions |
| FaaS | Només la funció | Tota la resta, inclòs l'escalat | No | Funcions sense servidor |
L'important és entendre què es guanya i què es perd en pujar per aquesta escala. Es guanya operació: menys pedaços per aplicar, menys configuració per mantenir, menys guàrdies. Es perd control i, molt en concret, es perden les eines d'aquest curs: en un PaaS no pots mirar /proc, no pots ajustar swappiness, no pots posar una regla d'nftables, no pots executar strace. Quan alguna cosa va malament i el proveïdor no et dona la mètrica que necessites, estàs cec.
I un advertiment que no se sol dir: a IaaS continues sent responsable de tot el sistema operatiu. És el model de responsabilitat compartida. El proveïdor garanteix que el maquinari i l'hipervisor funcionen; els pedaços del nucli, l'enfortiment de 05-03, el tallafocs, els usuaris i els registres continuen sent teus. Una instància acabada de crear amb la imatge oficial d'una distribució és exactament igual d'insegura que un servidor acabat d'instal·lar.
L'arrencada d'una instància, pas a pas
Convé veure la seqüència completa, perquè explica on encaixa cada peça:
sequenceDiagram
participant U as Tu (API/terraform)
participant P as Pla de control
participant H as Amfitrió físic
participant I as Instància
U->>P: crear_instancia(imatge, tipus, xarxa, user-data)
P->>P: triar amfitrió amb forat (planificació)
P->>H: crear VM, adjuntar volum des de la imatge
H->>I: arrencar (microprogramari → nucli → init)
I->>I: cloud-init: consulta al servei de metadades
I->>I: aplica user-data: usuaris, claus, paquets, fitxers
I->>P: instància a punt (~30-60 s)
Les peces, una a una:
- La imatge de màquina. Una plantilla de disc amb un sistema ja instal·lat —la mateixa idea de les plantilles de 06-01—, identificada per un ID. Pot ser oficial del proveïdor, de la distribució, o pròpia, construïda per tu amb tot el que necessites ja a dins. Aquesta darrera opció és la base de la infraestructura immutable.
- El tipus d'instància. Determina vCPU, memòria, xarxa i de vegades disc local. Aquí recuperes tot 06-01: aquestes vCPU són fils d'un procés en un amfitrió compartit, i el seu
steal timeés real. - El volum arrel. Es crea copiant (o enllaçant) la imatge. En acabar, normalment s'esborra amb la instància, llevat que es marqui el contrari.
- La xarxa: una interfície virtual a la xarxa definida per programari, amb IP privada, i un grup de seguretat associat.
- L'arrencada: microprogramari, gestor d'arrencada, nucli,
init. Exactament el que passa en qualsevol màquina; ho veuràs en detall a Serveis, Arrencada i systemd. cloud-init: la peça que converteix una imatge genèrica en el teu servidor.
cloud-init: aprovisionar meteo-01 al núvol
cloud-init és un conjunt de serveis que s'executen al primer arrencada, consulten el servei de metadades i apliquen la configuració que li has passat, anomenada user-data. És un estàndard de facto: funciona igual en gairebé tots els proveïdors i també a KVM local, cosa que el fa l'eina natural per a la rèplica de proves que vam crear a 06-01.
#cloud-config
hostname: meteo-01
fqdn: meteo-01.meteora.internal
timezone: Europe/Madrid
# --- Usuaris: compte d'operació amb clau pública, sense contrasenya ---
users:
- name: operador
groups: [sudo]
shell: /bin/bash
sudo: ["ALL=(ALL) NOPASSWD:/usr/bin/systemctl restart meteo-api"]
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... operador@meteora
# Compte de servei: MATEIX UID que al servidor físic
- name: meteora
uid: 990
gid: 990
system: true
shell: /usr/sbin/nologin
lock_passwd: true
# --- Paquets ---
package_update: true
package_upgrade: true
packages: [nftables, chrony, python3-venv, unattended-upgrades]
# --- Disc de dades: formatar i muntar amb les opcions del curs ---
disk_setup:
/dev/nvme1n1: {table_type: gpt, layout: true, overwrite: false}
fs_setup:
- device: /dev/nvme1n1
partition: 1
filesystem: ext4
label: meteora-dades
mounts:
- [LABEL=meteora-dades, /var/lib/meteora, ext4,
"defaults,noatime,nosuid,nodev,data=ordered", "0", "2"]
# --- Fitxers: configuració SENSE secrets ---
write_files:
- path: /etc/meteora/meteora.conf
owner: meteora:meteora
permissions: '0600'
content: |
[general]
dades = /var/lib/meteora/lectures
log = /var/log/meteora/meteo-api.log
# Els secrets NO van aquí: es llegeixen del gestor de secrets en arrencar
- path: /etc/nftables.conf
permissions: '0644'
content: |
table inet filtre {
chain entrada {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
tcp dport 443 accept
}
}
# --- Ordres finals, en ordre ---
runcmd:
- [install, -d, -o, meteora, -g, meteora, -m, '0750', /var/lib/meteora/lectures]
- [install, -d, -o, meteora, -g, meteora, -m, '0750', /var/log/meteora]
- [systemctl, enable, --now, nftables]
- [systemctl, enable, --now, meteo-api]
final_message: "meteo-01 a punt després de $UPTIME segons"Què fa i per què cada decisió:
#cloud-configa la primera línia és obligatori: és la signatura que diu acloud-initque interpreti el YAML. Sense ella el fitxer s'ignora en silenci, i és l'error número u.- Usuaris amb clau pública i sense contrasenya.
lock_passwd: trueper al compte de servei issh_authorized_keysper al d'operació apliquen directament 05-02. Elsudoestà acotat a una ordre concreta, no pas aALL. uid: 990explícit, per la mateixa raó que al Dockerfile de 06-02: els volums es comparteixen per número, no per nom. Sicloud-initassigna l'UID 999 i el volum té fitxers del 990, obtens permisos trencats.mountsambnoatime,nosuid,nodev: les opcions d'enfortiment de 04-03 i 05-03, declarades a l'aprovisionament en lloc d'editades a mà a/etc/fstab. Aquí hi ha el canvi cultural complet: la configuració es declara, no s'aplica.- Configuració sense secrets. Aquest és el punt crític: el user-data és llegible des de dins de la instància per qualsevol procés, com veurem ara mateix. Ficar-hi una contrasenya equival a publicar-la. Els secrets es llegeixen a l'arrencada d'un gestor de secrets, autenticant-se amb la identitat de la instància.
runcmdal final, en ordre, per al que no cobreixen els mòduls declaratius.
Metadades d'instància i el seu risc de seguretat
Tota instància pot consultar informació sobre ella mateixa en una adreça local especial, típicament 169.254.169.254:
curl http://169.254.169.254/latest/meta-data/instance-id
curl http://169.254.169.254/latest/meta-data/local-ipv4
curl http://169.254.169.254/latest/user-data # el teu cloud-config sencer!
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/rol-meteo
# {"AccessKeyId":"...","SecretAccessKey":"...","Token":"...","Expiration":"..."}Què acabes de veure, i per què és el risc de seguretat més gran específic del núvol. Aquest endpoint retorna, sense cap autenticació, les credencials temporals del rol assignat a la instància. Qualsevol procés de la màquina les pot demanar i actuar al núvol amb aquests permisos. I aquí hi ha el problema: si la teva aplicació té una vulnerabilitat de falsificació de peticions del costat del servidor (SSRF) —una cosa tan ximple com un paràmetre ?url= que l'aplicació descarrega—, un atacant pot demanar a la teva pròpia aplicació que consulti 169.254.169.254 i li retorni les credencials. No necessita executar codi: n'hi ha prou que el teu servidor faci una petició HTTP per ell.
És exactament el patró de la bretxa de Capital One del 2019, que va exposar dades de més de cent milions de persones. Les mitigacions són concretes i totes necessàries:
- Exigir la versió amb token del servei de metadades (IMDSv2 i equivalents), que obliga a un
PUTprevi per obtenir un token de sessió amb TTL baix: un SSRF simple, que només sap ferGET, deixa de funcionar. - Bloquejar l'accés a l'endpoint des dels processos que no el necessiten, amb
nftableso el mateix contenidor. - Rol amb permisos mínims: si
meteo-apinomés ha d'escriure en un bucket concret, que el rol no permeti res més. És el mínim privilegi de 05-01 aplicat al pla del núvol. - Mai posar secrets al user-data, perquè és llegible des d'allà.
Infraestructura immutable davant de mutable
Dues filosofies oposades de gestionar el cicle de vida d'un servidor:
| Mutable | Immutable | |
|---|---|---|
| Actualitzar | Es modifica el servidor existent (apt upgrade) |
Es construeix una imatge nova i es reemplacen les instàncies |
| Eines | Gestió de configuració contínua | Construcció d'imatges + desplegament |
| Reversió | Difícil: cal desfer canvis | Trivial: redesplegar la imatge anterior |
| Deriva de configuració | Inevitable amb el temps | Impossible per construcció |
| Reproductibilitat | Depèn de l'historial de cada màquina | Total: la imatge és la mateixa per a tothom |
| Depuració | Hi entres i mires | Complicat: la instància dolenta ja no hi és |
| Temps de desplegament | Minuts | Més llarg (construir + arrencar) |
La deriva de configuració és l'argument decisiu. En un parc de vint servidors mutables gestionats durant dos anys, cap màquina no és idèntica a una altra: un apt install d'urgència aquí, un fitxer editat a mà allà, un paquet que va fallar en actualitzar-se en dues d'elles. El resultat és que una fallada apareix només en tres servidors i ningú no sap per què, i que la frase "al meu funciona" es converteix en la resposta habitual.
Amb infraestructura immutable, totes les instàncies de la versió 1.4.0 són bit a bit idèntiques, de manera que una fallada o és a totes o no és a cap. I la reversió és redesplegar la 1.3.0, cosa que converteix un desplegament arriscat en una operació avorrida.
El que es perd, i és real: depurar es complica. Si una instància es comporta malament i la política és substituir-la, el problema desapareix amb ella i no n'aprens res. La pràctica correcta és treure la instància malalta del balancejador però no destruir-la, deixant-la en quarantena per investigar-la —cosa que enllaça directament amb la preservació d'evidències de 05-04—, i substituir-la per una altra per restablir el servei. Contenir i analitzar no són incompatibles: són fases diferents.
Sistemes operatius mínims i immutables
Si la instància és bestiar i només executa contenidors, per què vol un sistema operatiu complet amb compilador, gestor de paquets, servidor de correu i cinquanta utilitats?
| Sistema | Idea | Actualització | Gestor de paquets |
|---|---|---|---|
| Flatcar / Container Linux | SO mínim només per a contenidors | Dues particions arrel A/B, atòmica | No n'hi ha |
| Bottlerocket | SO de contenidors, arrel de només lectura, verificada | Imatge A/B amb reversió | No n'hi ha |
| Talos Linux | Només Kubernetes: sense shell ni SSH, API gRPC | Declarativa per API | No n'hi ha |
| Fedora CoreOS | Sistema base atòmic amb rpm-ostree |
Transaccional, reversible | Limitat |
| "Distroless" (imatges) | Només el temps d'execució i l'aplicació | Reconstruir la imatge | No n'hi ha |
El que es guanya és mesurable i substancial:
- Superfície d'atac diminuta. Sense shell no hi ha reverse shell; sense
curlniwgetno es descarrega la segona fase d'un atac; sense compilador no es compila un exploit local. És el principi de superfície mínima de 05-01 portat a l'extrem, i elimina classes senceres d'atac, no les dificulta. - Menys pedaços. Un sistema amb 80 paquets té menys CVE al mes que un amb 500. Menys soroll, menys guàrdies.
- Actualitzacions atòmiques i reversibles. L'esquema A/B escriu la imatge nova a la partició inactiva i només canvia l'arrencada al final: o s'actualitza sencera o no s'actualitza, i si no arrenca bé, torna sola a l'anterior. És el contrari de l'
apt upgradeque es queda a mitges. - Arrencada ràpida, perquè hi ha poquíssims serveis per iniciar.
El que es perd és igual de real: depurar és incòmode. Sense strace, sense tcpdump, sense ss i de vegades sense shell, les tècniques del mòdul 7 no es poden aplicar directament. La resposta de l'ecosistema són els contenidors de depuració efímers: es llança un contenidor amb les eines dins dels namespaces del procés problemàtic —el nsenter de 06-02, industrialitzat—, s'investiga i es descarta. Funciona bé, però cal saber-ho fer abans que passi l'incident, no durant.
Emmagatzematge al núvol: blocs, efímer i objectes
Aquí és on el mòdul 2 es torna molt visible, i on més errors de disseny es cometen.
| Tipus | Què és | Latència típica | Persistència | Semàntica |
|---|---|---|---|---|
| Efímer d'instància | NVMe físic de l'amfitrió | 20-100 µs | Es perd en aturar la instància | Sistema de fitxers normal |
| Volum de blocs en xarxa | Disc virtual accedit per xarxa | 0,3-1 ms | Sobreviu a la instància | Sistema de fitxers normal |
| Emmagatzematge d'objectes | Magatzem clau-valor per HTTP | 20-100 ms | Molt alta (11 nous) | No és un sistema de fitxers |
Volums de blocs en xarxa
Es comporten com un disc: es particionen, es formaten amb ext4 i es munten. Però són a l'altre costat d'una xarxa, i això es nota exactament on prediu 02-05:
| Mètrica | SSD NVMe local | Volum de blocs en xarxa |
|---|---|---|
| Latència de lectura 4 KB | 20-100 µs | 300-1.000 µs (5-10× pitjor) |
| IOPS | 500.000+ | 3.000-64.000 (segons el que paguis) |
| Throughput | 3-7 GB/s | 125-1.000 MB/s |
| Persistència | No | Sí |
| Instantànies | No | Sí, integrades |
La diferència clau no és només el número: és que les IOPS s'aprovisionen i es paguen. Un volum bàsic dona sovint 3 IOPS per GB, de manera que un volum de 100 GB rendeix 300 IOPS —menys que un disc dur giratori del 2005— per molt que el maquinari subjacent sigui flaix. És la font de sorpresa més habitual en migrar: la mateixa aplicació, en la mateixa versió, va quatre vegades més lenta, i el motiu no és la CPU sinó un sostre d'IOPS contractat.
Per a Meteora, l'ingestor escriu 8.000 lectures per segon. Si les escriu d'una en una, són 8.000 IOPS i el volum bàsic s'ofega; si les agrupa en lots de 512 lectures (12.288 bytes), baixen a unes 16 escriptures per segon. L'agrupació, que al servidor físic era una optimització menor, aquí és la diferència entre funcionar i no funcionar.
Emmagatzematge efímer
És un NVMe físic de l'amfitrió: rapidíssim i, sovint, inclòs al preu de la instància. Però es perd en aturar la instància o si l'amfitrió falla. El seu ús correcte és tot allò que es pot reconstruir: memòries cau, fitxers temporals, índexs derivats, dades intermèdies d'un procés per lots. Mai la font de la veritat.
Emmagatzematge d'objectes
És la peça més incompresa, perquè no és un sistema de fitxers encara que la seva interfície ho sembli:
| Aspecte | Sistema de fitxers | Emmagatzematge d'objectes |
|---|---|---|
| Unitat | Fitxer amb inode (04-01) | Objecte complet, amb una clau |
| Modificació parcial | Sí, pwrite en un desplaçament |
No: se substitueix l'objecte sencer |
| Jerarquia | Directoris reals | Plana; la / de la clau és decorativa |
| Reanomenar | Canvi d'entrada de directori, instantani | Copiar i esborrar: proporcional a la mida |
| Llistar | readdir sobre un directori |
Consulta paginada sobre un prefix, lenta |
Bloqueig, fsync, permisos POSIX |
Sí | No |
| Latència | Microsegons | Desenes de mil·lisegons |
Per això muntar-lo com si fos un disc és gairebé sempre mala idea: les eines que tradueixen POSIX a objectes han d'emular el que no existeix, i un mv d'un fitxer gran es converteix a copiar tot l'objecte i esborrar-lo, un readdir es converteix en diverses peticions HTTP paginades, i no hi ha bloqueig ni escriptura parcial. Funciona en demostracions i es trenca en producció amb dades reals.
Aplicat a Meteora, la decisió és neta:
| Dada | On ha de viure | Per què |
|---|---|---|
Fitxer del dia en curs (2026-08-31.dat) |
Volum de blocs | S'escriu contínuament, amb append i fsync |
| Fitxers de dies tancats | Objectes (comprimits) | Només es llegeixen sencers, i surten molt més barats |
| Índexs i agregats horaris | Volum de blocs, o base de dades gestionada | Accés aleatori i consultes |
Memòria cau /dev/shm/meteora-cache |
Memòria de la instància | Reconstruïble |
| Còpies de seguretat | Objectes, amb versionat i immutabilitat | És la còpia 3-2-1 de 05-03, ara amb retenció forçada pel proveïdor |
Un detall que arrodoneix la decisió: l'emmagatzematge d'objectes ofereix classes d'accés amb preus molt diferents. Un fitxer diari de 17,3 MB comprimit queda en uns 4 MB; al llarg de cinc anys són uns 7,3 GB, amb un cost d'emmagatzematge fred ridícul. Mantenir aquestes mateixes dades en volums de blocs costa un ordre de magnitud més i no aporta res, perquè ningú no consulta el 14 de març del 2023 amb latència de mil·lisegons.
Xarxes definides per programari
La xarxa del núvol és una simulació construïda sobre la xarxa física del proveïdor, i les seves peces es corresponen una a una amb el que ja coneixes:
- Xarxa virtual privada: un espai d'adreces propi (per exemple
10.0.0.0/16) aïllat del d'altres clients, subdividit en subxarxes per zona de disponibilitat. Conceptualment és el pont de 06-01, a escala de centre de dades. - Subxarxes públiques i privades: la diferència real és si la seva taula de rutes té sortida a una passarel·la d'internet. Les bases de dades i els serveis interns van en privades; només el balancejador viu a la pública.
- Grups de seguretat: un tallafocs amb estat, aplicat per interfície de xarxa, no per màquina. És la diferència amb
nftables: la regla viatja amb la instància, s'avalua abans que el paquet arribi al sistema operatiu, i per defecte denega tot el que entra. - Adreces: la IP privada és estable durant la vida de la instància; la pública, si no es reserva, canvia a cada arrencada, motiu pel qual mai no s'ha de configurar res per IP pública.
Dos consells que eviten la majoria dels incidents de xarxa al núvol:
- El grup de seguretat no substitueix el tallafocs del sistema. És defensa en profunditat, com a 05-03: si algú s'equivoca a la regla del grup,
nftablesambpolicy dropcontinua allà. - Referencia grups, no rangs d'IP. La regla correcta per a la base de dades no és "permetre 10.0.1.0/24", sinó "permetre el trànsit que vingui del grup de seguretat de
meteo-api". Així la regla continua sent correcta quan l'autoescalat crea instàncies amb IP noves.
Orquestració: el sistema operatiu del clúster
Aquí hi ha la idea que fa que aquesta lliçó pertanyi de ple dret a un curs de sistemes operatius. Un orquestrador de contenidors fa amb un clúster exactament el que un sistema operatiu fa amb una màquina:
| Funció | Sistema operatiu (mòdul 2) | Orquestrador |
|---|---|---|
| Unitat d'execució | Procés | Pod (un o diversos contenidors) |
| Recurs a repartir | CPU, RAM de la màquina | CPU, RAM de tots els nodes |
| Planificador | CFS-EEVDF tria quin procés s'executa | Tria a quin node es col·loca el pod |
| Aïllament | Namespaces i cgroups | Els mateixos, més polítiques de xarxa |
| Noms | /proc, sockets, fitxers |
Serveis i DNS intern |
| Reinici davant d'una fallada | Restart= de systemd |
Controlador de rèpliques |
| Emmagatzematge | VFS i muntatges (04-03) | Volums persistents |
El component que tanca el cercle amb la lliçó anterior és el kubelet, l'agent que corre a cada node. La seva feina és senzilla de descriure: pregunta al pla de control quins pods li toquen, parla amb el runtime de contenidors (containerd o CRI-O, via la interfície CRI) per arrencar-los, munta els seus volums, executa les seves sondes de salut i reporta l'estat. És, literalment, l'init del node per a les càrregues del clúster.
Peticions i límits són cgroups, literalment
Quan escrius això en un manifest:
resources:
requests: # el que el planificador RESERVA per col·locar-te
cpu: "500m" # 0,5 nuclis
memory: "256Mi"
limits: # el SOSTRE que no pots passar
cpu: "1500m" # 1,5 nuclis
memory: "512Mi"El kubelet ho tradueix exactament als fitxers que vam escriure a mà a 06-02:
| Camp del manifest | Fitxer de cgroup v2 | Valor |
|---|---|---|
requests.cpu: 500m |
cpu.weight |
~51 (pes proporcional) |
limits.cpu: 1500m |
cpu.max |
150000 100000 |
requests.memory: 256Mi |
(només planificació) | No s'escriu: es fa servir per triar node |
limits.memory: 512Mi |
memory.max |
536870912 |
I d'aquí es dedueixen, sense cap màgia, els dos comportaments que més desconcerten qui comença:
- Superar el límit de CPU no mata: estrangula. És el
throttlingdecpu.maxque vam diagnosticar a 06-02 ambnr_throttled. L'aplicació no falla, només va a batzegades i amb un p99 horrible. - Superar el límit de memòria mata a l'instant. És l'OOM killer del cgroup: el contenidor mor amb codi 137 i el pod apareix com a
OOMKilled. Exactament el cas de l'agregadorde l'exercici anterior.
El planificador del clúster és l'equivalent del planificador de CPU de 02-02, un nivell més amunt: filtra els nodes que no serveixen (sense prou recursos lliures segons les requests, sense les etiquetes demanades, amb restriccions actives) i puntua els que queden per repartir la càrrega. I aquí una regla operativa que s'aprèn cara: el planificador col·loca segons les peticions, no segons l'ús real. Si demanes 2 CPU i n'uses 0,1, el clúster te'n reserva 2 i no col·loca ningú més en aquell forat. Peticions inflades són la causa número u de clústers caríssims amb nodes al 15 % d'ús.
Funcions sense servidor, microVM i sandboxes
Les funcions sense servidor porten l'escala a l'extrem: puges una funció, el proveïdor l'executa quan arriba un esdeveniment i et cobra per mil·lisegon. No hi ha servidor per administrar, no hi ha sistema operatiu per pedaçar.
Però per sota sí que hi ha alguna cosa, i aquesta cosa és interessant per a aquest curs, perquè planteja un problema difícil: cal executar codi de milers de clients diferents al mateix maquinari, amb aïllament de màquina virtual però arrencada de contenidor. Les màquines virtuals de 06-01 aïllen bé però triguen desenes de segons; els contenidors de 06-02 arrenquen en mil·lisegons però comparteixen nucli. Dues tecnologies ocupen aquest espai intermedi:
- Firecracker és un VMM minimalista escrit en Rust sobre KVM. Renuncia a gairebé tot el que QEMU emula: sense BIOS heretada, sense USB, sense VGA, sense PCI complet; només
virtioper a disc, xarxa i consola. El resultat és una microVM que arrenca en ~125 ms, consumeix uns 5 MB de sobrecàrrega i exposa a l'hipervisor una superfície diminuta. És l'hipervisor real darrere de les plataformes de funcions sense servidor, i és la demostració pràctica de la lliçó de VENOM a 06-01: treure dispositius emulats millora alhora la seguretat i el rendiment. - gVisor ataca el problema des de l'altre costat: és un nucli en espai d'usuari que intercepta les crides al sistema del contenidor i les implementa ell mateix, en Go, en lloc de deixar-les passar al nucli amfitrió. Redueix dràsticament la superfície —el contenidor ja no parla amb les 350 syscalls de Linux, sinó amb gVisor—, a canvi d'una penalització de rendiment notable en càrregues amb molta E/S.
| Tecnologia | Aïllament | Arrencada en fred | Sobrecàrrega de memòria | Compatibilitat |
|---|---|---|---|---|
| Contenidor (runc) | Nucli compartit | 20-200 ms | 1-10 MB | Total |
| gVisor | Nucli interceptat en espai d'usuari | 100-300 ms | 15-50 MB | Alta, amb forats |
| Firecracker (microVM) | Nucli propi, VM real | ~125 ms | ~5 MB + el convidat | Total |
| VM completa (QEMU) | Nucli propi, VM real | 10-60 s | 200-500 MB | Total |
La conclusió que convé retenir: la frontera entre VM i contenidor ha deixat de ser binària. Firecracker aconsegueix aïllament de VM amb arrencada gairebé de contenidor retallant tot el que no cal, i és la raó tècnica que les funcions sense servidor puguin ser alhora multiinquilí i barates.
Escalat automàtic i l'arrencada en fred
L'escalat automàtic ajusta el nombre d'instàncies o de pods segons una mètrica: ús de CPU, longitud d'una cua, peticions per segon. Sona trivial i té dos problemes reals.
El primer és l'arrencada en fred. Escalar no és instantani, i la latència s'acumula per capes:
| Capa | Temps típic fins a servir trànsit |
|---|---|
| Pod nou, imatge ja al node | 1-5 s |
| Pod nou, imatge per descarregar | 10-60 s |
Instància nova (IaaS) + arrencada + cloud-init |
40-120 s |
| Funció sense servidor (microVM) en fred | 100-500 ms |
| Funció en calent | 1-10 ms |
Si la teva càrrega es duplica en 30 segons i una instància nova en triga 90 a estar a punt, l'escalat automàtic arriba tard i els usuaris veuen errors. Les respostes són escalar per una mètrica avançada (la longitud de la cua de l'ingestor creix abans que la CPU se saturi), mantenir un coixí de capacitat ociosa, precarregar imatges als nodes, i escalar de manera agressiva en pujar i conservadora en baixar per no oscil·lar.
El segon problema és l'oscil·lació: si la mètrica puja i baixa al voltant del llindar, el sistema crea i destrueix instàncies sense parar, amb un cost alt i cap estabilitat. Es resol amb histèresi —llindars diferents per pujar i baixar— i amb períodes de refredament.
I un matís important per a Meteora: l'ingestor no escala igual que meteo-api. Les consultes HTTP són sense estat i es reparteixen a voluntat; la ingesta d'estacions concretes té afinitat i ordre. Escalar horitzontalment alguna cosa amb estat sense pensar-hi porta a lectures duplicades o perdudes.
Observabilitat quan la màquina desapareix
Aquí es veu amb cruesa per què 05-04 insistia tant a treure els registres de la màquina. Al núvol, aquesta recomanació passa de bona pràctica a requisit absolut, per una raó nova: la instància que va generar el registre pot no existir quan el vagis a llegir.
- Un pod que mor per OOM es reinicia i els seus registres anteriors desapareixen llevat que s'hagin enviat fora.
- Una instància substituïda per l'autoescalat s'endú el seu
journalctlamb ella. - El disc efímer, amb el que hi hagués a
/var/log, s'esborra en aturar la instància.
D'aquí les regles pràctiques:
- L'aplicació escriu a la sortida estàndard, no pas a un fitxer. Un agent al node recull, etiqueta i envia. És el contrari de
/var/log/meteora/meteo-api.log, i en un contenidor té tot el sentit: qui s'ha de preocupar d'on acaba el registre no és l'aplicació. - Registre estructurat amb context del núvol: al
request_idde 05-04 s'hi afegeixen ara identificador d'instància, zona, versió de la imatge i nom del pod. Sense això, un error que passa en una sola instància de vint és indistingible del soroll. - Traces distribuïdes, perquè una petició travessa balancejador, diversos serveis i una base de dades: un registre per servei ja no reconstrueix la història.
- Mètriques per agregat, no per màquina. "La CPU de meteo-01" deixa de significar res quan hi ha quinze instàncies efímeres; el que importa és el percentil i la distribució.
Què es perd en depurar? Força, i convé dir-ho: no pots entrar a mirar /proc en una instància que ja no existeix; no pots llançar strace sobre un procés que va morir fa deu minuts; no pots reproduir l'estat exacte d'un disc efímer esborrat. La compensació és que pots conservar la instància malalta en quarantena en lloc de matar-la, que és la tècnica que cal tenir escrita al procediment abans de necessitar-la.
Cost i densitat com a criteri de disseny
En un servidor físic, el cost és una inversió feta fa dos anys i no influeix en el disseny diari. Al núvol, cada decisió tècnica té una factura mensual, i això converteix el cost en un criteri d'arquitectura de ple dret.
Algunes relacions que convé interioritzar:
- Sobredimensionar surt car i és invisible. Peticions inflades en un manifest no produeixen cap error: produeixen nodes al 15 % d'ús i una factura triple. Mesurar l'ús real i ajustar és una tasca d'enginyeria, no de comptabilitat.
- La transferència de dades es paga, i sobretot la de sortida. Moure els fitxers diaris entre zones o cap a internet pot costar més que emmagatzemar-los. Col·locar el còmput al costat de les dades deixa de ser una qüestió de latència i passa a ser de diners.
- Les classes d'emmagatzematge importen molt. Ja ho vam veure: els dies tancats en emmagatzematge fred costen una fracció del que costen en volums de blocs.
- Les instàncies interrompibles (spot) costen entre un 60 % i un 90 % menys a canvi que te les puguin prendre amb un avís de dos minuts. Per a l'
agregador, que és una tasca per lots reprenible, són ideals. Per ameteo-api, no. - La densitat és estalvi. Cada contenidor que hi cap de més en un node és un node menys per pagar; aquí és on el cost base d'1-10 MB d'un contenidor davant dels 200-500 MB d'una VM es converteix en euros.
Cas final: migrar Meteora
Decisió a decisió, amb la justificació explícita:
| Peça | Decisió | Per què |
|---|---|---|
meteo-api |
Contenidor en un servei gestionat, 3 rèpliques en 2 zones, autoescalat per peticions/s, darrere d'un balancejador amb TLS | Sense estat, és el cas ideal de "bestiar"; amb 3 rèpliques se sobreviu a la pèrdua d'una zona |
ingestor |
Contenidor amb estat, rèpliques fixes amb afinitat per estació, cua gestionada al davant | Té ordre i afinitat: escalar-lo a cegues duplicaria o perdria lectures. La cua absorbeix els pics i desacobla |
agregador |
Tasca programada en instàncies interrompibles, amb reintent | Per lots, reprenible i tolerant a interrupció: estalvi del 70-90 % sense risc |
| Fitxer del dia | Volum de blocs amb IOPS aprovisionades, escriptura en lots de 512 lectures | Redueix de 8.000 a ~16 escriptures/s: la diferència entre funcionar i ofegar-se |
| Dies tancats | Objectes comprimits, amb transició automàtica a classe freda als 30 dies | Només es llegeixen sencers; el cost baixa un ordre de magnitud |
| Còpies de seguretat | Objectes en una altra regió, amb versionat i immutabilitat | És la 3-2-1 de 05-03; la retenció forçada pel proveïdor és l'única defensa real contra el segrest de dades |
meteora.conf |
Gestor de secrets, llegit en arrencar amb la identitat de la instància | Mai a la imatge ni al user-data, pel que hem vist a l'apartat 6 |
| SO dels nodes | Distribució mínima i immutable, actualització A/B | Superfície mínima i actualitzacions reversibles; ningú no entra per SSH a un node |
| Xarxa | Subxarxa privada per a tot; només el balancejador a la pública; grups de seguretat que es referencien entre si | Mínima exposició, i regles que sobreviuen a l'autoescalat |
| Registres i mètriques | Sortida estàndard → agent → col·lector extern, amb context de núvol | La instància pot no existir quan la vagis a llegir |
| Base de dades d'agregats | Servei gestionat amb rèplica en una altra zona | És la mascota del sistema: millor que la cuidi qui té guàrdies 24×7 |
I el que no convé migrar, que és igual d'important:
- L'emmagatzematge històric complet, tal com està. Moure cinc anys de fitxers diaris a volums de blocs seria caríssim i absurd: van a objectes, comprimits i en classe freda. Migrar "igual que estava" és l'error clàssic.
- La memòria cau a
/dev/shm/meteora-cachecom a peça compartida. En una màquina tenia sentit; amb rèpliques en diverses zones, una memòria cau local per instància és incoherent. O s'accepta que cada rèplica tingui la seva (si és reconstruïble i tolerant a estar desfasada), o es fa servir una memòria cau en xarxa. - El cron i els scripts de manteniment fets a mà. No sobreviuen a instàncies efímeres: passen a tasques programades de l'orquestrador.
- La FIFO
/run/meteora/lectures.fifoentre serveis. És IPC local (03-03) i només funciona dins d'una màquina; entre instàncies cal una cua de debò, amb persistència i reintents. - Les dades regulades fora de la seva jurisdicció. Si hi ha obligacions de residència de dades, la regió no és una decisió tècnica sinó legal, amb les implicacions de 05-04.
- I potser res, si el cas no ho justifica. Un servei estable, amb càrrega previsible i sense necessitat d'elasticitat pot sortir més car i més fràgil al núvol. El núvol es paga amb diners i amb complexitat; tots dos s'han de justificar.
Errors Habituals i Consells
Tractar les instàncies com a mascotes. Instal·lar a mà, configurar per SSH i confiar que la màquina continuï allà. La primera substitució automàtica s'endú per davant tots aquests canvis i ningú no els sap reconstruir.
Ficar secrets al user-data. És llegible des de dins de la instància per qualsevol procés a través del servei de metadades. Un secret allà és un secret publicat.
No protegir el servei de metadades. Un SSRF a l'aplicació es converteix en robatori de les credencials del rol de la instància; és el patró exacte d'una de les bretxes més grans conegudes. Exigeix la versió amb token, bloqueja l'accés des d'on no calgui i redueix els permisos del rol.
Suposar que el volum de blocs rendeix com un SSD local. És 5-10 vegades pitjor en latència i té un sostre d'IOPS que has contractat. Dissenya l'aplicació per agrupar escriptures abans de migrar, no després.
Muntar emmagatzematge d'objectes com si fos un disc. No hi ha escriptura parcial, ni bloqueig, ni fsync, ni reanomenament barat, i la latència és mil vegades més gran. Fes-lo servir amb la seva API.
Confondre peticions amb límits. Les peticions decideixen on et col·loquen i què se't reserva; els límits decideixen quan t'estrangulen o et maten. Peticions inflades donen clústers caríssims al 15 % d'ús; límits de memòria massa baixos donen reinicis amb codi 137 sense cap traça.
Oblidar que l'escalat automàtic triga. Si el teu pic arriba en 30 segons i la instància en triga 90 a arrencar, has escalat tard. Escala per una mètrica avançada i mantén coixí.
Dependre només dels registres locals. En un entorn efímer, el registre que no ha sortit de la màquina és un registre que s'ha perdut.
Consell: comença per l'estat. Abans de migrar res, fes l'inventari d'on viu cada dada i de quina és la seva font de la veritat. Tot el que no té estat migra fàcil; tota la resta és on són les decisions difícils.
Consell: prova de matar una instància expressament. En un entorn de proves, destrueix una rèplica de meteo-api en horari laboral i observa què passa. Si el servei no es recupera sol en menys d'un minut, el teu disseny encara tracta aquella instància com una mascota. És l'única manera de saber-ho abans que passi de debò.
Consell: posa una alarma de cost el primer dia. Un bucle d'escalat mal configurat, un volum oblidat o una transferència entre regions poden multiplicar la factura sense generar ni un sol error.
Exercicis
Exercici 1: escriure el cloud-config d'una rèplica de l'agregador
Escriu un fitxer #cloud-config complet que aprovisioni una instància per executar l'agregador, complint: (a) usuari de servei meteora amb UID 990, sense shell i amb la contrasenya blocada; (b) un compte d'operació amb clau pública i sudo limitat a reiniciar el servei; (c) un disc addicional formatat en ext4 i muntat a /var/lib/meteora amb les opcions del curs; (d) tallafocs amb política de denegació i només SSH des de la subxarxa privada; (e) el fitxer /etc/meteora/meteora.conf en mode 600 sense secrets, explicant d'on surten; (f) actualitzacions de seguretat automàtiques. Justifica cada bloc i assenyala tres coses que deliberadament no hi poses i per què.
Exercici 2: dimensionar recursos i diagnosticar un pod
meteo-api es desplega amb aquest manifest en nodes de 4 vCPU i 8 GiB:
Mesurat en producció, cada rèplica fa servir de manera sostinguda 0,2 vCPU i 300 MiB, amb pics de 0,8 vCPU i 450 MiB.
(a) Quantes rèpliques caben per node amb aquest manifest, i quantes n'hi cabrien amb peticions ajustades? Calcula el malbaratament i el seu impacte en el nombre de nodes necessaris per a 30 rèpliques. (b) Proposa valors de requests i limits justificats. (c) Després del canvi, alguns pods comencen a reiniciar-se amb codi 137 i altres mostren latència p99 molt alta sense reiniciar-se: explica què li passa a cada grup, quin fitxer de cgroup ho confirma i com ho corregeixes. (d) Explica per què posar requests igual a limits en memòria és bona idea però en CPU sol no ser-ho.
Exercici 3: decidir l'emmagatzematge de Meteora al núvol
Meteora genera un fitxer diari de 17.280.000 bytes (720.000 lectures × 24 B). Les consultes són: el 92 % sobre les últimes 48 hores, el 7 % sobre l'últim mes i l'1 % sobre l'històric de cinc anys. L'ingestor rep 8.000 lectures per segon. El volum de blocs bàsic ofereix 3 IOPS per GB.
(a) Calcula el volum anual de dades crues i comprimides (factor 4:1), i dissenya la ubicació de cada conjunt de dades amb la seva classe d'emmagatzematge. (b) Calcula les IOPS que necessita l'ingestor escrivint lectura a lectura i agrupant en lots de 512, i digues quina mida de volum bàsic caldria en cada cas només per assolir aquestes IOPS. (c) Justifica per què el fitxer del dia en curs no pot estar en emmagatzematge d'objectes, amb almenys tres raons tècniques concretes. (d) Dissenya la política de còpies de seguretat complint la regla 3-2-1 de 05-03 i explica què afegeix la immutabilitat davant d'un segrest de dades.
Solucions
Solució 1
#cloud-config
hostname: agregador-01
timezone: Europe/Madrid
users:
- name: meteora # (a) compte de servei
uid: 990
gid: 990
system: true
shell: /usr/sbin/nologin
lock_passwd: true
- name: operador # (b) compte d'operació
groups: [sudo]
shell: /bin/bash
lock_passwd: true
sudo: ["ALL=(ALL) NOPASSWD:/usr/bin/systemctl restart agregador"]
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... operador@meteora
package_update: true
packages: [nftables, chrony, unattended-upgrades]
disk_setup: # (c) disc de dades
/dev/nvme1n1: {table_type: gpt, layout: true, overwrite: false}
fs_setup:
- {device: /dev/nvme1n1, partition: 1, filesystem: ext4, label: meteora-dades}
mounts:
- [LABEL=meteora-dades, /var/lib/meteora, ext4,
"defaults,noatime,nosuid,nodev,data=ordered", "0", "2"]
write_files:
- path: /etc/nftables.conf # (d) tallafocs
permissions: '0644'
content: |
table inet filtre {
chain entrada {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
ip saddr 10.0.0.0/16 tcp dport 22 accept
}
}
- path: /etc/meteora/meteora.conf # (e) configuració SENSE secrets
owner: meteora:meteora
permissions: '0600'
content: |
[general]
dades = /var/lib/meteora/lectures
# secrets: es llegeixen del gestor en arrencar, amb la identitat de la instància
- path: /etc/apt/apt.conf.d/20auto-upgrades # (f)
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
runcmd:
- [install, -d, -o, meteora, -g, meteora, -m, '0750', /var/lib/meteora/lectures]
- [systemctl, enable, --now, nftables]
- [systemctl, enable, --now, unattended-upgrades]Justificació. L'UID 990 explícit és imprescindible perquè el volum es comparteix per número, no per nom (mateix motiu que al Dockerfile de 06-02). lock_passwd: true en tots dos comptes implanta el "només clau pública" de 05-02, i el sudo acotat a una ordre concreta aplica el mínim privilegi de 05-01 —recordant-ne el límit: acota el que s'executa, no el que es pot aconseguir—. Les opcions de muntatge noatime,nosuid,nodev són l'enfortiment de 04-03 declarat, no editat a mà. El tallafocs amb policy drop i SSH restringit a la subxarxa privada és defensa en profunditat a més del grup de seguretat. I les actualitzacions automàtiques tanquen la primera mesura de 05-03.
Tres coses que deliberadament no hi van:
- Cap secret, perquè el user-data és llegible per qualsevol procés de la instància via
169.254.169.254/latest/user-data: posar-l'hi és publicar-lo. Es llegeix del gestor de secrets en arrencar, autenticant-se amb el rol de la instància. - Cap clau privada SSH ni certificat TLS, pel mateix motiu. Només la clau pública de l'operador.
- Cap instal·lació pesada d'aplicació (compilar, descarregar artefactes grans, configurar a mà). Això va a la imatge, construïda i versionada, no a l'arrencada: si va aquí, cada instància triga minuts a estar a punt, depèn que els repositoris responguin i deixa de ser reproduïble —és infraestructura mutable disfressada—.
Solució 2
(a) Càlcul de densitat. Amb requests: 2000m / 4Gi en nodes de 4 vCPU i 8 GiB: per CPU hi caben 2 pods, per memòria n'hi caben 2 (deixant a més marge per al sistema del node, en realitat 1). Prenguem 2 pods per node en el millor dels casos: per a 30 rèpliques calen 15 nodes.
Amb peticions ajustades a l'ús real (per exemple 300m / 512Mi): per CPU hi caben 13 pods, per memòria 16; el límit és la CPU, uns 12 pods per node deixant marge per al sistema. Per a 30 rèpliques n'hi ha prou amb 3 nodes.
El malbaratament és de 5 vegades: es reserven 2000m per fer-ne servir 200m, és a dir s'aprofita el 10 % del que s'ha reservat. I com que el planificador col·loca segons les peticions i no segons l'ús, el clúster apareixerà amb nodes al 5-10 % de CPU real i tot i així "ple", incapaç d'acceptar més pods. És la causa número u de factures desproporcionades.
(b) Valors proposats:
Justificació: la petició de CPU se situa una mica per damunt de l'ús sostingut (0,2 vCPU) perquè el planificador reservi el necessari sense inflar; el límit de CPU es posa folgat (1 vCPU) per absorbir els pics de 0,8 sense estrangular. En memòria, petició i límit iguals a 512 MiB, amb marge sobre el pic de 450 MiB, perquè la memòria no és comprimible.
(c) Els dos símptomes i la seva causa:
- Els pods que reinicien amb codi 137 estan sent morts per l'OOM killer del cgroup: el seu consum real supera
memory.max. El 137 és 128 + 9 (SIGKILL) i l'estat del pod seràOOMKilled. Es confirma ambmemory.events(campoom_killdiferent de zero) o amb l'esdeveniment del pod. Correcció: apujar el límit de memòria per damunt del pic real mesurat —potser el pic de 450 MiB no cobria tots els casos— i afegir unmemory.highequivalent per tenir pressió abans que mort. - Els pods amb p99 alta que no reinicien estan estrangulats per CPU: han esgotat la seva quota
cpu.maxdins del període i queden aturats fins al següent. Es confirma ambnr_throttleddavant denr_periodsacpu.stat, exactament com a 06-02. Correcció: apujar el límit de CPU o ajustar el nombre de fils de l'aplicació a la quota; si l'únic que es buscava era prioritat, treure el límit i confiar en el pes derivat de la petició.
(d) Per què requests == limits és bona idea en memòria i dolenta en CPU. La memòria no és comprimible: no es pot "anar més a poc a poc" en memòria, o la tens o et maten. Igualar petició i límit garanteix que el que el planificador et va reservar és exactament el que pots fer servir, evita l'OOM per sobrecompromís del node i dona la classe de servei més estable. La CPU, en canvi, sí que és comprimible: es pot repartir en el temps. Igualar petició i límit en CPU malbarata la capacitat ociosa del node —el pod no pot aprofitar pics encara que hi hagi nuclis lliures— i provoca estrangulament evitable. L'habitual és petició ajustada a l'ús sostingut i límit generós o fins i tot absent en càrregues de confiança.
Solució 3
(a) Volum i ubicació. Diari: 17.280.000 B ≈ 16,5 MiB. Anual: 17.280.000 × 365 ≈ 6,3 GB crus, i amb compressió 4:1 uns 1,6 GB/any. En cinc anys, 7,9 GB comprimits: una quantitat ridícula, cosa que reforça que el criteri no ha de ser l'espai sinó la latència i el patró d'accés.
| Conjunt | Ubicació | Classe | Per què |
|---|---|---|---|
| Dia en curs + 48 h (92 % de consultes) | Volum de blocs amb IOPS aprovisionades | Estàndard | Escriptura contínua i lectura de baixa latència |
| Últim mes (7 %) | Objectes, sense comprimir o amb compressió lleugera | Estàndard/accés infreqüent | Consultes ocasionals, tolera desenes de ms |
| Històric de 5 anys (1 %) | Objectes comprimits | Fred / arxiu | Es consulta molt poc; cost mínim |
| Agregats horaris | Base de dades gestionada | — | Accés aleatori i consultes analítiques |
(b) IOPS.
- Lectura a lectura: 8.000 escriptures/s → 8.000 IOPS. Amb 3 IOPS/GB caldria un volum de 2.667 GB (uns 2,7 TB) per emmagatzemar 16,5 MiB al dia. És absurd: s'estaria pagant un volum enorme només per comprar IOPS.
- En lots de 512 lectures (512 × 24 = 12.288 B per escriptura): 8.000 / 512 ≈ 15,6 IOPS. Amb 3 IOPS/GB n'hi ha prou amb ~6 GB, i qualsevol volum raonable (per exemple 100 GB, amb 300 IOPS) hi sobra amb un marge de 20 vegades.
La conclusió és la de la lliçó: agrupar escriptures no és una microoptimització, és un requisit de disseny al núvol. El cost de l'agrupació és una finestra de pèrdua —les lectures del lot en curs si la instància mor—, que s'acota amb un fsync periòdic per temps a més de per mida, o posant una cua persistent al davant.
(c) Per què el dia en curs no pot anar en objectes, amb tres raons tècniques:
- No hi ha escriptura parcial ni
append. Afegir una lectura al final exigiria reescriure l'objecte sencer (16,5 MiB) cada vegada: 8.000 vegades per segon és impossible i costaria una fortuna en peticions. - La latència és mil vegades pitjor. 20-100 ms per operació davant dels microsegons d'un
writelocal; amb 8.000 escriptures/s, ni de bon tros. - No hi ha
fsync, ni bloqueig, ni semàntica POSIX. No es pot garantir la durabilitat d'un registre concret com a 04-05, ni coordinar escriptors concurrents, ni fer servir les eines del sistema de fitxers.
I una quarta raó de cost: l'emmagatzematge d'objectes es factura per petició, així que 8.000 peticions per segon serien més cares que tota la resta junta.
(d) Política 3-2-1 amb immutabilitat.
- 3 còpies: la del volum de blocs (producció), la d'objectes a la regió principal i la d'objectes en una altra regió.
- 2 mitjans diferents: volum de blocs i emmagatzematge d'objectes, que són sistemes independents amb modes de fallada diferents.
- 1 fora de l'emplaçament: la còpia en una altra regió cobreix la pèrdua d'una regió sencera.
- Verificació: suma de verificació en escriure i comprovació periòdica; i sobretot, prova de restauració trimestral amb el temps mesurat, perquè una còpia no provada no és una còpia (05-03).
Què afegeix la immutabilitat. Un segrest de dades amb les credencials de la instància pot xifrar el volum i també esborrar o sobreescriure els objectes, perquè té els mateixos permisos que l'aplicació. Amb versionat més bloqueig d'objectes en mode de compliment, el proveïdor rebutja qualsevol esborrament o modificació fins que expiri la retenció, fins i tot si la petició arriba amb credencials vàlides i d'administrador. Això treu la còpia de l'abast de l'atacant, que és exactament el mateix raonament que a 05-04 portava a enviar els registres a un col·lector extern amb credencials de només enviament. La mesura es completa amb credencials separades per a les còpies, diferents de les de l'aplicació, i amb alertes davant de qualsevol intent d'esborrament.
Conclusió
Quan la màquina deixa de ser un objecte físic i passa a ser una crida a una API, el que canvia no és l'administració sinó el model mental: la instància s'aprovisiona en segons, viu hores o dies, i pot desaparèixer sense avís, amb un compromís de disponibilitat individual que ronda el 99,5 %. D'aquí la regla que governa tota la lliçó —no intentis que la màquina no falli; dissenya perquè la seva fallada no importi— i la metàfora del bestiar davant de les mascotes, amb les seves conseqüències incòmodes: res de canvis manuals, cap dada important al disc de la instància, SSH com a excepció i no com a eina, i la reinstal·lació com a resposta normal. Amb el matís honest que no tot pot ser bestiar: el que té estat continua sent una mascota, i l'objectiu és concentrar-lo en les mínimes peces possibles.
Els models de servei dibuixen on queda la frontera del sistema operatiu: a IaaS és teu sencer —i amb ell els pedaços, l'enfortiment de 05-03, el tallafocs i els registres: una instància acabada de crear és tan insegura com un servidor acabat d'instal·lar—, i a mesura que es puja a CaaS, PaaS i FaaS es guanya operació i es perden, molt literalment, les eines d'aquest curs. L'arrencada d'una instància encadena imatge, tipus, volum arrel, xarxa i cloud-init, i aquest darrer és la peça que converteix una plantilla genèrica en el teu servidor: usuaris amb clau pública, UID 990 explícit perquè els volums es comparteixen per número, muntatges amb noatime,nosuid,nodev declarats en comptes d'editats, i mai un secret, perquè el user-data és llegible des de dins a través del servei de metadades —el mateix endpoint que lliura les credencials del rol i que converteix un SSRF qualsevol en un robatori de credencials, com a la bretxa de Capital One—.
D'aquí surt la infraestructura immutable: en lloc de modificar servidors es construeixen imatges noves, cosa que elimina per construcció la deriva de configuració i converteix la reversió en una cosa avorrida, a canvi de complicar la depuració —i d'aquí la tècnica de treure del balancejador sense destruir, que enllaça amb la preservació d'evidències de 05-04—. Els sistemes operatius mínims i immutables porten la idea a l'extrem: sense shell no hi ha reverse shell, sense curl no hi ha segona fase, sense compilador no hi ha exploit local; s'eliminen classes senceres d'atac a canvi d'haver de depurar amb contenidors efímers que entren als namespaces del procés, el nsenter de 06-02 industrialitzat.
En emmagatzematge, els números manen: el volum de blocs en xarxa és 5-10 vegades pitjor en latència que un NVMe local i té un sostre d'IOPS que es contracta, cosa que converteix l'agrupació d'escriptures en un requisit de disseny —de 8.000 IOPS a 16 amb lots de 512 lectures—; l'efímer és rapidíssim i desapareix, així que només val per al que és reconstruïble; i l'emmagatzematge d'objectes no és un sistema de fitxers: sense escriptura parcial, sense fsync, sense bloqueig, amb reanomenament que copia i latències de desenes de mil·lisegons, per la qual cosa muntar-lo com a disc és gairebé sempre un error. Aplicat a Meteora: dia en curs en blocs, dies tancats en objectes comprimits amb transició a classe freda, i còpies en una altra regió amb versionat i immutabilitat, que és l'única defensa real contra un segrest de dades que té les teves credencials.
I la peça que tanca el cercle del curs: l'orquestració és un sistema operatiu del clúster. El pod és el procés, el planificador del clúster és el planificador de 02-02 un nivell més amunt, el kubelet és l'init del node, i les requests i limits d'un manifest es tradueixen literalment a cpu.weight, cpu.max i memory.max a /sys/fs/cgroup —d'aquí que passar-se de CPU estranguli i passar-se de memòria mati amb un 137—. El planificador col·loca segons les peticions i no segons l'ús, cosa que fa de les peticions inflades la causa número u de clústers caríssims al 15 %. Al voltant, Firecracker i gVisor demostren que la frontera entre VM i contenidor ha deixat de ser binària (una microVM que arrenca en 125 ms retallant tot el que QEMU emulava de més), l'escalat automàtic ensopega sempre amb l'arrencada en fred i l'oscil·lació, l'observabilitat exigeix treure els registres de la instància perquè la instància pot no existir quan els vagis a llegir, i el cost es converteix en criteri d'arquitectura de ple dret.
Ens queda una família sencera de sistemes operatius que va justament en la direcció contrària a tot això. Aquí hem parlat de màquines que sobren, que es creen per API i que es llencen quan fan nosa; d'escalar cap enfora quan falta capacitat; de latències mesurades en mil·lisegons i de fallades que es toleren reintentant. Però les estacions meteorològiques de Meteora —aquells dispositius encastats que a 01-03 vam decidir que portarien un RTOS— no poden fer res d'això: tenen 64 KB de RAM, funcionen amb una bateria que ha de durar mesos, no poden demanar una altra unitat quan els falta memòria, i si el mostreig del sensor arriba 10 mil·lisegons tard, la dada està malament, no pas "arriba a poc a poc". I a l'altre extrem del mateix problema, el telèfon des del qual un usuari consulta l'API de Meteora executa un Linux que ha hagut de reinventar el seu IPC, la seva gestió de memòria i el seu model de permisos perquè la bateria i l'absència de swap ho canvien tot.
Dues famílies amb la mateixa arrel que hem estudiat i amb restriccions oposades a les del servidor. És Sistemes Operatius Mòbils i de Temps Real, i tanca el mòdul.
Fonaments de Sistemes Operatius
Mòdul 1: Introducció als Sistemes Operatius
- Conceptes Bàsics de Sistemes Operatius
- Història i Evolució dels Sistemes Operatius
- Tipus de Sistemes Operatius
- Funcions Principals d'un Sistema Operatiu
- Arquitectura del Nucli: Monolític, Microkernel i Híbrid
- Mode Usuari, Mode Nucli i Crides al Sistema
Mòdul 2: Gestió de Recursos
- Gestió de Processos
- Planificació de la CPU
- Gestió de Memòria
- Memòria Virtual i Paginació
- Gestió d'Emmagatzematge
- Gestió de Dispositius
- Controladors, Interrupcions i Operacions d'E/S
Mòdul 3: Concurrència
- Conceptes de Concurrència
- Fils i Processos
- Comunicació entre Processos (IPC)
- Sincronització i Exclusió Mútua
- Problemes Clàssics de Concurrència
- Interbloquejos: Prevenció, Detecció i Recuperació
Mòdul 4: Estructures de Fitxers
- Sistemes de Fitxers
- Estructures de Directoris
- Particions, Muntatge i Sistema de Fitxers Virtual
- Gestió de Fitxers
- Assignació d'Espai, Journaling i Integritat
- Seguretat i Permisos de Fitxers
Mòdul 5: Protecció i Seguretat del Sistema
- Principis de Protecció i Control d'Accés
- Usuaris, Autenticació i Escalada de Privilegis
- Amenaces Habituals i Enfortiment del Sistema
- Auditoria, Registres i Resposta a Incidents
Mòdul 6: Virtualització i Contenidors
- Virtualització: Hipervisors i Màquines Virtuals
- Contenidors: Namespaces i cgroups
- El Sistema Operatiu al Núvol
- Sistemes Operatius Mòbils i de Temps Real
