Questa guida fornisce le best practice per la progettazione, l'implementazione, i test il deployment di un servizio Knative serving. Per altri suggerimenti, vedi Migrazione di un servizio esistente.
Redazione di servizi efficaci
Questa sezione descrive le best practice generali per la progettazione e l'implementazione di un servizio Knative serving.
Come evitare attività in background
Quando un'applicazione in esecuzione su Knative serving termina la gestione di una richiesta, l'accesso dell'istanza di container alla CPU verrà disabilitato o gravemente limitato. Di conseguenza, non devi avviare routine o thread in background che vengono eseguiti all'esterno l'ambito dei gestori delle richieste.
L'esecuzione di thread in background può causare comportamenti imprevisti perché una successiva richiesta alla stessa istanza di container ripristina attività in background.
Per attività in background si intende tutto ciò che accade dopo che la risposta HTTP è stata sono recapitate. Rivedi il codice per assicurarti che tutte le operazioni asincrone vengano completate prima di consegnare la risposta.
Se sospetti la presenza di attività in background nel tuo servizio che non sono è subito evidente che puoi controllare i log: cerca tutto ciò che registrato dopo la voce della richiesta HTTP.
Eliminazione dei file temporanei
Nell'ambiente Cloud Run l'archiviazione del disco è un file system in memoria. I file scritti sul disco consumano memoria altrimenti disponibile per il tuo servizio, e può persistere tra una chiamata e l'altra. Se non elimini questi file, prima o poi genererà un errore di memoria insufficiente e un successivo avvio a freddo.
Ottimizzazione del rendimento
Questa sezione descrive le best practice per l'ottimizzazione del rendimento.
Avvio rapido dei servizi
Poiché le istanze di container vengono scalate secondo necessità, un metodo tipico è inizializzare completamente l'ambiente di esecuzione. Questo tipo di l'inizializzazione è chiamata "avvio a freddo". Se una richiesta del client attiva un attacco freddo l'avvio dell'istanza di container determina una latenza aggiuntiva.
La routine di avvio è costituita da:
- Avvio del servizio
- Avvio del container
- Esecuzione del punto di ingresso per avviare il server.
- Controllo della porta di servizio aperta in corso...
L'ottimizzazione per la velocità di avvio dei servizi riduce al minimo la latenza che ritarda una dall'istanza di container di gestire le richieste.
Utilizzare le dipendenze in modo oculato
Se usi un linguaggio dinamico con librerie dipendenti, ad esempio importando moduli in Node.js, il tempo di caricamento di questi moduli aggiunge latenza durante un avvio a freddo. Riduci la latenza di avvio nei seguenti modi:
- Riduci al minimo il numero e la dimensione delle dipendenze per creare un servizio snello.
- Carica lentamente il codice utilizzato di rado, se il tuo linguaggio lo supporta.
- Usa ottimizzazioni del caricamento del codice come PHP ottimizzazione del caricatore automatico del compositore.
Utilizzo delle variabili globali
In Knative serving, non si può presumere che lo stato del servizio sia mantenuto tra richieste. Tuttavia, Knative serving riutilizza le singole istanze di container per gestire il traffico continuo, quindi puoi dichiarare una variabile in ambito globale il suo valore affinché venga riutilizzato nelle chiamate successive. Eventuali richieste individuali beneficio di questo riutilizzo non può essere noto in anticipo.
Puoi anche memorizzare nella cache gli oggetti se sono costosi da ricreare richiesta di servizio. Lo spostamento dalla logica di richiesta all'ambito globale prestazioni migliori.
Node.js
Python
Vai
Java
Esecuzione dell'inizializzazione lazy delle variabili globali
L'inizializzazione delle variabili globali avviene sempre durante l'avvio, che aumenta l'avvio a freddo. Usa l'inizializzazione lazy per gli oggetti usati raramente per posticipare il costo in termini di tempo e ridurre i tempi di avvio a freddo.
Node.js
Python
Vai
Java
Ottimizzazione della contemporaneità
Le istanze di Knative serving possono gestire più richieste contemporaneamente,
"contemporaneamente", fino a una contemporaneità massima configurabile.
È diverso da Cloud Functions, che utilizza concurrency = 1
.
Dovresti mantenere l'impostazione di contemporaneità massima predefinita, a meno che il codice ha requisiti specifici di contemporaneità.
Ottimizzazione della contemporaneità per il servizio
Il numero di richieste in parallelo che ogni istanza di container può gestire può essere limitati dallo stack tecnologico e dall'uso di risorse condivise, come e connessioni ai database.
Per ottimizzare il servizio per ottenere la massima contemporaneità stabile:
- Ottimizza le prestazioni dei tuoi servizi.
- Imposta il livello previsto di supporto della contemporaneità in qualsiasi contemporaneità a livello di codice configurazione. Non tutti gli stack tecnologici richiedono questa impostazione.
- Esegui il deployment del servizio.
- Imposta la contemporaneità di Knative serving per il tuo servizio uguale o inferiore a qualsiasi configurazione a livello di codice. Se non esiste una configurazione a livello di codice, utilizza il metodo della contemporaneità prevista.
- Utilizzare i test di carico che supportano una contemporaneità configurabile. Devi confermare che il tuo servizio rimane stabile con il carico e la contemporaneità previsti.
- Se il servizio non funziona bene, vai al passaggio 1 per migliorare il servizio o al passaggio 2 per e ridurre la contemporaneità. Se il servizio funziona correttamente, torna al passaggio 2 e aumenta la contemporaneità.
Continua a eseguire l'iterazione finché non trovi la contemporaneità stabile massima.
Memoria corrispondente alla contemporaneità
Ogni richiesta gestita dal tuo servizio richiede una certa quantità di memoria aggiuntiva. Perciò, quando regoli la contemporaneità in alto o in basso, assicurati di regolare la memoria limite.
Evitando lo stato globale modificabile
Se vuoi sfruttare lo stato globale modificabile in un contesto simultaneo, prendi in considerazione passaggi nel codice per assicurarti che questa operazione venga eseguita in sicurezza. Ridurre al minimo il conflitto limitando l'inizializzazione una tantum e il riutilizzo delle variabili globali, come descritto sopra Prestazioni.
Se utilizzi variabili globali modificabili in un servizio che gestisce più richieste contemporaneamente, assicurati di usare blocchi o mutex per prevenire le racecondition.
Sicurezza dei container
Molte pratiche di sicurezza del software per uso generico si applicano alle applicazioni containerizzate. Esistono alcune pratiche specifiche dei container o che sono in linea con la filosofia e l'architettura dei container.
Per migliorare la sicurezza dei container:
Usa immagini di base protette e gestite attivamente, come quelle di Google immagini di base o dalle immagini ufficiali di Docker Hub.
Applica gli aggiornamenti della sicurezza ai tuoi servizi ricreando regolarmente il container ed eseguire nuovamente il deployment dei servizi.
Includi nel container solo ciò che è necessario all'esecuzione del tuo servizio. Extra codice, pacchetti e strumenti sono potenziali vulnerabilità di sicurezza. Vedi sopra per il relativo impatto sul rendimento.
Implementare un processo di compilazione deterministico. che includa versioni specifiche di librerie e software. In questo modo, le schede non verificate di includere codice nel tuo container.
Imposta il contenitore in modo che venga eseguito come utente diverso da
root
con il Istruzione DockerfileUSER
. Per alcune immagini container potrebbe essere già configurato un utente specifico.
Automazione della scansione di sicurezza
Attiva l'analisi delle vulnerabilità per l'analisi della sicurezza delle immagini container archiviate in Artifact Registry.
Puoi anche utilizzare Autorizzazione binaria per garantire che venga eseguito il deployment solo per le immagini container sicure.
Creazione di immagini container minime
Le immagini container di grandi dimensioni aumentano probabilmente le vulnerabilità di sicurezza perché contengono più elementi di quelli necessari al codice.
In Knative serving, la dimensione dell'immagine container non influisce avviare o richiedere il tempo di elaborazione e non viene conteggiato ai fini del calcolo della disponibilità di memoria del container.
Per creare un container minimo, valuta l'utilizzo di un'immagine di base magra come:
Ubuntu ha dimensioni più grandi, ma è una suite con un ambiente server pronto all'uso più completo.
Se il tuo servizio ha un processo di compilazione che utilizza molti strumenti, valuta la possibilità di creazioni multifase per mantenere il container leggero in fase di esecuzione.
Queste risorse forniscono ulteriori informazioni sulla creazione di immagini container lean:
- Best practice per Kubernetes: come e perché creare immagini container di piccole dimensioni
- 7 best practice per la creazione di container