\n\n\n\n Le mie fatture Cloud sono troppo alte: Ecco cosa noto ora - AgntMax \n

Le mie fatture Cloud sono troppo alte: Ecco cosa noto ora

📖 12 min read2,235 wordsUpdated Apr 4, 2026

Ciao a tutti, Jules Martin qui, di ritorno su agntmax.com!

Oggi voglio affrontare qualcosa che mi assilla, e probabilmente molti di voi, da circa un anno: il costo crescente dell’infrastruttura cloud, in particolare per quanto riguarda le funzioni serverless. Siamo stati tutti affascinati dal sogno del “pagare solo per ciò che usi”, e a lungo questo sembrava una realtà. Ma recentemente, ho visto le fatture aumentare, a volte in modo inspiegabile, anche quando i modelli di traffico sembravano stabili. È come se fossimo erosi dalla stessa flessibilità che avevamo adottato. Quindi, esploriamo qualcosa di molto specifico e attuale: Dominare il Mostro Serverless: Svelare e Ridurre i Costi Nascosti di AWS Lambda.

Il mio personale percorso in questo campo è iniziato circa sei mesi fa. Abbiamo un microservizio centrale che gestisce l’autenticazione degli utenti e la gestione delle sessioni. È quasi completamente costruito su AWS Lambda, API Gateway, DynamoDB e Cognito. Per molto tempo, i costi erano perfettamente prevedibili. Poi, la scorsa estate, la nostra fattura AWS per questo servizio specifico è aumentata di circa il 15%. Niente nuove funzionalità, nessun picco di traffico significativo. Inizialmente ho attribuito questo a una fluttuazione stagionale o a un piccolo bug che non avevo ancora scovato. Ma quando la fattura del mese seguente è arrivata ancora più alta, ho capito che dovevo approfondire. Non si trattava solo di un picco; era una tendenza, e ci stava costando soldi veri.

L’Illusione dei Livelli “Gratuiti” e la Realtà delle Invocazioni “Minuscole”

Uno dei maggiori vantaggi del serverless, in particolare per le startup o i piccoli team, è il generoso livello gratuito. Ed è generoso! Un milione di invocazioni gratuite al mese per Lambda, oltre a una quantità significativa di tempo di calcolo. Il problema è che man mano che la vostra applicazione cresce, queste invocazioni “gratuite” svaniscono più velocemente di una fetta di pizza durante un meetup tech. Ciò che spesso viene trascurato è il volume totale delle invocazioni minuscole, apparentemente insignificanti, che si accumulano. Pensate ai cron job, ai controlli di salute interni, o persino ai meccanismi di retry provenienti da altri servizi. Ognuna di queste invocazioni conta.

La mia indagine sul nostro servizio di autenticazione ha rivelato esattamente questo. Avevamo una funzione Lambda, chiamiamola auth-token-refresher, progettata per rinfrescare periodicamente i token di servizio interni. Era programmata per essere eseguita ogni cinque minuti. Sembra innocua, vero? 288 invocazioni al giorno. Moltiplicate per 30 giorni, e si ottengono 8.640 invocazioni al mese. Aggiungete i nostri ambienti di sviluppo, staging e produzione, e improvvisamente rappresenta più di 25.000 invocazioni solo per un piccolo compito di manutenzione. Avevamo una dozzina di tali funzioni. All’improvviso, le nostre invocazioni “minuscole” non erano più così piccole.

Trovare i Colpevoli: Le Metriche CloudWatch Sono il Vostro Miglior Amico

Il primo passo per dominare questa bestia è sapere dove va il vostro denaro. AWS CloudWatch è indispensabile qui. Non limitatevi a guardare il dashboard di fatturazione ad alto livello; esplorate le metriche specifiche delle vostre funzioni Lambda.

Ecco su cosa mi sono concentrato:

  1. Invocazioni: Questa è la metrica più semplice. Alti conteggi di invocazioni per funzioni che non gestiscono il traffico utente diretto sono segnali d’allerta immediati.
  2. Durata: Quanto dura ogni invocazione? Durate più lunghe significano costi di calcolo superiori.
  3. Utilizzo della Memoria: State sovraprovisionando la memoria per le vostre funzioni? Pagate per ciò che allocate, non per ciò che utilizzate.
  4. Tasso di Errori: Alti tassi di errore possono portare a retry, il che significa più invocazioni e cicli di calcolo sprecati.

Per il nostro auth-token-refresher, ho esaminato la sua metrica `Invocazioni`. Infatti, si eseguiva come un orologio, ogni cinque minuti. La durata era minima, solo circa 50 ms. Ma il volume enorme contribuiva al nostro costo complessivo di invocazione.

Esempio Pratico 1: Consolidare e Pianificare in Modo più Intelligente

La soluzione per auth-token-refresher e diverse altre funzioni di manutenzione simili era sorprendentemente semplice: la consolidazione. Anziché avere funzioni Lambda individuali attivate da eventi CloudWatch (o EventBridge oggigiorno) su orari separati, ho creato una singola funzione Lambda “Maintenance Runner”.

Questo “Maintenance Runner” viene attivato da una sola regola di evento CloudWatch, diciamo, una volta all’ora. All’interno di questo runner, ho un semplice dispatcher che verifica l’ora corrente e esegue i compiti necessari. Ad esempio:


import os
import datetime

def lambda_handler(event, context):
 current_hour = datetime.datetime.now().hour
 current_minute = datetime.datetime.now().minute

 # Compito 1: Rinfrescare il token di autenticazione (si eseguiva ogni 5 minuti)
 if current_minute % 10 == 0: # Si esegue ora ogni 10 minuti
 print("Esecuzione del rinfrescamento del token d'autenticazione...")
 # Chiamare la logica reale di rinfrescamento del token o un'altra funzione interna
 refresh_auth_token()

 # Compito 2: Pulire i log vecchi (si eseguiva ogni ora)
 if current_hour % 1 == 0 and current_minute == 0: # Si esegue all'inizio dell'ora
 print("Esecuzione della pulizia dei log...")
 cleanup_old_logs()

 # Compito 3: Controllare lo stato dei servizi esterni (si eseguiva ogni 30 minuti)
 if current_minute == 0 or current_minute == 30:
 print("Controllo dello stato dei servizi esterni...")
 check_external_service()

 return {
 'statusCode': 200,
 'body': 'Compiti di manutenzione eseguiti.'
 }

def refresh_auth_token():
 # ... logica reale di rinfrescamento del token ...
 pass

def cleanup_old_logs():
 # ... logica reale di pulizia dei log ...
 pass

def check_external_service():
 # ... logica reale di controllo dei servizi esterni ...
 pass

Questo semplice cambiamento ha immediatamente ridotto il numero di invocazioni per questi compiti di manutenzione da centinaia di migliaia al mese a qualche migliaio. I risparmi erano tangibili, non solo per quanto riguarda le invocazioni Lambda, ma anche per quanto riguarda l’ingestione dei log CloudWatch e le chiamate all’API Gateway (se una di esse era esposta tramite API Gateway).

Il Rischio della Sovraprovidenza di Memoria

Questo è un altro fattore di costo sottile che viene spesso trascurato. Quando create una funzione Lambda, allocate una certa quantità di memoria (ad esempio, 128 MB, 256 MB, 512 MB). Pagate per questa memoria allocata, indipendentemente da quanto effettivamente utilizzi la vostra funzione. Inoltre, la potenza della CPU cresce proporzionalmente all’allocazione di memoria. Quindi, se allocate 1 GB di memoria per uno semplice script Python che ha bisogno solo di 128 MB, non solo pagate troppo per la memoria; pagate anche per cicli di CPU aggiuntivi di cui non avete bisogno.

Ho imparato questo a mie spese con una funzione Lambda di elaborazione dati che era inizialmente configurata con 1 GB di memoria “nel caso in cui”. Quando ho guardato le sue metriche CloudWatch per l’utilizzo della memoria, rimaneva sistematicamente al di sotto di 200 MB, anche in periodi di carico elevato. In sostanza, stavamo pagando per 800 MB di RAM inutilizzata e il corrispondente boost CPU.

Esempio Pratico 2: Ottimizzare l’Allocazione di Memoria con Lambda Power Tuning

Determinare manualmente l’impostazione di memoria ottimale può essere noioso. Dovete distribuire, testare, monitorare, aggiustare e ripetere. Fortunatamente, esiste un ottimo strumento open-source chiamato AWS Lambda Power Tuning (sviluppato da Alex Casalboni in AWS) che semplifica questo processo.

È un’applicazione serverless che vi aiuta a visualizzare e identificare l’impostazione di memoria ottimale per le vostre funzioni Lambda in base ai costi e alle prestazioni. La distribuite nel vostro account AWS e poi potete usarla per testare le vostre funzioni.

Ecco generalmente come funziona:

  1. Distribuite lo strumento Power Tuning tramite il Serverless Application Repository o SAM.
  2. Invocate una macchina a stati (creata dallo strumento) con l’ARN della vostra funzione Lambda e un payload.
  3. La macchina a stati invoca il vostro Lambda più volte con configurazioni di memoria diverse (ad esempio, 128 MB, 256 MB, 512 MB, 1024 MB, ecc.).
  4. Analizza quindi i log di esecuzione e fornisce una visualizzazione che mostra i compromessi di costo e velocità per ciascuna impostazione di memoria.

Per la mia funzione Lambda di elaborazione dei dati, passando attraverso il Power Tuner, ho scoperto che 256 MB era la scelta migliore in termini di costi, con una degradazione delle prestazioni trascurabile rispetto a 1 GB. Abbiamo immediatamente ridotto l’allocazione della memoria a 256 MB, il che ha comportato una riduzione del 75% dei costi di calcolo per questa specifica funzione. Non era un caso isolato; ho da allora preso l’abitudine di far passare le nuove funzioni o quelle riesaminate tramite questo strumento.

Per utilizzarlo, dopo il deploy, generalmente iniziereste la macchina di stato con qualcosa di simile (regolando l’ARN e il payload):


aws stepfunctions start-execution \
 --state-machine-arn "arn:aws:states:REGIONE:ID_COMPTE:stateMachine:powerTuningStateMachine" \
 --input '{ "lambdaARN": "arn:aws:lambda:REGIONE:ID_COMPTE:function:NOME_DELLA_TUA_FUNZIONE", "num": 100, "payload": {}, "parallel": 5 }'

L’uscita fornisce un grafico chiaro, mostrando esattamente dove i vostri costi e la vostra velocità si incrociano per una performance ottimale. È un cambiamento significativo per l’ottimizzazione dei costi.

Verbosity dei Log e Avviamenti a Freddo

Due altri ambiti che possono spesso sorprendervi sono la verbosità dei log e gli avviamenti a freddo. I log di CloudWatch non sono gratuiti. Ogni riga che la vostra funzione Lambda stampa viene ingerita e conservata, e voi pagate per questo. Sebbene una buona registrazione sia cruciale per il debug, una registrazione troppo verbosa (ad esempio, stampare interi oggetti o ripetere messaggi di stato inutilmente) può rapidamente gonfiare la vostra fattura di CloudWatch Logs.

Ho trovato alcune funzioni che registravano l’intero corpo delle richieste HTTP ad ogni invocazione. Sebbene sia utile per lo sviluppo iniziale, in produzione, questo generava solo rumore e costava soldi. Un rapido aggiustamento per registrare solo i metadati essenziali (ID della richiesta, codice di stato, endpoint) ha ridotto in modo significativo la nostra ingestione di log.

Gli avviamenti a freddo, sebbene non rappresentino un “costo” diretto nello stesso modo, influenzano l’esperienza utente e possono comportare indirettamente più tentativi o durate di fatturazione più lunghe se la vostra funzione deve attendere delle risorse. Sebbene AWS abbia fatto progressi significativi nel ridurre i tempi di avviamento a freddo, ottimizzare la dimensione del pacchetto della vostra funzione ed evitare una logica di inizializzazione complessa al di fuori del gestore può ancora fare la differenza. Per le funzioni critiche sensibili alla latenza, la concorrenza provisionata è un’opzione, ma sappiate che pagate per questa concorrenza assegnata anche quando è inattiva.

Esempio Pratico 3 : Log Intelligenti e Variabili d’Ambiente

Per il logging, la soluzione più semplice è spesso la migliore. Utilizzate variabili d’ambiente per controllare i livelli di logging. In Python, ad esempio, potete fare così:


import os
import logging

LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO').upper()
logging.basicConfig(level=LOG_LEVEL)
logger = logging.getLogger()

def lambda_handler(event, context):
 logger.debug("Questo è un messaggio di debug, visibile solo se LOG_LEVEL è DEBUG")
 logger.info("Elaborazione dell'evento : %s", event.get('request_id'))
 try:
 # ... logica della funzione ...
 logger.debug("Elaborazione completata per request_id : %s", event.get('request_id'))
 return {
 'statusCode': 200,
 'body': 'Successo'
 }
 except Exception as e:
 logger.error("Errore durante l'elaborazione di request_id %s : %s", event.get('request_id'), str(e), exc_info=True)
 return {
 'statusCode': 500,
 'body': 'Errore'
 }

Impostando LOG_LEVEL su INFO in produzione e DEBUG in sviluppo/staging, potete ridurre notevolmente la vostra fattura di CloudWatch Logs senza sacrificare l’osservabilità quando ne avete bisogno.

Un altro consiglio è prestare attenzione a ciò che è inizializzato al di fuori del gestore. Qualsiasi codice direttamente nell’ambito globale della vostra funzione Lambda verrà eseguito durante l’avvio a freddo. Se avete operazioni costose come il pooling delle connessioni al database o grandi importazioni di librerie, considerate di rinviare la loro esecuzione fino a quando non sono realmente necessarie nel gestore, oppure assicuratevi che siano efficacemente memorizzate in cache per le successive invocazioni a caldo.

Punti Chiave per la Vostra Crociata sui Costi Senza Server

D’accordo, abbiamo coperto un bel po’ di cose. Ecco un riepilogo dei passaggi pratici che potete intraprendere immediatamente per iniziare a ridurre questi insidiosi costi di Lambda:

  • Monitorate senza sosta: Non vi limitate a dare un’occhiata alla vostra fattura AWS globale. Esplorate le metriche di CloudWatch per le Invocazioni, la Durata e l’Utilizzo della Memoria per ogni funzione Lambda. Configurate allarmi per i picchi inattesi.
  • Consolidate i compiti cron: Se avete più piccole funzioni Lambda programmate, considerate di combinarle in un unico “Maintenance Runner” che distribuisce i compiti secondo un programma meno frequente. Questo riduce drasticamente il numero di invocazioni.
  • Ottimizzate l’allocazione di memoria: Utilizzate strumenti come AWS Lambda Power Tuning per trovare la configurazione di memoria ottimale per le vostre funzioni. Non fate supposizioni e non sovraprovisionate. Ricordate, più memoria significa più CPU, e voi pagate per entrambe.
  • Controllate la verbosità dei log: Implementate livelli di logging guidati da variabili d’ambiente (ad esempio, INFO per la produzione, DEBUG per lo sviluppo). Evitate di registrare i corpi delle richieste intere o uno stato interno eccessivo in produzione. La vostra fattura di CloudWatch Logs vi ringrazierà.
  • Rivedete le funzioni inutilizzate: Auditate periodicamente le vostre funzioni Lambda. Ci sono funzioni vecchie, sperimentali o obsolete ancora attive e generanti costi? Eliminatele!
  • Monitorate la dimensione dei pacchetti: Pacchetti di deploy più piccoli significano avviamenti a freddo più rapidi e costi di storage inferiori. Includete solo le dipendenze necessarie.
  • Comprendete il vostro modello tariffario: Rileggete la pagina di tariffazione di Lambda. Comprendete come vengono fatturate le invocazioni, i GB-secondi e il trasferimento di dati. La conoscenza è potere, soprattutto quando si tratta del vostro portafoglio.

Domare il mostro senza server non è una questione di evitare il senza server; si tratta di essere astuti e intenzionali nel modo in cui lo utilizziamo. La flessibilità e la scalabilità sono inestimabili, ma senza la giusta vigilanza, questi “piccoli” costi possono accumularsi fino a rappresentare una parte significativa del vostro budget. Andate avanti, monitorate, ottimizzate e risparmiate!

Questo è tutto per me oggi. Fatemi sapere nei commenti se avete altri suggerimenti o consigli per l’ottimizzazione dei costi di Lambda!

🕒 Published:

✍️
Written by Jake Chen

AI technology writer and researcher.

Learn more →
Browse Topics: benchmarks | gpu | inference | optimization | performance
Scroll to Top