La lliçó anterior va acabar amb una pregunta que algú de l'equip anava a fer aquesta mateixa setmana: tothom parla de Kubernetes. És l'estàndard de facto de l'orquestració de contenidors, té un ecosistema enorme, funciona igual a qualsevol núvol i hi ha molta gent que el sap fer servir. Si MercadoFresco acaba de moure tota la seva botiga a contenidors i s'ha quedat a ECS, s'està equivocant?
Aquesta lliçó respon amb dades. Veuràs què és Kubernetes de debò i què resol que ECS no resol, quina part gestiona Amazon EKS i què continua sent feina teva, com es desplega la botiga de MercadoFresco amb manifests complets, i quin és el cost que gairebé mai apareix a les comparatives: la feina recurrent de les actualitzacions de versió. Al final, la decisió raonada de MercadoFresco i els criteris objectius que la canviarien. I amb ella, el tancament del mòdul i el salt al mòdul 11.
Avís de cost. El pla de control d'EKS costa 0,10 USD per hora i clúster, uns 73 USD al mes, independentment de la mida. Amb suport estès —quan la versió de Kubernetes surt del suport estàndard— passa a 0,60 USD per hora, uns 438 USD al mes, i és un càrrec automàtic que sorprèn molta gent. A això s'hi sumen els nodes (EC2 o Fargate), el balancejador i els complements. Un clúster de proves oblidat és dels residus més cars del curs: segueix la neteja del final. Dades i identificadors ficticis.
Contingut
- Què és Kubernetes i què resol que ECS no
- Vocabulari mínim però real
- El model declaratiu i el bucle de reconciliació
- Què gestiona EKS i què continua sent teu
- Opcions de còmput: nodes, Fargate i Auto Mode
- Crear un clúster amb
eksctli amb CDK kubectli l'accés al clúster- Autenticació: entrades d'accés enfront d'
aws-auth - IRSA i EKS Pod Identity: permisos d'AWS per a un pod
- Els manifests de la botiga de MercadoFresco
- Ingress i l'AWS Load Balancer Controller
- Autoescalat: HPA, Cluster Autoscaler i Karpenter
- Complements: per què un EKS buit no serveix de res
- Actualitzacions de versió: el cost ocult
- Observabilitat: Container Insights, Prometheus i Grafana
- ECS enfront d'EKS: la comparativa honesta
- La decisió de MercadoFresco i què la canviaria
- Cost i neteja
- Errors habituals i consells
- Exercicis
- Tancament del mòdul i transició al mòdul 11
Què és Kubernetes i què resol que ECS no
Kubernetes és un orquestrador de contenidors de codi obert, nascut a Google i donat a la Cloud Native Computing Foundation. Fa el mateix que ECS —mantenir contenidors en execució, repartir-los entre màquines, reposar-los, exposar-los per xarxa— amb una diferència fonamental de disseny: Kubernetes és una plataforma extensible amb una API pròpia, no un servei d'un proveïdor.
Aquesta diferència produeix tres capacitats que ECS no té:
- Portabilitat real. Un manifest de Kubernetes funciona a EKS, a Google Kubernetes Engine, a Azure Kubernetes Service, en un clúster propi i al portàtil del Luis amb
kind. Una definició de tasca d'ECS només funciona a AWS. Per a MercadoFresco això no és urgent avui, però és l'argument amb més pes a favor d'EKS. - Un ecosistema que resol problemes que tu no vols resoldre. Existeixen milers de components llestos per instal·lar: gestió de certificats (
cert-manager), desplegaments progressius (Argo Rollouts, Flagger), GitOps (Argo CD, Flux), malles de servei (Istio, Linkerd), operadors que gestionen bases de dades, cues o motors de cerca com si fossin recursos natius. A ECS, gairebé tot això o bé ho posa AWS o bé ho escrius tu. - Extensibilitat mitjançant l'API. Amb CRD (Custom Resource Definitions) i operadors es poden crear tipus de recurs propis. És el que permet escriure
kubectl applysobre un fitxer que declara «vull un clúster de Kafka amb tres rèpliques» i que un operador el construeixi i el mantingui. ECS no en té equivalent.
I produeix un cost que cal anomenar amb la mateixa claredat: Kubernetes és substancialment més complex. Hi ha més conceptes, més peces per instal·lar, més configuració que pot estar malament i més versions per actualitzar. La pregunta correcta no és «quin és millor?» sinó «el problema que tinc justifica aquesta complexitat?».
Vocabulari mínim però real
Aquests són els objectes que cal conèixer per llegir un manifest sense perdre's. La columna de la dreta ancora cadascun al que ja saps dels mòduls anteriors.
| Objecte | Què és | Equivalent aproximat |
|---|---|---|
| Clúster | El conjunt: pla de control més nodes | Clúster d'ECS |
| Node (node) | Una màquina que executa càrregues; sol ser una instància EC2 | Instància del clúster d'ECS |
| Pod | La unitat mínima: un o diversos contenidors que comparteixen xarxa i emmagatzematge | Tasca d'ECS |
| ReplicaSet | Garanteix que hi ha N pods iguals | La part del servei d'ECS que reposa |
| Deployment | Gestiona ReplicaSets i orquestra actualitzacions progressives | Servei d'ECS |
| Service | Nom i IP estables per a un conjunt de pods | Cloud Map o ECS Service Connect |
| Ingress | Encaminament HTTP extern cap a Services | Regles d'un ALB (03-03) |
| Namespace | Partició lògica dins del clúster | Agrupació per projecte o entorn |
| ConfigMap | Configuració no sensible com a parells clau-valor | environment de la definició de tasca |
| Secret | Configuració sensible (codificada en base64, no xifrada per omissió) | secrets des de Secrets Manager |
| DaemonSet | Un pod per node | No existeix a Fargate; sí a ECS sobre EC2 |
| Job / CronJob | Tasca que acaba, puntual o programada | run-task / EventBridge Scheduler |
Dos advertiments sobre aquesta taula, perquè són font constant d'errors:
- Un
Secretde Kubernetes no està xifrat per omissió. Està codificat en base64, que no és xifratge: qualsevol amb permís de lectura sobre el namespace el veu en clar. Es resol amb xifratge a etcd mitjançant KMS i, encara millor, amb el controlador CSI de secrets que porta els valors des de Secrets Manager (més avall). - El
Deploymentno és el servei i elServiceno és el Deployment. El Deployment gestiona els pods; el Service els dona un nom estable. A ECS, totes dues coses són dins de l'objecte «servei», i aquesta fusió és una de les raons per les quals ECS és més simple i menys flexible.
El model declaratiu i el bucle de reconciliació
Kubernetes no executa ordres: compara estats. Tu declares l'estat desitjat i un conjunt de controladors treballa contínuament perquè l'estat real hi coincideixi.
graph LR
U["kubectl apply -f<br/>manifest.yaml"] --> API["Servidor d'API<br/>pla de control"]
API --> ETCD[("etcd<br/>estat desitjat")]
API --> CM["Controladors<br/>(Deployment, ReplicaSet...)"]
CM -->|"compara desitjat<br/>amb real"| API
CM --> SCH["Planificador<br/>tria node"]
SCH --> KL["kubelet al node"]
KL --> POD["Pods en execucio"]
POD -->|"estat real"| API
API -.->|"diferencia detectada"| CM
La conseqüència pràctica és que esborrar un pod a mà no serveix de res: el ReplicaSet detecta que falten rèpliques i en crea un altre en segons. És la mateixa lògica del desiredCount d'ECS, generalitzada a tots els objectes del sistema i exposada com una API que qualsevol pot estendre.
I la conseqüència cultural és més important: a Kubernetes el manifest és la infraestructura. Això encaixa de manera natural amb el que s'ha après al mòdul 9 i porta a GitOps: un repositori Git és la font de veritat i un agent al clúster (Argo CD o Flux) aplica el que hi hagi, revertint qualsevol canvi manual. És una manera de treballar més rigorosa que la del mòdul 8, i també una peça més per instal·lar, actualitzar i operar.
Què gestiona EKS i què continua sent teu
Amazon EKS és Kubernetes gestionat: AWS opera el pla de control i tu operes tota la resta. La llista concreta importa perquè gairebé totes les decepcions amb EKS vénen d'esperar més del que ofereix.
| AWS gestiona | Detall |
|---|---|
| El pla de control | Servidor d'API, planificador, controladors i etcd, replicats en tres AZ |
| La seva disponibilitat i escalat | Es dimensiona sol; no hi ha mestres per administrar |
Les còpies d'etcd |
Automàtiques; ni les veus ni les gestiones |
| El procés d'actualització de versió | Un botó o una comanda, amb validacions prèvies |
| La integració amb IAM | Autenticació d'usuaris i rols d'AWS contra el clúster |
| Els complements gestionats | VPC CNI, CoreDNS, kube-proxy, EBS CSI i altres, amb versions compatibles |
| Continua sent teu | Detall |
|---|---|
| Els nodes | El seu tipus, la seva AMI, el seu apedaçament i el seu reemplaçament (excepte Fargate o Auto Mode) |
| Decidir quan actualitzar | I provar-ho, i executar-ho, tres o quatre vegades l'any |
| La compatibilitat dels teus manifests | Les API de Kubernetes es retiren entre versions i trenquen coses |
| Tot el programari del clúster | Controlador de balancejadors, autoescalador, controlador de secrets, mètriques |
| La xarxa | VPC, subxarxes, grups de seguretat, assignació d'IP a pods |
| La seguretat dins del clúster | RBAC, polítiques de xarxa, polítiques de seguretat de pods |
| L'observabilitat | Mètriques, registres i traces, igual que a ECS |
La frase que cal retenir: EKS gestiona el pla de control, no el clúster. Un clúster d'EKS acabat de crear no pot desplegar res útil: li falta el controlador de balancejadors, l'autoescalador, el controlador de secrets i les mètriques. Aquesta distància entre «clúster creat» i «clúster operatiu» és on viu la major part de la feina.
Opcions de còmput: nodes, Fargate i Auto Mode
Els pods s'han d'executar en algun lloc, i EKS ofereix quatre models.
| Opció | Qui gestiona els nodes | Apedaçament | Escalat | Quan té sentit |
|---|---|---|---|---|
| Grups de nodes gestionats | AWS crea i substitueix; tu llances l'actualització | Guiat per AWS, sense tall si el configures | Cluster Autoscaler o Karpenter | El cas general |
| Nodes autogestionats | Tu, amb un ASG propi | Tot teu | Teu | AMI personalitzada, requisits molt concrets |
| EKS sobre Fargate | Ningú: no hi ha nodes | Cap | Per pod | Càrregues aïllades, sense DaemonSet |
| EKS Auto Mode | AWS gestiona nodes, escalat i pedaços | AWS, amb reciclatge automàtic | Integrat, basat en Karpenter | Qui vol EKS amb l'operació mínima |
EKS sobre Fargate funciona amb perfils de Fargate: es declara quins namespaces o etiquetes fan que un pod s'executi sense node. Té limitacions importants que cal conèixer abans de comptar-hi: no admet DaemonSet, ni emmagatzematge persistent diferent d'EFS, ni hostPort, ni pods privilegiats, i un pod per tasca de Fargate amb l'arrodoniment de recursos que això implica. La conseqüència pràctica és que molts complements —que s'instal·len com a DaemonSet— no poden executar-se sobre Fargate, així que gairebé sempre cal almenys un grup de nodes petit per a ells.
EKS Auto Mode és la resposta d'AWS a l'argument d'aquesta lliçó: gestiona els nodes, l'escalat, l'apedaçament i diversos complements essencials, reciclant els nodes automàticament cada cert temps. Redueix molt la feina operativa a canvi d'un recàrrec sobre el preu del còmput i de menys control. El que no elimina és la part que més pesa: continues decidint i executant les actualitzacions de versió de Kubernetes i continues sent responsable que els teus manifests siguin compatibles.
Crear un clúster amb eksctl i amb CDK
eksctl és l'eina oficial de la comunitat i la via més ràpida. És declarativa: se li dona un fitxer i construeix la VPC —o fa servir la teva—, el pla de control, els grups de nodes i els complements.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: eks-mercadofresco
region: eu-west-1
version: "1.31"
tags:
Proyecto: mercadofresco
Entorno: desarrollo
Componente: orquestacion
Propietario: plataforma
CentroCoste: tecnologia
vpc:
id: vpc-mercadofresco # es reutilitza la VPC del modul 3
subnets:
private:
eu-west-1a: { id: snet-mercadofresco-app-a }
eu-west-1b: { id: snet-mercadofresco-app-b }
public:
eu-west-1a: { id: snet-mercadofresco-publica-a }
eu-west-1b: { id: snet-mercadofresco-publica-b }
clusterEndpoints:
publicAccess: true # restringit per CIDR mes avall
privateAccess: true
publicAccessCIDRs: ["203.0.113.0/24"] # nomes la xarxa corporativa
managedNodeGroups:
- name: ng-mercadofresco-general
instanceTypes: ["m6g.large"] # Graviton, com a 10-02
amiFamily: AmazonLinux2023
minSize: 2
maxSize: 8
desiredCapacity: 3
privateNetworking: true # nodes nomes en subxarxes privades
volumeSize: 50
volumeType: gp3
labels: { rol: general }
updateConfig: { maxUnavailablePercentage: 25 }
addons:
- name: vpc-cni
version: latest
configurationValues: '{"env":{"ENABLE_PREFIX_DELEGATION":"true"}}'
- name: coredns
- name: kube-proxy
- name: aws-ebs-csi-driver
- name: eks-pod-identity-agent
iam:
withOIDC: true # imprescindible per a IRSA
serviceAccounts:
- metadata: { name: aws-load-balancer-controller, namespace: kube-system }
wellKnownPolicies: { awsLoadBalancerController: true }
cloudWatch:
clusterLogging:
enableTypes: ["api", "audit", "authenticator"]Quatre decisions d'aquest fitxer que mereixen atenció:
publicAccessCIDRsrestringit. Per omissió el punt d'enllaç del servidor d'API és accessible des de qualsevol IP d'internet —protegit per autenticació, però exposat—. Restringir-lo a la xarxa corporativa o passar a només accés privat és una de les primeres coses que revisa una auditoria.privateNetworking: true. Els nodes en subxarxes privades, coherent amb tot el que va fer MercadoFresco al mòdul 3 i amb el que s'ha après a 10-02 sobre punts d'enllaç de VPC. Els mateixos punts d'enllaç de la lliçó anterior són necessaris aquí.withOIDC: true. Sense el proveïdor OIDC no hi ha IRSA, i sense IRSA l'única manera de donar permisos d'AWS a un pod és el rol del node, que és un mal greu: tots els pods d'aquest node heretarien aquests permisos.ENABLE_PREFIX_DELEGATION. Sense això, cada pod consumeix una IP secundària de l'ENI del node i el límit de pods per node s'assoleix molt abans d'esgotar CPU o memòria. És l'equivalent a EKS de l'awsvpcTrunkingde 10-01, i sorprèn igual.
En CDK (09-02), l'equivalent és més curt però exigeix entendre el mateix:
const cluster = new eks.Cluster(this, 'MercadoFrescoEks', {
clusterName: 'eks-mercadofresco',
version: eks.KubernetesVersion.V1_31,
kubectlLayer: new KubectlV31Layer(this, 'CapaKubectl'),
vpc,
vpcSubnets: [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }],
defaultCapacity: 0, // els nodes es declaren a part
authenticationMode: eks.AuthenticationMode.API, // entrades d'acces, sense aws-auth
clusterLogging: [eks.ClusterLoggingTypes.API, eks.ClusterLoggingTypes.AUDIT],
});
cluster.addNodegroupCapacity('General', {
instanceTypes: [new ec2.InstanceType('m6g.large')],
amiType: eks.NodegroupAmiType.AL2023_ARM_64_STANDARD,
minSize: 2, maxSize: 8, desiredSize: 3,
subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
});
// Els manifests tambe son infraestructura: es despleguen amb la pila.
cluster.addHelmChart('LoadBalancerController', {
chart: 'aws-load-balancer-controller',
repository: 'https://aws.github.io/eks-charts',
namespace: 'kube-system',
values: { clusterName: cluster.clusterName, serviceAccount: { create: false, name: 'aws-load-balancer-controller' } },
});kubectl i l'accés al clúster
kubectl és el client. Es configura amb una comanda que escriu el context a ~/.kube/config fent servir les credencials d'AWS actuals:
aws eks update-kubeconfig --name eks-mercadofresco --region eu-west-1
kubectl get nodes # els 3 nodes a Ready
kubectl get pods -A # els pods del sistema: coredns, aws-node, kube-proxy
kubectl config current-context # verificar SEMPRE contra quin cluster apuntesL'última comanda sembla trivial i no ho és: kubectl apunta a l'últim clúster configurat, i kubectl delete deployment tienda no pregunta en quin entorn ets. És el cdk destroy --all de 09-02 amb una altra forma. La disciplina que ho evita és doble: comptes separats per entorn (09-04), de manera que les credencials de desenvolupament no puguin tocar el clúster de producció, i un indicador del context actiu al prompt del terminal.
Autenticació: entrades d'accés enfront d'aws-auth
Kubernetes té el seu propi sistema de permisos, RBAC, amb Role, ClusterRole, RoleBinding i ClusterRoleBinding. EKS connecta aquest sistema amb IAM: IAM diu qui ets, RBAC diu què pots fer dins del clúster.
Històricament aquesta connexió es feia amb un ConfigMap anomenat aws-auth, i era una font notòria d'incidents: un error de sintaxi en editar-lo podia deixar tothom fora del clúster de manera irreversible, sense més sortida que recrear-lo. Avui la forma correcta són les entrades d'accés (access entries), que són API d'AWS: es creen amb la CLI o amb CDK, s'auditen a CloudTrail i no depenen d'editar YAML a mà.
# L'equip de plataforma, administrador del cluster
aws eks create-access-entry --cluster-name eks-mercadofresco \
--principal-arn arn:aws:iam::333344445555:role/AWSReservedSSO_AdministracionPlataforma_abc \
--type STANDARD
aws eks associate-access-policy --cluster-name eks-mercadofresco \
--principal-arn arn:aws:iam::333344445555:role/AWSReservedSSO_AdministracionPlataforma_abc \
--access-scope type=cluster \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy
# Els desenvolupadors, nomes al seu namespace i sense poder esborrar el cluster
aws eks associate-access-policy --cluster-name eks-mercadofresco \
--principal-arn arn:aws:iam::333344445555:role/AWSReservedSSO_DesarrolloCompleto_def \
--access-scope type=namespace,namespaces=mercadofresco \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSEditPolicyEls conjunts de permisos són els de 09-04: AdministracionPlataforma, DesarrolloCompleto i AnalisisDatos. La correspondència queda neta: el mateix mecanisme d'identitat que governa els cinc comptes governa també el clúster, sense usuaris de Kubernetes paral·lels ni credencials a part. És un dels avantatges reals d'EKS enfront d'un Kubernetes autogestionat.
IRSA i EKS Pod Identity: permisos d'AWS per a un pod
L'equivalent exacte del rol de tasca d'ECS (10-01). Un pod de la botiga necessita enviar a cola-mercadofresco-pedidos i llegir mercadofresco-carritos, i necessita fer-ho amb permisos propis, no amb els del node.
| Mecanisme | Com funciona | Avantatges | Inconvenients |
|---|---|---|---|
| Rol del node | Tots els pods hereten el rol de la instància | Zero configuració | Inacceptable: qualsevol pod fa tot el que fa qualsevol altre |
| IRSA (rols per a comptes de servei) | Proveïdor OIDC del clúster + política de confiança que el referencia | Madur, funciona a tot arreu | Configuració per rol una mica laboriosa, lligada a un clúster |
| EKS Pod Identity | Un agent al node i una associació entre compte de servei i rol | Més simple, reutilitzable entre clústers, sense OIDC | Requereix el complement; no aplica a EKS sobre Fargate |
Amb Pod Identity, que és l'opció recomanada avui:
aws eks create-pod-identity-association --cluster-name eks-mercadofresco \
--namespace mercadofresco --service-account sa-tienda \
--role-arn arn:aws:iam::333344445555:role/rol-pod-mercadofresco-tiendaI la política de confiança del rol, que és el que canvia respecte a un rol normal:
{"Version": "2012-10-17", "Statement": [{
"Effect": "Allow",
"Principal": { "Service": "pods.eks.amazonaws.com" },
"Action": ["sts:AssumeRole", "sts:TagSession"]
}]}La política de permisos és literalment la mateixa que la del rol de tasca d'ECS a 10-01: sqs:SendMessage sobre la cua, dynamodb:*Item sobre la taula de carros i s3:GetObject sobre les fotos del catàleg. El mateix principi de mínim privilegi, diferent manera d'ancorar-lo a la càrrega.
Els manifests de la botiga de MercadoFresco
Aquí hi ha el que a ECS era una definició de tasca més un servei. Comencem pel Namespace, el ServiceAccount i el ConfigMap:
apiVersion: v1
kind: Namespace
metadata:
name: mercadofresco
labels: { proyecto: mercadofresco, entorno: desarrollo }
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-tienda
namespace: mercadofresco
# Sense anotacions: amb Pod Identity l'associacio es fa des de l'API d'AWS.
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cfg-tienda
namespace: mercadofresco
data:
ENTORNO: "desarrollo"
COLA_PEDIDOS: "cola-mercadofresco-pedidos"
TABLA_CARRITOS: "mercadofresco-carritos"El Deployment, que és el cor del desplegament:
apiVersion: apps/v1
kind: Deployment
metadata:
name: tienda
namespace: mercadofresco
labels: { app: tienda, proyecto: mercadofresco }
spec:
replicas: 3
revisionHistoryLimit: 5 # quantes revisions es poden revertir
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0 # equival a minimumHealthyPercent 100 d'ECS
maxSurge: 2 # equival a maximumPercent 200
selector:
matchLabels: { app: tienda }
template:
metadata:
labels: { app: tienda, proyecto: mercadofresco }
spec:
serviceAccountName: sa-tienda
# Reparteix els pods entre AZ: l'equivalent de spread per AZ a ECS.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels: { app: tienda }
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
terminationGracePeriodSeconds: 30 # equival a stopTimeout d'ECS
containers:
- name: tienda
image: 555566667777.dkr.ecr.eu-west-1.amazonaws.com/mercadofresco/tienda@sha256:9c1e...f4a2
ports:
- containerPort: 8080
name: http
envFrom:
- configMapRef: { name: cfg-tienda }
env:
- name: BD_CONTRASENA
valueFrom:
secretKeyRef: { name: sec-tienda-rds, key: password }
resources:
requests: { cpu: "500m", memory: "1Gi" } # el que el planificador reserva
limits: { cpu: "1000m", memory: "2Gi" } # el sostre dur
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: { drop: ["ALL"] }
volumeMounts:
- { name: temporal, mountPath: /tmp }
startupProbe: # dona temps a arrencar sense que liveness mati
httpGet: { path: /salud, port: 8080 }
periodSeconds: 5
failureThreshold: 12 # fins a 60 s per a la primera arrencada
readinessProbe: # decideix si rep transit
httpGet: { path: /salud, port: 8080 }
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe: # decideix si es reinicia el contenidor
httpGet: { path: /salud, port: 8080 }
periodSeconds: 20
timeoutSeconds: 3
failureThreshold: 3
lifecycle:
preStop:
exec: { command: ["sleep", "5"] } # marge perque l'ALB desregistri
volumes:
- name: temporal
emptyDir: { sizeLimit: 1Gi }Els punts que cal entendre d'aquest manifest:
- Les tres sondes són tres preguntes diferents i confondre-les causa incidents.
startupProberespon «ha acabat d'arrencar?» i suspèn les altres dues fins que encerta.readinessProberespon «pot rebre trànsit ara?» i la seva fallada treu el pod del balanceig sense matar-lo.livenessProberespon «està penjat?» i la seva fallada reinicia el contenidor. L'error clàssic és apuntarlivenessProbea un/saludque consulta Aurora: quan la base de dades va lenta, Kubernetes reinicia tots els pods alhora i converteix un problema de latència en una caiguda total. requestsilimitsno són el mateix.requestsés el que el planificador reserva per decidir en quin node cap el pod;limitsés el sostre. Si la CPU supera el límit, el pod s'estrangula (s'alenteix); si la memòria el supera, el kernel el mata amb OOM i veuràsOOMKilledals esdeveniments. Posarrequestsmolt per sota de l'ús real produeix nodes sobrecompromesos que cauen alhora.maxUnavailable: 0ambmaxSurge: 2és exactament el100/200d'ECS: mai no hi ha menys capacitat sana que la desitjada, a costa de pagar uns minuts de capacitat doble durant el desplegament.preStopamb una espera curta resol el mateix problema que el drenatge del grup de destinació: quan Kubernetes decideix acabar un pod, l'ALB pot trigar uns segons a deixar d'enviar-li trànsit. Sense aquesta espera, es perden peticions a cada desplegament.- El
Secretreferenciat no s'escriu a mà. MercadoFresco fa servir el controlador CSI de secrets amb el proveïdor d'AWS, que muntamercadofresco/produccion/rds/mfadmindes de Secrets Manager i opcionalment el sincronitza com aSecretde Kubernetes. Així el secret no viu a Git ni aetcden base64.
El Service, que dona als pods un nom estable:
apiVersion: v1
kind: Service
metadata:
name: svc-tienda
namespace: mercadofresco
spec:
type: ClusterIP # nomes intern: qui exposa a l'exterior es l'Ingress
selector: { app: tienda }
ports:
- port: 80
targetPort: 8080
name: httpIngress i l'AWS Load Balancer Controller
Un Ingress per si sol no fa res: és una declaració que necessita un controlador que la tradueixi a un balancejador real. A EKS, aquest controlador és l'AWS Load Balancer Controller, que crea i configura un ALB de debò (03-03) a partir de les anotacions.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ing-tienda
namespace: mercadofresco
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip # directe al pod, sense salt pel node
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-west-1:333344445555:certificate/abc-123
alb.ingress.kubernetes.io/healthcheck-path: /salud
alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:eu-west-1:333344445555:regional/webacl/waf-mercadofresco-cdn/abc
alb.ingress.kubernetes.io/tags: Proyecto=mercadofresco,Entorno=desarrollo,Componente=tienda,Propietario=plataforma,CentroCoste=tecnologia
alb.ingress.kubernetes.io/group.name: mercadofresco # diversos Ingress comparteixen un ALB
spec:
ingressClassName: alb
rules:
- host: tienda.mercadofresco.example
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-tienda
port: { number: 80 }Tres observacions que connecten amb mòduls anteriors. target-type: ip fa que l'ALB enviï trànsit directament a la IP del pod, sense passar pel NodePort del node: és l'equivalent exacte del grup de destinació de tipus ip de 10-01, i estalvia un salt de xarxa. group.name permet que diversos Ingress comparteixin un únic ALB, cosa que importa perquè cada ALB costa uns 17 USD al mes de cost fix i crear-ne un per servei es paga ràpid. I les anotacions de WAF i certificat demostren que, per sota, continua sent el mateix ALB del mòdul 3 amb les mateixes proteccions del mòdul 4: EKS canvia com es declara, no què s'obté.
Autoescalat: HPA, Cluster Autoscaler i Karpenter
A Kubernetes hi ha dos escalats i són independents: el de pods i el de nodes. Confondre'ls és la causa de la queixa «he configurat l'autoescalat i no escala».
L'HorizontalPodAutoscaler és l'equivalent de l'autoescalat del servei d'ECS:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-tienda
namespace: mercadofresco
spec:
scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: tienda }
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource: { name: cpu, target: { type: Utilization, averageUtilization: 65 } }
behavior:
scaleUp:
stabilizationWindowSeconds: 30 # creixer rapid, com a 10-01
policies: [{ type: Percent, value: 100, periodSeconds: 30 }]
scaleDown:
stabilizationWindowSeconds: 300 # decreixer a poc a poc
policies: [{ type: Percent, value: 25, periodSeconds: 60 }]Escalar per peticions per destinació —que a 10-01 es va demostrar millor que la CPU— exigeix aquí instal·lar a més KEDA o l'adaptador de mètriques de CloudWatch, perquè l'HPA natiu només entén CPU i memòria. És un exemple petit i representatiu del patró general: el que a ECS és un paràmetre, a Kubernetes sol ser un component més per instal·lar i mantenir.
Per als nodes hi ha dues opcions:
| Cluster Autoscaler | Karpenter | |
|---|---|---|
| Com decideix | Ajusta la mida de grups de nodes predefinits | Tria el tipus d'instància adequat per als pods pendents |
| Velocitat | Minuts | Segons fins a llançar; l'arrencada continua sent d'EC2 |
| Eficiència | Limitada pels tipus del grup | Alta: consolida i tria la mida òptima |
| Spot | Possible, amb grups a part | Natiu, amb substitució en rebre l'avís |
| Complexitat | Baixa, és el tradicional | Mitjana: un altre controlador per instal·lar i actualitzar |
Karpenter és avui l'opció recomanada i és genuïnament bona: observa els pods que no caben, decideix quina instància els allotjaria millor, la llança i, quan en sobra, consolida les càrregues i apaga nodes. Però convé veure el conjunt amb perspectiva: per aconseguir a EKS el que a Fargate ve posat —que la capacitat aparegui quan cal i desaparegui quan no—, cal instal·lar, configurar, actualitzar i vigilar un controlador més. I fins i tot amb Karpenter, el pod nou espera que arrenqui una instància EC2: els dos minuts que MercadoFresco volia eliminar reapareixen quan no hi ha lloc.
Complements: per què un EKS buit no serveix de res
Un clúster acabat de crear té tres coses i li'n falten moltes. Aquesta és la llista mínima real per poder executar la botiga de MercadoFresco:
| Complement | Per a què | Gestionat per AWS? |
|---|---|---|
VPC CNI (aws-node) |
Dona a cada pod una IP de la VPC | Sí |
| CoreDNS | Resolució DNS dins del clúster | Sí |
| kube-proxy | Regles de xarxa per als Services | Sí |
| EKS Pod Identity Agent | Permisos d'AWS per pod | Sí |
| EBS CSI / EFS CSI | Volums persistents | Sí |
| AWS Load Balancer Controller | Converteix Ingress en ALB | No: l'instal·les i l'actualitzes tu |
| Secrets Store CSI + proveïdor d'AWS | Porta secrets des de Secrets Manager | No |
| Metrics Server | Mètriques que necessita l'HPA | No |
| Karpenter o Cluster Autoscaler | Escalat de nodes | No |
| CloudWatch Observability | Container Insights i registres | Sí (complement) |
| KEDA (opcional) | Escalat per mètriques externes | No |
| cert-manager (opcional) | Certificats interns | No |
Els cinc marcats com a «No» són programari que MercadoFresco hauria d'instal·lar amb Helm, versionar, provar i actualitzar, cadascun amb el seu propi cicle de vida i la seva pròpia matriu de compatibilitat amb les versions de Kubernetes. Cap no és difícil per separat. La suma sí que ho és, i és la part d'EKS que no apareix a les comparatives d'una tarda.
A ECS, l'equivalent d'aquesta taula sencera és: res. El balancejador és un paràmetre del servei, els secrets són un camp de la definició de tasca, l'escalat és Application Auto Scaling i les mètriques vénen amb Container Insights.
Actualitzacions de versió: el cost ocult
Aquest és l'argument central de la lliçó i el que més pes té a la decisió final.
Kubernetes publica unes tres versions menors l'any. EKS dona suport estàndard durant uns 14 mesos per versió; després entra automàticament en suport estès, que dura uns 12 mesos més i costa 0,60 USD per hora en lloc de 0,10, és a dir, uns 438 USD al mes per clúster en lloc de 73. En acabar l'estès, AWS actualitza el clúster pel seu compte.
El que implica en feina real, tres o quatre vegades l'any i per clúster:
- Llegir les notes de la versió i detectar les API retirades. Kubernetes retira versions d'API entre versions menors, i un manifest que funcionava deixa d'aplicar-se. Eines com
kubentajuden a trobar-los, però la revisió és teva. - Comprovar la compatibilitat de cada complement: el controlador de balancejadors, Karpenter, el CSI de secrets, KEDA, el CNI. Cadascun té la seva matriu, i de vegades cal actualitzar el complement abans que el clúster.
- Actualitzar el pla de control, que triga uns 25-40 minuts i no es pot revertir.
- Actualitzar els nodes, substituint instàncies en tandes i drenant pods, amb el risc habitual que un
PodDisruptionBudgetmal posat bloquegi el drenatge. - Provar-ho tot en un clúster de preproducció abans, cosa que implica mantenir aquest clúster, amb el seu pla de control de 73 USD al mes i els seus mateixos complements.
| Activitat | Freqüència | Esforç estimat |
|---|---|---|
| Actualització de versió menor (preproducció i producció) | 3 l'any | 2-4 dies d'una persona cada vegada |
| Actualització de complements fora de cicle | 6-10 l'any | 2-4 hores cada vegada |
| Seguiment de CVE dels components del clúster | Continu | 2-4 hores al mes |
| Total anual aproximat | 20-30 dies de feina de plataforma |
Vint o trenta dies l'any són més d'un mes d'una persona. Aquest és el cost ocult d'EKS, i no l'elimina Auto Mode: Auto Mode s'encarrega dels nodes, però les versions de Kubernetes, la compatibilitat dels teus manifests i els complements que instal·lis continuen sent teus.
A ECS aquesta feina simplement no existeix. No hi ha versió d'ECS per actualitzar; AWS fa evolucionar el servei sense que ningú planifiqui res. És la comparació més honesta que es pot fer entre tots dos, i per a un equip de plataforma petit és decisiva.
Observabilitat: Container Insights, Prometheus i Grafana
Tot el del mòdul 5 continua aplicant-se; canvien les eines natives de l'ecosistema.
- Container Insights s'activa amb el complement d'observabilitat de CloudWatch i dona mètriques de clúster, node, pod i contenidor, més els registres dels contenidors a
/aws/containerinsights/eks-mercadofresco/application. És la via més directa i la que menys peces afegeix. - Amazon Managed Service for Prometheus és un Prometheus gestionat i compatible amb
PromQL. Encaixa bé perquè la majoria dels components de l'ecosistema —el controlador de balancejadors, Karpenter, KEDA— ja exposen mètriques en format Prometheus. Es recull amb l'agent de CloudWatch o amb el recol·lector d'OpenTelemetry, i es paga per mostres ingerides i emmagatzemades. - Amazon Managed Grafana és el Grafana gestionat, amb accés mitjançant IAM Identity Center (09-04) i fonts de dades cap a Prometheus, CloudWatch i X-Ray. Es paga per usuari actiu al mes.
- Els registres del pla de control —
api,audit,authenticator— s'activen al clúster i van a CloudWatch Logs. El d'auditoria és el que respon «qui va esborrar aquest Deployment», i convé activar-lo des del primer dia perquè no és retroactiu.
L'observació honesta: la combinació Prometheus més Grafana és més potent que CloudWatch per a mètriques de Kubernetes, amb millor consulta i un catàleg de taulers llestos. I també és més peces: dos serveis més per configurar, dues factures més i dos llocs on mirar durant un incident. Per a MercadoFresco, amb els taulers mercadofresco-produccion i -negocio ja construïts a 05-01, el guany no compensa la fragmentació.
ECS enfront d'EKS: la comparativa honesta
| Criteri | Amazon ECS | Amazon EKS |
|---|---|---|
| Corba d'aprenentatge | Dies: cinc conceptes | Setmanes o mesos: desenes d'objectes i patrons |
| Cost del pla de control | 0 USD | 73 USD/mes, o 438 amb suport estès |
| Portabilitat | Cap: només AWS | Total: qualsevol núvol o servidor propi |
| Ecosistema | El que ofereix AWS | Enorme: operadors, GitOps, malles, milers de gràfics de Helm |
| Extensibilitat | Molt limitada | CRD i operadors: s'estén l'API |
| Integració amb AWS | Nativa i sense peces | Bona, però mitjançant controladors que instal·les tu |
| Actualitzacions | Cap: AWS ho fa | 3 l'any, 20-30 dies de feina anuals |
| Complements per mantenir | Cap | 5-8 components amb el seu propi cicle |
| Personal necessari | Qualsevol equip amb AWS | Algú que sàpiga Kubernetes, no que l'estigui aprenent |
| Mercat laboral | Menor | Ampli: és una habilitat transferible |
| Fargate | Sí, plenament integrat | Sí, amb limitacions (sense DaemonSet, sense EBS) |
| Multinúvol i híbrid | No | Sí, incloses instal·lacions pròpies |
| Velocitat per arribar a producció | Dies | Setmanes |
| Sostre de complexitat que suporta | Mitjà | Molt alt |
Cap de les dues columnes és «la bona». La lectura correcta és: EKS compra flexibilitat, portabilitat i ecosistema, i ho paga amb complexitat, personal i feina recurrent. Si necessites el que compra, el preu és raonable. Si no ho necessites, has comprat feina.
La decisió de MercadoFresco i què la canviaria
MercadoFresco es queda a ECS amb Fargate. I convé que la raó estigui escrita, perquè una decisió sense arguments escrits es revisa cada sis mesos en funció de l'última conferència a què va anar algú.
Els arguments, en ordre de pes:
- L'equip de plataforma és la Marta i mig Luis. Vint o trenta dies l'any d'actualitzacions sobre dues persones que a més porten la xarxa, la seguretat, el pipeline i les guàrdies no és un cost assumible: seria el 10-15 % de la seva capacitat total dedicat a mantenir l'orquestrador, no la botiga.
- No hi ha cap requisit que ECS no cobreixi. La botiga és un servei HTTP amb estat extern, uns treballadors que consumeixen cues i unes funcions per esdeveniments. Res d'això no necessita CRD, operadors, malles de servei ni planificació avançada de pods.
- No hi ha requisit multinúvol. MercadoFresco és a AWS i no hi ha pla ni pressió comercial per canviar-ho. La portabilitat de Kubernetes és una assegurança, i una assegurança que no es farà servir és només una prima.
- La velocitat importa. El mòdul 10 ha portat la botiga d'EC2 a contenidors en setmanes. Amb EKS, aquestes mateixes setmanes haurien estat per aixecar el clúster, els complements i l'aprenentatge de l'equip, sense haver mogut encara la botiga.
- El cost directe també compta, encara que sigui l'argument menor: 73 USD al mes per clúster i per entorn són uns 220 USD mensuals per a desenvolupament, preproducció i producció, enfront de 0 USD d'ECS. Són pocs diners comparats amb el cost de personal, però no són zero.
I els criteris objectius que canviarien la decisió, escrits per endavant perquè la revisió futura sigui una comprovació i no un debat:
| Criteri | Llindar concret | Per què inclinaria la balança |
|---|---|---|
| Experiència prèvia de l'equip | Dues o més persones amb Kubernetes en producció | La corba deixa de ser un cost i passa a ser un actiu |
| Requisit multinúvol o híbrid | Un contracte, una normativa o un magatzem amb còmput local | És l'única cosa que ECS no pot donar de cap manera |
| Necessitat d'operadors de l'ecosistema | Un component que només existeix com a operador de Kubernetes | Reimplementar-lo costa més que adoptar EKS |
| Mida de l'equip de plataforma | Quatre o més persones dedicades | Hi ha capacitat per absorbir la feina recurrent |
| Nombre de serveis | Més de 30-40 serveis amb equips diferents | Els namespaces, RBAC i GitOps comencen a guanyar de debò |
| Requisits de planificació avançats | Afinitats complexes, GPU compartides, prioritat entre càrregues | El planificador de Kubernetes és molt superior |
Mentre cap d'aquests llindars no es compleixi, la resposta a «ens hauríem de passar a Kubernetes?» és no, i aquí està el perquè. El dia que se'n compleixin dos, la resposta canvia, i aquesta taula diu exactament quan.
Amb un matís que evita l'error contrari: el Luis hauria d'aprendre Kubernetes igualment. És una habilitat de mercat i dona criteri per jutjar arquitectures alienes. Aprendre'l no obliga a adoptar-lo, i adoptar-lo sense saber-lo és la pitjor combinació possible.
Cost i neteja
| Concepte | Cost aproximat mensual |
|---|---|
| Pla de control, suport estàndard | 73 USD per clúster |
| Pla de control, suport estès | 438 USD per clúster |
3 nodes m6g.large sota demanda |
≈ 165 USD |
| Volums EBS dels nodes (3 × 50 GB gp3) | ≈ 12 USD |
| ALB creat per l'Ingress | ≈ 17 USD més consum |
| Managed Prometheus i Grafana | Des de ~20 USD segons ús i usuaris |
| Clúster de desenvolupament mínim i realista | ≈ 270-290 USD/mes |
Multiplicat per tres entorns, un EKS equivalent al muntatge actual de MercadoFresco costaria de l'ordre de 800 USD al mes enfront dels aproximadament 250 USD d'ECS amb Fargate i arm64 —i aquesta comparació no inclou els 20-30 dies anuals de feina de plataforma, que és el cost més gran.
Neteja, i aquí l'ordre importa més que en cap altra lliçó: els recursos d'AWS creats des de dins del clúster —l'ALB de l'Ingress, els volums EBS dels PersistentVolumeClaim— no s'esborren en esborrar el clúster i queden orfes facturant.
# 1. PRIMER els objectes de Kubernetes que creen recursos d'AWS
kubectl delete ingress --all -n mercadofresco # esborra l'ALB
kubectl delete pvc --all -n mercadofresco # esborra els volums EBS
kubectl delete svc --all -n mercadofresco # esborra qualsevol NLB de type LoadBalancer
# 2. Comprovar que de debo han desaparegut abans de seguir
aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName,`k8s`)].LoadBalancerArn'
aws ec2 describe-volumes --filters Name=status,Values=available --query 'Volumes[].VolumeId'
# 3. Ara si, el cluster complet (eksctl esborra nodes, rols i la pila)
eksctl delete cluster --name eks-mercadofresco --region eu-west-1
# 4. Residus habituals: grups de registres i el proveidor OIDC
aws logs delete-log-group --log-group-name /aws/eks/eks-mercadofresco/cluster
aws iam list-open-id-connect-providersSi s'esborra el clúster abans que els Ingress, el controlador que sabia esborrar l'ALB desapareix amb ell i el balancejador es queda facturant indefinidament. És el residu més car i més freqüent d'EKS.
Errors Habituals i Consells
Error: livenessProbe que consulta la base de dades. Quan Aurora va lenta, Kubernetes reinicia tots els pods alhora i una degradació es converteix en caiguda. Consell: liveness comprova només que el procés respon; les dependències van a readiness.
Error: no posar startupProbe. Una aplicació que triga 40 segons a arrencar és reiniciada per liveness abans d'acabar, en bucle. Consell: startupProbe amb failureThreshold generós; suspèn les altres dues fins que encerta.
Error: requests molt per sota de l'ús real. Els nodes queden sobrecompromesos i cauen diversos pods alhora. Consell: requests proper al percentil 95 real i limits amb marge, mesurat amb Container Insights.
Error: donar permisos d'AWS mitjançant el rol del node. Tots els pods del node ho hereten tot. Consell: Pod Identity o IRSA sempre, fins i tot a desenvolupament, perquè el que es fa a desenvolupament es copia a producció.
Error: editar aws-auth a mà. Un error de sintaxi deixa tothom fora del clúster sense marxa enrere. Consell: fes servir entrades d'accés (AuthenticationMode: API) i no toquis aquest ConfigMap.
Error: guardar Secret de Kubernetes a Git. Base64 no és xifratge. Consell: controlador CSI de secrets amb Secrets Manager, i xifratge d'etcd amb KMS activat en la creació del clúster.
Error: esborrar el clúster abans que els Ingress. L'ALB queda orfe facturant. Consell: l'ordre de neteja de dalt, amb verificació entre passos.
Error: deixar que el clúster entri en suport estès sense adonar-se'n. La factura es multiplica per sis en silenci. Consell: una alarma al calendari als 12 mesos de cada versió i un pressupost per compte (11-04) que detecti el salt.
Error: un ALB per cada Ingress. Deu serveis, deu balancejadors, 170 USD al mes. Consell: alb.ingress.kubernetes.io/group.name per compartir un ALB entre Ingress.
Error: triar EKS per currículum. És una raó real i sincera, i una mala raó tècnica. Consell: si l'equip vol aprendre Kubernetes, que munti un clúster de laboratori amb pressupost propi; la producció es decideix amb els criteris de la taula.
Consell: si tries EKS, tria també Karpenter i Auto Mode des del principi. Començar amb Cluster Autoscaler i migrar després és feina duplicada.
Consell: activa els registres d'auditoria del pla de control el primer dia. No són retroactius, i són l'única cosa que respon «qui va esborrar aquest Deployment».
Consell: fixa topologySpreadConstraints per zona en tot Deployment de producció. Sense ells, el planificador pot posar les tres rèpliques a la mateixa AZ i una zona caiguda et deixa sense servei.
Exercicis
Exercici 1: traduir el servei de treballadors a Kubernetes
Els treballadors de cola-mercadofresco-pedidos corren avui a Fargate amb 0,5 vCPU i 1 GB, escalant de 2 a 8 tasques segons el retard de la cua, amb un repartiment 1:4 entre sota demanda i Spot. Escriu l'equivalent a Kubernetes: (a) el Deployment complet, amb les sondes que corresponguin a un procés sense servidor HTTP i l'apagada ordenada; (b) com resols l'autoescalat per profunditat de cua, indicant quin component addicional cal i per què l'HPA natiu no basta; (c) com aconsegueixes l'equivalent del repartiment entre capacitat sota demanda i Spot; i (d) enumera totes les peces que has hagut d'afegir al clúster per aconseguir el que a ECS eren tres paràmetres.
Exercici 2: l'incident de les sondes
Un divendres a les 19:20, amb el pic en marxa, Aurora pateix una degradació i les consultes passen de 20 ms a 900 ms. Als dos minuts, la botiga desapareix sencera: tots els pods són a CrashLoopBackOff, l'ALB no té destinacions sanes i mercadofresco-alb-latencia-alta ha donat pas a un error total. La base de dades, mentrestant, continua responent, lenta però viva. Explica (a) la cadena causal exacta que ha convertit una degradació en una caiguda total; (b) quina configuració concreta del manifest és la culpable i per què a ECS amb la comprovació d'estat del grup de destinació el resultat hauria estat diferent; (c) com es redissenyen les tres sondes perquè aquest incident sigui una degradació i no una caiguda; (d) quin mecanisme afegiries al codi de la botiga per degradar amb elegància; i (e) quina alarma hauria avisat abans.
Exercici 3: la revisió de la decisió, divuit mesos després
Han passat divuit mesos. MercadoFresco ha crescut: opera a quatre ciutats, té 22 serveis en lloc de 3, l'equip de plataforma són ara 4 persones de les quals 2 han treballat amb Kubernetes a la seva feina anterior, i el client majorista més gran exigeix per contracte que la seva instància del servei de comandes pugui executar-se al seu propi centre de dades. A més, l'equip de dades vol fer servir un operador de Kubernetes per gestionar els seus fluxos de processament. Aplica la taula de criteris de la lliçó i respon: (a) quins llindars es compleixen ara; (b) quina és la teva recomanació i amb quin nivell de confiança; (c) si recomanes migrar, com ho faries sense repetir els errors del pla de migració de 09-04; (d) què es queda a ECS encara que migris; i (e) quin cost anual total estimaries per a la decisió, incloent-hi personal.
Solucions
Solució 1
(a) El Deployment.
apiVersion: apps/v1
kind: Deployment
metadata: { name: trabajadores-pedidos, namespace: mercadofresco }
spec:
replicas: 2
selector: { matchLabels: { app: trabajadores-pedidos } }
template:
metadata: { labels: { app: trabajadores-pedidos } }
spec:
serviceAccountName: sa-trabajadores
terminationGracePeriodSeconds: 120 # equival a stopTimeout 120 d'ECS
topologySpreadConstraints:
- { maxSkew: 1, topologyKey: topology.kubernetes.io/zone,
whenUnsatisfiable: ScheduleAnyway, labelSelector: { matchLabels: { app: trabajadores-pedidos } } }
containers:
- name: trabajador
image: 555566667777.dkr.ecr.eu-west-1.amazonaws.com/mercadofresco/trabajadores@sha256:71ab...c3d9
resources:
requests: { cpu: "500m", memory: "1Gi" }
limits: { cpu: "500m", memory: "1Gi" }
securityContext: { runAsNonRoot: true, runAsUser: 10002, readOnlyRootFilesystem: true }
# Sense HTTP: s'executa una comanda que comprova la marca de batec a /tmp.
livenessProbe:
exec: { command: ["python", "-m", "trabajadores.salud"] }
periodSeconds: 30
failureThreshold: 3
startupProbe:
exec: { command: ["python", "-m", "trabajadores.salud"] }
periodSeconds: 5
failureThreshold: 12
volumeMounts: [{ name: temporal, mountPath: /tmp }]
volumes: [{ name: temporal, emptyDir: {} }]No hi ha readinessProbe i és deliberat: readiness decideix si un pod rep trànsit d'un Service, i a un treballador de cua ningú no li envia trànsit. Posar-ne una seria soroll sense efecte. liveness sí que és imprescindible, per la mateixa raó que a 10-01: un treballador penjat no mor, deixa de consumir la cua i ningú no se n'assabenta. L'apagada ordenada és el mateix gestor de SIGTERM d'aquell exercici, amb terminationGracePeriodSeconds: 120 com a equivalent del stopTimeout.
(b) Autoescalat per profunditat de cua. L'HPA natiu només entén CPU i memòria de les mètriques de recursos, i ja s'ha vist que la CPU d'un consumidor de cua no reflecteix el retard. Cal KEDA, que instal·la un adaptador de mètriques externes i porta un escalador específic per a SQS:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata: { name: escalado-trabajadores, namespace: mercadofresco }
spec:
scaleTargetRef: { name: trabajadores-pedidos }
minReplicaCount: 2
maxReplicaCount: 8
cooldownPeriod: 300
triggers:
- type: aws-sqs-queue
metadata:
queueURL: https://sqs.eu-west-1.amazonaws.com/333344445555/cola-mercadofresco-pedidos
queueLength: "15" # missatges per replica, com a 10-02
awsRegion: eu-west-1
identityOwner: operatorL'alternativa sense KEDA és l'adaptador de mètriques de CloudWatch més un HPA amb mètrica externa, que és més artesanal. En qualsevol cas, és un component més per instal·lar, versionar i actualitzar per aconseguir el que a ECS era una política d'Application Auto Scaling.
(c) L'equivalent del repartiment sota demanda / Spot. No hi ha un capacityProviderStrategy; s'aconsegueix amb Karpenter declarant dos NodePool, un amb capacity-type: on-demand i un altre amb spot, i fent servir al Deployment nodeAffinity preferida cap a Spot més topologySpreadConstraints sobre l'etiqueta karpenter.sh/capacity-type per garantir que almenys una rèplica caigui a sota demanda. També cal el gestor d'interrupcions, que Karpenter inclou: escolta l'avís de dos minuts d'EC2 i drena el node. Resultat: el que a ECS eren dues línies de --capacity-provider-strategy aquí són dos NodePool, regles d'afinitat, restriccions de topologia i un controlador.
(d) Les peces afegides. Per igualar tres paràmetres d'ECS ha calgut: Karpenter (nodes i Spot), KEDA (escalat per cua), Metrics Server (base de l'HPA), EKS Pod Identity Agent (permisos d'SQS del pod) i, si es vol observabilitat equivalent, el complement de CloudWatch Observability. Cinc components, cadascun amb la seva versió, la seva compatibilitat amb la versió de Kubernetes i el seu propi cicle d'actualització. Aquesta és exactament l'aritmètica de la secció de complements.
Solució 2
(a) La cadena causal. Aurora es degrada a 900 ms. El /salud de la botiga consulta la base de dades, així que comença a trigar més dels 3 segons de timeoutSeconds. La livenessProbe acumula 3 fallades consecutives —uns 60 segons amb periodSeconds: 20— i Kubernetes reinicia el contenidor. En reiniciar-se, el pod ha d'arrencar de nou, precarregar la memòria cau del catàleg i tornar a connectar amb la mateixa Aurora lenta, amb la qual cosa falla també l'arrencada. Com que tots els pods consulten la mateixa base de dades, això els passa als tres alhora i de manera sincronitzada. Els reinicis repetits porten a CrashLoopBackOff, amb esperes creixents entre intents. I hi ha un agreujant: els reinicis massius obren i tanquen connexions contra una Aurora ja saturada, empitjorant la causa arrel. Un bucle de realimentació complet.
(b) La culpable i la diferència amb ECS. La culpable és la livenessProbe apuntant a un /salud que comprova dependències externes. A ECS, la comprovació d'estat del grup de destinació té un efecte diferent: una destinació no sana es treu del balanceig, i el servei només reposa tasques si la tasca mor o si el desplegament ho exigeix. L'equivalent de liveness a ECS és el healthCheck del contenidor, que la majoria de la gent configura de manera més laxa o ni tan sols posa. És a dir: Kubernetes és més agressiu per omissió i et dona una eina més perillosa, i per això exigeix entendre-la. La diferència no és que ECS sigui millor, és que Kubernetes et deixa disparar més lluny.
(c) El redisseny de les tres sondes.
livenessProbe→/vivo, un punt d'enllaç que només confirma que el procés respon i el bucle d'esdeveniments no està bloquejat. Sense tocar Aurora, sense tocar la memòria cau, sense tocar la xarxa. AmbperiodSeconds: 20ifailureThreshold: 5, per no reiniciar per un pic transitori.readinessProbe→/listo, que sí que comprova les dependències: connexió a Aurora i a ElastiCache. La seva fallada treu el pod del balanceig però no el mata, així que quan Aurora es recupera el pod torna a rebre trànsit sense haver reiniciat. Aquí la fallada és reversible i barata.startupProbe→/listoambfailureThresholdampli (12 × 5 s = 60 s), que cobreix la precàrrega del catàleg i suspèn les altres dues mentrestant.
Amb aquest disseny, l'incident del divendres hauria estat: tots els pods marcats com a no llestos, l'ALB retornant 503 a les peticions que necessiten base de dades, els pods vius i amb la memòria cau calenta, i recuperació immediata en recuperar-se Aurora. Degradació, no caiguda.
(d) Degradació amb elegància al codi. Que /listo distingeixi entre «no puc fer res» i «puc fer una part». La botiga pot servir el catàleg des de mercadofresco-catalogo a ElastiCache encara que Aurora vagi lenta; el que no pot és confirmar comandes. Amb un interruptor de circuit (07-05) al voltant de les crides a Aurora, la botiga deixa d'intentar-ho després de N fallades, retorna un missatge clar al pas de pagament i continua servint navegació. El client veu «ara mateix no podem confirmar comandes» en lloc d'una pàgina en blanc, i Aurora deixa de rebre l'allau de reintents que impedia la seva recuperació.
(e) L'alarma que hauria avisat abans. La de latència d'Aurora, ReadLatency i WriteLatency, amb llindar sobre el percentil 99 i no sobre la mitjana —la mitjana triga molt a moure's—. Hauria saltat al minut de la degradació, abans que la primera livenessProbe acumulés les seves tres fallades, donant un marge d'acció real. Complementàriament, una alarma sobre reinicis de pods (pod_number_of_container_restarts a Container Insights) hauria identificat el bucle de realimentació immediatament, que és la informació que faltava per diagnosticar en calent.
Solució 3
(a) Llindars que es compleixen. Quatre dels sis:
| Criteri | Es compleix? | Detall |
|---|---|---|
| Experiència prèvia | Sí | 2 de 4 persones amb Kubernetes en producció |
| Multinúvol o híbrid | Sí, i és contractual | El majorista exigeix execució al seu centre de dades |
| Operadors de l'ecosistema | Sí | L'equip de dades vol un operador de fluxos |
| Mida de l'equip | Sí | 4 persones dedicades |
| Nombre de serveis | Parcialment | 22, per sota del llindar de 30-40 però a prop |
| Planificació avançada | No | Res no ho exigeix encara |
(b) Recomanació. Sí, migrar a EKS, amb confiança alta. El criteri decisiu és el segon: el requisit híbrid contractual és l'única cosa que ECS no pot satisfer de cap manera, i no és una preferència sinó una obligació amb un client. Els altres tres reforcen que ara el cost és assumible: hi ha experiència, hi ha equip i hi ha una necessitat concreta d'ecosistema. La decisió de fa divuit mesos no era errònia: era correcta amb les dades d'aleshores, i aquesta és precisament la utilitat d'haver escrit els criteris per endavant.
(c) Com migrar. Aplicant les lliçons de 09-04 i del mateix mòdul 10:
- Un clúster nou, no una conversió. El clúster de desenvolupament primer, amb Auto Mode o Karpenter des del principi per no duplicar feina.
- Primer un servei no crític. El servei d'informes o el de notificacions, no la botiga. S'aprèn amb una cosa la fallada de la qual no costa comandes.
- Els complements abans que les càrregues, amb les seves versions fixades a Git i desplegats amb Helm des del pipeline, mai a mà.
- Convivència real i prolongada. ECS i EKS alhora durant mesos, amb l'ALB repartint per pesos igual que a 10-01 i 10-02. Res d'una nit de tall.
- La botiga, l'última, i amb el mateix repartiment 90/10 que es va fer servir per passar d'EC2 a Fargate.
- Data límit explícita per fase, que és l'error que 09-04 assenyalava: les migracions a mitges duren anys si ningú no posa fites.
- La instal·lació del client majorista al final, quan l'equip ja operi EKS amb desimboltura, no com a primer projecte.
(d) Què es queda a ECS encara que migris. El que no guanya res amb el canvi: les Lambdes (-cobrar-pago, -reservar-stock, -generar-miniaturas, -asignar-reparto), que no són contenidors i continuen sent la millor opció per a feina esporàdica; les tasques programades de càrrega a Redshift, que funcionen perfectament amb EventBridge Scheduler; i probablement els treballadors de les cues menys crítiques durant força temps, perquè migrar-los no aporta i sí que consumeix atenció. Migrar-ho tot per coherència estètica és un error car: la coherència es mesura en criteris, no en tecnologies.
(e) Cost anual estimat. Infraestructura: 3 clústers × 73 USD × 12 = 2.628 USD de plans de control, més el diferencial de nodes enfront de Fargate, que amb Karpenter i Spot ben fets servir pot ser fins i tot favorable —diguem-ne neutre—. Personal: 25 dies l'any de feina de plataforma en actualitzacions i manteniment del clúster, més un cost únic de 2-3 mesos-persona per a la migració. Amb un cost intern estimat de 400 USD per dia, el recurrent són uns 10.000 USD l'any i la migració, uns 20.000-25.000 USD d'una vegada. Total del primer any: de l'ordre de 35.000 USD. Aquest és el número que cal posar davant de la direcció juntament amb el contracte del client majorista, perquè la decisió no és tècnica: és una inversió amb una justificació comercial concreta.
Conclusió
MercadoFresco ha acabat el mòdul amb la botiga fora de les màquines i amb una resposta raonada a la pregunta de Kubernetes.
Tens Kubernetes entès de debò: un orquestrador extensible amb API pròpia, el valor real del qual és a la portabilitat, l'ecosistema i l'extensibilitat amb CRD i operadors; el seu vocabulari mínim —Pod, ReplicaSet, Deployment, Service, Ingress, Namespace, ConfigMap i Secret, amb l'advertiment que un Secret és base64 i no xifratge—; i el model declaratiu amb bucle de reconciliació que explica per què esborrar un pod a mà no serveix de res i per què GitOps hi encaixa de manera natural. Tens clar què gestiona EKS —pla de control en tres AZ, etcd, el mecanisme d'actualització i la integració amb IAM— i la frase que evita la majoria de les decepcions: EKS gestiona el pla de control, no el clúster.
Tens les quatre opcions de còmput amb els seus límits reals —inclosa la que EKS sobre Fargate no admet DaemonSet, cosa que obliga a mantenir nodes per als complements—, la creació del clúster amb eksctl i amb CDK, aws eks update-kubeconfig i la disciplina de mirar el context abans d'escriure un delete. I l'autenticació moderna: entrades d'accés en lloc d'aws-auth, amb els conjunts de permisos de 09-04 governant també el clúster, i Pod Identity com a equivalent exacte del rol de tasca d'ECS.
Tens els manifests complets de la botiga: Deployment amb les tres sondes ben separades —startup per arrencar, readiness per rebre trànsit, liveness per reiniciar—, requests i limits com a conceptes diferents, repartiment per AZ amb topologySpreadConstraints, preStop per no perdre peticions i context de seguretat sense privilegis; el Service; i l'Ingress amb l'AWS Load Balancer Controller, que crea el mateix ALB del mòdul 3 amb el WAF del mòdul 4, amb target-type: ip i group.name per no pagar un balancejador per servei. Més l'autoescalat en dos plans: HPA per als pods, Karpenter per als nodes, i l'observació que per igualar tres paràmetres d'ECS van caldre cinc components.
I tens l'argument que gairebé ningú no posa per escrit: el cost ocult de les actualitzacions. Tres versions l'any, 14 mesos de suport estàndard, un salt automàtic de 73 a 438 USD mensuals en entrar a l'estès, i 20-30 dies de feina de plataforma l'any revisant API retirades, matrius de compatibilitat i drenatges de nodes. A ECS aquesta feina no existeix. Amb la comparativa honesta entre tots dos —EKS compra flexibilitat, portabilitat i ecosistema, i ho paga amb complexitat, personal i feina recurrent— i la decisió de MercadoFresco: es queda a ECS amb Fargate, per un equip de plataforma de dues persones, l'absència de requisits que ECS no cobreixi, l'absència de necessitat multinúvol i la velocitat; amb els sis criteris objectius, escrits per endavant, que canviarien aquesta decisió el dia que es compleixin.
Què ha canviat per a MercadoFresco en aquest mòdul. Ja no hi ha AMI per reconstruir quan canvia una dependència: hi ha una imatge a mercadofresco/tienda versionada per commit i desplegada per digest. Ja no hi ha sistema operatiu per apedaçar: l'amfitrió és d'AWS i l'escaneig continu d'Inspector avisa del que sí que és teu. I ja no hi ha arrencades de dos minuts: hi ha tasques que reben trànsit en quaranta segons, amb un escalat programat que a més les té llestes abans que arribi el pic del divendres.
graph TB
U[Clients] --> CF["CloudFront E2QWERTY123ABC<br/>+ waf-mercadofresco-cdn"]
CF --> ALB["alb-mercadofresco-tienda<br/>tg-mercadofresco-tienda / -verde"]
ALB --> FG["ECS Fargate<br/>svc-mercadofresco-tienda-fg<br/>arm64, 2-20 tasques"]
FG --> AU[("aurora-mercadofresco-pedidos")]
FG --> EC[("mercadofresco-catalogo<br/>ElastiCache")]
FG --> DY[("mercadofresco-carritos")]
FG --> SQS["cola-mercadofresco-pedidos"]
SQS --> TR["ECS Fargate + Spot<br/>svc-mercadofresco-trabajadores"]
TR --> SF["mercadofresco-procesar-pedido<br/>Lambdes de pagament, estoc i repartiment"]
ECR["ECR 555566667777<br/>mercadofresco/tienda"] -.digest.-> FG
PIPE["pipeline-mercadofresco-tienda<br/>blue/green canari"] -.desplega.-> FG
OBS["Container Insights, X-Ray<br/>mercadofresco-produccion"] -.observa.-> FG
I aquí arriba la pregunta que ningú no ha fet encara i que el gerent farà dilluns al matí. L'arquitectura està completa: és elàstica, segura, observable, desplegable des d'un pipeline, descrita en codi i repartida en cinc comptes. Però quant costa tot això? Està ben gastat? Com es reparteix entre producció, preproducció i desenvolupament, i entre les quatre ciutats? Hi ha res encès que ningú no faci servir? I què es podria comprometre per endavant per pagar menys?
Al mòdul 11, «Millors pràctiques i gestió de costos», es respon amb mètode. 11-01 revisa l'arquitectura completa amb el Well-Architected Framework i els seus sis pilars, que és la manera estructurada d'auditar el que s'ha construït. 11-02 posa ordre a l'etiquetatge i l'assignació de costos, convertint les cinc etiquetes obligatòries en informes que algú pugui llegir. 11-03 analitza la factura de debò amb Cost Explorer. 11-04 posa límits i avisos amb Budgets. 11-05 compromet capacitat amb Savings Plans i instàncies reservades, que és on la comparació Fargate enfront d'EC2 de 10-02 queda per fi tancada. I 11-06 tanca el curs amb el projecte final: dissenyar, justificar i pressupostar una arquitectura completa per a MercadoFresco, amb tot el que s'ha après en onze mòduls.
Curs d'AWS
Mòdul 1: Introducció a AWS
- Què és AWS?
- Configuració del teu compte d'AWS
- Infraestructura global d'AWS
- Consola d'administració d'AWS
- AWS CLI i SDK
Mòdul 2: Serveis principals d'AWS
Mòdul 3: Xarxes i lliurament de contingut
- Amazon VPC
- Grups de seguretat i llistes de control d'accés
- Elastic Load Balancing
- Amazon CloudFront
- Route 53
Mòdul 4: Seguretat i identitat
- AWS Identity and Access Management (IAM)
- AWS Key Management Service (KMS)
- Secrets Manager i Parameter Store
- AWS Shield
- AWS WAF
Mòdul 5: Monitoratge i gestió
- Amazon CloudWatch
- AWS X-Ray i traçabilitat distribuïda
- AWS CloudTrail
- AWS Config
- AWS Trusted Advisor
Mòdul 6: Bases de dades
- Com triar la base de dades adequada
- Amazon DynamoDB
- Amazon Aurora
- Amazon Redshift
- Amazon ElastiCache
Mòdul 7: Integració d'aplicacions
- Amazon SQS
- Amazon SNS
- Amazon EventBridge
- AWS Step Functions
- Patrons d'integració: idempotència, reintents i cues de missatges fallits
