Extinderea și completarea Kubernetes (prezentare generală și raport video)

Extinderea și completarea Kubernetes (prezentare generală și raport video)

8 aprilie la conferință Saint HighLoad++ 2019, în cadrul secțiunii „DevOps și operațiuni”, a fost dat un raport „Extinderea și completarea Kubernetes”, la crearea căruia au participat trei angajați ai companiei Flant. În ea, vorbim despre numeroase situații în care am dorit să extindem și să completăm capacitățile Kubernetes, dar pentru care nu am găsit o soluție gata făcută și simplă. Avem soluțiile necesare sub formă de proiecte Open Source, iar acest discurs este dedicat și acestora.

Prin tradiție, ne face plăcere să vă prezentăm video cu raportul (50 de minute, mult mai informativ decât articolul) și rezumatul principal sub formă de text. Merge!

Miez și completări în K8-uri

Kubernetes schimbă industria și abordările de administrare care au fost stabilite de mult timp:

  • Multumita lui abstracții, nu mai operam cu concepte precum setarea unei config sau rularea unei comenzi (Chef, Ansible...), ci folosim gruparea de containere, servicii etc.
  • Putem pregăti aplicații fără să ne gândim la nuanțele site specific, pe care va fi lansat: bare metal, cloud al unuia dintre furnizori etc.
  • Cu K8s nu ai fost niciodată mai accesibil cele mai bune practici privind organizarea infrastructurii: tehnici de scalare, auto-vindecare, toleranță la erori etc.

Cu toate acestea, desigur, totul nu este atât de bine: Kubernetes și-a adus și propriile provocări noi.

Kubernetes nu este o combină care rezolvă toate problemele tuturor utilizatorilor. Miezul Kubernetes este responsabil doar pentru un set de funcții minime necesare care sunt prezente în fiecare cluster:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Nucleul Kubernetes definește un set de bază de primitive pentru gruparea containerelor, gestionarea traficului și așa mai departe. Am vorbit despre ele mai detaliat în raport acum 2 ani.

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Pe de altă parte, K8s oferă oportunități excelente de a extinde funcțiile disponibile, care ajută la închiderea altora - specific - nevoile utilizatorului. Adăugările la Kubernetes sunt responsabilitatea administratorilor de cluster, care trebuie să instaleze și să configureze tot ceea ce este necesar pentru a-și pune clusterul „în forma potrivită” [pentru a-și rezolva problemele specifice]. Ce fel de completări sunt acestea? Să ne uităm la câteva exemple.

Exemple de suplimente

După ce am instalat Kubernetes, putem fi surprinși că rețeaua care este atât de necesară pentru interacțiunea podurilor atât în ​​interiorul unui nod, cât și între noduri nu funcționează de la sine. Nucleul Kubernetes nu garantează conexiunile necesare, ci determină rețeaua interfață (CNI) pentru suplimente de la terți. Trebuie să instalăm unul dintre aceste suplimente, care va fi responsabil pentru configurarea rețelei.

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Un exemplu apropiat sunt soluțiile de stocare a datelor (disc local, dispozitiv de blocare a rețelei, Ceph...). Inițial au fost în miez, dar odată cu apariția CSI situația se schimbă în ceva similar cu cel descris deja: interfața este în Kubernetes, iar implementarea ei este în module terțe.

Alte exemple includ:

  • Pătrundere-controlere (vezi recenzia lor în articolul nostru recent).
  • CertificatAcreditat-manager:

    Extinderea și completarea Kubernetes (prezentare generală și raport video)

  • operatori este o clasă întreagă de suplimente (care include certificat-managerul menționat), ele definesc primitive și controllere. Logica muncii lor este limitată doar de imaginația noastră și ne permite să transformăm componente de infrastructură gata făcute (de exemplu, un DBMS) în primitive, cu care este mult mai ușor de lucrat (decât cu un set de containere și setările acestora). A fost scris un număr mare de operatori - chiar dacă mulți dintre ei nu sunt încă pregătiți pentru producție, este doar o chestiune de timp:

    Extinderea și completarea Kubernetes (prezentare generală și raport video)

  • Metrici - o altă ilustrare a modului în care Kubernetes a separat interfața (Metrics API) de implementare (suplimente terțe, cum ar fi adaptorul Prometheus, agentul de cluster Datadog...).
  • Pentru monitorizare și statistică, unde în practică nu numai că sunt necesare Prometeu și Grafana, dar și kube-state-metrics, node-exporter etc.

Și aceasta nu este o listă completă de completări... De exemplu, la compania Flant pe care o instalăm în prezent 29 completări (toate care creează un total de 249 de obiecte Kubernetes). Mai simplu spus, nu putem vedea viața unui cluster fără adăugiri.

Automatizare

Operatorii sunt proiectați pentru a automatiza operațiunile de rutină pe care le întâlnim în fiecare zi. Iată exemple din viața reală pentru care scrierea unui operator ar fi o soluție excelentă:

  1. Există un registru privat (adică care necesită o conectare) cu imagini pentru aplicație. Se presupune că fiecărui pod îi este atribuit un secret special care permite autentificarea în registru. Sarcina noastră este să ne asigurăm că acest secret este găsit în spațiul de nume, astfel încât podurile să poată descărca imagini. Pot exista o mulțime de aplicații (fiecare dintre ele are nevoie de un secret) și este util să actualizați secretele în mod regulat, astfel încât opțiunea de a așeza secretele manual este eliminată. Aici operatorul vine în ajutor: creăm un controler care va aștepta să apară spațiul de nume și, pe baza acestui eveniment, va adăuga un secret spațiului de nume.
  2. Permiteți accesul implicit de la poduri la Internet este interzis. Dar uneori poate fi necesar: este logic ca mecanismul de permisiuni de acces să funcționeze simplu, fără a necesita abilități specifice, de exemplu, prin prezența unei anumite etichete în spațiul de nume. Cum ne poate ajuta operatorul aici? Este creat un controler care așteaptă ca eticheta să apară în spațiul de nume și adaugă politica corespunzătoare pentru accesul la Internet.
  3. O situație similară: să presupunem că trebuie să adăugăm o anumită altera, dacă are o etichetă similară (cu un fel de prefix). Acțiunile cu operatorul sunt evidente...

În orice cluster, sarcinile de rutină trebuie rezolvate și corect acest lucru se poate face folosind operatori.

Rezumând toate poveștile descrise, am ajuns la concluzia că pentru a lucra confortabil în Kubernetes de care aveți nevoie: A) instalați suplimente, b) dezvolta operatori (pentru rezolvarea sarcinilor zilnice de administrare).

Cum se scrie o declarație pentru Kubernetes?

În general, schema este simplă:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

... dar apoi se dovedește că:

  • API-ul Kubernetes este un lucru destul de netrivial, care necesită mult timp pentru a stăpâni;
  • De asemenea, programarea nu este pentru toată lumea (limbajul Go a fost ales ca limbaj preferat deoarece există un cadru special pentru acesta - Operator SDK);
  • Situația este similară cu cadrul în sine.

Linia de jos: pentru a scrie un controler (operator) trebuie să cheltuiesc resurse semnificative a studia materialul. Acest lucru ar fi justificat pentru operatorii „mari” - să zicem, pentru SGBD-ul MySQL. Dar dacă ne amintim de exemplele descrise mai sus (desfășurarea secretelor, accesarea podurilor pe Internet...), pe care și noi vrem să le facem corect, atunci vom înțelege că efortul depus va depăși rezultatul de care avem nevoie acum:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

În general, apare o dilemă: cheltuiți o mulțime de resurse și găsiți instrumentul potrivit pentru a scrie declarații sau faceți-o în mod demodat (dar rapid). Pentru a o rezolva - pentru a găsi un compromis între aceste extreme - am creat propriul nostru proiect: operator-shell (vezi și a lui anunț recent pe hub).

Operator Shell

Cum lucrează? Clusterul are un pod care conține un binar Go cu un operator shell. Alături este un set de cârlige (mai multe detalii despre ele - vezi mai jos). Operatorul shell însuși se abonează la anumite evoluțiile în API-ul Kubernetes, la apariția căruia lansează hook-urile corespunzătoare.

Cum știe operatorul shell ce cârlige să apeleze la ce evenimente? Aceste informații sunt transmise operatorului shell-ului de către cârlige în sine și o fac foarte simplu.

Un cârlig este un script Bash sau orice alt fișier executabil care acceptă un singur argument --config și răspunde cu JSON. Acesta din urmă determină ce obiecte îl interesează și la ce evenimente (pentru aceste obiecte) ar trebui să se răspundă:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Voi ilustra implementarea pe operatorul shell a unuia dintre exemplele noastre - descompunerea secretelor pentru accesarea unui registru privat cu imagini de aplicație. Este format din două etape.

Practică: 1. Scrie un cârlig

În primul rând, în cârligul vom procesa --config, indicând faptul că ne interesează spațiile de nume și, în special, momentul creării lor:

[[ $1 == "--config" ]] ; then
  cat << EOF
{
  "onKubernetesEvent": [
    {
      "kind": "namespace",
      "event": ["add"]
    }
  ]
}
EOF
…

Cum ar arăta logica? De asemenea, destul de simplu:

…
else
  createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
  kubectl create -n ${createdNamespace} -f - << EOF
Kind: Secret
...
EOF
fi

Primul pas este să aflați ce spațiu de nume a fost creat, iar al doilea este să îl creați folosind kubectl secret pentru acest spațiu de nume.

Practică: 2. Asamblarea imaginii

Tot ce rămâne este să treci cârligul creat operatorului shell - cum să faci asta? Operatorul shell în sine vine ca o imagine Docker, deci sarcina noastră este să adăugăm hook-ul într-un director special din această imagine:

FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooks

Tot ce rămâne este să-l asamblați și să-l împingeți:

$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1

Atingerea finală este de a implementa imaginea în cluster. Pentru a face asta, hai să scriem Implementare:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-operator
spec:
  template:
    spec:
      containers:
      - name: my-operator
        image: registry.example.com/my-operator:v1 # 1
      serviceAccountName: my-operator              # 2

Există două puncte la care să acordați atenție:

  1. indicarea imaginii nou create;
  2. Aceasta este o componentă de sistem care (cel puțin) are nevoie de drepturi pentru a se abona la evenimente în Kubernetes și pentru a aloca secrete spațiilor de nume, așa că creăm un ServiceAccount (și un set de reguli) pentru hook.

Rezultat - ne-am rezolvat problema rude pentru Kubernetes într-un mod care creează un operator pentru descompunerea secretelor.

Alte caracteristici ale operatorului shell

Pentru a limita obiectele de tipul ales cu care va funcționa cârligul, pot fi filtrate, selectând în funcție de anumite etichete (sau folosind matchExpressions):

"onKubernetesEvent": [
  {
    "selector": {
      "matchLabels": {
        "foo": "bar",
       },
       "matchExpressions": [
         {
           "key": "allow",
           "operation": "In",
           "values": ["wan", "warehouse"],
         },
       ],
     }
     …
  }
]

Prevăzut mecanism de deduplicare, care - folosind un filtru jq - vă permite să convertiți obiecte JSON mari în altele mici, unde rămân doar acei parametri pe care vrem să-i monitorizăm pentru modificări.

Când un cârlig este apelat, operatorul shell îl trece date obiect, care poate fi folosit pentru orice nevoie.

Evenimentele care declanșează cârlige nu se limitează la evenimente Kubernetes: operatorul shell oferă suport pentru chemând cârlige după timp (similar cu crontab într-un programator tradițional), precum și un eveniment special la inceput. Toate aceste evenimente pot fi combinate și atribuite aceluiași cârlig.

Și încă două caracteristici ale operatorului shell:

  1. el lucreaza asincron. Deoarece a fost primit un eveniment Kubernetes (cum ar fi un obiect în curs de creare), alte evenimente (cum ar fi ștergerea aceluiași obiect) ar fi putut avea loc în cluster, iar hook-urile trebuie să țină seama de acest lucru. Dacă cârligul a fost executat cu o eroare, atunci va fi implicit rechemare până la finalizarea cu succes (acest comportament poate fi modificat).
  2. Se exportă metrici pentru Prometheus, cu care puteți înțelege dacă operatorul shell funcționează, aflați numărul de erori pentru fiecare cârlig și dimensiunea curentă a cozii.

Pentru a rezuma această parte a raportului:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Instalarea suplimentelor

Pentru a lucra confortabil cu Kubernetes, a fost menționată și necesitatea instalării suplimentelor. Vă voi spune despre asta folosind exemplul drumului companiei noastre către cum o facem acum.

Am început să lucrăm cu Kubernetes cu mai multe clustere, singura completare la care a fost Ingress. Trebuia instalat diferit în fiecare cluster și am realizat mai multe configurații YAML pentru diferite medii: bare metal, AWS...

Pe măsură ce erau mai multe clustere, au fost mai multe configurații. În plus, am îmbunătățit ei înșiși aceste configurații, drept urmare au devenit destul de eterogene:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Pentru a pune totul în ordine, am început cu un script (install-ingress.sh), care a luat drept argument tipul de cluster în care vom implementa, a generat configurația YAML necesară și a lansat-o în Kubernetes.

Pe scurt, drumul nostru ulterior și raționamentul asociat cu acesta au fost următoarele:

  • pentru a lucra cu configurații YAML, este necesar un motor de șablon (în primele etape este simplu sed);
  • odată cu creșterea numărului de clustere, a apărut și necesitatea actualizării automate (cea mai timpurie soluție a fost să puneți scriptul în Git, să îl actualizați folosind cron și să îl rulați);
  • un script similar a fost necesar pentru Prometeu (install-prometheus.sh), totuși, se remarcă prin faptul că necesită mult mai multe date de intrare, precum și stocarea acestora (într-un mod bun - centralizat și într-un cluster), iar unele date (parole) ar putea fi generate automat:

    Extinderea și completarea Kubernetes (prezentare generală și raport video)

  • riscul de a implementa ceva greșit într-un număr tot mai mare de clustere creștea constant, așa că ne-am dat seama că instalatorii (adică două scripturi: pentru Ingress și Prometheus) a fost nevoie de staging (mai multe ramuri în Git, mai multe cron-uri pentru a le actualiza în clusterele corespunzătoare: stabile sau de testare);
  • с kubectl apply a devenit dificil de lucrat pentru că nu este declarativ și poate doar să creeze obiecte, dar nu să ia decizii cu privire la starea acestora/le șterge;
  • Ne lipseau câteva funcții pe care nu le implementam deloc la momentul respectiv:
    • control deplin asupra rezultatului actualizărilor clusterului,
    • determinarea automată a unor parametri (intrare pentru scripturi de instalare) pe baza datelor care pot fi obținute din cluster (descoperire),
    • dezvoltarea sa logica sub forma descoperirii continue.

Am implementat toată această experiență acumulată în cadrul celuilalt proiect al nostru - addon-operator.

Operator de supliment

Se bazează pe operatorul shell deja menționat. Întregul sistem arată astfel:

Următoarele se adaugă la cârligele operatorului shell:

  • stocarea valorilor,
  • Diagrama de cârmă,
  • componentă care monitorizează depozitul de valori și - în cazul oricăror modificări - îi cere lui Helm să reroleze graficul.

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Astfel, putem reacționa la un eveniment în Kubernetes, lansăm un hook, iar din acest hook putem face modificări în stocare, după care graficul va fi re-descărcat. În diagrama rezultată, separăm setul de cârlige și diagrama într-o singură componentă, pe care o numim modul:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Pot exista multe module, iar acestora adăugăm cârlige globale, un magazin de valori globale și o componentă care monitorizează acest magazin global.

Acum, când se întâmplă ceva în Kubernetes, putem reacționa la el folosind un cârlig global și putem schimba ceva în magazinul global. Această modificare va fi observată și va face ca toate modulele din cluster să fie lansate:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Această schemă îndeplinește toate cerințele pentru instalarea suplimentelor care au fost menționate mai sus:

  • Helm este responsabil pentru modelare și declarativitate.
  • Problema actualizării automate a fost rezolvată folosind un cârlig global, care merge la registru într-un program și, dacă vede o nouă imagine de sistem acolo, o lansează (adică „însuși”).
  • Stocarea setărilor în cluster este implementată folosind ConfigMap, care conține datele primare pentru depozite (la pornire, acestea sunt încărcate în depozite).
  • Problemele legate de generarea parolei, descoperirea și descoperirea continuă au fost rezolvate folosind cârlige.
  • Stagingul se realizează datorită etichetelor, pe care Docker le acceptă imediat.
  • Rezultatul este monitorizat folosind metrici prin care putem înțelege starea.

Acest întreg sistem este implementat sub forma unui singur binar în Go, care se numește addon-operator. Acest lucru face ca diagrama să pară mai simplă:

Extinderea și completarea Kubernetes (prezentare generală și raport video)

Componenta principală din această diagramă este un set de module (evidențiat cu gri mai jos). Acum putem scrie un modul pentru add-on-ul necesar cu puțin efort și să fim siguri că va fi instalat în fiecare cluster, va fi actualizat și va răspunde la evenimentele de care are nevoie în cluster.

Utilizări „Flant”. addon-operator pe peste 70 de clustere Kubernetes. Statusul curent - versiunea alfa. Acum pregătim documentația pentru lansarea beta, dar deocamdată în depozit exemple disponibile, pe baza căruia vă puteți crea propriul supliment.

De unde pot obține modulele pentru addon-operator? Publicarea bibliotecii noastre este următoarea etapă pentru noi; intenționăm să facem acest lucru în vară.

Videoclipuri și diapozitive

Videoclip de la spectacol (~50 de minute):

Prezentarea raportului:

PS

Alte rapoarte pe blogul nostru:

Ați putea fi, de asemenea, interesat de următoarele publicații:

Sursa: www.habr.com

Adauga un comentariu