Productieklare afbeeldingen voor k8s

Dit verhaal gaat over hoe we containers gebruiken in een productieomgeving, specifiek Kubernetes. Het artikel is gewijd aan het verzamelen van statistieken en logboeken van containers, en aan het bouwen van afbeeldingen.

Productieklare afbeeldingen voor k8s

Wij zijn van het fintech-bedrijf Exness, dat diensten ontwikkelt voor online handelen en fintech-producten voor B2B en B2C. Onze R&D heeft veel verschillende teams, de ontwikkelingsafdeling heeft meer dan 100 medewerkers.

Wij vertegenwoordigen het team dat verantwoordelijk is voor het platform waarop onze ontwikkelaars code kunnen verzamelen en uitvoeren. Wij zijn in het bijzonder verantwoordelijk voor het verzamelen, opslaan en rapporteren van statistieken, logbestanden en gebeurtenissen uit applicaties. We exploiteren momenteel ongeveer drieduizend Docker-containers in een productieomgeving, onderhouden onze 50 TB big data-opslag en bieden architecturale oplossingen die zijn gebouwd rond onze infrastructuur: Kubernetes, Rancher en verschillende publieke cloudproviders. 

Onze motivatie

Wat brandt? Niemand kan antwoorden. Waar is de haard? Het is moeilijk te begrijpen. Wanneer vatte het vlam? Je kunt het ontdekken, maar niet meteen. 

Productieklare afbeeldingen voor k8s

Waarom staan ​​sommige containers overeind terwijl andere zijn gevallen? Welke container was de schuldige? De buitenkant van de containers is immers hetzelfde, maar van binnen heeft elke container zijn eigen Neo.

Productieklare afbeeldingen voor k8s

Onze ontwikkelaars zijn competente jongens. Ze leveren goede diensten die winst opleveren voor het bedrijf. Maar er zijn mislukkingen wanneer containers met applicaties op een dwaalspoor raken. De ene container verbruikt te veel CPU, de andere verbruikt het netwerk, een derde verbruikt I/O-bewerkingen en de vierde is volkomen onduidelijk wat deze met sockets doet. Het valt allemaal en het schip zinkt. 

Agenten

Om te begrijpen wat er binnen gebeurt, hebben we besloten agenten rechtstreeks in containers te plaatsen.

Productieklare afbeeldingen voor k8s

Deze agenten zijn containmentprogramma's die containers in een zodanige staat houden dat ze elkaar niet kapot maken. Agenten zijn gestandaardiseerd en dit maakt een gestandaardiseerde benadering van het onderhoud van containers mogelijk. 

In ons geval moeten agenten logboeken in een standaardformaat aanleveren, getagd en beperkt. Ze moeten ons ook gestandaardiseerde statistieken bieden die uitbreidbaar zijn vanuit het perspectief van bedrijfsapplicaties.

Agenten betekenen ook hulpprogramma's voor bediening en onderhoud die kunnen werken in verschillende orkestratiesystemen die verschillende images ondersteunen (Debian, Alpine, Centos, enz.).

Ten slotte moeten agenten eenvoudige CI/CD ondersteunen die Docker-bestanden bevatten. Anders valt het schip uit elkaar, omdat containers langs "scheve" rails worden afgeleverd.

Bouw proces en doelbeeldapparaat

Om alles gestandaardiseerd en beheersbaar te houden, moet er een soort standaard bouwproces worden gevolgd. Daarom hebben we besloten om containers per container te verzamelen - dit is recursie.

Productieklare afbeeldingen voor k8s

Hier worden de containers weergegeven door vaste contouren. Tegelijkertijd besloten ze er distributiekits in te stoppen, zodat ‘het leven niet op frambozen lijkt’. Waarom dit is gedaan leggen wij hieronder uit.
 
Het resultaat is een buildtool: een versiespecifieke container die verwijst naar specifieke distributieversies en specifieke scriptversies.

Hoe gebruiken we het? We hebben een Docker Hub die een container bevat. We spiegelen het binnen ons systeem om externe afhankelijkheden weg te nemen. Het resultaat is een geel gemarkeerde container. We maken een sjabloon om alle distributies en scripts die we nodig hebben in de container te installeren. Daarna stellen we een kant-en-klare afbeelding samen: ontwikkelaars plaatsen er code en enkele van hun eigen speciale afhankelijkheden in. 

Wat is er goed aan deze aanpak? 

  • Ten eerste, volledige versiecontrole van bouwtools: bouw container-, script- en distributieversies. 
  • Ten tweede hebben we standaardisatie bereikt: we creëren op dezelfde manier sjablonen, tussenliggende en gebruiksklare afbeeldingen. 
  • Ten derde geven containers ons draagbaarheid. Vandaag gebruiken we Gitlab, en morgen stappen we over naar TeamCity of Jenkins en kunnen we onze containers op dezelfde manier laten draaien. 
  • Ten vierde: het minimaliseren van afhankelijkheden. Het was geen toeval dat we distributiekits in de container stopten, omdat we hierdoor voorkomen dat we ze elke keer van internet moeten downloaden. 
  • Ten vijfde is de bouwsnelheid toegenomen: door de aanwezigheid van lokale kopieën van afbeeldingen kunt u voorkomen dat u tijd verspilt aan het downloaden, aangezien er een lokale afbeelding is. 

Met andere woorden: we hebben een gecontroleerd en flexibel montageproces gerealiseerd. We gebruiken dezelfde tools om containers met volledige versies te bouwen. 

Hoe onze bouwprocedure werkt

Productieklare afbeeldingen voor k8s

Met één commando wordt de assembly gestart, het proces wordt uitgevoerd in de afbeelding (rood gemarkeerd). De ontwikkelaar heeft een Docker-bestand (geel gemarkeerd), we renderen het en vervangen variabelen door waarden. En gaandeweg voegen we kop- en voetteksten toe - dit zijn onze agenten. 

Header voegt distributies toe van de overeenkomstige afbeeldingen. En footer installeert onze services erin, configureert de lancering van werklast, logboekregistratie en andere agenten, vervangt het toegangspunt, enz. 

Productieklare afbeeldingen voor k8s

We hebben er lang over nagedacht of we een toezichthouder moesten installeren. Uiteindelijk besloten we dat we hem nodig hadden. Wij kozen voor S6. De supervisor zorgt voor containerbeheer: hiermee kunt u verbinding maken als het hoofdproces crasht en zorgt voor handmatig beheer van de container zonder deze opnieuw te maken. Logboeken en statistieken zijn processen die in de container worden uitgevoerd. Ze moeten ook op de een of andere manier worden gecontroleerd, en dat doen we met de hulp van een supervisor. Ten slotte zorgt de S6 voor het huishouden, de signaalverwerking en andere taken.

Omdat we verschillende orkestratiesystemen gebruiken, moet de container na het bouwen en draaien begrijpen in welke omgeving hij zich bevindt en handelen naargelang de situatie. Bijvoorbeeld:
Dit stelt ons in staat één image te bouwen en deze in verschillende orkestratiesystemen uit te voeren, en het zal gelanceerd worden rekening houdend met de specifieke kenmerken van dit orkestratiesysteem.

 Productieklare afbeeldingen voor k8s

Voor dezelfde container krijgen we verschillende procesbomen in Docker en Kubernetes:

Productieklare afbeeldingen voor k8s

De payload wordt uitgevoerd onder toezicht van S6. Besteed aandacht aan verzamelaars en evenementen. Dit zijn onze agenten die verantwoordelijk zijn voor logboeken en statistieken. Kubernetes heeft ze niet, maar Docker wel. Waarom? 

Als we naar de specificatie van de “pod” (hierna: Kubernetes-pod) kijken, zullen we zien dat de gebeurtenissencontainer wordt uitgevoerd in een pod, die een aparte verzamelcontainer heeft die de functie vervult van het verzamelen van statistieken en logboeken. We kunnen gebruik maken van de mogelijkheden van Kubernetes: het draaien van containers in één pod, in één proces en/of netwerkruimte. Introduceer uw agenten daadwerkelijk en voer enkele functies uit. En als dezelfde container in Docker wordt gelanceerd, krijgt deze dezelfde mogelijkheden als de uitvoer, dat wil zeggen dat hij logboeken en statistieken kan leveren, aangezien de agenten intern worden gelanceerd. 

Statistieken en logboeken

Het leveren van statistieken en logboeken is een complexe taak. Er zijn verschillende aspecten aan haar beslissing.
De infrastructuur is gemaakt voor de uitvoering van de payload, en niet voor de massale levering van logs. Dat wil zeggen dat dit proces moet worden uitgevoerd met minimale vereisten voor containerresources. We streven ernaar onze ontwikkelaars te helpen: “Koop een Docker Hub-container, voer deze uit en wij kunnen de logs leveren.” 

Het tweede aspect is het beperken van het aantal logboeken. Als er in meerdere containers een toename van het aantal logbestanden optreedt (de applicatie voert een stack-trace in een lus uit), neemt de belasting van de CPU, de communicatiekanalen en het logverwerkingssysteem toe, en dit beïnvloedt de werking van de host als een hele en andere containers op de host, soms leidt dit tot het "vallen" van de host. 

Het derde aspect is dat het noodzakelijk is om zoveel mogelijk methoden voor het verzamelen van meetgegevens kant-en-klaar te ondersteunen. Van het lezen van bestanden en het pollen van Prometheus-endpoint tot het gebruik van applicatiespecifieke protocollen.

En het laatste aspect is het minimaliseren van het verbruik van hulpbronnen.

We kozen voor een open-source Go-oplossing genaamd Telegraf. Dit is een universele connector die meer dan 140 soorten ingangskanalen (input plug-ins) en 30 soorten uitgangskanalen (output plug-ins) ondersteunt. We hebben het afgerond en nu zullen we u vertellen hoe we het gebruiken met Kubernetes als voorbeeld. 

Productieklare afbeeldingen voor k8s

Stel dat een ontwikkelaar een werklast implementeert en Kubernetes een verzoek ontvangt om een ​​pod te maken. Op dit punt wordt voor elke pod automatisch een container met de naam Collector gemaakt (we gebruiken mutatiewebhook). Collector is onze agent. In het begin configureert deze container zichzelf om te werken met Prometheus en het logverzamelingssysteem.

  • Om dit te doen, gebruikt het pod-annotaties en creëert het, afhankelijk van de inhoud, bijvoorbeeld een Prometheus-eindpunt; 
  • Op basis van de podspecificatie en specifieke containerinstellingen beslist het hoe logboeken moeten worden aangeleverd.

We verzamelen logs via de Docker API: ontwikkelaars hoeven ze alleen maar in stdout of stderr te zetten, en Collector zal het uitzoeken. Logboeken worden met enige vertraging in delen verzameld om mogelijke overbelasting van de host te voorkomen. 

Metrische gegevens worden verzameld over werkbelastinginstanties (processen) in containers. Alles wordt getagd: naamruimte, onder, enzovoort, en vervolgens geconverteerd naar Prometheus-formaat - en wordt beschikbaar voor verzameling (behalve logbestanden). We sturen ook logs, statistieken en gebeurtenissen naar Kafka en verder:

  • Logboeken zijn beschikbaar in Graylog (voor visuele analyse);
  • Logboeken, statistieken en gebeurtenissen worden naar Clickhouse gestuurd voor langdurige opslag.

In AWS werkt alles precies hetzelfde, alleen vervangen we Graylog door Kafka door Cloudwatch. We sturen de logs daarheen en alles blijkt erg handig: het is meteen duidelijk tot welk cluster en welke container ze behoren. Hetzelfde geldt voor Google Stackdriver. Dat wil zeggen dat ons schema zowel on-premise met Kafka als in de cloud werkt. 

Als we geen Kubernetes met pods hebben, is het schema iets ingewikkelder, maar het werkt volgens dezelfde principes.

Productieklare afbeeldingen voor k8s

Dezelfde processen worden binnen de container uitgevoerd, ze worden georkestreerd met behulp van S6. Alle dezelfde processen worden in dezelfde container uitgevoerd.

Dientengevolge

We hebben een complete oplossing gecreëerd voor het bouwen en lanceren van afbeeldingen, met opties voor het verzamelen en leveren van logs en statistieken:

  • We ontwikkelden een gestandaardiseerde aanpak voor het samenstellen van afbeeldingen en op basis daarvan ontwikkelden we CI-sjablonen;
  • Agenten voor gegevensverzameling zijn onze Telegraf-extensies. We hebben ze goed getest in productie;
  • We gebruiken mutatiewebhook om containers met agenten in pods te implementeren; 
  • Geïntegreerd in het Kubernetes/Rancher-ecosysteem;
  • We kunnen dezelfde containers in verschillende orkestratiesystemen uitvoeren en het resultaat krijgen dat we verwachten;
  • Creëerde een volledig dynamische containerbeheerconfiguratie. 

Co-auteur: Ilja Prudnikov

Bron: www.habr.com

Voeg een reactie