Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

8. april på konferansen Saint HighLoad++ 2019, som en del av "DevOps and Operations"-delen, ble det gitt en rapport "Expanding and complementing Kubernetes", hvor tre ansatte i Flant-selskapet deltok. I den snakker vi om en rekke situasjoner der vi ønsket å utvide og utfylle evnene til Kubernetes, men som vi ikke fant en ferdig og enkel løsning for. Vi har de nødvendige løsningene i form av Open Source-prosjekter, og denne talen er også dedikert til dem.

Av tradisjon er vi glade for å presentere video av rapporten (50 minutter, mye mer informativ enn artikkelen) og hovedoppsummeringen i tekstform. Gå!

Kjerne og tillegg i K8s

Kubernetes endrer bransjen og tilnærminger til administrasjon som lenge har vært etablert:

  • Takk til ham abstraksjoner, vi opererer ikke lenger med konsepter som å sette opp en konfigurasjon eller kjøre en kommando (Chef, Ansible...), men bruker gruppering av containere, tjenester osv.
  • Vi kan utarbeide søknader uten å tenke på nyansene bestemt nettsted, som den vil bli lansert på: bart metall, sky fra en av leverandørene, etc.
  • Med K8s har du aldri vært mer tilgjengelig beste praksis om organisering av infrastruktur: skaleringsteknikker, selvhelbredelse, feiltoleranse, etc.

Men selvfølgelig er ikke alt så glatt: Kubernetes kom også med sine egne nye utfordringer.

Kubernetes no er en skurtresker som løser alle problemene til alle brukere. Kjernen Kubernetes er kun ansvarlig for et sett med minimum nødvendige funksjoner som finnes i hver klynge:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Kubernetes-kjernen definerer et grunnleggende sett med primitiver for gruppering av containere, administrasjon av trafikk og så videre. Vi snakket om dem mer detaljert i rapport for 2 år siden.

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

På den annen side gir K8s store muligheter til å utvide de tilgjengelige funksjonene, som bidrar til å lukke andre - spesifikk – brukerbehov. Tillegg til Kubernetes er ansvaret til klyngeadministratorer, som må installere og konfigurere alt som er nødvendig for å få klyngen deres "i riktig form" [for å løse deres spesifikke problemer]. Hva slags tillegg er dette? La oss se på noen eksempler.

Eksempler på tillegg

Etter å ha installert Kubernetes, kan vi bli overrasket over at nettverket som er så nødvendig for samspillet mellom poder både i en node og mellom noder, ikke fungerer alene. Kubernetes-kjernen garanterer ikke de nødvendige tilkoblingene; i stedet bestemmer den nettverket grensesnitt (CNI) for tredjeparts tillegg. Vi må installere ett av disse tilleggene, som vil være ansvarlig for nettverkskonfigurasjonen.

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Et nærliggende eksempel er datalagringsløsninger (lokal disk, nettverksblokkenhet, Ceph...). Til å begynne med var de i kjernen, men med adventen CSI situasjonen endres til noe som ligner på det som allerede er beskrevet: grensesnittet er i Kubernetes, og implementeringen er i tredjepartsmoduler.

Andre eksempler inkluderer:

  • Ingress-kontrollere (se anmeldelsen deres i vår siste artikkel).
  • cert-leder:

    Utvide og komplettere Kubernetes (gjennomgang og videorapport)

  • Operatører er en hel klasse med tillegg (som inkluderer den nevnte cert-manageren), de definerer primitive(r) og kontroller(er). Logikken i arbeidet deres begrenses bare av fantasien vår og lar oss gjøre ferdige infrastrukturkomponenter (for eksempel en DBMS) til primitiver, som er mye lettere å jobbe med (enn med et sett med beholdere og deres innstillinger). Et stort antall operatører er skrevet - selv om mange av dem ennå ikke er klare for produksjon, er det bare et spørsmål om tid:

    Utvide og komplettere Kubernetes (gjennomgang og videorapport)

  • Beregninger - nok en illustrasjon av hvordan Kubernetes skilte grensesnittet (Metrics API) fra implementeringen (tredjeparts-tillegg som Prometheus-adapter, Datadog-klyngeagent...).
  • For overvåking og statistikk, hvor det i praksis ikke bare trengs Prometheus og Grafana, men også kube-state-metrics, node-exporter, etc.

Og dette er ikke en komplett liste over tillegg... For eksempel hos Flant-firmaet vi for tiden installerer 29 tillegg (som alle oppretter totalt 249 Kubernetes-objekter). Enkelt sagt kan vi ikke se livet til en klynge uten tillegg.

Automatisering

Operatører er designet for å automatisere rutineoperasjoner som vi møter hver dag. Her er eksempler fra det virkelige liv hvor å skrive en operatør ville være en utmerket løsning:

  1. Det er et privat (dvs. krever pålogging) register med bilder for applikasjonen. Det antas at hver pod er tildelt en spesiell hemmelighet som tillater autentisering i registeret. Vår oppgave er å sørge for at denne hemmeligheten blir funnet i navneområdet slik at pods kan laste ned bilder. Det kan være mange applikasjoner (som hver trenger en hemmelighet), og det er nyttig å oppdatere selve hemmelighetene regelmessig, slik at muligheten til å legge ut hemmeligheter for hånd elimineres. Det er her operatøren kommer til unnsetning: vi lager en kontroller som venter på at navneområdet skal vises og, basert på denne hendelsen, vil legge til en hemmelighet til navneområdet.
  2. Tillat tilgang fra pods til Internett er som standard forbudt. Men noen ganger kan det være nødvendig: det er logisk at tilgangstillatelsesmekanismen fungerer enkelt, uten å kreve spesifikke ferdigheter, for eksempel ved tilstedeværelsen av en bestemt etikett i navneområdet. Hvordan kan operatøren hjelpe oss her? Det opprettes en kontroller som venter på at etiketten vises i navneområdet og legger til riktig policy for Internett-tilgang.
  3. En lignende situasjon: anta at vi trengte å legge til en viss plette, hvis den har en lignende etikett (med et slags prefiks). Handlingene med operatøren er åpenbare...

I enhver klynge skal rutineoppgaver løses, og riktig dette kan gjøres ved hjelp av operatører.

Ved å oppsummere alle historiene som er beskrevet, kom vi til den konklusjonen at for komfortabelt arbeid i Kubernetes du trenger: A) installere tillegg, b) utvikle operatører (for å løse daglige administrasjonsoppgaver).

Hvordan skrive en erklæring for Kubernetes?

Generelt er ordningen enkel:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

... men så viser det seg at:

  • Kubernetes API er en ganske ikke-triviell ting som tar mye tid å mestre;
  • programmering er heller ikke for alle (Go-språket ble valgt som det foretrukne språket fordi det er et spesielt rammeverk for det - Operatør SDK);
  • Situasjonen er lik med selve rammeverket.

Den nederste linjen: å skrive en kontroller (operatør) må bruke betydelige ressurser å studere materiell. Dette ville være berettiget for "store" operatører - for eksempel for MySQL DBMS. Men hvis vi husker eksemplene beskrevet ovenfor (utfolding av hemmeligheter, tilgang til pods til Internett ...), som vi også ønsker å gjøre riktig, vil vi forstå at innsatsen som brukes vil oppveie resultatet vi trenger nå:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Generelt oppstår et dilemma: bruk mye ressurser og finn det riktige verktøyet for å skrive utsagn, eller gjør det på den gamle måten (men raskt). For å løse det - for å finne et kompromiss mellom disse ytterpunktene - laget vi vårt eget prosjekt: shell-operatør (se også hans nylig kunngjøring på navet).

Shell-operatør

Hvordan jobber han? Klyngen har en pod som inneholder en Go-binær med en shell-operator. Ved siden av ham er et sett med kroker (mer detaljer om dem - se nedenfor). Shell-operatøren selv abonnerer på visse utviklingen i Kubernetes API, ved forekomsten av hvilken den lanserer de tilsvarende krokene.

Hvordan vet shell-operatøren hvilke kroker han skal ringe på hvilke hendelser? Denne informasjonen overføres til skalloperatøren av krokene selv, og de gjør det veldig enkelt.

En hook er et Bash-skript eller en hvilken som helst annen kjørbar fil som godtar et enkelt argument --config og svarer med JSON. Sistnevnte bestemmer hvilke objekter som er av interesse for den og hvilke hendelser (for disse objektene) som skal reageres på:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Jeg vil illustrere implementeringen på shell-operatoren av et av eksemplene våre - dekomponere hemmeligheter for tilgang til et privat register med applikasjonsbilder. Den består av to stadier.

Øv: 1. Skriv en krok

Først av alt, i kroken vil vi behandle --config, som indikerer at vi er interessert i navnerom, og spesifikt øyeblikket da de ble opprettet:

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

Hvordan vil logikken se ut? Også ganske enkelt:

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

Det første trinnet er å finne ut hvilket navneområde som ble opprettet, og det andre er å opprette det ved hjelp av kubectl hemmelig for dette navneområdet.

Øv: 2. Sette sammen bildet

Alt som gjenstår er å sende den opprettede kroken til skalloperatøren - hvordan gjør jeg dette? Selve shell-operatoren kommer som et Docker-bilde, så vår oppgave er å legge til kroken til en spesiell katalog i dette bildet:

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

Alt som gjenstår er å sette det sammen og skyve det:

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

Siste touch er å distribuere bildet til klyngen. For å gjøre dette, la oss skrive Utplassering:

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

Det er to punkter å være oppmerksom på:

  1. indikasjon på det nyopprettede bildet;
  2. Dette er en systemkomponent som (minst) trenger rettigheter for å abonnere på arrangementer i Kubernetes og til å tildele hemmeligheter til navneområder, så vi oppretter en ServiceAccount (og et sett med regler) for kroken.

Resultat - vi løste problemet vårt slektninger for Kubernetes på en måte som skaper en operatør for å dekomponere hemmeligheter.

Andre shell-operator funksjoner

For å begrense objektene av den valgte typen som kroken vil fungere med, de kan filtreres, velge i henhold til visse etiketter (eller bruke matchExpressions):

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

sørget for dedupliseringsmekanisme, som - ved hjelp av et jq-filter - lar deg konvertere store JSON-objekter til små, hvor bare de parameterne gjenstår som vi ønsker å overvåke for endringer.

Når en krok kalles, passerer skalloperatøren den objektdata, som kan brukes til ethvert behov.

Hendelsene som utløser kroker er ikke begrenset til Kubernetes-hendelser: shell-operatøren gir støtte for ringer kroker etter tid (ligner på crontab i en tradisjonell planlegger), samt en spesiell begivenhet ved oppstart. Alle disse hendelsene kan kombineres og tilordnes samme krok.

Og ytterligere to funksjoner til shell-operatoren:

  1. Det fungerer asynkront. Siden en Kubernetes-hendelse (som et objekt som opprettes) ble mottatt, kan andre hendelser (som det samme objektet som ble slettet) ha oppstått i klyngen, og kroker må ta hensyn til dette. Hvis kroken ble utført med en feil, vil den som standard være det minnes til vellykket fullføring (denne oppførselen kan endres).
  2. Den eksporterer beregninger for Prometheus, som du kan forstå om shell-operatøren fungerer med, finn ut antall feil for hver krok og gjeldende køstørrelse.

For å oppsummere denne delen av rapporten:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Installerer tillegg

For komfortabelt arbeid med Kubernetes ble behovet for å installere tilleggsprogrammer også nevnt. Jeg vil fortelle deg om det ved å bruke eksemplet på selskapets vei til hvordan vi gjør det nå.

Vi begynte å jobbe med Kubernetes med flere klynger, det eneste tillegget var Ingress. Den måtte installeres forskjellig i hver klynge, og vi laget flere YAML-konfigurasjoner for forskjellige miljøer: bart metall, AWS...

Ettersom det var flere klynger, ble det flere konfigurasjoner. I tillegg forbedret vi disse konfigurasjonene selv, som et resultat av at de ble ganske heterogene:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

For å sette alt i orden, startet vi med et manus (install-ingress.sh), som tok som et argument hvilken type klynge vi vil distribuere til, genererte den nødvendige YAML-konfigurasjonen og rullet den ut til Kubernetes.

Kort sagt, vår videre vei og resonnementet knyttet til den var som følger:

  • for å jobbe med YAML-konfigurasjoner, kreves en malmotor (i de første stadiene er dette enkelt sed);
  • med økningen i antall klynger kom behovet for automatisk oppdatering (den tidligste løsningen var å legge skriptet i Git, oppdatere det ved hjelp av cron og kjøre det);
  • et lignende skript var nødvendig for Prometheus (install-prometheus.sh), men det er bemerkelsesverdig for det faktum at det krever mye mer inndata, så vel som lagringen deres (på en god måte - sentralisert og i en klynge), og noen data (passord) kan genereres automatisk:

    Utvide og komplettere Kubernetes (gjennomgang og videorapport)

  • risikoen for å rulle ut noe galt til et økende antall klynger vokste stadig, så vi innså at installatører (dvs. to skript: for Ingress og Prometheus) staging var nødvendig (flere grener i Git, flere crons for å oppdatere dem i tilsvarende: stabile eller testklynger);
  • с kubectl apply det har blitt vanskelig å jobbe med fordi det ikke er deklarativt og bare kan lage objekter, men ikke ta beslutninger om deres status/slette dem;
  • Vi manglet noen funksjoner som vi ikke hadde implementert i det hele tatt på det tidspunktet:
    • full kontroll over resultatet av klyngeoppdateringer,
    • automatisk bestemmelse av noen parametere (inndata for installasjonsskript) basert på data som kan hentes fra klyngen (oppdagelse),
    • sin logiske utvikling i form av kontinuerlig oppdagelse.

Vi implementerte all denne akkumulerte erfaringen innenfor rammen av vårt andre prosjekt - addon-operatør.

Addon-operatør

Den er basert på den allerede nevnte shell-operatoren. Hele systemet ser slik ut:

Følgende er lagt til skall-operatørkrokene:

  • verdilagring,
  • Hjelmdiagram,
  • komponent som overvåker verdilageret og - i tilfelle endringer - ber Helm om å rulle diagrammet på nytt.

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Dermed kan vi reagere på en hendelse i Kubernetes, starte en krok, og fra denne kroken kan vi gjøre endringer i lagringen, hvoretter diagrammet vil bli lastet ned på nytt. I det resulterende diagrammet skiller vi settet med kroker og diagrammet i en komponent, som vi kaller modul:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Det kan være mange moduler, og til dem legger vi til globale kroker, en global verdibutikk og en komponent som overvåker denne globale butikken.

Nå, når noe skjer i Kubernetes, kan vi reagere på det ved å bruke en global krok og endre noe i den globale butikken. Denne endringen vil bli lagt merke til og vil føre til at alle moduler i klyngen rulles ut:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Denne ordningen tilfredsstiller alle kravene for å installere tillegg som ble angitt ovenfor:

  • Helm er ansvarlig for maling og deklarativitet.
  • Problemet med automatisk oppdatering ble løst ved hjelp av en global hook, som går til registeret etter en tidsplan og, hvis den ser et nytt systembilde der, ruller det ut (dvs. "seg selv").
  • Lagring av innstillinger i klyngen implementeres ved hjelp av ConfigMap, som inneholder primærdataene for lagringene (ved oppstart lastes de inn i lagringene).
  • Problemer med passordgenerering, oppdagelse og kontinuerlig oppdagelse ble løst ved hjelp av kroker.
  • Staging oppnås takket være tags, som Docker støtter ut av esken.
  • Resultatet overvåkes ved hjelp av beregninger som gjør at vi kan forstå statusen.

Hele dette systemet er implementert i form av en enkelt binær i Go, som kalles addon-operator. Dette gjør at diagrammet ser enklere ut:

Utvide og komplettere Kubernetes (gjennomgang og videorapport)

Hovedkomponenten i dette diagrammet er et sett med moduler (uthevet i grått nedenfor). Nå kan vi skrive en modul for det nødvendige tillegget med litt innsats og være sikre på at den vil bli installert i hver klynge, vil bli oppdatert og svare på hendelsene den trenger i klyngen.

"Flant" bruker addon-operatør på 70+ Kubernetes-klynger. Nåværende status - alfa-versjon. Nå forbereder vi dokumentasjon for å slippe betaen, men foreløpig i depotet eksempler tilgjengelig, på grunnlag av dette kan du lage ditt eget tillegg.

Hvor kan jeg få tak i modulene for addon-operatør? Å publisere biblioteket vårt er neste trinn for oss; vi planlegger å gjøre dette til sommeren.

Videoer og lysbilder

Video fra forestillingen (~50 minutter):

Presentasjon av rapporten:

PS

Andre rapporter på bloggen vår:

Du kan også være interessert i følgende publikasjoner:

Kilde: www.habr.com

Legg til en kommentar