Nel corso degli anni, Pinterest ha visto 300 milioni di utenti creare oltre 200 miliardi di pin su più di 4 miliardi di bacheche. Per gestire quest'esercito di utenti e l'ampia base di contenuti, il portale ha sviluppato migliaia di servizi, dai microservizi in grado di funzionare con pochi CPU ai giganteschi monoliti che operano su un'intera flotta di macchine virtuali. E così è arrivato il momento in cui l'azienda ha puntato lo sguardo su k8s. Cosa ha attratto Pinterest nel “cubetto”? Lo scoprirete nella nostra traduzione di un recente articolo da .

Quindi, centinaia di milioni di utenti e centinaia di miliardi di pin. Per gestire quest'esercito di utenti e l'ampia base di contenuti, abbiamo sviluppato migliaia di servizi, dai microservizi in grado di funzionare con pochi CPU ai giganteschi monoliti che operano su un'intera flotta di macchine virtuali. Inoltre, abbiamo una varietà di framework che possono anch'essi richiedere risorse CPU, memoria o accesso alle operazioni di input/output.
Nella gestione di questo zoo di strumenti, il team di sviluppo si trova ad affrontare diverse problematiche:
- Gli ingegneri non hanno un modo unificato per avviare l'ambiente di lavoro. I servizi stateless, i servizi stateful e i progetti in fase di sviluppo attivo si basano su stack tecnologici completamente diversi. Ciò ha portato alla creazione di un intero corso di formazione per gli ingegneri e ha reso il lavoro del nostro team infrastrutturale notevolmente più complesso.
- Gli sviluppatori, che dispongono di un proprio parco di macchine virtuali, creano un'enorme pressione sui nostri amministratori interni. Di conseguenza, operazioni semplici come l'aggiornamento del sistema operativo o dell'AMI si allungano per settimane o mesi. Questo porta a un aumento del carico in situazioni che sembrano assolutamente quotidiane.
- Difficoltà nella creazione di strumenti di gestione dell'infrastruttura globali sopra alle soluzioni già esistenti. La situazione è complicata ulteriormente dal fatto che non è semplice trovare i proprietari delle macchine virtuali. In altre parole, non sappiamo se sia sicuro estrarre queste risorse per utilizzarle in altre aree della nostra infrastruttura.
I sistemi di orchestrazione dei container sono un modo per unificare la gestione del carico di lavoro. Ti aprono la strada per aumentare la velocità di sviluppo e semplificano la gestione dell'infrastruttura, poiché tutte le risorse coinvolte nel progetto sono gestite da un unico sistema centralizzato.

Figura 1: Priorità dell'infrastruttura (affidabilità, produttività degli sviluppatori ed efficienza).
Il team della Cloud Management Platform in Pinterest ha conosciuto K8s nel 2017. Nella prima metà del 2017, abbiamo documentato gran parte delle nostre capacità produttive, inclusi API e tutti i nostri server web. Successivamente, abbiamo effettuato una valutazione attenta di diversi sistemi di orchestrazione delle soluzioni container, costruzione e gestione dei cluster. Alla fine del 2017, abbiamo deciso di utilizzare Kubernetes. Era abbastanza flessibile e ampiamente supportato dalla comunità degli sviluppatori.
Attualmente abbiamo creato i nostri strumenti di avvio del cluster basati su Kops e abbiamo migato i componenti esistenti dell'infrastruttura a Kubernetes, come rete, sicurezza, metriche, registrazione, gestione delle identità e traffico. Abbiamo anche implementato un sistema di modellazione del carico di lavoro per la nostra risorsa, la cui complessità è nascosta agli sviluppatori. Ora ci concentriamo sulla stabilità del cluster, sulla sua scalabilità e sull'integrazione di nuovi clienti.
Kubernetes: il percorso di Pinterest
Iniziare a lavorare con Kubernetes su larga scala in Pinterest come piattaforma che sarà amata dai nostri ingegneri ha comportato molte difficoltà.
Come grande azienda, abbiamo investito risorse significative negli strumenti infrastrutturali. Un esempio possono essere gli strumenti di sicurezza che gestiscono certificati e distribuiscono chiavi, i componenti di controllo del traffico, i sistemi di rilevamento dei servizi, i componenti di visibilità e invio di log e metriche. Tutto questo non è stato messo insieme per caso: abbiamo seguito un normale percorso di tentativi ed errori e quindi desideravamo integrare tutto questo nella nuova infrastruttura su Kubernetes invece di reinventare la ruota su una nuova piattaforma. Questo approccio ha semplificato nel complesso la migrazione, poiché tutto il supporto alle applicazioni esiste già, non deve essere creato da zero.
D'altra parte, i modelli di previsione dei carichi in Kubernetes (ad esempio, deployment, jobs e DaemonSets) non sono sufficienti per il nostro progetto. Questi problemi di usabilità rappresentano enormi ostacoli al passaggio a Kubernetes. Ad esempio, abbiamo sentito sviluppatori di servizi lamentarsi della mancanza o della configurazione errata dell'ingresso. Inoltre, ci siamo scontrati con un utilizzo inappropriato dei templater, quando sono state create centinaia di copie con specifi che uguali e job, il che ha portato a terribili problemi di debugging.
Era anche molto difficile supportare diverse versioni all'interno dello stesso cluster. Immaginate la complessità del supporto clienti se è necessario lavorare contemporaneamente con molte versioni dello stesso ambiente di esecuzione, con tutti i loro problemi, bug e aggiornamenti.
Risorse e controllori personalizzati di Pinterest
Per facilitare il processo di implementazione di Kubernetes per i nostri ingegneri, e per semplificare l'infrastruttura e accelerare le sue prestazioni, abbiamo sviluppato le nostre definizioni di risorse personalizzate (CRD).
Le CRD offrono le seguenti funzionalità:
- Integrazione di diverse risorse native di Kubernetes per funzionare come un unico carico. Ad esempio, la risorsa PinterestService comprende deployment, servizio di ingresso e configMap. Questo consente agli sviluppatori di non preoccuparsi della configurazione del DNS.
- Implementazione della necessaria supporto per le applicazioni. L'utente deve concentrarsi solo sulla specifica del container secondo la propria logica di business, mentre il controllore CRD implementa tutti i necessari init-container, variabili d'ambiente e specifiche pod. Questo offre un livello di comfort sostanzialmente diverso per gli sviluppatori.
- I controllori CRD gestiscono anche il ciclo di vita delle risorse personalizzate e aumentano la disponibilità del debugging. Ciò include il confronto tra le specifiche desiderate e quelle reali, l'aggiornamento dello stato delle CRD e la registrazione degli eventi e altro ancora. Senza CRD, gli sviluppatori sarebbero costretti a gestire un numero elevato di risorse, il che aumenterebbe solo la probabilità di errore.
Ecco un esempio di PinterestService e di una risorsa interna gestita dal nostro controllore:

Come mostrato sopra, per supportare il contenitore personalizzato è necessario integrare al suo interno un contenitore di inizializzazione e alcune estensioni per garantire sicurezza, visibilità e gestione del traffico di rete. Inoltre, abbiamo creato modelli di schede di configurazione e implementato il supporto per i modelli PVC per i job batch, oltre al tracciamento di molte variabili ambientali per monitorare l'identificazione, il consumo di risorse e la raccolta di "spazzatura".
È difficile immaginare che gli sviluppatori vogliano scrivere questi file di configurazione a mano senza il supporto del CRD, per non parlare di ulteriore supporto e debug delle configurazioni.
Flusso di lavoro per il deployment delle applicazioni

Nell'immagine sopra è mostrato come distribuire una risorsa personalizzata Pinterest nel cluster Kubernetes:
- Gli sviluppatori interagiscono con il nostro cluster Kubernetes tramite CLI e interfaccia utente.
- Gli strumenti CLI/UI estraggono i file YAML di configurazione del flusso di lavoro e altre proprietà di build (lo stesso identificativo della versione) da Artifactory, inviandoli quindi al Job Submission Service. Questo passaggio garantisce che nel cluster vengano fornite solo versioni funzionanti.
- JSS funge da gateway per diverse piattaforme, incluso Kubernetes. Qui avviene l'autenticazione dell'utente, l'assegnazione delle quote e un controllo parziale della configurazione del nostro CRD.
- Dopo la verifica del CRD presso JSS, le informazioni vengono inviate all'API della piattaforma k8s.
- Il nostro controller CRD monitora gli eventi su tutte le risorse personalizzate. Trasforma il CR in risorse nativa di k8s, aggiunge i moduli necessari, imposta le variabili ambientali appropriate ed esegue altre operazioni ausiliarie, garantendo alle applicazioni containerizzate supporto infrastrutturale adeguato.
- Successivamente, il controller CRD invia i dati ottenuti all'API di Kubernetes affinché vengano elaborati dal planner e messi in esecuzione.
Nota: questo flusso di lavoro pre-rilascio del deployment è stato creato per i primi utenti della nuova piattaforma k8s. Attualmente siamo in fase di affinamento di questo processo per integrarlo completamente con il nostro nuovo CI/CD. Ciò significa che non possiamo raccontarvi tutto ciò che concerne Kubernetes. Non vediamo l'ora di condividere la nostra esperienza e di parlare dei progressi del team in questa direzione nel nostro prossimo post sul blog "Building a CI/CD platform for Pinterest".
Tipi di risorse speciali
In base alle specifiche esigenze di Pinterest, abbiamo sviluppato i seguenti CRD che sono adatti per diversi flussi di lavoro:
- PinterestService è un servizio stateless che è in funzione da tempo. Molti dei nostri sistemi principali si basano su un insieme di questi servizi.
- PinterestJobSet modella operazioni batch a ciclo completo. In Pinterest esiste uno scenario comune in cui più lavoro avvia gli stessi contenitori in parallelo, indipendentemente da altri processi simili.
- PinterestCronJob è ampiamente utilizzato in combinazione con carichi di lavoro periodici leggeri. Questa è un’interfaccia per il funzionamento nativo di cron con meccanismi di supporto di Pinterest che si occupano di sicurezza, traffico, log e metriche.
- PinterestDaemon comprende i demoni dell'infrastruttura. Questa famiglia continua a crescere, poiché aggiungiamo sempre più supporto per i nostri cluster.
- PinterestTrainingJob si applica ai processi Tensorflow e Pytorch, fornendo lo stesso livello di supporto durante il funzionamento di tutti gli altri CRD. Poiché in Pinterest utilizziamo attivamente Tensorflow e altri sistemi di machine learning, abbiamo avuto motivo di costruire un CRD separato attorno a loro.
Stiamo inoltre lavorando su PinterestStatefulSet, che sarà presto adattato per archivi di dati e altri sistemi stateful.
Supporto per l'ambiente di esecuzione
Quando il modulo delle applicazioni viene avviato in Kubernetes, riceve automaticamente un certificato per identificarsi. Questo certificato viene utilizzato per accedere al vault dei segreti o per comunicare con altri servizi attraverso mTLS. Nel frattempo, il configuratore di inizializzazione dei contenitori e il Daemon caricheranno tutte le dipendenze necessarie prima dell'avvio dell'applicazione container. Quando tutto sarà pronto, il traffico sidecar e il Daemon registreranno l'indirizzo IP del modulo nel nostro Zookeeper, affinché i clienti possano trovarlo. Tutto ciò funzionerà poiché il modulo di rete è stato configurato prima dell'avvio dell'applicazione.
Qui sopra sono riportati esempi tipici di supporto per i carichi di lavoro in esecuzione. Per altri tipi di carichi di lavoro potrebbe essere necessario un supporto leggermente diverso, ma tutti sono rappresentati come sidecar a livello di pod, nodi o Daemon a livello di macchine virtuali. Ci assicuriamo che tutto ciò sia distribuito nell'ambito dell'infrastruttura di gestione e coordinato tra le applicazioni, riducendo in modo significativo il carico di lavoro in termini di operazioni tecniche e supporto clienti.
Test e QA
Abbiamo creato una pipeline di test end-to-end sopra l'infrastruttura di test già esistente in Kubernetes. Questi test si estendono a tutti i nostri cluster. La nostra pipeline ha subito molte revisioni prima di diventare parte del cluster di prodotto.
Oltre ai sistemi di test, abbiamo sistemi di monitoraggio e alerting che controllano costantemente lo stato dei componenti del sistema, il consumo delle risorse e altri indicatori chiave, avvisandoci solo quando è necessario un intervento umano.
Alternative
Abbiamo preso in considerazione alcune alternative alle risorse personalizzate, come i controllori di accesso mutazionale e i sistemi di template. Tuttavia, tutti comportano seri problemi operativi, quindi abbiamo scelto la strada CRD.
Il controllore di accesso mutazionale è stato utilizzato per introdurre i sidecar, le variabili ambientali e altro supporto durante l'esecuzione. Tuttavia, ha affrontato vari problemi, come il binding delle risorse e la gestione del loro ciclo di vita, problemi che non si presentano con la CRD.
Nota: I sistemi di template, come i diagrammi Helm, sono ampiamente utilizzati per il lancio di applicazioni con configurazioni simili. Tuttavia, le nostre applicazioni di lavoro sono troppo varie per poter essere gestite tramite template. Inoltre, durante il deployment continuo con l'uso di template, si verificheranno troppi errori.
Lavoro imminente
Attualmente affrontiamo un carico di lavoro misto su tutti i nostri cluster. Per supportare tali processi di diversi tipi e dimensioni, stiamo lavorando nelle seguenti direzioni:
- Un insieme di cluster distribuisce grandi applicazioni su diversi cluster per garantire scalabilità e stabilità.
- Garantire stabilità, scalabilità e visibilità del cluster per creare un collegamento tra l'applicazione e il suo SLA.
- Gestione delle risorse e delle quote, affinché le applicazioni non entrino in conflitto tra loro e la scala del cluster sia controllata da noi.
- Una nuova piattaforma CI/CD per supportare e distribuire applicazioni in Kubernetes.
Fonte: habr.com
