Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

8. aprila na konferenciji Saint HighLoad++ 2019, u okviru sekcije „DevOps i operacije“, dat je izveštaj „Proširenje i dopuna Kubernetesa“ u čijem kreiranju su učestvovala tri radnika kompanije Flant. U njemu govorimo o brojnim situacijama u kojima smo željeli proširiti i dopuniti mogućnosti Kubernetesa, ali za koje nismo našli gotovo i jednostavno rješenje. Imamo potrebna rješenja u vidu Open Source projekata, a njima je posvećen i ovaj govor.

Po tradiciji, sa zadovoljstvom predstavljamo video izvještaja (50 minuta, mnogo informativnije od članka) i glavni sažetak u tekstualnom obliku. Idi!

Jezgro i dodaci u K8s

Kubernetes mijenja industriju i pristupe administraciji koji su odavno uspostavljeni:

  • Zahvaljujući njemu apstrakcije, više ne radimo s konceptima kao što je postavljanje konfiguracije ili pokretanje naredbe (Chef, Ansible...), već koristimo grupiranje kontejnera, servisa itd.
  • Možemo pripremiti aplikacije bez razmišljanja o nijansama određenom sajtu, na kojem će biti pokrenut: goli metal, oblak nekog od provajdera itd.
  • Sa K8s nikada niste bili pristupačniji najbolje prakse o organiziranju infrastrukture: tehnike skaliranja, samoizlječenja, tolerancije grešaka, itd.

Međutim, naravno, nije sve tako glatko: Kubernetes je doneo i svoje nove izazove.

Kubernet ne je kombajn koji rješava sve probleme svih korisnika. Kernel Kubernetes je odgovoran samo za skup minimalno potrebnih funkcija koje su prisutne svaki klaster:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Kubernetes jezgro definira osnovni skup primitiva za grupisanje kontejnera, upravljanje prometom i tako dalje. O njima smo detaljnije govorili u izvještaj prije 2 godine.

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

S druge strane, K8s nudi velike mogućnosti za proširenje dostupnih funkcija, koje pomažu zatvaranju drugih - specifično — potrebe korisnika. Dodaci u Kubernetes su odgovornost administratora klastera, koji moraju da instaliraju i konfigurišu sve što je potrebno da bi njihov klaster doveo „u pravi oblik“ [kako bi rešili svoje specifične probleme]. Kakvi su ovo dodaci? Pogledajmo neke primjere.

Primjeri dodataka

Nakon što smo instalirali Kubernetes, mogli bismo se iznenaditi da umrežavanje koje je toliko neophodno za interakciju podova kako unutar čvora tako i između čvorova ne radi samostalno. Kubernetes kernel ne garantuje potrebne veze, već određuje mrežu sučelje (CNI) za dodatke trećih strana. Moramo instalirati jedan od ovih dodataka, koji će biti odgovoran za konfiguraciju mreže.

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Blizak primjer su rješenja za pohranu podataka (lokalni disk, mrežni blok uređaj, Ceph...). U početku su bili u jezgru, ali s pojavom CSI situacija se menja u nešto slično već opisanoj: interfejs je u Kubernetesu, a njegova implementacija je u modulima treće strane.

Ostali primjeri uključuju:

  • Ulaz-kontrolori (pogledajte njihovu recenziju u naš nedavni članak).
  • cert-manager:

    Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

  • Operatori je čitava klasa dodataka (koji uključuje spomenuti cert-manager), oni definiraju primitiv(e) i kontroler(e). Logika njihovog rada ograničena je samo našom maštom i omogućava nam da gotove infrastrukturne komponente (na primjer, DBMS) pretvorimo u primitive, s kojima je mnogo lakše raditi (nego sa skupom kontejnera i njihovim postavkama). Ogroman broj operatera je napisan - čak i ako mnogi od njih još nisu spremni za proizvodnju, samo je pitanje vremena:

    Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

  • metrika - još jedna ilustracija kako je Kubernetes odvojio interfejs (Metrics API) od implementacije (dodaci treće strane kao što je Prometheus adapter, Datadog klaster agent...).
  • Do praćenje i statistiku, gdje u praksi nisu samo potrebni Prometej i Grafana, ali i kube-state-metrics, node-exporter, itd.

I ovo nije potpuna lista dodataka... Na primjer, u kompaniji Flant koju trenutno instaliramo 29 dodataka (svi kreiraju ukupno 249 Kubernetes objekata). Jednostavno rečeno, ne možemo vidjeti život klastera bez dodataka.

Automatizacija

Operateri su dizajnirani da automatizuju rutinske operacije sa kojima se svakodnevno susrećemo. Evo primjera iz stvarnog života za koje bi pisanje operatora bilo odlično rješenje:

  1. Postoji privatni (tj. zahtijeva prijavu) registar sa slikama za aplikaciju. Pretpostavlja se da je svakom pod-u dodeljena posebna tajna koja omogućava autentifikaciju u registru. Naš zadatak je osigurati da se ova tajna pronađe u imenskom prostoru kako bi podovi mogli preuzimati slike. Može biti mnogo aplikacija (od kojih je za svaku potrebna tajna), a korisno je redovno ažurirati same tajne, pa je eliminisana opcija ručnog izlaganja tajni. Tu u pomoć priskače operator: kreiramo kontroler koji će čekati da se pojavi imenski prostor i na osnovu ovog događaja će dodati tajnu u prostor imena.
  2. Dozvolite prema zadanim postavkama pristup sa podova na Internet je zabranjen. Ali ponekad može biti potrebno: logično je da mehanizam dozvole pristupa radi jednostavno, bez potrebe za posebnim vještinama, na primjer, prisustvom određene oznake u imenskom prostoru. Kako nam operater ovdje može pomoći? Kreiran je kontroler koji čeka da se oznaka pojavi u imenskom prostoru i dodaje odgovarajuću politiku za pristup Internetu.
  3. Slična situacija: pretpostavimo da trebamo dodati određenu nečistoća, ako ima sličnu oznaku (sa nekom vrstom prefiksa). Radnje sa operaterom su očigledne...

U svakom klasteru, rutinski zadaci moraju biti riješeni, i desno ovo se može uraditi pomoću operatora.

Sumirajući sve opisane priče, došli smo do zaključka da za udoban rad u Kubernetesu koji vam je potreban: A) instalirati dodatke, b) razvijati operatere (za rješavanje svakodnevnih administratorskih zadataka).

Kako napisati izjavu za Kubernetes?

Općenito, shema je jednostavna:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

... ali onda se ispostavi da:

  • Kubernetes API je prilično netrivijalna stvar za koju je potrebno mnogo vremena za savladavanje;
  • programiranje takođe nije za svakoga (Go jezik je izabran kao preferirani jezik jer postoji poseban okvir za njega - Operator SDK);
  • Slična je situacija i sa samim okvirom.

Bottom line: da napišem kontroler (operater) mora troše značajna sredstva studirati materijal. Ovo bi bilo opravdano za “velike” operatere – recimo za MySQL DBMS. Ali ako se prisjetimo gore opisanih primjera (otkrivanje tajni, pristup podovima na Internet...), koje također želimo ispravno učiniti, onda ćemo shvatiti da će uloženi trud nadmašiti rezultat koji nam je sada potreban:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Generalno, postavlja se dilema: potrošiti puno resursa i pronaći pravi alat za pisanje izjava ili to učiniti na starinski način (ali brzo). Da bismo to riješili - kako bismo pronašli kompromis između ovih ekstrema - kreirali smo vlastiti projekt: shell-operator (vidi i njegovu nedavno saopštenje na čvorištu).

Shell-operator

Kako on radi? Klaster ima pod koji sadrži Go binarni program sa shell-operatorom. Pored njega je skup kuke (više detalja o njima - pogledajte ispod). Shell-operator se sam pretplatio na određene događaji u Kubernetes API-ju, po čijoj pojavi pokreće odgovarajuće kuke.

Kako shell-operator zna koje kuke treba pozvati na koje događaje? Ovu informaciju šalju-operateru prenose same kuke, a oni to rade vrlo jednostavno.

Hook je Bash skripta ili bilo koja druga izvršna datoteka koja prihvata jedan argument --config i odgovara sa JSON-om. Potonji određuje koji su objekti za njega od interesa i na koje događaje (za te objekte) treba odgovoriti:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Ilustrovaću implementaciju na shell-operatoru jednog od naših primera - dekomponovanje tajni za pristup privatnom registru sa slikama aplikacije. Sastoji se od dvije faze.

Vježbajte: 1. Napišite kuku

Prije svega, u kuki ćemo obraditi --config, što ukazuje da nas zanimaju prostori imena, a konkretno, trenutak njihovog stvaranja:

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

Kako bi izgledala logika? Takođe prilično jednostavno:

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

Prvi korak je da saznate koji je imenski prostor kreiran, a drugi je da ga kreirate koristeći kubectl tajna za ovaj imenski prostor.

Vježba: 2. Sastavljanje slike

Ostaje samo da kreiranu zakačicu proslijedite shell-operatoru - kako to učiniti? Sam shell-operator dolazi kao Docker slika, tako da je naš zadatak da dodamo kuku u poseban direktorij na ovoj slici:

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

Ostaje samo da ga sastavite i gurnete:

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

Posljednji dodir je postavljanje slike u klaster. Da to uradimo, pišimo razvoj:

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

Dvije su tačke na koje treba obratiti pažnju:

  1. indikacija novonastale slike;
  2. Ovo je sistemska komponenta kojoj (najmanje) su potrebna prava da se pretplati na događaje u Kubernetes-u i da dodijeli tajne prostorima imena, tako da kreiramo ServiceAccount (i skup pravila) za kuku.

Rezultat - riješili smo naš problem rođaci za Kubernetes na način koji kreira operator za dekomponovanje tajni.

Ostale karakteristike shell-operatora

Da biste ograničili objekte odabranog tipa s kojima će kuka raditi, mogu se filtrirati, odabirom prema određenim oznakama (ili korištenjem matchExpressions):

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

Pod uslovom mehanizam deduplikacije, koji - pomoću jq filtera - omogućava vam da velike JSON objekte pretvorite u male, pri čemu ostaju samo oni parametri koje želimo pratiti zbog promjena.

Kada se pozove kuka, shell-operator je proslijeđuje objektni podaci, koji se može koristiti za sve potrebe.

Događaji koji pokreću kuke nisu ograničeni na Kubernetes događaje: shell-operator pruža podršku za calling hooks po vremenu (slično crontab u tradicionalnom planeru), kao i poseban događaj onStartup. Svi ovi događaji se mogu kombinovati i dodijeliti istoj kukici.

I još dvije karakteristike shell-operatora:

  1. Radi asinhrono. Pošto je Kubernetes događaj (kao što je objekat koji se kreira) primljen, drugi događaji (kao što je isti objekat koji je obrisan) su se mogli dogoditi u klasteru, a zakačice treba da vode računa o tome. Ako je zakačivanje izvršeno s greškom, tada će po defaultu biti ponovni poziv do uspješnog završetka (ovo ponašanje se može promijeniti).
  2. Izvozi metrika za Prometheus, s kojim možete razumjeti da li shell-operator radi, saznajte broj grešaka za svaku zakačicu i trenutnu veličinu reda.

Da rezimiramo ovaj dio izvještaja:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Instaliranje dodataka

Za udoban rad sa Kubernetesom, spomenuta je i potreba za instaliranjem dodataka. Reći ću vam o tome koristeći primjer puta naše kompanije do toga kako to sada radimo.

Počeli smo raditi s Kubernetesom s nekoliko klastera, jedini dodatak kojem je bio Ingress. Trebalo je drugačije instalirati u svaki klaster, a napravili smo nekoliko YAML konfiguracija za različita okruženja: goli metal, AWS...

Kako je bilo više klastera, bilo je više konfiguracija. Osim toga, poboljšali smo same te konfiguracije, zbog čega su postale prilično heterogene:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Da bismo sve posložili, počeli smo sa skriptom (install-ingress.sh), koji je kao argument uzeo tip klastera na koji ćemo rasporediti, generisao je potrebnu YAML konfiguraciju i uveo je u Kubernetes.

Ukratko, naš dalji put i rezonovanje vezano za njega bilo je sljedeće:

  • za rad sa YAML konfiguracijama potreban je šablonski mehanizam (u prvim fazama ovo je jednostavan sed);
  • sa povećanjem broja klastera pojavila se potreba za automatskim ažuriranjem (najranije rešenje je bilo staviti skriptu u Git, ažurirati je pomoću crona i pokrenuti);
  • sličan scenario je bio potreban za Prometeja (install-prometheus.sh), međutim, ističe se po tome što zahtijeva mnogo više ulaznih podataka, kao i njihovo skladištenje (na dobar način - centralizirano i u klasteru), a neki podaci (lozinke) bi se mogli automatski generirati:

    Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

  • rizik od uvođenja nečeg pogrešnog na sve veći broj klastera je stalno rastao, pa smo shvatili da instalateri (tj. dvije skripte: za Ingress i Prometheus) bilo je potrebno insceniranje (nekoliko grana u Gitu, nekoliko cron-ova za njihovo ažuriranje u odgovarajućim: stabilnim ili testnim klasterima);
  • с kubectl apply postalo je teško raditi s njim jer nije deklarativno i može samo kreirati objekte, ali ne i donositi odluke o njihovom statusu/brisati ih;
  • Nedostajale su nam neke funkcije koje u to vrijeme uopće nismo implementirali:
    • potpuna kontrola nad rezultatom ažuriranja klastera,
    • automatsko određivanje nekih parametara (unos za instalacione skripte) na osnovu podataka koji se mogu dobiti iz klastera (otkrivanje),
    • njegov logički razvoj u obliku kontinuiranog otkrivanja.

Sve ovo stečeno iskustvo implementirali smo u okviru našeg drugog projekta - addon-operator.

Addon-operator

Zasnovan je na već spomenutom shell-operatoru. Ceo sistem izgleda ovako:

Sljedeće se dodaje kukicama shell-operatora:

  • pohranjivanje vrijednosti,
  • Helm chart,
  • komponenta koja prati skladište vrijednosti i - u slučaju bilo kakvih promjena - traži od Helma da ponovo okrene grafikon.

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Tako možemo reagovati na događaj u Kubernetes-u, pokrenuti zakačicu i sa ovog kuka možemo izvršiti promjene u memoriji, nakon čega će se grafikon ponovo preuzeti. U rezultirajućem dijagramu razdvajamo skup kukica i grafikon u jednu komponentu, koju nazivamo modul:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Modula može biti mnogo, a njima dodajemo globalne kuke, globalno skladište vrijednosti i komponentu koja nadgleda ovu globalnu trgovinu.

Sada, kada se nešto dogodi u Kubernetesu, možemo reagovati na to koristeći globalnu kuku i promijeniti nešto u globalnoj trgovini. Ova promjena će biti primjećena i uzrokovat će uvođenje svih modula u klaster:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Ova shema zadovoljava sve zahtjeve za instaliranje dodataka koji su gore navedeni:

  • Helm je odgovoran za šabloniranje i deklarativnost.
  • Problem automatskog ažuriranja riješen je korištenjem globalne kuke, koja ide u registar po rasporedu i, ako tamo vidi novu sliku sistema, pokreće je (tj. „sebe“).
  • Pohranjivanje postavki u klaster implementirano je pomoću ConfigMap, koji sadrži primarne podatke za skladišta (pri pokretanju se učitavaju u skladišta).
  • Problemi s generiranjem lozinki, otkrivanjem i kontinuiranim otkrivanjem riješeni su pomoću kukica.
  • Staging se postiže zahvaljujući tagovima, koje Docker podržava iz kutije.
  • Rezultat se prati pomoću metrike po kojoj možemo razumjeti status.

Cijeli ovaj sistem je implementiran u obliku jedne binarne datoteke u Go, koja se zove addon-operator. Ovo čini dijagram jednostavnijim:

Proširivanje i dopuna Kubernetesa (pregled i video izvještaj)

Glavna komponenta u ovom dijagramu je skup modula (označeno sivom bojom ispod). Sada možemo uz malo truda napisati modul za potreban dodatak i biti sigurni da će biti instaliran u svaki klaster, biti ažuriran i odgovoriti na događaje koji su mu potrebni u klasteru.

"Flant" koristi addon-operator na 70+ Kubernetes klastera. Trenutni status - alfa verzija. Sada pripremamo dokumentaciju za puštanje beta verzije, ali za sada u spremištu dostupni primjeri, na osnovu kojeg možete kreirati vlastiti dodatak.

Gdje mogu nabaviti module za addon-operator? Izdavanje naše biblioteke je sljedeća faza za nas, planiramo to učiniti na ljeto.

Video zapisi i slajdovi

Video sa nastupa (~50 minuta):

Prezentacija izvještaja:

PS

Ostali izvještaji na našem blogu:

Možda će vas zanimati i sljedeće publikacije:

izvor: www.habr.com

Dodajte komentar