Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Mi chiamo Viktor Yagofarov e mi occupo dello sviluppo della piattaforma Kubernetes presso la compagnia DomClick nel ruolo di responsabile tecnico dello sviluppo nel team Ops (operazioni). Vorrei parlare del nostro processo Dev Ops, delle particolarità della gestione di uno dei più grandi cluster k8s in Russia, e delle pratiche DevOps/SRE adottate dal nostro team.

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Team Ops

Attualmente nel team Ops lavorano 15 persone. Tre di loro si occupano dell'ufficio, due lavorano in un altro fuso orario e sono disponibili anche di notte. In questo modo, c'è sempre qualcuno di Ops al monitor pronto a reagire a qualsiasi tipo di incidente. Non abbiamo turni notturni, il che preserva la nostra salute mentale e consente a tutti di riposare e trascorrere il tempo libero non solo davanti al computer.

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Le competenze sono varie: specialisti di rete, DBA, esperti del stack ELK, amministratori/sviluppatori Kubernetes, specialisti di monitoraggio, virtualizzazione, hardware, ecc. Ci unisce una cosa: ognuno di noi può sostituire in qualche modo l'altro: ad esempio, inserire nuovi nodi nel cluster k8s, aggiornare PostgreSQL, scrivere un pipeline CI/CD + Ansible, automatizzare qualcosa in Python/Bash/Go, collegare apparecchiature nei data center. Forti competenze in un'area non impediscono di cambiare direzione e iniziare a investire in un'altra area. Ad esempio, io sono entrato in azienda come specialista di PostgreSQL e ora la mia principale responsabilità è i cluster Kubernetes. Nel team qualsiasi crescita è benvenuta e si sviluppa molto il senso di supporto reciproco.

A proposito, stiamo cercando. I requisiti per i candidati sono piuttosto standard. Personalmente, è importante per me che la persona si integri nel team, sia non conflittuale, ma anche capace di difendere le proprie opinioni, desideri di svilupparsi e non abbia paura di fare qualcosa di nuovo, proponendo le proprie idee. Inoltre, è fondamentale avere competenze di programmazione in linguaggi di scripting, conoscenza delle basi di Linux e dell'inglese. L'inglese è necessario semplicemente affinché la persona possa cercare online una soluzione a un problema in caso di errore, in 10 secondi, e non in 10 minuti. Con esperti di Linux molto competenti è attualmente molto difficile: è divertente, ma due candidati su tre non possono rispondere alla domanda "Che cos'è il Load Average? Di cosa è composto?", e considerano la domanda "Come raccogliere un core dump da un programma C" come qualcosa proveniente da un mondo di supereroi... o di dinosauri. Dobbiamo accettarlo, poiché di solito le persone hanno sviluppato molto altre competenze e noi insegneremo il "linux". La risposta alla domanda "perché bisogna sapere tutto questo per un ingegnere DevOps nel moderno mondo del cloud" dovrà rimanere al di fuori di questo articolo, ma se dovessi sintetizzarla in tre parole: tutto questo è necessario.

Team Tools

Il team Tools gioca un ruolo significativo nell'automazione. Il loro obiettivo principale è la creazione di strumenti grafici e CLI comodi per gli sviluppatori. Ad esempio, il nostro strumento interno Confer consente di rilasciare un'applicazione in Kubernetes con pochi clic del mouse, configurandole le risorse, le chiavi dal vault, ecc. Prima usavamo Jenkins + Helm 2, ma abbiamo dovuto sviluppare il nostro strumento per eliminare il copia-incolla e portare uniformità nel ciclo di vita del software.

Il team Ops non scrive pipeline per gli sviluppatori, ma può fornire consulenza su qualsiasi questione riguardante la loro scrittura (alcuni hanno ancora Helm 3).

DevOps

Per quanto riguarda il DevOps, lo vediamo in questo modo:

I team Dev scrivono codice, lo rilasciano tramite Confer in dev -> qa/stage -> prod. La responsabilità affinché il codice non rallenti e non generi errori ricade sui team Dev e Ops. Durante il giorno, l'incidente con la propria applicazione deve essere gestito, in primo luogo, dal turno di lavoro del team Ops, mentre di sera e durante la notte l'amministratore di turno (Ops) deve svegliare il programmatore di turno se è certo che il problema non sia nell'infrastruttura. Tutte le metriche e gli avvisi nel monitoraggio appaiono automaticamente o semi-automaticamente.

La zona di responsabilità degli Ops inizia nel momento in cui l'applicazione viene distribuita in produzione, ma la responsabilità degli sviluppatori non finisce qui: facciamo lo stesso lavoro e siamo sulla stessa barca.

Gli sviluppatori consigliano gli amministratori nel caso abbiano bisogno di aiuto nella scrittura di un microservizio per admin (ad esempio, backend Go + HTML5), mentre gli amministratori consigliano gli sviluppatori su qualsiasi questione infrastrutturale o relativa a k8s.

A proposito, non abbiamo affatto un monolito, solo microservizi. Il loro numero oscilla attualmente tra 900 e 1000 nel cluster k8s di produzione, se lo misuriamo in base alla quantità. deploymentsIl numero di pod varia tra 1700 e 2000. Attualmente, ci sono circa 2000 pod nel cluster di produzione.

Non posso fornire numeri esatti, poiché seguiamo i microservizi non necessari e li rimuoviamo in modo semi-automatico. Monitorare le entità superflue in k8s ci aiuta useless-operator, il che risparmia notevolmente risorse e denaro.

Gestione delle risorse

Monitoraggio

In un grande cluster, un monitoraggio ben strutturato e informativo diventa un pilastro fondamentale. Finora non abbiamo trovato una soluzione universale che copra il 100% di tutte le richieste in materia di monitoraggio, quindi di tanto in tanto sviluppiamo diverse soluzioni personalizzate in questo ambito.

  • ZabbixIl monitoraggio tradizionale, che è principalmente destinato a monitorare lo stato generale dell'infrastruttura. Ci avvisa quando un nodo si guasta a causa di CPU, memoria, dischi, rete e così via. Niente di stratosferico, ma abbiamo anche un DaemonSet di agenti, con cui monitoriamo, ad esempio, lo stato del DNS nel cluster: cerchiamo pod coredns che rallentano e controlliamo la disponibilità degli host esterni. Potrebbe sembrare superfluo, ma su grandi volumi di traffico questo componente è un importante punto di rottura. In precedenza ho già descrittoparlato di come ho affrontato la performance del DNS nel cluster.
  • Prometheus OperatorUna serie di diversi exporter offre una grande panoramica di tutti i componenti del cluster. Successivamente, visualizziamo tutto questo su grandi dashboard in Grafana e utilizziamo alertmanager per le notifiche.

Un altro strumento utile per noi è diventato list-ingress. Abbiamo scritto questo strumento dopo aver incontrato più volte la situazione in cui un team sovrappone i proprio percorsi Ingress a quelli di un altro team, generando errori 50x. Attualmente, prima del deployment in produzione, gli sviluppatori controllano di non interferire con nessuno, e per il mio team questo è uno strumento utile per la diagnosi iniziale dei problemi di Ingress. È divertente notare che inizialmente era stato scritto per gli amministratori e appariva piuttosto 'grezzo', ma dopo che lo strumento è stato apprezzato dai team di sviluppo, ha subito un notevole miglioramento e ora non sembra più 'un'interfaccia web fatta per gli amministratori'. Presto abbandoneremo questo strumento e simili situazioni saranno validate prima del rilascio della pipeline.

Risorse dei team in 'Kube'

Prima di passare agli esempi, è opportuno spiegare come funziona la gestione delle risorse per microservizi.

Per comprendere quali team e in quali quantità utilizzano le proprie risorse (CPU, memoria, SSD locale), riserviamo a ciascun team una propria namespace in 'Kube' e ne limitiamo le massime capacità riguardo CPU, memoria e disco, discutendo in anticipo le esigenze dei team. Di conseguenza, in generale, un team non bloccherà l'intero cluster per il deployment, riservando a se stesso migliaia di core e terabyte di memoria. Gli accessi ai namespace vengono forniti tramite AD (utilizziamo RBAC). I namespace e i loro limiti vengono inseriti attraverso pull request nel repository GIT e successivamente vengono distribuiti automaticamente tramite la pipeline di Ansible.

Esempio di allocazione delle risorse per un team:

namespaces:

  chat-team:
    pods: 23
    limits:
      cpu: 11
      memory: 20Gi
    requests:
      cpu: 11
      memory: 20Gi

Richieste e limiti

In 'Kube' Request — è la quantità di risorse riservate garantite per pod (uno o più container Docker) nel cluster. Il limite è il massimo non garantito. Spesso si può notare nei grafici come un certo team abbia impostato richieste eccessive per tutte le sue applicazioni e non possa effettuare il deployment di un'applicazione in 'Kube', poiché all'interno del loro namespace tutte le richieste sono già 'consumate'.

La soluzione corretta in questa situazione è monitorare il reale consumo di risorse e confrontarlo con la quantità richiesta (Request).

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi
Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Negli screenshot sopra è visibile che le 'richieste' (Requested) di CPU si avvicinano alla reale quantità di thread, mentre i Limiti possono superare il reale numero di thread della CPU =)

Ora analizziamo in dettaglio un namespace (ho scelto il namespace kube-system — namespace di sistema per i componenti del «Cubo») e vediamo il rapporto tra il tempo di CPU e la memoria realmente utilizzati e quelli richiesti:

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

È evidente che la memoria e la CPU riservate ai servizi di sistema siano molto superiori a quelle effettivamente utilizzate. Nel caso di kube-system questo è giustificato: è capitato che il controller ingress nginx o nodelocaldns, durante i picchi, utilizzassero molta CPU e consumassero molta RAM, quindi è giustificato avere un margine qui. Inoltre, non possiamo fare affidamento solo sui grafici delle ultime 3 ore: sarebbe opportuno avere metriche storiche su un lungo periodo di tempo.

È stato sviluppato un sistema di «raccomandazioni». Ad esempio, qui è possibile vedere quali risorse sarebbe meglio aumentare i «limiti» (il massimo consentito) per evitare il «throttling»: il momento in cui si è già consumata CPU o memoria per il periodo di tempo assegnato e si è in attesa che vengano «scongelati»:

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Ecco i pod che dovrebbero moderare le loro richieste:

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Su throttling + la monitorizzazione delle risorse potrebbe riempire più di un articolo, quindi sentitevi liberi di fare domande nei commenti. In poche parole, posso dire che automatizzare metriche di questo tipo è un compito piuttosto complesso e richiede molto tempo e destrezza con le funzioni «window» e «CTE» di Prometheus / VictoriaMetrics (questi termini sono tra virgolette perché in PromQL non esiste nulla di simile, e bisogna costruire query complesse lunghe diversi schermi di testo e occuparsi della loro ottimizzazione).

Di conseguenza, gli sviluppatori hanno strumenti per monitorare i propri namespace nel «Cubo» e possono decidere autonomamente dove e quando a quali applicazioni è possibile «ridurre» le risorse, mentre a quali pod si può concedere tutta la CPU per tutta la notte.

Metodologie

Nell'azienda, come è di moda ora è alla moda, seguiamo pratiche DevOps e SRE-pratiche. Quando in azienda ci sono 1000 microservizi, circa 350 sviluppatori e 15 admin per tutta l'infrastruttura, bisogna «essere alla moda»: dietro a tutte queste «buzzword» si cela un'urgente necessità di automatizzare tutto, e gli admin non devono diventare il collo di bottiglia nei processi.

Come Ops, forniamo diverse metriche e dashboard per gli sviluppatori, connesse alla velocità di risposta dei servizi e ai loro errori.

Utilizziamo metodologie come: RED, USARE e Golden Signals, combinandoli insieme. Cerchiamo di ridurre al minimo il numero di dashboard in modo che a colpo d'occhio si possa capire quale servizio sta attualmente degradando (ad esempio, i codici di risposta al secondo, il tempo di risposta al 99° percentile), e così via. Non appena sono necessarie nuove metriche per le dashboard comuni, le disegniamo e le aggiungiamo immediatamente.

Non disegno grafici da un mese. Probabilmente è un buon segno: significa che la maggior parte delle 'richieste' è già stata realizzata. A volte, in una settimana, disegnavo almeno un nuovo grafico al giorno.

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi

Il risultato ottenuto è prezioso perché ora gli sviluppatori raramente si rivolgono agli amministratori con domande su 'dove posso vedere una certa metrica'.

Implementazione Service Mesh non è lontano e dovrebbe semplificare notevolmente la vita di tutti, i colleghi di Tools sono già vicini all'implementazione di un 'Istio per persone sane': il ciclo di vita di ogni richiesta HTTP(s) sarà visibile nel monitoraggio, e sarà sempre possibile capire 'in quale fase tutto si è rotto' durante le interazioni tra servizi (e non solo). Iscriviti agli aggiornamenti del hub dell'azienda DomKlick. =)

Supporto per l'infrastruttura Kubernetes

Storicamente, abbiamo utilizzato una versione patchata Kubespray — Ruolo Ansible per il deployment, l'espansione e l'aggiornamento di Kubernetes. A un certo punto, il supporto per le installazioni non kubeadm è stato rimosso dal ramo principale, e non è stata proposta una transizione a kubeadm. Di conseguenza, l'azienda Southbridge ha creato il proprio fork (con supporto kubeadm e rapida risoluzione di problemi critici).

Il processo di aggiornamento di tutti i cluster k8s è il seguente:

  • Prendiamo Kubespray da Southbridge, confrontiamo con il nostro ramo, uniamo.
  • Distribuiamo l'aggiornamento in Stress- 'Cubo'.
  • Distribuiamo l'aggiornamento nodo per nodo (in Ansible è 'serial: 1') in Dev- 'Cubo'.
  • Aggiorniamo Prod sabato sera nodo per nodo.

In futuro, ci sono piani per sostituire Kubespray con qualcosa di più veloce e passare a kubeadm.

Abbiamo in totale tre 'Cubi': Stress, Dev e Prod. Prevediamo di avviare un altro (hot standby) Cubo Prod in un secondo data center. Stress e Dev vivono in 'virtual machines' (oVirt per Stress e VMWare cloud per Dev). Prod- 'Cubo' vive su 'hardware nudo' (bare metal): sono nodi identici con 32 thread CPU, 64-128 GB di memoria e 300 GB SSD RAID 10 — in totale sono 50 unità. Tre nodi 'snelli' sono dedicati ai 'master' Prod-'Cubo': 16 GB di memoria, 12 thread CPU.

Per la produzione preferiamo usare 'hardware nudo' ed evitiamo strati extra come OpenStack: non abbiamo bisogno di 'vicini rumorosi' e del tempo rubato dalla CPU steal time. Inoltre, la complessità dell'amministrazione aumenta di circa il doppio nel caso di OpenStack in-house.

Per CI/CD dei componenti «Kubernetes» e altre infrastrutture utilizziamo un server GIT separato, Helm 3 (abbiamo fatto il passaggio in modo piuttosto doloroso da Helm 2, ma siamo molto contenti dell'opzione atomic), Jenkins, Ansible e Docker. Amore per i feature branch e il deploy in ambienti diversi da un unico repository.

Conclusione

Kubernetes in DomClick: come dormire tranquilli gestendo un cluster di 1000 microservizi
Così, in linea generale, il processo DevOps in DomClick appare dal punto di vista dell'ingegnere di funzionamento. L'articolo è risultato meno tecnico di quanto mi aspettassi: quindi, seguite le novità di DomClick su Habr: ci saranno articoli più 'hardcore' su Kubernetes e non solo.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster