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 DomKlik in qualità di responsabile tecnico dello sviluppo nel team Ops (operazioni). Vorrei raccontarvi come sono organizzati i nostri processi Dev <-> Ops, le peculiarità della gestione di uno dei più grandi cluster k8s in Russia e le 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 del team Ops davanti al monitor, pronto a reagire a un incidente di qualsiasi complessità. 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 variano: ci sono esperti di rete, DBA, specialisti del stack ELK, amministratori/developers di Kubernetes, monitoraggio, virtualizzazione, hardware, ecc. Ciò che ci unisce è che ognuno di noi può sostituire in qualche modo un altro: ad esempio, introdurre nuovi nodi in un cluster k8s, aggiornare PostgreSQL, scrivere pipeline CI/CD + Ansible, automatizzare qualcosa in Python/Bash/Go, collegare hardware nel data center. Una forte competenza in un determinato settore non esclude di cambiare direzione e iniziare a svilupparsi in un altro campo. Ad esempio, sono entrato in un'azienda come specialista di PostgreSQL, e ora il mio principale ambito di responsabilità sono i cluster Kubernetes. Nella squadra, ogni crescita è benvenuta e c'è un forte senso di sostegno reciproco.

A proposito, stiamo cercando personale. I requisiti per i candidati sono abbastanza standard. Personalmente, è importante per me che la persona si integri nel team, sia collaborativa, ma anche capace di difendere il proprio punto di vista, desideri crescere e non teme di provare qualcosa di nuovo, proponendo le proprie idee. Inoltre, è fondamentale avere competenze nella programmazione in linguaggi script, conoscenza di base di Linux e della lingua inglese. L'inglese è necessario semplicemente affinché la persona possa cercare la soluzione a un problema in caso di difficoltà in 10 secondi anziché in 10 minuti. Con specialisti con una profonda conoscenza di Linux è attualmente molto difficile: è divertente, ma due candidati su tre non riescono a rispondere alla domanda 'Che cos'è il Load Average? Di cosa si compone?', e considerano la domanda 'Come creare un core dump da un programma in C' qualcosa proveniente dal mondo dei supereroi... o dei dinosauri. Dobbiamo accettarlo, poiché di solito le persone hanno sviluppato fortemente altre competenze, e noi insegneremo il 'Linux'. La risposta alla domanda 'perché è tutto ciò che un ingegnere DevOps deve sapere nel mondo moderno del cloud' dovrà rimanere al di fuori di questo articolo, ma se dovessimo riassumerlo in tre parole: è tutto necessario.

Team Tools

Un ruolo importante nell'automazione è ricoperto dal team Tools. Il loro compito principale è creare strumenti grafici e CLI accessibili per gli sviluppatori. Ad esempio, il nostro strumento interno Confer consente di rilasciare un'applicazione in Kubernetes con pochi semplici clic, configurandone risorse, chiavi da vault, ecc. In passato utilizzavamo Jenkins + Helm 2, ma abbiamo dovuto sviluppare uno strumento proprio per eliminare la copia e incolla e garantire coerenza nel ciclo di vita del software.

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

DevOps

Per quanto riguarda DevOps, lo vediamo in questo modo:

I team di sviluppo scrivono codice e lo rilasciano tramite Confer in dev -> qa/stage -> prod. La responsabilità di garantire che il codice non si blocchi e non generi errori ricade sui team di sviluppo e operazioni. Durante il giorno, la persona di guardia del team Ops deve reagire agli incidenti relativi alla propria applicazione, mentre di sera e di notte l'amministratore di guardia (Ops) deve svegliare il developer di guardia se sa con certezza che il problema non è dovuto all'infrastruttura. Tutte le metriche e gli alert nel monitoraggio appaiono automaticamente o semi-automaticamente.

L'area di responsabilità di Ops inizia al momento del rilascio dell'applicazione in produzione, ma la responsabilità di Dev non finisce qui: stiamo facendo lo stesso lavoro e siamo nella stessa barca.

Gli sviluppatori consultano gli amministratori se hanno bisogno di aiuto nella scrittura di un microservizio per gli amministratori (ad esempio, backend Go + HTML5), mentre gli amministratori consultano gli sviluppatori su qualsiasi questione relativa all'infrastruttura o a problematiche legate a k8s.

A proposito, non abbiamo affatto un monolite, solo microservizi. Il loro numero oscilla attualmente tra 900 e 1000 nel cluster k8s di produzione, se lo si misura in base al numero di deployments. Il numero di nodi varia tra 1700 e 2000. Attualmente ci sono circa 2000 nodi nel cluster di produzione.

Non posso fornire numeri esatti, poiché monitoriamo i microservizi non necessari e li rimuoviamo in modo semi-automatico. Ci aiuta a tenere traccia delle entità superflue in k8s useless-operator, il che consente di risparmiare risorse e denaro.

Gestione delle risorse

Monitoraggio

Un elemento fondamentale per la gestione di un grande cluster è un monitoraggio ben strutturato e informativo. Fino ad ora non abbiamo trovato una soluzione universale che copra il 100% di tutte le esigenze di monitoraggio, quindi periodicamente sviluppiamo diverse soluzioni personalizzate in questo ambiente.

  • Zabbix. Il monitoraggio tradizionale, concepito principalmente per tenere sotto controllo lo stato generale dell'infrastruttura. Ci informa quando una nodo non risponde a causa di CPU, memoria, disco, rete e così via. Niente di straordinario, ma abbiamo anche un DaemonSet di agenti che utilizziamo per monitorare lo stato del DNS nel cluster: cerchiamo i pod coredns in difficoltà, verifichiamo la disponibilità degli host esterni. Potrebbe sembrare superfluo, ma con grandi volumi di traffico, questo componente rappresenta un importante punto di failure. In precedenza ho già descritto, come ho affrontato le problematiche di performance del DNS nel cluster.
  • Prometheus Operator. Un insieme di diversi esportatori fornisce una panoramica completa di tutti i componenti del cluster. Successivamente, visualizziamo tutto questo su ampi dashboard in Grafana, utilizzando alertmanager per le notifiche.

Un altro strumento utile per noi è stato list-ingress. Abbiamo scritto questo dopo aver incontrato diverse volte la situazione in cui un team sovrascrive con i propri percorsi l'Ingress di un altro team, causando errori 50x. Ora, prima del deploy in produzione, gli sviluppatori verificano di non urtare nessuno, e per il mio team questo è uno strumento utile per una diagnosi iniziale dei problemi con gli Ingress. È divertente che inizialmente sia stato scritto per gli admin e avesse un aspetto piuttosto "grezzo", ma dopo che lo strumento è stato apprezzato dai team di sviluppo, è notevolmente cambiato, assumendo un aspetto più professionale. Presto abbandoneremo questo strumento e situazioni simili saranno validate ancora prima del rilascio del pipeline.

Risorse dei team in "Kube"

Prima di procedere con gli esempi, è importante spiegare come funzionano le risorse allocate per microservizi.

Per comprendere quali team e in che quantità utilizzano le proprie risorse (processore, memoria, SSD locale), assegniamo a ciascun team le proprie namespace In 'Kube', we limit its maximum capacities for CPU, memory, and disk, after discussing the team's needs. Accordingly, one team generally won't block the entire cluster for deployment by allocating thousands of cores and terabytes of memory. Access to namespaces is granted through AD (we use RBAC). Namespaces and their limits are added through a pull request in the GIT repository, and then everything is automatically deployed via the Ansible pipeline.

Example of resource allocation for a team:

namespaces:

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

Requests and limits

In 'Kube' Richiesta — is the amount of resources guaranteed to be reserved for pod (one or more Docker containers) in the cluster. Limit is the unguaranteed maximum. Often, you can see on charts how a team set too many requests for all its applications and cannot deploy an application in 'Kube', as all requests under their namespace have already been 'used up'.

The correct way out of such a situation: monitor actual resource consumption and compare it with the requested amount (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, si può vedere che le CPU «richieste» (Requested) si adattano al reale numero di thread, mentre i Limiti possono superare il numero reale di thread dei processori centrali =)

Ora esaminiamo in dettaglio un namespace (ho scelto il namespace kube-system — il namespace di sistema per i componenti del 'Cubo') e vediamo il rapporto tra il tempo di CPU e la memoria realmente utilizzati rispetto a ciò che è stato richiesto:

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

È ovvio che è riservata molta più memoria e CPU per i servizi di sistema rispetto a ciò che viene realmente utilizzato. Nel caso di kube-system, ciò è giustificato: è successo che il controller nginx ingress o nodelocaldns a picco richiedessero tanto CPU e consumassero molta RAM, quindi in questo caso è valido avere tale margine. Inoltre, non possiamo affidarci ai grafici delle ultime 3 ore: è preferibile vedere metriche storiche su un lungo periodo di tempo.

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

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

Ci sono però dei pod che bisognerebbe moderare:

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

Riguardo throttling + il monitoraggio delle risorse può dar vita a più di un articolo, quindi non esitate a porre domande nei commenti. Posso dire in poche parole che l'automazione di queste metriche è piuttosto complessa e richiede molto tempo e destrezza con le funzioni 'window' e 'CTE' in Prometheus / VictoriaMetrics (questi termini sono tra virgolette poiché in PromQL non esistono cose simili, e bisogna costruire query piuttosto complesse che occupano più schermi di testo e ottimizzarle).

Alla fine, gli sviluppatori dispongono di strumenti per monitorare i propri namespaces in Kubernetes, e possono decidere autonomamente dove e quando a quali applicazioni ‘tagliare’ le risorse, e a quali pod si può concedere tutta la CPU per tutta la notte.

Metodologie

Nell'azienda, come ora è di moda, seguiamo pratiche DevOps e SRE-pratiche. Quando in azienda ci sono 1000 microservizi, circa 350 sviluppatori e 15 amministratori per tutta l'infrastruttura, è necessario 'essere alla moda': dietro a tutti questi 'buzzword' si nasconde un'urgenza nel automatizzare tutto, e gli amministratori non devono diventare il collo di bottiglia nei processi.

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

Utilizziamo metodologie come: RED, USE e Golden Signals, combinandole insieme. Cerchiamo di ridurre al minimo il numero di dashboard in modo che sia chiaro a colpo d'occhio quale servizio sta attualmente degradando (ad esempio, i codici di risposta al secondo, il tempo di risposta al percentile 99), e così via. Non appena servono nuove metriche per i dashboard generali, le realizziamo e le aggiungiamo subito.

Non ho disegnato 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 poiché ora gli sviluppatori raramente si rivolgono agli amministratori con domande su "dove posso vedere una certa metrica".

Implementazione Service Mesh è imminente e dovrebbe semplificare notevolmente la vita di tutti; i colleghi di Tools sono già prossimi all'implementazione dell'astratto «Istio del robusto»: il ciclo di vita di ogni richiesta HTTP(s) sarà visibile nel monitoraggio, e sarà sempre possibile capire «in quale fase si è rotto tutto» durante le interazioni tra servizi (e non solo). Iscriviti per ricevere aggiornamenti dal hub di DomClick. =)

Supporto per l'infrastruttura Kubernetes

Storicamente, utilizziamo una versione patchata di Kubespray — un 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. Alla fine, la compagnia Southbridge ha creato un proprio fork (con supporto per kubeadm e una rapida risoluzione dei problemi critici).

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

  • Prendiamo Kubespray da Southbridge, confrontiamo con il nostro ramo e facciamo il merge.
  • Applichiamo l'aggiornamento a Stress-«Kube».
  • Applichiamo l'aggiornamento a un nodo alla volta (in Ansible si tratta di «serial: 1») a Dev-«Kube».
  • Aggiorniamo Prod sabato sera, nodo per nodo.

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

In totale abbiamo tre “Cubi”: Stress, Dev e Prod. Prevediamo di lanciare un altro (hot standby) Cubo Prod nel secondo data center. Stress e Dev Vivono in “macchine virtuali” (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 RAM e 300 GB SSD RAID 10 — in totale sono 50. Tre nodi “snelli” sono dedicati ai “master” Prod-Cubo: 16 GB di RAM, 12 thread CPU.

Per la produzione preferiamo utilizzare “hardware nudo” ed evitiamo strati intermedi come OpenStack: non abbiamo bisogno di “vicini rumorosi” e CPU steal time. Inoltre, la complessità dell'amministrazione raddoppia nel caso di OpenStack in-house.

Per i componenti infrastrutturali e i CI/CD “Cubo” utilizziamo un server GIT separato, Helm 3 (abbiamo fatto la transizione in modo piuttosto doloroso da Helm 2, ma siamo molto contenti della funzionalità atomic), Jenkins, Ansible e Docker. Amiamo le feature branch e il deployment in diversi ambienti 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 casa DomClick appare dal punto di vista dell'ingegnere operativo. L'articolo è risultato meno tecnico di quanto mi aspettassi: pertanto, seguite le notizie 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