La revisió Well-Architected va deixar cinc riscos alts al pilar de costos, i el primer de tots és el que bloqueja els altres: la factura de MercadoFresco no es pot llegir. Arriba un import consolidat de 2.237,60 USD al mes i, a sota, una llista de serveis. Res no diu quina part és producció i quina part és l'entorn de proves que el Luis va deixar encès, ni quant costa el catàleg comparat amb les comandes, ni si Madrid surt més car per client que Sevilla.

Aquesta lliçó resol aquest problema abans de tocar cap eina d'anàlisi. Veuràs com es dissenya una estratègia d'etiquetatge que serveixi de debò, com s'activen les etiquetes d'assignació de costos —i el detall que arruïna molta gent: no són retroactives—, com s'imposa l'etiquetatge en lloc de demanar-lo per correu, com s'auditen els recursos sense etiquetar, quan el compte separa millor que l'etiqueta, com agrupar conceptes de negoci amb categories de cost, i com arribar a la dada definitiva amb l'informe de costos i ús consultat des d'Athena. El final és la mètrica que canvia la conversa amb el gerent: el cost per comanda.

Avís de cost. Etiquetar és gratis: les etiquetes no costen diners, ni activar-les com a dimensions d'assignació de costos, ni les categories de cost. El que sí que costa és l'informe de costos i ús: l'emmagatzematge a S3 (cèntims amb aquest volum) i, sobretot, les consultes d'Athena a 5 USD per TB escanejat, que amb particions i format Parquet es queden en menys d'1 USD al mes i sense elles es poden disparar. Dades, comptes i identificadors ficticis.

Contingut

  1. El problema real: una factura que ningú no pot llegir
  2. Quines preguntes ha de poder respondre MercadoFresco
  3. Dissenyar l'estratègia d'etiquetatge
  4. Convencions de noms i valors tancats
  5. Quantes etiquetes són massa i quins recursos no admeten etiquetes
  6. Activar les etiquetes d'assignació de costos
  7. El detall crític: les etiquetes no són retroactives
  8. Imposar l'etiquetatge en lloc de demanar-lo
  9. Polítiques d'etiquetes d'Organizations
  10. Condicions IAM: aws:RequestTag i aws:TagKeys
  11. Regles de Config amb remediació
  12. Aspectes del CDK, ECS i el pipeline
  13. Quin mecanisme cobreix què: la taula de decisió
  14. Auditar el que no està etiquetat i fixar un objectiu realista
  15. El compte com a dimensió de cost
  16. Categories de cost: del recurs al concepte de negoci
  17. L'informe de costos i ús (CUR)
  18. Consultar el CUR amb Athena
  19. Costos compartits i costos no assignables
  20. Cost unitari: el cost per comanda de MercadoFresco
  21. Mostrar i reintegrar costos: showback i chargeback
  22. Errors habituals i consells
  23. Exercicis
  24. Conclusió

El problema real: una factura que ningú no pot llegir

La Marta obre la consola de facturació per primera vegada amb intenció d'entendre-la. El que veu és això:

Factura d'agost del 2026 — Organitzacio o-a1b2c3d4e5
Total abans d'impostos .................................. 2.237,60 USD
  Amazon Relational Database Service .................... 342,60
  Amazon Elastic Container Service ...................... 262,40
  Amazon Virtual Private Cloud .......................... 362,40
  Amazon CloudWatch ..................................... 214,90
  Amazon ElastiCache .................................... 135,40
  Amazon Simple Storage Service ......................... 128,90
  ...

És informació, però no serveix per decidir res, perquè cap pregunta del gerent no es respon amb aquesta llista. «Quant costa l'entorn de desenvolupament?»: la factura no ho sap, sap quant costa RDS en total. «L'analítica de la Sara es paga sola?»: no hi ha cap línia anomenada «analítica». «Aquests 362 USD de VPC, de què són?»: NAT Gateway i endpoints repartits entre tots els components. «Quant costa servir Sevilla?»: aquesta dimensió directament no existeix.

El diagnòstic és senzill: la factura està organitzada segons l'estructura d'AWS, no segons l'estructura del negoci. L'etiquetatge és el mecanisme per traduir d'una a l'altra.

Quines preguntes ha de poder respondre MercadoFresco

Abans de decidir quines etiquetes posar, cal escriure les preguntes. És l'ordre correcte i gairebé ningú no el segueix: la majoria de les estratègies d'etiquetatge fracassen perquè es dissenyen «per si de cas» i acaben amb vint etiquetes que no responen res. Les preguntes de MercadoFresco, acordades entre la Marta, la Sara i el gerent:

Pregunta Dimensió que la respon Qui pregunta
Quant costa producció enfront de preproducció i desenvolupament? Entorno i compte Gerència
Quant costa cada part del sistema? Componente Marta
Qui és responsable de cada despesa? Propietario Marta
Quant imputem a operacions i quant a màrqueting? CentroCoste Administració
Quant costa servir cada ciutat? Derivada: no s'etiqueta, es calcula Gerència
Quant costa cada comanda? Derivada: cost total / comandes Gerència
Quina despesa no està assignada a ningú? Absència d'etiquetes Marta

Les dues últimes files contenen la lliçó més important d'aquesta secció: no tot es resol amb una etiqueta. La ciutat no es pot etiquetar perquè la infraestructura és compartida: el mateix ALB, el mateix clúster i la mateixa base de dades serveixen les quatre ciutats. El cost per ciutat és un repartiment, no una mesura, i es calcula a partir del nombre de comandes. Intentar forçar-ho amb una etiqueta Ciudad produiria una dada falsa amb aparença de dada vertadera, que és pitjor que no tenir la dada.

Dissenyar l'estratègia d'etiquetatge

Una etiqueta és un parell clau-valor que s'adjunta a un recurs. Sona trivial i no ho és: és l'únic mecanisme transversal que travessa tots els serveis d'AWS, i les decisions del primer dia s'arrosseguen anys. Les cinc etiquetes obligatòries de MercadoFresco, que ja fas servir des del mòdul 1, ara amb la seva justificació completa:

Clau Valors permesos Per a què serveix Obligatòria a
Proyecto mercadofresco Separar de la resta si algun dia conviuen diversos projectes en un compte Tot
Entorno produccion, preproduccion, desarrollo Repartiment per entorn; base dels pressupostos Tot
Componente tienda, catalogo, pedidos, reparto, analitica La dimensió que més es consulta Tot
Propietario marta, luis, sara Saber a qui preguntar i a qui avisar Tot
CentroCoste operaciones, marketing Imputació comptable Tot

A més d'aquestes cinc n'hi ha quatre d'opcionals, que es permeten però no s'exigeixen i que resolen problemes concrets: Temporal=si i FechaBaja=yyyy-mm-dd marquen recursos de vida curta que es poden esborrar sense preguntar; Cumplimiento=rgpd assenyala els que contenen dades personals; i Automatizacion=apagado-nocturno selecciona què apaga el planificador.

Una regla d'or sobre la qual convé ser inflexible: una etiqueta que no té un consumidor no es crea. Si ningú no hi filtrarà, agruparà ni automatitzarà, no ha d'existir, perquè cada etiqueta afegeix fricció a cada creació de recurs i soroll a cada informe.

Convencions de noms i valors tancats

Les etiquetes d'AWS distingeixen majúscules de minúscules. Entorno=Produccion, entorno=produccion i Entorno=produccion són tres etiquetes diferents que produeixen tres línies diferents a l'informe de costos. És la causa número u d'informes d'assignació inservibles.

Les convencions de MercadoFresco, escrites a mercadofresco-infra/docs/etiquetado.md:

Regla Correcte Incorrecte
Claus en PascalCase, sense espais CentroCoste centro coste, centro_coste
Valors en minúscules, sense espais ni accents preproduccion Preproducción, Pre Produccion
Sense dades personals ni secrets marta marta.gomez@...
Guions, no guions baixos apagado-nocturno apagado_nocturno
Valors tancats, d'una llista publicada catalogo catálogo-v2, cat
Prefix aws: prohibit El reserva AWS i no es pot fer servir

El punt que més discussió genera i que més importa és el dels valors tancats. Una etiqueta amb valors lliures és un camp de text, i un camp de text sempre acaba amb pedidos, Pedidos, pedido, pedidos-nuevo i pedidos2, és a dir, amb cinc components on n'hi ha un. La llista de valors permesos es publica, es versiona i s'imposa tècnicament a les seccions següents.

Tres límits tècnics que convé recordar: 50 etiquetes per recurs, clau de fins a 128 caràcters i valor de fins a 256, i —el que més cost deixa sense assignar— les etiquetes no s'hereten: una instància EC2 etiquetada no etiqueta els seus volums EBS tret que es demani explícitament.

Quantes etiquetes són massa i quins recursos no admeten etiquetes

Quantes. L'experiència del sector és consistent: entre 4 i 8 etiquetes obligatòries és el rang que funciona. Per sota de 4 no es pot repartir el cost amb criteri; per damunt de 8, la gent copia i enganxa valors sense pensar i la qualitat de la dada s'ensorra. MercadoFresco en té cinc, que és un bon lloc on estar. El senyal que en sobra alguna és fàcil de reconèixer: quan algú crea un recurs i ha de preguntar quin valor posar-hi, aquesta etiqueta sobra o està mal definida.

Què no es pot etiquetar. Aquesta és la part que trenca les expectatives i cal conèixer abans de prometre una cobertura del 100 %:

Concepte Etiquetable? Conseqüència per al cost
EC2, EBS, Lambda, DynamoDB, Aurora, SQS, SNS, EventBridge
Bucket S3 Sí, a nivell de bucket, no d'objecte ni prefix Un bucket compartit entre components no es reparteix amb etiquetes
Transferència de dades entre AZ No Apareix sense etiqueta; cal repartir-la
Peticions a KMS La clau sí, l'ús no sempre Import petit; s'assumeix compartit
Suport d'AWS i Marketplace No Càrrec de compte; es reparteix per categoria de cost
Crèdits, descomptes i impostos No S'apliquen al total, no a l'etiqueta

D'aquí surt un principi que estalvia frustracions: l'objectiu no és etiquetar el 100 % del cost, sinó etiquetar el 100 % del que és etiquetable i repartir la resta amb una regla escrita.

Activar les etiquetes d'assignació de costos

Aquí hi ha el pas que MercadoFresco no havia fet i que converteix una etiqueta en una dimensió de la factura. Posar una etiqueta a un recurs no fa que aparegui als informes de cost. Cal activar-la explícitament com a etiqueta d'assignació de costos, i només es pot fer des del compte de gestió (999988887777), a Billing → Cost allocation tags. Hi ha dues famílies: les generades per AWS, amb prefix aws:, i les definides per l'usuari, que són les teves. Les primeres són gratis i sorprenentment útils: aws:createdBy registra quina identitat va crear el recurs i respon a «qui ha encès això?» encara que ningú no posés Propietario; aws:cloudformation:stack-name dona el cost per pila, que amb la IaC del mòdul 9 és un repartiment gairebé gratuït i molt precís; i aws:ecs:serviceName separa el cost de Fargate entre svc-mercadofresco-tienda-fg i svc-mercadofresco-trabajadores sense etiquetar res.

Activar-les des de la CLI, al compte de gestió:

# Veure quines etiquetes coneix el sistema i quin es el seu estat
aws ce list-cost-allocation-tags --status Inactive --output table

# Activar les cinc obligatories i tres generades per AWS
aws ce update-cost-allocation-tags-status --cost-allocation-tags-status \
  'TagKey=Proyecto,Status=Active' \
  'TagKey=Entorno,Status=Active' \
  'TagKey=Componente,Status=Active' \
  'TagKey=Propietario,Status=Active' \
  'TagKey=CentroCoste,Status=Active' \
  'TagKey=aws:createdBy,Status=Active' \
  'TagKey=aws:cloudformation:stack-name,Status=Active' \
  'TagKey=aws:ecs:serviceName,Status=Active'

# Comprovar el resultat
aws ce list-cost-allocation-tags --status Active --output table

Quatre detalls d'aquest bloc. L'ordre viu a l'espai de noms ce encara que la funcionalitat estigui a la consola de facturació, i només funciona al compte de gestió. Una etiqueta només apareix a la llista si AWS l'ha vista almenys una vegada en algun recurs: primer s'etiqueta alguna cosa, després s'activa. Després d'activar-la triga fins a 24 hores a aparèixer als informes. I hi ha un límit de 500 etiquetes actives per organització, irrellevant amb cinc i molt rellevant en organitzacions que les van deixar créixer sense control.

El detall crític: les etiquetes no són retroactives

Aquesta és la frase que cal subratllar de tota la lliçó:

Una etiqueta d'assignació de costos només s'aplica al cost generat a partir del moment en què s'activa. Mai cap enrere.

Conseqüències amb els números de MercadoFresco: la Marta activa les etiquetes el 12 d'agost, i a Cost Explorer tot el cost de l'1 a l'11 apareix com a (sense etiquetar) en les cinc dimensions encara que els recursos estiguessin etiquetats des del març. El primer mes amb dades netes és el setembre; l'agost és mixt i no serveix per comparar. I si d'aquí a tres mesos s'afegeix una sisena etiqueta, les comparacions interanuals per aquesta dimensió no existiran fins l'any següent.

D'aquí surten tres consells que estalvien mesos: activa les etiquetes el dia que defineixis la convenció, encara que la cobertura sigui baixa, perquè el rellotge comença en activar i no en acabar d'etiquetar; activa també les generades per AWS des del principi, que són gratis i no depenen de ningú; i anota la data d'activació al document d'etiquetatge, perquè d'aquí a sis mesos la resposta a «per què el juliol no té repartiment?» estigui escrita.

Hi ha una excepció parcial: l'informe de costos i ús es pot regenerar cap enrere fins a cert punt en activar etiquetes noves, i alguns mesos anteriors arriben a omplir-se. No és fiable ni universal, així que la regla mental continua sent: no són retroactives.

Imposar l'etiquetatge en lloc de demanar-lo

MercadoFresco fa mesos que té una convenció d'etiquetatge escrita i una cobertura real del 68 %. No és falta de voluntat: és que demanar per correu que la gent etiqueti no funciona mai, en cap empresa. El que funciona és fer que no es pugui crear un recurs mal etiquetat, o que si es crea, es corregeixi sol.

graph TD
  DEV["El Luis crea un recurs"] --> Q1{"Per CDK<br/>o pipeline?"}
  Q1 -->|Si| CDK["Aspecte del CDK<br/>etiqueta tota la pila"]
  Q1 -->|No, a ma| IAM["Politica IAM amb<br/>aws:RequestTag"]
  IAM -->|Falta etiqueta| DENY["AccessDenied"]
  IAM -->|Etiquetes OK| CREA["Recurs creat"]
  CDK --> CREA
  CREA --> TPOL["Politica d'etiquetes<br/>d'Organizations"]
  CREA --> CFG["Regla required-tags<br/>de Config + remediacio"]

Els cinc mecanismes són complementaris, no alternatius. Un a un.

Polítiques d'etiquetes d'Organizations

Una política d'etiquetes (tag policy) es defineix al compte de gestió i s'adjunta a l'arrel o a una OU. Defineix quines claus existeixen, amb quina grafia exacta i quins valors admeten, i pot a més impedir operacions que incompleixin la política per a tipus de recurs concrets.

{
  "tags": {
    "Entorno": {
      "tag_key": { "@@assign": "Entorno" },
      "tag_value": { "@@assign": ["produccion", "preproduccion", "desarrollo"] },
      "enforced_for": {
        "@@assign": ["ec2:instance", "ec2:volume", "rds:db", "rds:cluster",
                     "s3:bucket", "lambda:function", "dynamodb:table",
                     "elasticache:replicationgroup"]
      }
    },
    "Componente": {
      "tag_key": { "@@assign": "Componente" },
      "tag_value": {
        "@@assign": ["tienda", "catalogo", "pedidos", "reparto", "analitica"]
      }
    },
    "CentroCoste": {
      "tag_key": { "@@assign": "CentroCoste" },
      "tag_value": { "@@assign": ["operaciones", "marketing"] }
    }
  }
}

Les claus Proyecto i Propietario es declaren igual, amb la seva llista tancada de valors.

Què fa cada part. tag_key amb @@assign fixa la grafia canònica: a partir d'aquí, un recurs etiquetat amb entorno=produccion en minúscula es marca com a no conforme. tag_value amb @@assign defineix la llista tancada. enforced_for és la part amb dents: per als tipus llistats, la creació o l'etiquetatge que incompleixi la política es rebutja; sense això, la política només informa. I l'operador @@assign sobreescriu el que s'hereta, amb @@append i @@remove disponibles per combinar polítiques de diferents nivells de la jerarquia.

Com s'aplica:

# Crear la politica al compte de gestio 999988887777
aws organizations create-policy --name "etiquetas-mercadofresco" \
  --type TAG_POLICY --content file://etiquetas-mercadofresco.json

# Adjuntar-la a l'OU Cargas (produccio, preproduccio i desenvolupament)
aws organizations attach-policy \
  --policy-id p-mfetiq0001 --target-id ou-a1b2-cargas001

# Comprovar el compliment a tota l'organitzacio
aws resourcegroupstaggingapi get-compliance-summary \
  --target-id-filters 111122223333 222233334444 333344445555 \
  --group-by RESOURCE_TYPE

Advertiment sobre enforced_for: es desplega en mode informatiu primer, perquè activar-lo de cop en producció pot trencar el pipeline, l'autoescalat o qualsevol automatització que creï recursos sense les cinc etiquetes. MercadoFresco ho aplica en tres fases: informatiu dues setmanes, enforced_for en desenvolupament dues setmanes més, i només aleshores en producció.

Condicions IAM: aws:RequestTag i aws:TagKeys

La política d'etiquetes governa valors; IAM governa qui pot fer què, i permet exigir etiquetes en el moment de la creació amb dues claus de condició: aws:RequestTag/<Clau>, el valor que s'intenta posar a la petició, i aws:TagKeys, la llista de claus presents en ella. Aquesta política exigeix les cinc etiquetes en crear instàncies i volums, i a més impedeix canviar Entorno després:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ExigirLasCincoEtiquetasAlCrear",
      "Effect": "Allow",
      "Action": ["ec2:RunInstances", "ec2:CreateVolume"],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/Proyecto": "mercadofresco",
          "aws:RequestTag/Entorno": ["produccion", "preproduccion", "desarrollo"],
          "aws:RequestTag/Componente": [
            "tienda", "catalogo", "pedidos", "reparto", "analitica"
          ]
        },
        "ForAllValues:StringEquals": {
          "aws:TagKeys": [
            "Proyecto", "Entorno", "Componente", "Propietario", "CentroCoste",
            "Temporal", "FechaBaja", "Cumplimiento", "Automatizacion"
          ]
        },
        "ForAnyValue:StringEquals": {
          "aws:TagKeys": ["Propietario", "CentroCoste"]
        }
      }
    },
    {
      "Sid": "ProhibirCambiarElEntornoDeUnRecursoExistente",
      "Effect": "Deny",
      "Action": ["ec2:CreateTags", "ec2:DeleteTags"],
      "Resource": "*",
      "Condition": {
        "ForAnyValue:StringEquals": { "aws:TagKeys": ["Entorno", "CentroCoste"] }
      }
    }
  ]
}

Els operadors de conjunt d'IAM són la part on més es falla. StringEquals sobre aws:RequestTag/X exigeix que l'etiqueta X hi sigui present i tingui un d'aquests valors: si falta, l'acció es denega, i aquesta és la manera de fer obligatòria una etiqueta. ForAllValues:StringEquals sobre aws:TagKeys significa «totes les claus que enviïs han de ser en aquesta llista», és a dir, una llista blanca que impedeix inventar-se etiquetes. ForAnyValue:StringEquals significa «almenys una d'aquestes claus hi ha de ser present». I el segon Statement és un Deny explícit sobre el canvi posterior d'Entorno i CentroCoste: sense ell, qualsevol podria crear un recurs ben etiquetat i cinc minuts després moure'n el cost a un altre centre de cost.

Un advertiment pràctic: exigir etiquetes per IAM a ec2:RunInstances és més complicat del que sembla, perquè una sola crida crea la instància, els seus volums i les seves interfícies de xarxa. Per això aquest mecanisme es reserva per a la creació manual i el gruix de l'etiquetatge es resol al CDK.

Regles de Config amb remediació

IAM impedeix crear malament. Config detecta el que ja està malament, inclòs el creat abans de posar les regles. La regla gestionada required-tags accepta fins a sis claus amb els seus valors.

aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "mercadofresco-etiquetas-obligatorias",
  "Description": "Les cinc etiquetes obligatories del projecte",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "REQUIRED_TAGS"
  },
  "InputParameters": "{\"tag1Key\":\"Proyecto\",\"tag1Value\":\"mercadofresco\",\"tag2Key\":\"Entorno\",\"tag2Value\":\"produccion,preproduccion,desarrollo\",\"tag3Key\":\"Componente\",\"tag3Value\":\"tienda,catalogo,pedidos,reparto,analitica\",\"tag4Key\":\"Propietario\",\"tag5Key\":\"CentroCoste\",\"tag5Value\":\"operaciones,marketing\"}",
  "Scope": {
    "ComplianceResourceTypes": [
      "AWS::EC2::Instance", "AWS::EC2::Volume", "AWS::RDS::DBInstance",
      "AWS::S3::Bucket", "AWS::Lambda::Function", "AWS::DynamoDB::Table",
      "AWS::ElasticLoadBalancingV2::LoadBalancer"
    ]
  }
}'

Sobre la remediació, cal tenir criteri i no automatitzar-ho tot igual:

Etiqueta Remediable automàticament? Com
Proyecto Sempre val mercadofresco; s'aplica sense preguntar
Entorno Es dedueix del compte: 111122223333produccion
Propietario Semi Es dedueix d'aws:createdBy de CloudTrail i es proposa
CentroCoste Parcialment Per defecte operaciones; es revisa a mà
Componente No Ningú tret del creador no sap si és catàleg o comandes

MercadoFresco automatitza les dues primeres amb un document de Systems Manager i avisa en les altres tres, amb una notificació diària a alertas-mercadofresco. La regla que evita el desastre: la remediació automàtica mai no inventa un valor de negoci. Etiquetar-ho tot com a Componente=tienda per defecte produiria un informe de costos preciós i completament fals.

Aspectes del CDK, ECS i el pipeline

El mecanisme que a la pràctica resol el 90 % del problema no és cap dels anteriors: és etiquetar a l'origen, a la infraestructura com a codi del mòdul 9. Al CDK, els aspectes (Tags) apliquen etiquetes a tot l'arbre de constructes d'una pila, inclosos els recursos que crea un constructe de nivell 3 sense que tu els escriguis:

from aws_cdk import App, Stack, Tags

app = App()
pila = PilaBotigaMercadoFresco(app, "MercadoFrescoTiendaProd", entorn="produccion")

# Un sol bloc etiqueta TOTS els recursos de la pila, inclosos els que crea
# ApplicationLoadBalancedFargateService per sota sense que tu els escriguis.
for clau, valor in {
    "Proyecto": "mercadofresco", "Entorno": "produccion",
    "Componente": "tienda", "Propietario": "luis",
    "CentroCoste": "operaciones",
}.items():
    Tags.of(pila).add(clau, valor)

# Excepcions puntuals sense renunciar a l'aspecte global
Tags.of(pila).add("Automatizacion", "apagado-nocturno",
                  exclude_resource_types=["AWS::ECS::Service"])

app.synth()

Tags.of(pila).add(...) recorre tot l'arbre de la pila, que és la diferència amb etiquetar recurs a recurs, i exclude_resource_types permet excepcions. Com que la pila la crea CloudFormation, a més queda automàticament aws:cloudformation:stack-name, que dona un repartiment per pila gratis.

A ECS, dues opcions concretes eviten que el cost de còmput més gran es quedi sense assignar:

aws ecs create-service \
  --cluster ecs-mercadofresco --service-name svc-mercadofresco-tienda-fg \
  --task-definition mercadofresco-tienda \
  --propagate-tags TASK_DEFINITION \
  --enable-ecs-managed-tags \
  --tags key=Proyecto,value=mercadofresco key=Entorno,value=produccion \
         key=Componente,value=tienda key=Propietario,value=luis \
         key=CentroCoste,value=operaciones

--propagate-tags TASK_DEFINITION fa que cada tasca hereti les etiquetes: sense aquesta opció el cost de Fargate no porta les teves etiquetes, que és exactament el que li passava a MercadoFresco amb 262,40 USD mensuals sense repartir. I --enable-ecs-managed-tags afegeix aws:ecs:clusterName i aws:ecs:serviceName, útils per separar la botiga dels treballadors.

I al pipeline (08-04), el pas de desplegament exporta les etiquetes com a variables i cdk deploy les rep. La comprovació es fa a més a build-mercadofresco-puerta-calidad: si cdk synth genera una plantilla amb algun recurs etiquetable sense les cinc claus, el pipeline falla. Aquesta és la barrera definitiva.

Quin mecanisme cobreix què: la taula de decisió

Mecanisme Moment Què garanteix Què NO cobreix Cost
Aspectes del CDK (09-02) En desplegar Tot el creat per IaC porta les 5 etiquetes El creat a mà o per un altre mitjà 0
Porta de qualitat del pipeline (08-02) Abans de desplegar Cap plantilla mal etiquetada no arriba a AWS El que no passa pel pipeline 0
Condicions IAM (04-01) En crear a mà No es pot crear sense etiquetes correctes Recursos ja existents; serveis sense suport 0
Política d'etiquetes (09-04) En crear i en etiquetar Grafia i valors canònics a tota l'organització Absència total de l'etiqueta si no hi ha enforced_for 0
Regla required-tags de Config (05-04) Continu, després del fet Detecta tot el no conforme, inclòs l'antic No impedeix crear; remeia només el deduïble ~0,001 USD per avaluació
--propagate-tags d'ECS En crear el servei Que el cost de les tasques porti etiquetes Altres serveis amb el mateix problema 0

L'estratègia completa de MercadoFresco és la suma: CDK i pipeline per al camí normal, IAM per al camí manual, política d'etiquetes per a la grafia, i Config com a xarxa de seguretat que ho audita tot. Cap dels cinc no sobra i cap no basta per si sol.

Auditar el que no està etiquetat i fixar un objectiu realista

Amb els mecanismes actius, queda la feina d'arqueologia: els recursos creats abans. 1. Tag Editor (dins de Resource Groups) cerca recursos per regió, tipus i etiqueta —inclosa la cerca per absència d'etiqueta— i permet etiquetar en bloc centenars de recursos de cop: és la drecera per arreglar l'històric. 2. L'API d'etiquetatge de recursos, per automatitzar-ho:

# Recursos SENSE l'etiqueta Componente al compte de produccio
aws resourcegroupstaggingapi get-resources --region eu-west-1 \
  --query 'ResourceTagMappingList[?!(Tags[?Key==`Componente`])].ResourceARN' \
  --output text | tr '\t' '\n' | sort

# Etiquetar en bloc un conjunt d'ARN coneguts
aws resourcegroupstaggingapi tag-resources \
  --resource-arn-list \
    arn:aws:sqs:eu-west-1:111122223333:cola-mercadofresco-almacen \
    arn:aws:sns:eu-west-1:111122223333:mercadofresco-pedido-confirmado \
  --tags Proyecto=mercadofresco,Entorno=produccion,Componente=pedidos,Propietario=luis,CentroCoste=operaciones

3. Un informe de cobertura que s'executa cada dilluns i publica el resultat com a mètrica:

import boto3
from collections import defaultdict

OBLIGATORIES = {"Proyecto", "Entorno", "Componente", "Propietario", "CentroCoste"}

def cobertura(sessio, entorn):
    api = sessio.client("resourcegroupstaggingapi", region_name="eu-west-1")
    cw = sessio.client("cloudwatch", region_name="eu-west-1")
    total, complets, falten, orfes = 0, 0, defaultdict(int), []

    # El paginador es obligatori: sense ell, nomes es miren els primers 100 recursos
    for pagina in api.get_paginator("get_resources").paginate(ResourcesPerPage=100):
        for recurs in pagina["ResourceTagMappingList"]:
            total += 1
            absents = OBLIGATORIES - {t["Key"] for t in recurs["Tags"]}
            if not absents:
                complets += 1
                continue
            for clau in absents:
                falten[clau] += 1
            if len(absents) == 5:               # sense cap etiqueta obligatoria
                orfes.append(recurs["ResourceARN"])

    pct = round(100 * complets / total, 1) if total else 100.0
    print(f"[{entorn}] {complets}/{total} complets = {pct} % "
          f"| orfes: {len(orfes)}")
    for clau, n in sorted(falten.items(), key=lambda x: -x[1]):
        print(f"    falta {clau}: {n} recursos")

    cw.put_metric_data(Namespace="MercadoFresco/Tienda", MetricData=[{
        "MetricName": "CoberturaEtiquetado",
        "Dimensions": [{"Name": "Entorno", "Value": entorn}],
        "Value": pct, "Unit": "Percent"}])
    return orfes

# A la practica s'assumeix un rol a cada compte amb sts:AssumeRole
cobertura(boto3.Session(), "produccion")

Dues decisions d'aquest script mereixen comentari. Separa recursos incomplets (els falta alguna etiqueta) d'orfes (no en tenen cap): els orfes són gairebé sempre restes abandonades i són el millor lloc per on començar a esborrar. I publica CoberturaEtiquetado com a mètrica personalitzada a MercadoFresco/Tienda amb dimensió Entorno, perquè la cobertura visqui al mateix tauler que el negoci i admeti una alarma quan baixi.

Un objectiu del 100 % és una manera elegant de garantir que ningú no es prengui l'indicador seriosament, perquè hi ha cost que no es pot etiquetar per definició. Els objectius de MercadoFresco, escrits i acordats:

Indicador Inicial A 3 mesos Estable
Recursos amb les 5 etiquetes 68 % 90 % 95 %
Cost assignat a un Componente 61 % 92 % 97 % del que és etiquetable
Recursos sense cap etiqueta 47 0 0
Cost amb Entorno assignat 74 % 98 % 99 %

Convé mesurar els dos indicadors per separat, perquè són molt diferents: cinquanta funcions Lambda sense etiquetar abaixen molt la cobertura per recursos i gairebé gens la de cost, i un clúster d'Aurora sense etiquetar fa el contrari. El que importa per a la factura és la cobertura per cost; el que importa per a la higiene operativa, la de recursos.

El compte com a dimensió de cost

Després de tota la feina d'etiquetatge convé reconèixer una cosa: per a la dimensió Entorno, MercadoFresco no necessitava etiquetes. L'estructura de comptes del mòdul 9 ja separa els entorns de manera perfecta i impossible de falsejar:

Compte Entorn Cost mensual %
111122223333 producció 1.482,10 USD 66,2 %
222233334444 preproducció 402,80 USD 18,0 %
333344445555 desenvolupament 246,50 USD 11,0 %
555566667777 eines (pipeline, ECR) 62,40 USD 2,8 %
444455556666 seguretat (trail, Config, GuardDuty) 38,90 USD 1,7 %
999988887777 gestió 4,90 USD 0,2 %
Total 2.237,60 USD 100 %

Aquest repartiment té tres propietats que cap etiqueta no pot igualar: és complet, perquè tot el cost pertany a un compte, inclòs el no etiquetable —transferència entre AZ, suport, Marketplace—; no es pot falsejar ni oblidar, perquè ningú no crea un recurs «sense compte»; i és retroactiu, perquè existeix des del primer dia sense haver activat res. D'aquí surt la regla pràctica, que és una de les conclusions del mòdul 9 vista des dels diners:

El que vulguis separar de debò, separa-ho per compte. El que vulguis analitzar dins d'un mateix àmbit, separa-ho per etiqueta.

Se separa per compte quan a més del cost es vol aïllar el radi de dany, l'accés o les quotes: entorns, unitats de negoci, clients grans. Se separa per etiqueta quan conviuen en el mateix àmbit i només cal atribuir: components, propietaris, centres de cost.

Categories de cost: del recurs al concepte de negoci

Queda un salt. El gerent no pregunta per comptes ni per etiquetes: pregunta per conceptes de negoci. «Plataforma», «producte» i «analítica» no són ni un compte ni una etiqueta: són combinacions.

Les categories de cost (Cost Categories) són regles definides al compte de gestió que creen una dimensió nova a partir de comptes, etiquetes, serveis o tipus de càrrec. Es comporten com una etiqueta més a Cost Explorer, Budgets i el CUR.

aws ce create-cost-category-definition \
  --name "AreaNegocio" \
  --rule-version CostCategoryExpression.v1 \
  --default-value "plataforma" \
  --rules '[
    {
      "Value": "analitica",
      "Rule": {
        "Or": [
          {"Tags": {"Key": "Componente", "Values": ["analitica"], "MatchOptions": ["EQUALS"]}},
          {"Dimensions": {"Key": "SERVICE", "Values": ["Amazon Redshift", "Amazon Athena"], "MatchOptions": ["EQUALS"]}}
        ]
      },
      "Type": "REGULAR"
    },
    {
      "Value": "producto",
      "Rule": {
        "And": [
          {"Dimensions": {"Key": "LINKED_ACCOUNT", "Values": ["111122223333"], "MatchOptions": ["EQUALS"]}},
          {"Tags": {"Key": "Componente", "Values": ["tienda", "catalogo", "pedidos", "reparto"], "MatchOptions": ["EQUALS"]}}
        ]
      },
      "Type": "REGULAR"
    }
  ]'

Una tercera regla, entornos-no-productivos, agrupa per LINKED_ACCOUNT els comptes 222233334444 i 333344445555.

Quatre detalls fan que això funcioni. L'ordre de les regles importa: s'avaluen de dalt a baix i guanya la primera que coincideix, per això analitica va abans que producto. --default-value "plataforma" captura tot el que no encaixa —NAT, ALB, endpoints, observabilitat, govern— i és la clau perquè no quedi cost sense classificar, que és justament el problema de les etiquetes. Es poden combinar And, Or i Not barrejant comptes amb etiquetes. I les categories sí que s'apliquen amb cert efecte retroactiu en crear-se, a diferència de les etiquetes.

Resultat per a MercadoFresco, amb les categories mútuament excloents:

Àrea de negoci Cost mensual % Interpretació
producto 1.129,80 USD 50,5 % El que el client fa servir directament
entornos-no-productivos 585,80 USD 26,2 % Preproducció + desenvolupament
plataforma 306,10 USD 13,7 % Xarxa, observabilitat, govern, CI/CD
analitica 215,90 USD 9,6 % Redshift, Athena, informes
Total 2.237,60 USD 100 %

Aquesta taula obre la conversa que la Marta feia mesos que no podia tenir: més d'una quarta part de la factura són entorns on no hi ha ni un client. No és necessàriament dolent —fan falta— però és un número que mereix una decisió, no un accident.

L'informe de costos i ús (CUR)

Cost Explorer, que veurem a 11-03, és una eina d'anàlisi interactiu amb límits: quan la pregunta és massa específica —«cost per component i per hora creuat amb les comandes de cada ciutat»— cal la dada en brut. L'AWS Cost and Usage Report (CUR) és el registre més detallat que AWS publica: una fila per recurs, per tipus d'ús i per hora, amb més de 150 columnes. Conté:

Grup de columnes Contingut Exemple
lineItem/* Compte, servei, tipus d'ús, quantitat, cost no combinat line_item_unblended_cost
product/* Atributs del producte: regió, tipus d'instància, família product_region
pricing/* Model de preu aplicat pricing_term: OnDemand, Reserved, SavingsPlan
reservation/*, savingsPlan/* Cobertura i cost amortitzat dels compromisos savings_plan_effective_cost
resourceTags/* Les teves etiquetes, una columna per etiqueta activada resource_tags_user_componente
costCategory/* Les teves categories de cost cost_category_area_negocio

Configuració de MercadoFresco, creada des del compte de gestió:

aws cur put-report-definition --report-definition '{
  "ReportName": "cur-mercadofresco-horario",
  "TimeUnit": "HOURLY",
  "Format": "Parquet",
  "Compression": "Parquet",
  "AdditionalSchemaElements": ["RESOURCES", "SPLIT_COST_ALLOCATION_DATA"],
  "S3Bucket": "mercadofresco-informes-analitica",
  "S3Prefix": "cur",
  "S3Region": "eu-west-1",
  "AdditionalArtifacts": ["ATHENA"],
  "RefreshClosedReports": true,
  "ReportVersioning": "OVERWRITE_REPORT"
}'

Cada opció i per què:

  • TimeUnit: HOURLY: sense granularitat horària no es veu el pic del divendres ni es pot calcular la base estable per als Savings Plans d'11-05.
  • Format: Parquet: columnar i comprimit. Athena cobra per bytes escanejats, i Parquet redueix l'escaneig entre 10 i 30 vegades enfront de CSV: la diferència entre pagar 0,60 USD al mes i pagar-ne 18.
  • AdditionalSchemaElements: RESOURCES: afegeix line_item_resource_id. Sense això l'informe no diu a quin recurs correspon cada línia, que és la meitat de la utilitat. SPLIT_COST_ALLOCATION_DATA reparteix a més el cost d'una tasca d'ECS entre els seus contenidors.
  • AdditionalArtifacts: ATHENA: genera el manifest i el CREATE TABLE sense escriure l'esquema a mà. I RefreshClosedReports reprocessa mesos tancats quan arriben ajustos o crèdits tardans.
  • Destinació mercadofresco-informes-analitica, el mateix bucket de la Sara, amb una política que permeti escriure a billingreports.amazonaws.com.

Advertiment de volum: aquest CUR genera uns 1,8 GB al mes en Parquet. Amb cicle de vida a Glacier Instant Retrieval als 90 dies costa cèntims; sense això, en tres anys són desenes de GB que ningú no consulta.

Consultar el CUR amb Athena

Amb la taula creada per l'artefacte d'Athena, la pregunta que obria la lliçó es respon per fi. Aquesta consulta reparteix el cost per Componente i calcula el percentatge sobre el total:

-- Cost del mes per Componente, amb el percentatge sobre el total,
-- separant el compartit i el no assignat.
WITH linies AS (
  SELECT
    CASE
      WHEN resource_tags_user_componente IS NULL
        OR resource_tags_user_componente = '' THEN 'sense-etiquetar'
      ELSE resource_tags_user_componente
    END                                   AS component,
    line_item_usage_account_id            AS compte,
    line_item_product_code                AS servei,
    line_item_unblended_cost              AS cost
  FROM cur_mercadofresco_horario
  WHERE year  = '2026'
    AND month = '8'
    AND line_item_line_item_type IN ('Usage', 'DiscountedUsage', 'SavingsPlanCoveredUsage')
),
totals AS (
  SELECT SUM(cost) AS total FROM linies
)
SELECT
  l.component,
  ROUND(SUM(l.cost), 2)                             AS cost_usd,
  ROUND(100 * SUM(l.cost) / MAX(t.total), 1)        AS percentatge,
  COUNT(DISTINCT l.servei)                          AS serveis_implicats
FROM linies l
CROSS JOIN totals t
GROUP BY l.component
ORDER BY cost_usd DESC;

Les parts que no són evidents. WHERE year AND month fa servir les particions: sense aquest filtre Athena escaneja tot l'històric i una consulta de 0,05 USD passa a costar diversos euros, que és la primera font de factures sorpresa d'Athena. line_item_line_item_type filtra el tipus de línia; sense això es barregen Tax, Credit, Refund i RIFee amb l'ús real i les sumes no quadren amb res. line_item_unblended_cost és el cost no combinat, el que correspon a l'ús d'aquella hora —a 11-03 veurem quan convé l'amortitzat—. I el CASE converteix nuls i cadenes buides en 'sense-etiquetar': sense això, el cost no assignat desapareix de l'informe, que és la manera més habitual d'enganyar-se un mateix.

Resultat sobre el mes de MercadoFresco:

Component Cost USD % Serveis
pedidos 604,30 27,0 % 11
tienda 512,40 22,9 % 9
compartit (sense component propi) 452,30 20,2 % 14
catalogo 286,70 12,8 % 8
analitica 214,50 9,6 % 6
reparto 118,90 5,3 % 7
sense-etiquetar 48,50 2,2 % 5
Total 2.237,60 100 %

I la segona consulta, la del cost per ciutat, que il·lustra el repartiment del que no es pot etiquetar. Creua el cost amb una taula de comandes que la Sara ja té a Redshift i que s'exporta a S3:

-- Cost imputat per ciutat: el directe no existeix, tot es repartiment per comandes.
WITH cost_variable AS (            -- computo, base de dades, cues i xarxa de la botiga
  SELECT SUM(line_item_unblended_cost) AS total
  FROM cur_mercadofresco_horario
  WHERE year = '2026' AND month = '8'
    AND line_item_usage_account_id = '111122223333'
    AND line_item_line_item_type IN ('Usage', 'SavingsPlanCoveredUsage')
    AND resource_tags_user_componente IN ('tienda', 'catalogo', 'pedidos', 'reparto')
),
comandes_ciutat AS (
  SELECT ciudad, COUNT(*) AS comandes FROM pedidos_agosto_2026 GROUP BY ciudad
),
total_comandes AS (SELECT SUM(comandes) AS n FROM comandes_ciutat)
SELECT
  p.ciudad,
  p.comandes,
  ROUND(100.0 * p.comandes / MAX(t.n), 1)                  AS pct_comandes,
  ROUND(MAX(c.total) * p.comandes / MAX(t.n), 2)           AS cost_imputat_usd,
  ROUND(MAX(c.total) / MAX(t.n), 5)                        AS cost_per_comanda_usd
FROM comandes_ciutat p
CROSS JOIN total_comandes t
CROSS JOIN cost_variable c
GROUP BY p.ciudad, p.comandes
ORDER BY p.comandes DESC;
Ciutat Comandes % Cost imputat Cost per comanda
Madrid 75.600 42,0 % 639,30 USD 0,00846 USD
Barcelona 50.400 28,0 % 426,20 USD 0,00846 USD
València 30.600 17,0 % 258,70 USD 0,00846 USD
Sevilla 23.400 13,0 % 197,90 USD 0,00846 USD
Total 180.000 100 % 1.522,10 USD 0,00846 USD

I aquí cal ser honest amb el resultat, perquè és un parany clàssic: el cost per comanda surt idèntic a les quatre ciutats perquè l'hem repartit proporcionalment a les comandes. La taula no descobreix res sobre les ciutats; només tradueix el cost a un llenguatge que el negoci entén. Perquè digués alguna cosa real caldria separar el que sí que difereix —per exemple, si Sevilla tingués el seu propi magatzem amb infraestructura dedicada, o si el repartiment d'una ciutat fes servir més crides a l'API de mapes—. Un repartiment lineal és una convenció comptable, no un descobriment. Dir-ho en veu alta quan es presenta la taula és el que separa una anàlisi d'una il·lusió.

Costos compartits i costos no assignables

Els 452,30 USD de la fila compartit són la part més interessant de l'informe, perquè és on viu la despesa que ningú no reclama:

Concepte compartit Cost Per què no té component
NAT Gateway (3 entorns) 243,80 USD El fan servir tots els components alhora
Endpoints de VPC i transferència entre AZ 118,60 USD Infraestructura de xarxa comuna
ALB alb-mercadofresco-tienda 47,20 USD Un sol balancejador per a tota la botiga
CloudTrail, Config, GuardDuty (compte de seguretat) 38,90 USD Govern de tota l'organització
Route 53 i certificats 3,80 USD Servei global

Hi ha tres maneres de tractar-ho i convé triar-ne una i escriure-la: deixar-ho com a «compartit» i presentar-ho a part, que és el més honest i el que fa MercadoFresco perquè ningú no discuteix una xifra que no se li imputa; repartir-ho proporcionalment al cost directe de cada component, senzill i defensable; o repartir-ho per ús real —bytes pel NAT, peticions per l'ALB—, el més just i el més car de calcular.

La regla de la Marta: repartir només quan el repartiment canviï una decisió. Si ningú no farà res diferent segons com s'imputin 3,80 USD de Route 53, repartir-los és feina perduda. Amb els 243,80 USD de NAT sí que canvia alguna cosa —porta directament a l'optimització d'11-03— i per això s'analitza en detall.

I després hi ha el cost no assignable de debò: els 48,50 USD de sense-etiquetar, on l'objectiu no és repartir-los sinó que desapareguin. Cada mes la revisió agafa aquesta llista, identifica els recursos i els etiqueta o els esborra: mitja hora de feina que després es manté sola.

Cost unitari: el cost per comanda de MercadoFresco

Tot l'anterior desemboca aquí. El cost absolut és una mètrica pobra: si la factura puja de 2.237 a 2.600 USD, és una mala notícia? Depèn completament de si el negoci ha crescut més o menys que això. La mètrica que sí que diu alguna cosa és el cost unitari: cost dividit per unitat de valor de negoci. Per a MercadoFresco, la unitat natural és la comanda.

Cost total mensual (agost) ..... 2.237,60 USD
Comandes servides a l'agost .... 180.000
Cost per comanda ............... 0,01243 USD (1,24 centims de dolar)

I el desglossament per component del cost per comanda, que és on apareixen les converses útils:

Component Cost mensual Cost per comanda Comentari
pedidos 604,30 USD 0,00336 USD Aurora, cues, Step Functions, Lambdes
tienda 512,40 USD 0,00285 USD Fargate, ALB, CloudFront
compartit 452,30 USD 0,00251 USD El segon més gran: NAT i xarxa
catalogo 286,70 USD 0,00159 USD ElastiCache, S3, CloudFront
analitica 214,50 USD 0,00119 USD No escala amb les comandes
reparto 118,90 USD 0,00066 USD DynamoDB, Lambdes
sense-etiquetar 48,50 USD 0,00027 USD A eliminar
Total 2.237,60 USD 0,01243 USD

Per què aquesta mètrica és millor que el total, amb tres exemples concrets. Creixement sa: si les comandes pugen un 30 % i la factura un 18 %, el cost per comanda baixa, la factura ha pujat i és una bona notícia; amb el total absolut, aquesta notícia sembla dolenta. Detecció d'ineficiència: si el cost per comanda puja dos mesos seguits sense canvi d'arquitectura, hi ha alguna cosa que no va bé —un recurs encès, una consulta que s'ha tornat cara, un registre que creix sense control—. I decisions de producte: permet respondre «surt rendible la comanda de 12 euros?» i «quant costarà obrir a Portugal?» amb un número en lloc d'una intuïció.

MercadoFresco publica CostePorPedido com a mètrica personalitzada a MercadoFresco/Tienda i la posa al tauler mercadofresco-negocio, al costat de PedidosConfirmados. És la primera vegada que una dada de la factura viu al costat d'una dada de negoci, i aquest veïnatge és la meitat del valor. Com a suport es calculen altres tres unitats: cost per client actiu (0,048 USD/mes), cost per ciutat servida (559,40 USD) i cost d'infraestructura sobre ingressos (0,42 %).

Mostrar i reintegrar costos: showback i chargeback

Amb el repartiment fet, queda la part organitzativa, que és on aquestes iniciatives moren o arrelen. Dos models:

Model Què és Efecte Risc
Showback (mostrar) S'informa cada equip del que gasta, sense moure diners Crea consciència; gairebé sense fricció Es pot ignorar
Chargeback (reintegrar) El cost s'imputa al pressupost de l'equip Canvia comportaments de debò Discussions sobre el repartiment; pot incentivar decisions dolentes

MercadoFresco, amb tres persones, fa showback: un informe mensual automàtic per Propietario el dia 3, que no és una llista de números sinó la variació enfront del mes anterior, el cost per comanda i una sola recomanació concreta; i amb la regla que ningú no s'emporti una sorpresa en públic, perquè si la despesa del Luis s'ha disparat, la Marta l'hi diu abans de la reunió i no durant.

El chargeback arriba quan hi ha pressupostos departamentals de debò. I convé conèixer l'efecte pervers que produeix mal aplicat: si a un equip se li cobra cada entorn de proves, deixa de crear entorns de proves i comença a provar en producció. Un model de costos que empitjora l'enginyeria no és un estalvi.

Errors Habituals i Consells

Error: creure que posar etiquetes n'hi ha prou per veure-les a la factura. El recurs està etiquetat des del març i l'informe continua dient «sense etiquetar». Consell: cal activar cada etiqueta com a etiqueta d'assignació de costos al compte de gestió, i fins a 24 hores després no apareix.

Error: esperar que les etiquetes siguin retroactives. S'activen a l'agost i algú demana el repartiment del maig. Consell: no existeix i no existirà. Activa-les el dia que defineixis la convenció, encara que la cobertura sigui del 40 %.

Error: valors lliures. Al cap de sis mesos hi ha Componente amb els valors tienda, Tienda, tienda-web, web i front. Consell: llista tancada, publicada i imposada amb política d'etiquetes d'Organizations. Un informe amb cinc valors on n'hi ha un és inservible i ja no es pot arreglar cap enrere.

Error: demanar l'etiquetatge per correu. La cobertura puja al 70 % i allà es queda per sempre. Consell: el 90 % es resol al CDK amb Tags.of(pila) i a la porta de qualitat del pipeline; el que arriba per una altra via es cobreix amb IAM i s'audita amb Config.

Error: oblidar --propagate-tags a ECS. El servei està etiquetat però les tasques no, i el cost de còmput més gran apareix sense repartir. Consell: --propagate-tags TASK_DEFINITION i --enable-ecs-managed-tags a tots els serveis.

Error: perseguir el 100 % de cobertura. Es perden setmanes intentant etiquetar coses que no admeten etiquetes. Consell: l'objectiu és el 95 % dels recursos i el 97 % del cost etiquetable; la resta es deixa com a «compartit» a la vista.

Error: escanejar tot el CUR a cada consulta d'Athena. Una consulta que havia de costar 0,03 USD acaba costant diversos euros i es repeteix cada hora en un tauler. Consell: filtra sempre per year i month, fes servir Parquet i posa un límit de bytes escanejats al grup de treball d'Athena.

Error: presentar el cost absolut a la reunió mensual. La factura puja, tothom s'alarma i ningú no sap si és bo o dolent. Consell: presenta el cost per comanda primer i el total després: canvia la conversa de «gastem molt» a «gastem bé o malament».

Consell: activa aws:createdBy des del primer dia. És gratis, no depèn de la disciplina de ningú i respon a la pregunta més freqüent de l'anàlisi de costos: «qui ha encès això?».

Consell: etiqueta també el que no costa diners i guarda la convenció a mercadofresco-infra, no en un document solt. Un grup de seguretat etiquetat amb Proyecto=mercadofresco és la diferència entre esborrar amb confiança i no atrevir-s'hi el dia de la neteja; i una convenció versionada es revisa per pull request i no es bifurca.

Exercicis

Exercici 1: dissenyar l'etiquetatge d'una empresa nova

GranjaDigital ven caixes de verdura per subscripció. Té un compte únic d'AWS amb dos entorns barrejats (producció i proves), quatre persones i quatre sistemes: web de subscripció, motor de facturació recurrent, planificador de rutes de repartiment i tauler d'informes. Imputa els seus costos a dues àrees: «tecnologia» i «logística».

  1. Proposa un conjunt d'etiquetes obligatòries amb els seus valors permesos, justificant-ne cadascuna.
  2. Indica què separaries per compte en lloc de per etiqueta i per què.
  3. Escriu la política d'etiquetes d'Organizations per a l'etiqueta d'entorn.
  4. Quin mecanisme d'imposició recomanes primer, tenint en compte que encara no fan servir IaC?

Exercici 2: llegir un informe d'assignació

Parteix del repartiment per component que has vist a la lliçó: factura total de 2.237,60 USD amb 180.000 comandes, de les quals analitica suposa 214,50 USD. Al mes següent, les comandes pugen a 234.000 (+30 %) i la factura total a 2.594,00 USD.

  1. Calcula el cost per comanda dels dos mesos.
  2. És una bona o una mala notícia? Justifica-ho.
  3. Si analitica ha passat de 214,50 a 361,00 USD i la resta ha crescut proporcionalment a les comandes, què investigaries?
  4. Escriu la consulta SQL sobre el CUR que et permetria confirmar la teva sospita.

Exercici 3: costos compartits i decisions

Dels 452,30 USD compartits de MercadoFresco, 243,80 USD són NAT Gateway repartits així: 100,00 USD en producció, 74,00 en preproducció i 69,80 en desenvolupament.

  1. Proposa dues maneres diferents d'imputar aquest cost als components i digues quina triaries.
  2. Sense entrar encara en optimització, quines dues preguntes et suggereix aquest repartiment?
  3. Canviaria la teva recomanació d'imputació si el NAT costés 12 USD al mes en lloc de 243,80? Per què?

Solucions

Solució a l'exercici 1

(1) Etiquetes obligatòries proposades — quatre, no cinc:

Clau Valors Justificació
Entorno produccion, pruebas Comparteixen compte: és l'única manera de separar-los
Componente web, facturacion, rutas, informes Els quatre sistemes; «què em costa cada cosa»
Area tecnologia, logistica La imputació comptable que ja fan servir
Propietario Nom de les quatre persones Saber a qui avisar

No s'hi inclou Proyecto: amb un sol projecte i un sol compte seria una etiqueta d'un únic valor, és a dir, soroll.

(2) Què separar per compte. Producció i proves han d'estar en comptes separats, i aquesta és la recomanació més valuosa de l'exercici: aïllament del radi de dany, quotes independents, permisos nets i —el que aquí importa— repartiment de cost complet, retroactiu i impossible de falsejar, inclòs el cost no etiquetable. Amb aquesta separació, Entorno passa a ser redundant i queden tres etiquetes obligatòries.

(3) Política d'etiquetes per a l'entorn:

{
  "tags": {
    "Entorno": {
      "tag_key": { "@@assign": "Entorno" },
      "tag_value": { "@@assign": ["produccion", "pruebas"] },
      "enforced_for": { "@@assign": ["ec2:instance", "ec2:volume", "rds:db",
                                     "s3:bucket", "lambda:function"] }
    }
  }
}

Amb l'advertiment de desplegar enforced_for en dues fases: primer sense ell per veure què es trenca.

(4) Què imposar primer sense IaC, de major a menor retorn immediat: Config amb required-tags i notificació diària, que no impedeix res però dona la foto real en 24 hores; Tag Editor per etiquetar en bloc l'existent, una feina d'una tarda; la política d'etiquetes en mode informatiu, per fixar la grafia abans que es bifurqui; i les condicions IAM només quan l'anterior sigui estable. Amb la recomanació de fons de començar a fer servir IaC: quatre persones creant recursos a mà garanteixen que la cobertura mai no passarà del 80 %.

Solució a l'exercici 2

(1) Cost per comanda:

Mes 1: 2.237,60 / 180.000 = 0,012431 USD · Mes 2: 2.594,00 / 234.000 = 0,011085 USD · variació −10,8 %.

(2) És una bona notícia, i clara. La factura ha pujat un 15,9 % mentre el negoci creixia un 30 %. El cost per comanda baixa un 10,8 %, la qual cosa significa que l'arquitectura està escalant millor que linealment: hi ha components amb cost fix —NAT, ALB, observabilitat, govern— que es reparteixen entre més comandes. Presentar només el total («la factura ha pujat 356 USD») donaria la impressió contrària i podria portar a frenar el creixement per por.

(3) Què investigar a analitica. Ha crescut un 68,3 % mentre el negoci creixia un 30 %: és l'única partida que es desvia. Hipòtesis per ordre de probabilitat: una càrrega o consulta programada que s'executa més vegades de les necessàries, o un grup de treball de Redshift que no es pausa; consultes d'Athena sense filtrar per partició, que escanegen tot l'històric del CUR cada vegada; creixement real per més dades històriques, que justificaria un 30 % però no un 68 %; o un informe nou que ningú no ha dimensionat.

(4) Consulta per confirmar-ho:

-- Desglossament diari del component analitica, per servei i tipus d'us,
-- comparant els dos mesos.
SELECT
  month,
  line_item_product_code                                AS servei,
  line_item_usage_type                                  AS tipus_us,
  ROUND(SUM(line_item_unblended_cost), 2)               AS cost_usd,
  ROUND(SUM(line_item_usage_amount), 2)                 AS quantitat
FROM cur_mercadofresco_horario
WHERE year = '2026'
  AND month IN ('8', '9')
  AND resource_tags_user_componente = 'analitica'
  AND line_item_line_item_type = 'Usage'
GROUP BY month, line_item_product_code, line_item_usage_type
ORDER BY month, cost_usd DESC;

La columna line_item_usage_type és la que resol el cas: distingeix entre RPU-Hours de Redshift i DataScanned-Bytes d'Athena. Si el creixement és a DataScanned-Bytes, la causa és una consulta sense particionar; si és a RPU-Hours, és un grup de treball que no es pausa. Afegir line_item_resource_id al GROUP BY assenyalaria el recurs exacte.

Solució a l'exercici 3

(1) Dues maneres d'imputar els 243,80 USD de NAT. L'opció A, proporcional al cost directe de cada component, és trivial de calcular, estable i comprensible, però assumeix que un component car fa servir més xarxa, cosa que no sempre és certa: analitica és car i fa servir poca sortida per NAT, mentre que reparto és barat i crida constantment una API externa de mapes. L'opció B, per bytes processats reals segons els registres de flux de la VPC, és el repartiment just, però exigeix activar i emmagatzemar aquests registres —que costen diners—, processar-los i acceptar que el resultat variï cada mes.

Elecció: l'opció A, i presentar el NAT també com a línia pròpia. Amb 243,80 USD, la diferència entre un repartiment i l'altre és de desenes de dòlars i el cost de calcular l'opció B es menja el benefici. L'important no és a qui s'imputa, sinó que el número estigui a la vista.

(2) Dues preguntes que suggereix el repartiment. Primera: per què desenvolupament i preproducció paguen 143,80 USD de NAT, gairebé tant com producció, si no hi ha ni un client a dins? Gairebé tot aquest import és el càrrec fix per hora de cada NAT Gateway, no el trànsit, i si n'hi ha dos per redundància cal preguntar-se si un entorn de desenvolupament necessita alta disponibilitat de sortida a internet. Segona: quin trànsit surt pel NAT que podria no sortir-ne? Imatges d'ECR, crides a S3, registres a CloudWatch: tot això pot anar per endpoints de VPC. És l'anàlisi que 10-02 va deixar oberta i que 11-03 tanca amb números.

(3) Canviaria amb 12 USD? Sí, completament. Amb 12 USD al mes, la resposta correcta és no imputar-lo en absolut: deixar-lo a la bossa de «compartit» i no dedicar-hi ni una hora. El criteri no és la puresa comptable, sinó si l'anàlisi pot canviar una decisió. Dotze dòlars no canvien cap decisió; 243,80 USD al mes són gairebé 2.926 USD a l'any i sí que la canvien. L'esforç d'assignació ha de ser proporcional a l'import en joc, i aquesta és la diferència entre gestió de costos i comptabilitat ritual.

Conclusió

MercadoFresco ja no té una factura: té un model de costos. Saps per què el problema no era la xifra sinó la seva forma: la factura ve organitzada segons l'estructura d'AWS —serveis— i el negoci pregunta segons la seva —entorns, components, ciutats, comandes—. I saps que l'ordre correcte per resoldre-ho és escriure primer les preguntes i només després decidir les etiquetes, perquè les estratègies d'etiquetatge dissenyades «per si de cas» acaben amb vint claus que no responen res.

Tens l'estratègia d'etiquetatge completa: les cinc obligatòries del curs amb la seva justificació, les opcionals amb el seu consumidor concret, les convencions de grafia —valors en minúscules, sense accents, claus en PascalCase, prefix aws: prohibit— i, sobretot, els valors tancats, perquè una etiqueta de text lliure sempre acaba amb cinc variants del mateix component. Amb el rang que funciona a la pràctica, de 4 a 8 etiquetes obligatòries, i el senyal inequívoc que en sobren: quan algú ha de preguntar quin valor posar-hi.

Tens clar que una etiqueta no és una dimensió de cost fins que s'activa al compte de gestió, que les generades per AWS —aws:createdBy, aws:cloudformation:stack-name, aws:ecs:serviceName— són gratis i no depenen de la disciplina de ningú, i el detall que arruïna molta gent: l'activació no és retroactiva. El cost anterior queda com a «sense etiquetar» per sempre, encara que els recursos estiguessin etiquetats des de feia mesos.

Tens els cinc mecanismes per imposar l'etiquetatge en lloc de demanar-lo, amb el que cobreix cadascun: aspectes del CDK amb Tags.of(pila), que resolen el 90 % del problema de cop; la porta de qualitat del pipeline, que impedeix que una plantilla mal etiquetada arribi a AWS; les condicions IAM amb aws:RequestTag i aws:TagKeys, inclòs el Deny explícit que evita que algú canviï el centre de cost després; les polítiques d'etiquetes d'Organizations amb enforced_for desplegat per fases; i les regles de Config com a xarxa de seguretat, amb la regla que evita el desastre: la remediació automàtica mai no inventa un valor de negoci. Més el --propagate-tags TASK_DEFINITION d'ECS, sense el qual el cost de còmput més gran apareix sense repartir. I l'auditoria que ho tanca: Tag Editor per a l'arqueologia, l'API d'etiquetatge per automatitzar-la, l'informe setmanal publicat com a mètrica CoberturaEtiquetado, i els dos indicadors que cal mesurar per separat —cobertura per recursos i per cost—, amb objectius del 95 % i el 97 % en lloc d'un 100 % impossible.

Tens les dues dimensions que les etiquetes no cobreixen. El compte, que separa millor que qualsevol etiqueta perquè és complet, retroactiu i impossible de falsejar —d'aquí la regla: el que vulguis separar de debò, separa-ho per compte; el que vulguis analitzar dins d'un àmbit, separa-ho per etiqueta—. I les categories de cost, que tradueixen comptes i etiquetes a conceptes de negoci amb un valor per defecte que garanteix que no quedi cost sense classificar, i que van revelar la dada incòmoda: més d'una quarta part de la factura són entorns sense un sol client a dins. Tot això recolzat en l'informe de costos i ús configurat amb criteri —horari, en Parquet, amb RESOURCES i artefacte d'Athena, lliurat a mercadofresco-informes-analitica— i en les consultes SQL que reparteixen el cost per component i per ciutat, amb els dos detalls que separen una consulta de 0,03 USD d'una de diversos euros: filtrar sempre per partició i per line_item_line_item_type. I amb l'honestedat de reconèixer que un repartiment lineal per comandes és una convenció comptable, no un descobriment.

I tens la mètrica que canvia la conversa: el cost per comanda, avui 0,01243 USD sobre 180.000 comandes i 2.237,60 USD de factura, publicat al tauler mercadofresco-negocio al costat de PedidosConfirmados. Amb la raó per la qual és millor que el total: quan el negoci creix un 30 % i la factura un 16 %, el total diu «males notícies» i el cost unitari diu la veritat. Més el model organitzatiu triat —showback, no chargeback— i l'efecte pervers que convé tenir present: un model de costos que fa que la gent deixi de crear entorns de proves no és un estalvi.

Amb la factura per fi llegible, la pregunta següent ja no és qui gasta, sinó en què, i sobretot què de tot això no calia. Els 243,80 USD de NAT Gateway, els 214,90 de CloudWatch i aquests 452,30 de cost compartit demanen a crits que algú els obri i els miri per dins.

A 11-03, «AWS Cost Explorer», s'obre la factura de debò: el desglossament complet per servei, els conceptes de facturació que cal entendre abans de mirar cap gràfic —cost no combinat, amortitzat i net—, les tres sorpreses clàssiques que gairebé sempre hi són, la detecció automàtica d'anomalies, i les deu optimitzacions concretes que MercadoFresco executarà amb el seu estalvi calculat una per una.

Curs d'AWS

Mòdul 1: Introducció a AWS

Mòdul 2: Serveis principals d'AWS

Mòdul 3: Xarxes i lliurament de contingut

Mòdul 4: Seguretat i identitat

Mòdul 5: Monitoratge i gestió

Mòdul 6: Bases de dades

Mòdul 7: Integració d'aplicacions

Mòdul 8: Eines per a desenvolupadors

Mòdul 9: Infraestructura com a codi i govern de comptes

Mòdul 10: Contenidors a AWS

Mòdul 11: Millors pràctiques i gestió de costos

© Copyright 2026. Tots els drets reservats