Utöka och komplettera Kubernetes (recension och videorapport)

Utöka och komplettera Kubernetes (recension och videorapport)

8 april på konferensen Saint HighLoad++ 2019, som en del av avsnittet "DevOps and Operations" gavs en rapport "Expanding and complementing Kubernetes", i skapandet av vilken tre anställda i Flant-företaget deltog. I den pratar vi om många situationer där vi ville utöka och komplettera Kubernetes kapacitet, men för vilka vi inte hittade en färdig och enkel lösning. Vi har de nödvändiga lösningarna i form av Open Source-projekt, och detta tal är också tillägnat dem.

Av tradition är vi glada att kunna presentera video av rapporten (50 minuter, mycket mer informativ än artikeln) och huvudsammanfattningen i textform. Gå!

Kärna och tillägg i K8s

Kubernetes förändrar branschen och tillvägagångssätten för administration som länge har etablerats:

  • Tack vare honom abstraktioner, vi arbetar inte längre med koncept som att sätta upp en konfiguration eller köra ett kommando (Chef, Ansible...), utan använder gruppering av behållare, tjänster, etc.
  • Vi kan förbereda ansökningar utan att tänka på nyanserna specifik webbplats, där den kommer att lanseras: bar metall, moln från en av leverantörerna, etc.
  • Med K8s har du aldrig varit mer tillgänglig bästa praxis om att organisera infrastruktur: skalningstekniker, självläkning, feltolerans, etc.

Men naturligtvis är allt inte så smidigt: Kubernetes kom också med sina egna nya utmaningar.

Kubernetes ingen är en skördetröska som löser alla användares problem. kärna Kubernetes ansvarar endast för en uppsättning av de minsta nödvändiga funktioner som finns i varje klunga:

Utöka och komplettera Kubernetes (recension och videorapport)

Kubernetes-kärnan definierar en grundläggande uppsättning primitiver för att gruppera containrar, hantera trafik och så vidare. Vi pratade mer om dem i rapport för 2 år sedan.

Utöka och komplettera Kubernetes (recension och videorapport)

Å andra sidan erbjuder K8s stora möjligheter att utöka de tillgängliga funktionerna, som hjälper till att stänga andra - specifik — användarbehov. Tillägg till Kubernetes är klusteradministratörers ansvar, som måste installera och konfigurera allt som behövs för att få sitt kluster "i rätt form" [för att lösa sina specifika problem]. Vad är det för tillägg? Låt oss titta på några exempel.

Exempel på tillägg

Efter att ha installerat Kubernetes kan vi bli förvånade över att nätverket som är så nödvändigt för interaktionen mellan poddar både inom en nod och mellan noder inte fungerar på egen hand. Kubernetes-kärnan garanterar inte de nödvändiga anslutningarna, utan den bestämmer nätverket gränssnitt (CNI) för tillägg från tredje part. Vi måste installera ett av dessa tillägg, som kommer att ansvara för nätverkskonfigurationen.

Utöka och komplettera Kubernetes (recension och videorapport)

Ett nära exempel är datalagringslösningar (lokal disk, nätverksblockenhet, Ceph...). Till en början var de i kärnan, men med tillkomsten CSI situationen ändras till något liknande det som redan beskrivits: gränssnittet är i Kubernetes, och dess implementering är i tredjepartsmoduler.

Andra exempel inkluderar:

  • Ingress-kontroller (se deras recension i vår senaste artikel).
  • cert-chef:

    Utöka och komplettera Kubernetes (recension och videorapport)

  • operatörer är en hel klass av tillägg (som inkluderar den nämnda cert-hanteraren), de definierar primitiva(r) och kontroller(er). Logiken i deras arbete begränsas endast av vår fantasi och tillåter oss att förvandla färdiga infrastrukturkomponenter (till exempel en DBMS) till primitiver, som är mycket lättare att arbeta med (än med en uppsättning behållare och deras inställningar). Ett stort antal operatörer har skrivits - även om många av dem ännu inte är redo för produktion är det bara en tidsfråga:

    Utöka och komplettera Kubernetes (recension och videorapport)

  • Metrik - ytterligare en illustration av hur Kubernetes separerade gränssnittet (Metrics API) från implementeringen (tillägg från tredje part som Prometheus-adapter, Datadog-klusteragent...).
  • för övervakning och statistik, där det i praktiken inte bara behövs Prometheus och Grafana, men även kube-state-metrics, node-exporter, etc.

Och det här är inte en komplett lista över tillägg... Till exempel hos Flant-företaget vi installerar för närvarande 29 tillägg (som alla skapar totalt 249 Kubernetes-objekt). Enkelt uttryckt kan vi inte se livet för ett kluster utan tillägg.

Automation

Operatörer är utformade för att automatisera rutinoperationer som vi möter varje dag. Här är exempel från verkliga livet där att skriva en operatör skulle vara en utmärkt lösning:

  1. Det finns ett privat (dvs kräver en inloggning) register med bilder för applikationen. Det antas att varje pod tilldelas en speciell hemlighet som tillåter autentisering i registret. Vår uppgift är att se till att denna hemlighet finns i namnutrymmet så att poddar kan ladda ner bilder. Det kan finnas många applikationer (som var och en behöver en hemlighet), och det är användbart att uppdatera själva hemligheterna regelbundet, så möjligheten att lägga ut hemligheter för hand elimineras. Det är här operatören kommer till undsättning: vi skapar en kontroller som väntar på att namnområdet ska dyka upp och, baserat på denna händelse, lägger till en hemlighet till namnområdet.
  2. Som standard är åtkomst från pods till Internet förbjuden. Men ibland kan det krävas: det är logiskt att åtkomstbehörighetsmekanismen fungerar enkelt, utan att kräva specifika färdigheter, till exempel genom närvaron av en viss etikett i namnutrymmet. Hur kan operatören hjälpa oss här? En kontroller skapas som väntar på att etiketten ska visas i namnområdet och lägger till lämplig policy för Internetåtkomst.
  3. En liknande situation: anta att vi behövde lägga till en viss bismak, om den har en liknande etikett (med något slags prefix). Handlingarna med operatören är uppenbara...

I vilket kluster som helst måste rutinuppgifter lösas, och korrekt detta kan göras med hjälp av operatorer.

Genom att sammanfatta alla beskrivna berättelser kom vi fram till att för bekvämt arbete i Kubernetes du behöver:A) installera tillägg, b) utveckla operatörer (för att lösa dagliga administratörsuppgifter).

Hur skriver man ett uttalande för Kubernetes?

I allmänhet är schemat enkelt:

Utöka och komplettera Kubernetes (recension och videorapport)

... men så visar det sig att:

  • Kubernetes API är en ganska icke-trivial sak som tar mycket tid att bemästra;
  • programmering är inte heller för alla (Go-språket valdes som det föredragna språket eftersom det finns ett speciellt ramverk för det - Operatörs-SDK);
  • Situationen är liknande med själva ramverket.

Summan av kardemumman: att skriva en kontroller (operatör) måste spendera betydande resurser att studera materiel. Detta skulle vara motiverat för "stora" operatörer - säg för MySQL DBMS. Men om vi kommer ihåg exemplen som beskrivits ovan (avslöja hemligheter, komma åt pods till Internet...), vilket vi också vill göra korrekt, då kommer vi att förstå att den ansträngning som lagts ner kommer att uppväga det resultat vi behöver nu:

Utöka och komplettera Kubernetes (recension och videorapport)

Generellt sett uppstår ett dilemma: spendera mycket resurser och hitta rätt verktyg för att skriva uttalanden, eller gör det på gammaldags sätt (men snabbt). För att lösa det - för att hitta en kompromiss mellan dessa ytterligheter - skapade vi vårt eget projekt: skal-operatör (se även hans nyligen tillkännagivande på navet).

Shell-operatör

Hur fungerar han? Klustret har en pod som innehåller en Go-binär med en skal-operator. Bredvid honom finns en uppsättning krokar (mer information om dem - se nedan). Skaloperatören själv prenumererar på vissa utvecklingen i Kubernetes API, när den uppträder lanserar motsvarande krokar.

Hur vet skaloperatören vilka krokar som ska anropas på vilka händelser? Denna information överförs till skal-operatören av krokarna själva, och de gör det mycket enkelt.

En hook är ett Bash-skript eller någon annan körbar fil som accepterar ett enda argument --config och svarar med JSON. Den senare bestämmer vilka objekt som är av intresse för den och vilka händelser (för dessa objekt) som ska besvaras:

Utöka och komplettera Kubernetes (recension och videorapport)

Jag kommer att illustrera implementeringen på skal-operatören av ett av våra exempel - nedbrytande hemligheter för att komma åt ett privat register med applikationsbilder. Den består av två steg.

Öva: 1. Skriv en krok

Först av allt, i kroken kommer vi att bearbeta --config, vilket indikerar att vi är intresserade av namnrymder, och specifikt ögonblicket då de skapades:

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

Hur skulle logiken se ut? Också ganska enkelt:

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

Det första steget är att ta reda på vilket namnområde som skapades, och det andra är att skapa det med hjälp av kubectl hemlighet för detta namnutrymme.

Öva: 2. Montering av bilden

Allt som återstår är att skicka den skapade kroken till skal-operatören - hur gör man detta? Själva skaloperatorn kommer som en Docker-bild, så vår uppgift är att lägga till kroken i en speciell katalog i den här bilden:

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

Allt som återstår är att montera den och trycka den:

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

Sista handen är att distribuera bilden till klustret. För att göra detta, låt oss skriva konfiguration:

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 finns två punkter att vara uppmärksam på:

  1. indikation på den nyskapade bilden;
  2. Detta är en systemkomponent som (minst) behöver rättigheter för att prenumerera på händelser i Kubernetes och för att tilldela hemligheter till namnutrymmen, så vi skapar ett ServiceAccount (och en uppsättning regler) för hooken.

Resultat - vi löste vårt problem släktingar för Kubernetes på ett sätt som skapar en operatör för att bryta ner hemligheter.

Andra funktioner för skaloperator

För att begränsa objekten av din valda typ som kroken kommer att fungera med, de kan filtreras, välja enligt vissa etiketter (eller använda matchExpressions):

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

Försedd dedupliceringsmekanism, som - med hjälp av ett jq-filter - låter dig konvertera stora JSON-objekt till små, där bara de parametrar finns kvar som vi vill övervaka för ändringar.

När en krok anropas passerar skaloperatören den objektdata, som kan användas för alla behov.

Händelser som utlöser hooks är inte begränsade till Kubernetes-händelser: skal-operatören ger stöd för ringa krokar efter tid (liknar crontab i en traditionell schemaläggare), såväl som en speciell händelse vid start. Alla dessa händelser kan kombineras och tilldelas samma hook.

Och ytterligare två funktioner hos skaloperatorn:

  1. Det fungerar asynkront. Eftersom en Kubernetes-händelse (som ett objekt som skapas) togs emot, kan andra händelser (som att samma objekt tas bort) ha inträffat i klustret, och hooks måste ta hänsyn till detta. Om kroken exekverades med ett fel, kommer det att vara det som standard återkallelse tills framgångsrikt slutförande (detta beteende kan ändras).
  2. Den exporterar metrik för Prometheus, med vilken du kan förstå om skal-operatören fungerar, ta reda på antalet fel för varje krok och den aktuella köstorleken.

För att sammanfatta denna del av rapporten:

Utöka och komplettera Kubernetes (recension och videorapport)

Installerar tillägg

För bekvämt arbete med Kubernetes nämndes också behovet av att installera tillägg. Jag kommer att berätta om det med exemplet på vårt företags väg till hur vi gör det nu.

Vi började arbeta med Kubernetes med flera kluster, det enda tillägget var Ingress. Det behövde installeras på olika sätt i varje kluster, och vi gjorde flera YAML-konfigurationer för olika miljöer: bar metall, AWS...

Eftersom det fanns fler kluster blev det fler konfigurationer. Dessutom förbättrade vi dessa konfigurationer själva, som ett resultat av vilket de blev ganska heterogena:

Utöka och komplettera Kubernetes (recension och videorapport)

För att få ordning på allt började vi med ett manus (install-ingress.sh), som tog som ett argument den typ av kluster som vi kommer att distribuera till, genererade den nödvändiga YAML-konfigurationen och rullade ut den till Kubernetes.

Kort sagt, vår vidare väg och resonemanget i samband med den var följande:

  • för att arbeta med YAML-konfigurationer krävs en mallmotor (i de första stegen är detta enkelt sed);
  • med ökningen av antalet kluster kom behovet av automatisk uppdatering (den tidigaste lösningen var att lägga skriptet i Git, uppdatera det med cron och köra det);
  • ett liknande skript krävdes för Prometheus (install-prometheus.sh), men det är anmärkningsvärt för det faktum att det kräver mycket mer indata, såväl som deras lagring (på ett bra sätt - centraliserat och i ett kluster), och vissa data (lösenord) kan genereras automatiskt:

    Utöka och komplettera Kubernetes (recension och videorapport)

  • risken att rulla ut något fel till ett växande antal kluster växte hela tiden, så vi insåg att installatörer (dvs två skript: för Ingress och Prometheus) iscensättning behövdes (flera grenar i Git, flera crons för att uppdatera dem i motsvarande: stabila eller testkluster);
  • с kubectl apply det har blivit svårt att arbeta med eftersom det inte är deklarativt och bara kan skapa objekt, men inte fatta beslut om deras status/ta bort dem;
  • Vi saknade några funktioner som vi inte alls hade implementerat vid den tiden:
    • full kontroll över resultatet av klusteruppdateringar,
    • automatisk bestämning av vissa parametrar (indata för installationsskript) baserat på data som kan erhållas från klustret (upptäckt),
    • dess logiska utveckling i form av kontinuerlig upptäckt.

Vi implementerade all denna samlade erfarenhet inom ramen för vårt andra projekt - addon-operatör.

Addon-operatör

Den är baserad på den redan nämnda skal-operatören. Hela systemet ser ut så här:

Följande läggs till i skalmanöverkrokarna:

  • värdelagring,
  • Rordiagram,
  • komponent som övervakar värdelagret och - vid eventuella ändringar - ber Helm att rulla om diagrammet.

Utöka och komplettera Kubernetes (recension och videorapport)

Således kan vi reagera på en händelse i Kubernetes, starta en hook, och från denna hook kan vi göra ändringar i lagringen, varefter diagrammet kommer att laddas ner igen. I det resulterande diagrammet separerar vi uppsättningen krokar och diagrammet i en komponent, som vi kallar modul:

Utöka och komplettera Kubernetes (recension och videorapport)

Det kan finnas många moduler, och till dem lägger vi till globala krokar, en global värdebutik och en komponent som övervakar denna globala butik.

Nu, när något händer i Kubernetes, kan vi reagera på det med en global hook och ändra något i den globala butiken. Denna förändring kommer att märkas och kommer att leda till att alla moduler i klustret rullas ut:

Utöka och komplettera Kubernetes (recension och videorapport)

Detta schema uppfyller alla krav för att installera tillägg som angavs ovan:

  • Helm ansvarar för mallbildning och deklarativitet.
  • Problemet med automatisk uppdatering löstes med en global hook, som går till registret enligt ett schema och, om det ser en ny systemavbildning där, rullar den ut (dvs. "själv").
  • Lagring av inställningar i klustret implementeras med hjälp av ConfigMap, som innehåller primärdata för lagringarna (vid start laddas de in i lagringarna).
  • Problem med lösenordsgenerering, upptäckt och kontinuerlig upptäckt löstes med hjälp av krokar.
  • Staging uppnås tack vare taggar, som Docker stöder direkt.
  • Resultatet övervakas med hjälp av mätvärden som gör att vi kan förstå statusen.

Hela detta system är implementerat i form av en enda binär i Go, som kallas addon-operator. Detta gör att diagrammet ser enklare ut:

Utöka och komplettera Kubernetes (recension och videorapport)

Huvudkomponenten i detta diagram är en uppsättning moduler (markerad i grått nedan). Nu kan vi skriva en modul för det nödvändiga tillägget med lite ansträngning och vara säkra på att den kommer att installeras i varje kluster, kommer att uppdateras och svara på de händelser den behöver i klustret.

"Flant" använder addon-operatör på 70+ Kubernetes-kluster. Nuvarande status - alfaversion. Nu förbereder vi dokumentation för att släppa betan, men för närvarande i förvaret exempel tillgängliga, på basis av vilken du kan skapa ditt eget tillägg.

Var kan jag få tag i modulerna för addon-operator? Att publicera vårt bibliotek är nästa steg för oss, vi planerar att göra detta under sommaren.

Videor och bilder

Video från föreställningen (~50 minuter):

Presentation av rapporten:

PS

Andra rapporter på vår blogg:

Du kan också vara intresserad av följande publikationer:

Källa: will.com

Lägg en kommentar