Produktionsfärdiga bilder för k8s

Den här historien handlar om hur vi använder behållare i en produktionsmiljö, närmare bestämt Kubernetes. Artikeln ägnas åt att samla in mätvärden och loggar från containrar, samt att bygga bilder.

Produktionsfärdiga bilder för k8s

Vi är från fintechföretaget Exness som utvecklar tjänster för onlinehandel och fintechprodukter för B2B och B2C. Vår FoU har många olika team, utvecklingsavdelningen har 100+ anställda.

Vi representerar teamet som ansvarar för plattformen för våra utvecklare att samla in och köra kod. Vi är särskilt ansvariga för att samla in, lagra och rapportera mätvärden, loggar och händelser från applikationer. Vi driver för närvarande cirka tre tusen Docker-containrar i en produktionsmiljö, underhåller vår 50 TB stordatalagring och tillhandahåller arkitektoniska lösningar som är byggda kring vår infrastruktur: Kubernetes, Rancher och olika offentliga molnleverantörer. 

Vår motivation

Vad är det som brinner? Ingen kan svara. Var är härden? Det är svårt att förstå. När fattade det eld? Du kan ta reda på det, men inte direkt. 

Produktionsfärdiga bilder för k8s

Varför står vissa containrar medan andra har fallit? Vilken container var skyldig? Utsidan av behållarna är trots allt densamma, men inuti har var och en sin egen Neo.

Produktionsfärdiga bilder för k8s

Våra utvecklare är kompetenta killar. De gör bra tjänster som ger vinst till företaget. Men det finns misslyckanden när containrar med applikationer hamnar på avvägar. En behållare förbrukar för mycket CPU, en annan förbrukar nätverket, en tredje förbrukar I/O-operationer och den fjärde är helt oklart vad den gör med sockets. Allt faller och fartyget sjunker. 

Agenter

För att förstå vad som händer inuti beslutade vi att placera agenter direkt i containrar.

Produktionsfärdiga bilder för k8s

Dessa medel är begränsningsprogram som håller behållare i ett sådant tillstånd att de inte bryter sönder varandra. Agenter är standardiserade, och detta möjliggör ett standardiserat tillvägagångssätt för att serva containrar. 

I vårt fall måste agenter tillhandahålla loggar i standardformat, taggade och strypta. De bör också förse oss med standardiserade mått som är utbyggbara ur ett affärsapplikationsperspektiv.

Med agenter menas också verktyg för drift och underhåll som kan fungera i olika orkestreringssystem som stöder olika bilder (Debian, Alpine, Centos, etc.).

Slutligen måste agenter stödja enkel CI/CD som inkluderar Docker-filer. Annars kommer fartyget att falla isär, eftersom containrar kommer att börja levereras längs "krokiga" skenor.

Bygg process och målbildsenhet

För att hålla allt standardiserat och hanterbart måste någon form av standardbyggprocess följas. Därför bestämde vi oss för att samla behållare för behållare - det här är rekursion.

Produktionsfärdiga bilder för k8s

Här representeras behållarna av solida konturer. Samtidigt bestämde de sig för att lägga distributionssatser i dem så att "livet inte verkar som hallon." Varför detta gjordes kommer vi att förklara nedan.
 
Resultatet är ett byggverktyg – en versionsspecifik behållare som refererar till specifika distributionsversioner och specifika skriptversioner.

Hur använder vi det? Vi har en Docker Hub som innehåller en container. Vi speglar det inuti vårt system för att bli av med externa beroenden. Resultatet är en behållare märkt med gult. Vi skapar en mall för att installera alla distributioner och skript vi behöver i behållaren. Efter det sätter vi ihop en färdig att använda bild: utvecklare lägger in kod och några av sina egna speciella beroenden i den. 

Vad är bra med detta tillvägagångssätt? 

  • Först, fullständig versionskontroll av byggverktyg - bygg container-, skript- och distributionsversioner. 
  • För det andra har vi uppnått standardisering: vi skapar mallar, mellanliggande och färdiga bilder på samma sätt. 
  • För det tredje ger containrar oss portabilitet. Idag använder vi Gitlab, och imorgon byter vi till TeamCity eller Jenkins och vi kommer att kunna köra våra containrar på samma sätt. 
  • För det fjärde, minimera beroenden. Det var ingen slump att vi lade distributionspaket i behållaren, eftersom det gör att vi slipper ladda ner dem från Internet varje gång. 
  • För det femte har bygghastigheten ökat - närvaron av lokala kopior av bilder gör att du slipper slösa tid på nedladdning, eftersom det finns en lokal bild. 

Vi har med andra ord uppnått en kontrollerad och flexibel monteringsprocess. Vi använder samma verktyg för att bygga alla fullständiga versioner av containrar. 

Hur vår byggprocedur fungerar

Produktionsfärdiga bilder för k8s

Sammansättningen startas med ett kommando, processen exekveras i bilden (markerad i rött). Utvecklaren har en Docker-fil (markerad i gult), vi renderar den och ersätter variabler med värden. Och längs vägen lägger vi till sidhuvuden och sidfötter – det här är våra agenter. 

Header lägger till distributioner från motsvarande bilder. Och sidfoten installerar våra tjänster inuti, konfigurerar lanseringen av arbetsbelastning, loggning och andra agenter, ersätter entrypoint, etc. 

Produktionsfärdiga bilder för k8s

Vi funderade länge på om vi skulle installera en arbetsledare. Till slut bestämde vi oss för att vi behövde honom. Vi valde S6. Arbetsledaren tillhandahåller containerhantering: låter dig ansluta till den om huvudprocessen kraschar och tillhandahåller manuell hantering av containern utan att återskapa den. Loggar och mätvärden är processer som körs inuti behållaren. De behöver också kontrolleras på något sätt, och det gör vi med hjälp av en handledare. Slutligen tar S6 hand om hushållning, signalbehandling och andra uppgifter.

Eftersom vi använder olika orkestreringssystem, efter att ha byggt och kört, måste containern förstå vilken miljö den befinner sig i och agera efter situationen. Till exempel:
Detta gör att vi kan bygga en bild och köra den i olika orkestreringssystem, och den kommer att lanseras med hänsyn till detaljerna i detta orkestreringssystem.

 Produktionsfärdiga bilder för k8s

För samma behållare får vi olika processträd i Docker och Kubernetes:

Produktionsfärdiga bilder för k8s

Nyttolasten exekveras under övervakning av S6. Var uppmärksam på samlare och evenemang - det här är våra agenter som ansvarar för loggar och mätvärden. Kubernetes har dem inte, men Docker har det. Varför? 

Om vi ​​tittar på specifikationen för "podden" (nedan – Kubernetes pod), kommer vi att se att händelsebehållaren exekveras i en pod, som har en separat samlarbehållare som utför funktionen att samla in mätvärden och loggar. Vi kan använda funktionerna hos Kubernetes: köra behållare i en pod, i en enda process och/eller nätverksutrymme. Presentera faktiskt dina agenter och utför vissa funktioner. Och om samma behållare lanseras i Docker kommer den att få samma kapacitet som output, det vill säga att den kommer att kunna leverera loggar och mätvärden, eftersom agenterna kommer att lanseras internt. 

Mätvärden och loggar

Att leverera mätvärden och loggar är en komplex uppgift. Det finns flera aspekter på hennes beslut.
Infrastrukturen skapas för att utföra nyttolasten och inte för massleverans av stockar. Det vill säga att denna process måste utföras med minimala krav på behållarresurs. Vi strävar efter att hjälpa våra utvecklare: "Skaffa en Docker Hub-behållare, kör den och vi kan leverera loggarna." 

Den andra aspekten är att begränsa volymen av stockar. Om en ökning av volymen loggar inträffar i flera behållare (applikationen matar ut en stack-trace i en slinga), ökar belastningen på CPU, kommunikationskanaler och loggbehandlingssystem, och detta påverkar driften av värden som en hela och andra behållare på värden, ibland leder detta till att värden "faller". 

Den tredje aspekten är att det är nödvändigt att stödja så många metoder för insamling av mätvärden som möjligt direkt. Från att läsa filer och polla Prometheus-slutpunkt till att använda applikationsspecifika protokoll.

Och den sista aspekten är att minimera resursförbrukningen.

Vi valde en Go-lösning med öppen källkod som heter Telegraf. Detta är en universell kontakt som stöder mer än 140 typer av ingångskanaler (input plugins) och 30 typer av output kanaler (output plugins). Vi har färdigställt det och nu kommer vi att berätta hur vi använder det med Kubernetes som exempel. 

Produktionsfärdiga bilder för k8s

Låt oss säga att en utvecklare distribuerar en arbetsbelastning och Kubernetes får en begäran om att skapa en pod. Vid denna tidpunkt skapas automatiskt en behållare som heter Collector för varje pod (vi använder mutation webhook). Collector är vår agent. I början konfigurerar den här behållaren sig själv för att fungera med Prometheus och logginsamlingssystemet.

  • För att göra detta använder den podkommentarer, och beroende på innehållet skapar den, säg, en Prometheus-slutpunkt; 
  • Baserat på podspecifikationen och specifika behållarinställningar bestämmer den hur loggar ska levereras.

Vi samlar in loggar via Docker API: utvecklare behöver bara lägga dem i stdout eller stderr, och Collector kommer att reda ut det. Loggar samlas in i bitar med viss fördröjning för att förhindra eventuell överbelastning av värden. 

Mätvärden samlas in över arbetsbelastningsinstanser (processer) i containrar. Allt är taggat: namnområde, under och så vidare, och konverteras sedan till Prometheus-format – och blir tillgängligt för insamling (förutom loggar). Vi skickar även loggar, mätvärden och händelser till Kafka och vidare:

  • Loggar finns tillgängliga i Graylog (för visuell analys);
  • Loggar, mätvärden, händelser skickas till Clickhouse för långtidslagring.

Allt fungerar exakt likadant i AWS, bara vi byter ut Graylog mot Kafka med Cloudwatch. Vi skickar loggarna dit, och allt blir väldigt bekvämt: det är omedelbart klart vilket kluster och behållare de tillhör. Samma sak gäller för Google Stackdriver. Det vill säga, vårt schema fungerar både lokalt med Kafka och i molnet. 

Om vi ​​inte har Kubernetes med poddar är schemat lite mer komplicerat, men det fungerar på samma principer.

Produktionsfärdiga bilder för k8s

Samma processer exekveras inuti behållaren, de orkestreras med S6. Alla samma processer körs i samma container.

Som ett resultat,

Vi har skapat en komplett lösning för att bygga och lansera bilder, med alternativ för att samla in och leverera loggar och mätvärden:

  • Vi utvecklade ett standardiserat tillvägagångssätt för att montera bilder, och utifrån det utvecklade vi CI-mallar;
  • Datainsamlingsagenter är våra Telegraf-tillägg. Vi testade dem väl i produktionen;
  • Vi använder mutation webhook för att implementera behållare med agenter i baljor; 
  • Integrerad i Kubernetes/Ranchers ekosystem;
  • Vi kan köra samma containrar i olika orkestreringssystem och få det resultat vi förväntar oss;
  • Skapat en helt dynamisk containerhanteringskonfiguration. 

Medförfattare: Ilja Prudnikov

Källa: will.com

Lägg en kommentar