Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Vandaag ben ik van plan om het te hebben over het schrijven van applicaties en wat de vereisten zijn voordat uw applicatie goed werkt in Kubernetes. Zodat er geen kopzorgen zijn bij de applicatie, zodat je er geen ‘krakjes’ omheen hoeft te verzinnen en bouwen – en alles werkt zoals Kubernetes zelf het bedoeld heeft.

Deze lezing maakt deel uit van "Slurm Nightschool op Kubernetes" Je kunt de open theoriecolleges van de Avondschool bekijken op YouTube, gegroepeerd in een afspeellijst. Voor degenen die liever tekst dan video verkiezen, hebben we dit artikel opgesteld.

Mijn naam is Pavel Selivanov, momenteel ben ik de leidende DevOps-ingenieur bij Mail.ru Cloud Solutions, we maken clouds, we maken management kubernetes enzovoort. Mijn taken omvatten nu assistentie bij de ontwikkeling, het uitrollen van deze clouds, het uitrollen van de applicaties die we schrijven en het direct ontwikkelen van de tools die we aan onze gebruikers leveren.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Ik doe DevOps, denk ik de afgelopen, waarschijnlijk drie jaar. Maar in principe doe ik nu waarschijnlijk al zo’n vijf jaar wat DevOps doet. Daarvoor was ik vooral bezig met administratieve zaken. Ik begon lang geleden met Kubernetes te werken - waarschijnlijk zijn er ongeveer vier jaar verstreken sinds ik ermee begon te werken.

Over het algemeen begon ik toen Kubernetes waarschijnlijk versie 1.3 was, en misschien 1.2 - toen het nog in de kinderschoenen stond. Nu staat het niet meer in de kinderschoenen - en het is duidelijk dat er in de markt een enorme vraag is naar ingenieurs die Kubernetes willen kunnen doen. En bedrijven hebben een zeer grote vraag naar zulke mensen. Daarom verscheen deze lezing feitelijk.

Als we spreken volgens het plan waar ik het over zal hebben, ziet het er zo uit, tussen haakjes staat het geschreven (TL;DR) - “te lang; niet lezen". Mijn presentatie vandaag zal uit eindeloze lijsten bestaan.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Eigenlijk houd ik zelf niet van zulke presentaties als ze gemaakt worden, maar dit is zo’n onderwerp dat ik er bij het voorbereiden van deze presentatie simpelweg niet goed achter kwam hoe ik deze informatie anders moest ordenen.

Omdat deze informatie over het algemeen “ctrl+c, ctrl+v” is, afkomstig uit onder andere onze Wiki in de DevOps-sectie, waar we vereisten voor ontwikkelaars hebben geschreven: “jongens, zodat we uw applicatie lanceren in Kubernetes, het zou zo moeten zijn."

Daarom bleek de presentatie zo’n grote lijst te zijn. Sorry. Ik zal proberen zoveel mogelijk te vertellen, zodat het indien mogelijk niet saai wordt.

Waar we nu naar gaan kijken:

  • dit zijn in de eerste plaats logboeken (applicatielogboeken?), wat ermee te doen in Kubernetes, wat ermee te doen, wat ze zouden moeten zijn;
  • wat te doen met configuraties in Kubernetes, wat zijn de beste en slechtste manieren om een ​​applicatie voor Kubernetes te configureren;
  • Laten we het hebben over wat toegankelijkheidscontroles in het algemeen zijn en hoe ze eruit zouden moeten zien;
  • laten we het hebben over wat een sierlijke afsluiting is;
  • laten we het nog eens over hulpbronnen hebben;
  • Laten we het onderwerp gegevensopslag nogmaals bespreken;
  • en aan het einde zal ik je vertellen wat de term deze mysterieuze cloud-native applicatie is. Cloudnativeness, als bijvoeglijk naamwoord van deze term.

Logboeken

Ik stel voor om te beginnen met de logboeken - met waar deze logboeken in Kubernetes moeten worden geplaatst. Nu heb je een applicatie in Kubernetes gelanceerd. Volgens de klassiekers schreven applicaties voorheen altijd ergens in een bestand logs. Slechte applicaties schreven logbestanden naar een bestand in de homedirectory van de ontwikkelaar die de applicatie lanceerde. Goede applicaties schreven logs ergens in een bestand /var/log.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Dienovereenkomstig hadden goede beheerders bovendien een aantal dingen in hun infrastructuur geconfigureerd die deze logs konden roteren - dezelfde rsyslog, die naar deze logs kijkt en wanneer er iets mee gebeurt, zijn het er veel, het maakt back-upkopieën en plaatst de logs daar , verwijdert oude bestanden, meer dan een week, zes maanden en nog wat meer. In theorie zouden we voorzieningen moeten hebben zodat simpelweg omdat de applicatie logs schrijft, de ruimte op de productieservers (gevechtsservers?) niet opraakt. En dienovereenkomstig stopte de hele productie niet vanwege de houtblokken.

Wanneer we naar de wereld van Kubernetes verhuizen en daar hetzelfde uitvoeren, is het eerste waar je op kunt letten het feit dat mensen, terwijl ze logs in een bestand schreven, deze blijven schrijven.

Het blijkt dat als we het over Kubernetes hebben, de juiste plaats om ergens vanuit een docker-container logs te schrijven, simpelweg is om ze vanuit de applicatie naar de zogenaamde Stdout/Stderr te schrijven, dat wil zeggen de standaarduitvoerstromen van het besturingssysteem, standaardfout uitgang. Dit is in principe de meest correcte, eenvoudigste en meest logische manier om logs in Docker en specifiek in Kubernetis te zetten. Want als jouw applicatie logs naar Stdout/Stderr schrijft, dan is het aan Docker en de Kubernetes add-on om te beslissen wat ze met deze logs gaan doen. Docker bouwt zijn speciale bestanden standaard in JSON-formaat.

Hier rijst de vraag: wat gaat u nu doen met deze logboeken? De eenvoudigste manier is duidelijk: we hebben de mogelijkheid om dit te doen kubectl logs en kijk naar deze logs van deze “pods”. Maar waarschijnlijk is dit geen erg goede optie - er moet iets anders met de logboeken worden gedaan.

Laten we het voor nu, nu we het onderwerp logs hebben aangestipt, tegelijkertijd hebben over zoiets als logs eruit zouden moeten zien. Dat wil zeggen dat dit niet direct van toepassing is op Kubernetes, maar als we gaan nadenken over wat we met logs moeten doen, zou het goed zijn om hier ook over na te denken.

We hebben een soort tool nodig, op een minnelijke manier, die de logbestanden die onze havenarbeider in zijn bestanden stopt, ergens naartoe stuurt. Over het algemeen lanceren we meestal een soort agent binnen Kubernetes in de vorm van een DaemonSet - een logboekverzamelaar, die eenvoudigweg wordt verteld waar de logboeken die Docker verzamelt zich bevinden. En deze verzamelagent neemt ze gewoon mee, ontleedt ze misschien zelfs op de een of andere manier onderweg, verrijkt ze misschien met wat extra meta-informatie en stuurt ze uiteindelijk ergens heen om ze op te slaan. Variaties zijn daar al mogelijk. De meest voorkomende is waarschijnlijk Elasticsearch, waar u logs kunt opslaan en ze daar gemakkelijk kunt ophalen. Maak vervolgens met behulp van een verzoek, bijvoorbeeld met behulp van Kibana, grafieken op basis daarvan, bouw waarschuwingen op basis daarvan, enzovoort.

Het belangrijkste idee, ik wil het nog een keer herhalen, is dat binnen Docker, en vooral binnen Kubernetes, het opslaan van je logs in een bestand een heel slecht idee is.

Omdat het in de eerste plaats moeilijk is om de logboeken in de container in een bestand te krijgen. Je moet eerst de container ingaan, daar uitvoeren en dan naar de logs kijken. Het volgende punt is dat als je logbestanden in een bestand hebt, de containers meestal een minimalistische omgeving hebben en er geen hulpprogramma's zijn die normaal gesproken nodig zijn voor normaal werk met logs. Begraaf ze, bekijk ze, open ze in een teksteditor. Het volgende moment is wanneer we logbestanden in een bestand in een container hebben. Als deze container wordt verwijderd, begrijpt u, zullen de logbestanden daarmee ook sterven. Dienovereenkomstig betekent elke herstart van de container dat er geen logbestanden meer zijn. Nogmaals, slechte optie.

En het laatste punt is dat je in containers meestal je applicatie hebt, en dat is alles: dit is meestal het enige actieve proces. Er wordt helemaal niet gesproken over enig proces dat bestanden met uw logs zou roteren. Zodra de logs naar een bestand worden geschreven, betekent dit dat, neem me niet kwalijk, we de productieserver beginnen te verliezen. Omdat ze in de eerste plaats moeilijk te vinden zijn, niemand ze volgt en niemand ze controleert - dienovereenkomstig groeit het bestand eindeloos totdat de ruimte op de server simpelweg opraakt. Daarom zeg ik nogmaals dat inloggen in Docker, vooral in Kubernetes, op een bestand een slecht idee is.

Het volgende punt, hier wil ik het hier nog eens over hebben - aangezien we het over het onderwerp logs hebben, zou het goed zijn om te praten over hoe logs eruit moeten zien om het gemakkelijk te maken om ermee te werken. Zoals ik al zei, het onderwerp heeft niet direct betrekking op Kubernetes, maar het heeft wel een zeer goede relatie met het onderwerp DevOps. Over het onderwerp ontwikkelingscultuur en vriendschap tussen deze twee verschillende afdelingen - Dev en Ops, zodat iedereen zich op zijn gemak voelt.

Dit betekent dat logs tegenwoordig idealiter in JSON-formaat geschreven zouden moeten worden. Als je zelf een onbegrijpelijke applicatie hebt, die logs in onbegrijpelijke formaten schrijft omdat je een soort print of iets dergelijks invoegt, dan is het tijd om een ​​soort raamwerk te googlen, een soort wrapper waarmee je normale loggen kunt implementeren; schakel daar logboekparameters in JSON in, omdat JSON een eenvoudig formaat is en het parseren ervan eenvoudig is.

Als uw JSON volgens bepaalde criteria niet werkt, en niemand weet wat, schrijf dan op zijn minst logs in een formaat dat kan worden geparseerd. Hier is het eerder de moeite waard om na te denken over het feit dat, bijvoorbeeld, als je een aantal containers of alleen processen met nginx draait, en elk zijn eigen loginstellingen heeft, het waarschijnlijk erg lastig voor je zal zijn om ontleed ze. Omdat je voor elke nieuwe nginx-instantie je eigen parser moet schrijven, omdat ze logs anders schrijven. Nogmaals, het was waarschijnlijk de moeite waard om erover na te denken om ervoor te zorgen dat al deze nginx-instanties dezelfde logconfiguratie hadden en al hun logs absoluut uniform schreven. Hetzelfde geldt voor absoluut alle toepassingen.

Uiteindelijk wil ik ook olie op het vuur gooien dat, idealiter, logboeken met meerdere regels moeten worden vermeden. Het punt is: als je ooit met logboekverzamelaars hebt gewerkt, dan heb je hoogstwaarschijnlijk gezien wat ze je beloven, dat ze met meerregelige logboeken kunnen werken, weten hoe ze deze moeten verzamelen, enzovoort. Naar mijn mening kan geen enkele verzamelaar tegenwoordig meerregelige logs normaal, volledig en zonder fouten verzamelen. Op een menselijke manier, zodat het handig en foutloos is.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Maar stacktrace bestaat altijd uit logboeken met meerdere regels en hoe u deze kunt vermijden. De vraag hier is dat een log een registratie is van een gebeurtenis, en dat stactrace eigenlijk geen log is. Als we logbestanden verzamelen en deze ergens in Elasticsearch plaatsen en er vervolgens grafieken uit trekken, en enkele rapporten van gebruikersactiviteit op uw site samenstellen, betekent dit dat er iets onverwachts gebeurt, een onverwerkte situatie in uw applicatie, als u een stacktrace krijgt. En het is zinvol om automatisch een stacktrace ergens naar een systeem te uploaden dat ze kan volgen.

Dit is software (dezelfde Sentry) die speciaal is gemaakt om met stacktrace te werken. Het kan onmiddellijk geautomatiseerde taken aanmaken, deze aan iemand toewijzen, waarschuwen wanneer er stacttraces optreden, deze stacttraces op één type groeperen, enzovoort. In principe heeft het niet veel zin om over stactraces te praten als we het over logs hebben, omdat dit tenslotte verschillende dingen zijn met verschillende doeleinden.

Configuratie

Vervolgens praten we over configuratie in Kubernetes: wat ermee te doen en hoe applicaties binnen Kubernetes geconfigureerd moeten worden. Over het algemeen zeg ik meestal dat Docker niet over containers gaat. Iedereen weet dat Docker over containers gaat, zelfs degenen die niet veel met Docker hebben gewerkt. Ik herhaal: Docker gaat niet over containers.

Docker gaat naar mijn mening over standaarden. En voor vrijwel alles bestaan ​​standaarden: standaarden voor het bouwen van je applicatie, standaarden voor het installeren van je applicatie.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

En dit ding - we gebruikten het eerder, het werd vooral populair met de komst van containers - dit ding heet ENV-variabelen (omgeving), dat wil zeggen omgevingsvariabelen die zich in je besturingssysteem bevinden. Dit is over het algemeen een ideale manier om uw applicatie te configureren, want als u applicaties heeft in JAVA, Python, Go, Perl, God verhoede, en ze allemaal de databasehost, databasegebruiker en databasewachtwoordvariabelen kunnen lezen, dan is dit ideaal. Je hebt applicaties in vier verschillende talen op dezelfde manier in het databaseplan geconfigureerd. Er zijn geen verschillende configuraties meer.

Alles kan worden geconfigureerd met ENV-variabelen. Als we het over Kubernetes hebben, is er een geweldige manier om ENV-variabelen rechtstreeks binnen Deployment te declareren. Dienovereenkomstig, als we het hebben over geheime gegevens, kunnen we geheime gegevens van ENV-variabelen (wachtwoorden voor databases, enz.) onmiddellijk naar een geheim pushen, een geheim cluster maken en in de ENV-beschrijving in Implementatie aangeven dat we niet rechtstreeks declareren de waarde van deze variabele en de waarde van deze databasewachtwoordvariabele worden uit het geheim gelezen. Dit is standaard Kubernetes-gedrag. En dit is de meest ideale optie om uw applicaties te configureren. Alleen op codeniveau geldt dit opnieuw voor ontwikkelaars. Als je DevOps bent, kun je vragen: “Jongens, leer je applicatie alsjeblieft omgevingsvariabelen te lezen. En we zullen allemaal gelukkig zijn."

Als iedereen in het bedrijf dezelfde omgevingsvariabelen leest, is dat geweldig. Zodat het niet gebeurt dat sommigen wachten op de postgres-database, anderen wachten op de databasenaam, anderen wachten op iets anders, anderen wachten op een of andere dbn, zodat er dienovereenkomstig uniformiteit is.

Het probleem ontstaat als je zoveel omgevingsvariabelen hebt dat je Deployment gewoon opent - en er zijn vijfhonderd regels met omgevingsvariabelen. In dit geval ben je simpelweg de omgevingsvariabelen ontgroeid en hoef je jezelf niet langer te martelen. In dit geval zou het zinvol zijn om configs te gaan gebruiken. Dat wil zeggen: train uw toepassing om configuraties te gebruiken.

De enige vraag is dat de configuraties niet zijn wat je denkt. Config.pi is geen configuratie die handig in gebruik is. Of een configuratie in je eigen formaat, alternatief begaafd - dit is ook niet de configuratie die ik bedoel.

Waar ik het over heb is configuratie in acceptabele formaten, dat wil zeggen dat veruit de meest populaire standaard de .yaml-standaard is. Het is duidelijk hoe je het moet lezen, het is voor mensen leesbaar, het is duidelijk hoe je het vanuit de applicatie moet lezen.

Zo kun je naast YAML bijvoorbeeld ook JSON gebruiken, parseren is ongeveer net zo handig als YAML als het gaat om het van daaruit lezen van de applicatieconfiguratie. Het is merkbaar lastiger voor mensen om te lezen. Je kunt het formaat a la ini proberen. Vanuit menselijk oogpunt is het best handig om te lezen, maar het kan lastig zijn om het automatisch te verwerken, in die zin dat als je ooit je eigen configuraties wilt genereren, het ini-formaat misschien al onhandig is om te genereren.

Maar hoe dan ook, welk formaat je ook kiest, het punt is dat het vanuit Kubernetes-oogpunt erg handig is. U kunt uw volledige configuratie in Kubernetes plaatsen, in de ConfigMap. En neem dan deze configuratiemap en vraag of deze in uw pod in een specifieke map moet worden gemount, waar uw toepassing de configuratie uit deze configuratiemap zal lezen alsof het slechts een bestand is. Dit is in feite wat goed is om te doen als u veel configuratie-opties in uw applicatie heeft. Of het is gewoon een soort complexe structuur, er is nesting.

Als u een configmap heeft, kunt u uw applicatie heel goed leren om bijvoorbeeld automatisch wijzigingen bij te houden in het bestand waarin de configmap is aangekoppeld, en ook uw applicatie automatisch opnieuw te laden wanneer de configuratie verandert. Dit zou over het algemeen een ideale optie zijn.

Nogmaals, ik heb hier al over gesproken: geheime informatie staat niet in de configuratiemap, geheime informatie zit niet in variabelen, geheime informatie zit niet in geheimen. Van daaruit verbindt u deze geheime informatie met diplomatie. Meestal slaan we alle beschrijvingen van Kubernetes-objecten, implementaties, configuratiekaarten en services op in git. Dienovereenkomstig is het een slecht idee om het wachtwoord in de database in git te plaatsen, zelfs als het jouw git is, die je intern in het bedrijf hebt. Omdat git op zijn minst alles onthoudt en het simpelweg verwijderen van wachtwoorden daar niet zo eenvoudig is.

Gezondheids controle

Het volgende punt is dit ding genaamd Health check. Over het algemeen controleert een Health check eenvoudigweg of uw applicatie werkt. Tegelijkertijd hebben we het meestal over bepaalde webapplicaties, waarvoor dit vanuit het oogpunt van de gezondheidscontrole (het is beter om hier en verder niet te vertalen) een speciale URL zal zijn, die ze verwerken als een standaard, dat doen ze meestal /health.

Bij het openen van deze URL zegt onze applicatie daarom "ja, oké, alles gaat goed met mij, 200" of "nee, alles gaat niet goed met mij, zo'n 500." Dienovereenkomstig, als onze applicatie geen http is, geen webapplicatie, hebben we het nu over een soort daemon, we kunnen uitzoeken hoe we gezondheidscontroles kunnen uitvoeren. Dat wil zeggen, het is niet nodig, als de applicatie niet http is, dan werkt alles zonder een gezondheidscontrole en dit kan op geen enkele manier worden gedaan. Je kunt periodiek wat informatie in het bestand bijwerken, je kunt een speciaal commando voor je daemon bedenken, zoals: daemon status, wat zal zeggen: "Ja, alles is in orde, de daemon werkt, hij leeft."

Waar is het voor? Het eerste en meest voor de hand liggende is waarschijnlijk waarom een ​​gezondheidscontrole nodig is: om te begrijpen of de applicatie werkt. Ik bedoel, het is gewoon stom, als het nu zover is, lijkt het erop dat het werkt, dus je kunt er zeker van zijn dat het werkt. En het blijkt dat de applicatie draait, de container draait, de instantie werkt, alles in orde is - en dan hebben de gebruikers al alle telefoonnummers van de technische ondersteuning afgesloten en zeggen ze "wat ben je..., jij in slaap gevallen, niets werkt.”

Een gezondheidscontrole is precies zo’n manier om vanuit het perspectief van de gebruiker te zien of het werkt. Eén van de methoden. Laten we het zo zeggen. Vanuit het oogpunt van Kubernetes is dit ook een manier om te begrijpen wanneer de applicatie start, omdat we begrijpen dat er een verschil is tussen het moment waarop de container werd gelanceerd, gemaakt en gestart, en wanneer de applicatie rechtstreeks in deze container werd gelanceerd. Want als we een gemiddelde Java-toepassing nemen en deze in het dock proberen te starten, kan deze gedurende veertig seconden, of zelfs een minuut, of zelfs tien, prima starten. In dit geval kunt u op zijn minst op de poorten kloppen, daar zal hij niet antwoorden, dat wil zeggen dat hij nog niet klaar is om verkeer te ontvangen.

Nogmaals, met behulp van een gezondheidscontrole en met behulp van het feit dat we hier aan de slag gaan, kunnen we in Kubernetes begrijpen dat niet alleen een container in de applicatie is gestegen, maar dat de applicatie zelf is gestart, deze reageert al op de gezondheidscontrole, wat betekent dat we verkeer daarheen kunnen sturen.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Waar ik het nu over heb heet Readiness/Liveness-tests binnen Kubernetes; dienovereenkomstig zijn onze gereedheidstests verantwoordelijk voor de beschikbaarheid van de applicatie in balancering. Dat wil zeggen, als er gereedheidstests worden uitgevoerd in de applicatie, dan is alles in orde, het clientverkeer gaat naar de applicatie. Als er geen gereedheidstests worden uitgevoerd, neemt de applicatie eenvoudigweg niet deel, neemt deze specifieke instantie niet deel aan de balancering, wordt deze uit de balancering verwijderd en stroomt er geen clientverkeer. Daarom zijn Liveness-tests binnen Kubernetes nodig, zodat de applicatie, als deze vastloopt, opnieuw kan worden opgestart. Als de liveness test niet werkt voor een applicatie die in Kubernetes is gedeclareerd, dan wordt de applicatie niet zomaar uit de balancering gehaald, maar opnieuw opgestart.

En hier is een belangrijk punt dat ik graag wil noemen: vanuit praktisch oogpunt wordt de gereedheidstest doorgaans vaker gebruikt en vaker nodig dan de liveness-test. Dat wil zeggen: simpelweg gedachteloos zowel gereedheids- als liveheidstests verklaren, omdat Kubernetes dat kan, en laten we alles gebruiken wat het kan, is geen goed idee. Ik zal uitleggen waarom. Omdat punt nummer twee bij het testen is dat het een goed idee zou zijn om de onderliggende service in uw gezondheidscontroles te controleren. Dit betekent dat als u een webapplicatie heeft, bepaalde informatie vrijkomt, die deze op zijn beurt uiteraard ergens vandaan moet halen. In een database bijvoorbeeld. Welnu, het slaat de informatie die in deze REST API binnenkomt op in dezelfde database. Als uw healthcheck vervolgens eenvoudigweg reageert als gecontacteerd met slashhealth, zegt de applicatie "200, oké, alles is in orde", en tegelijkertijd is de database van uw applicatie ontoegankelijk, en zegt de healthcheck-applicatie "200, oké, alles is in orde". ” - Dit is een slechte gezondheidscontrole. Dit is niet hoe het zou moeten werken.

Dat wil zeggen, uw aanvraag, als er een verzoek om gaat /health, het antwoordt niet alleen maar "200, oké", het gaat bijvoorbeeld eerst naar de database, probeert er verbinding mee te maken, doet daar iets heel basaals, zoals er een selecteren, controleert gewoon of er een verbinding is in de database database en u kunt de database bevragen. Als dit allemaal is gelukt, is het antwoord ‘200, oké’. Als dit niet lukt, wordt er aangegeven dat er een fout is opgetreden en dat de database niet beschikbaar is.

Daarom keer ik in dit verband opnieuw terug naar de Readiness/Liveness-tests - waarom je hoogstwaarschijnlijk een readiness-test nodig hebt, maar dat er sprake is van een liveness-test. Want als je health checks precies beschrijft zoals ik net zei, dan zal blijken dat deze niet beschikbaar zijn in het instancegedeelteв или со всех instancein een database bijvoorbeeld. Toen u een gereedheidstest uitvoerde, begonnen onze gezondheidscontroles te mislukken, en dienovereenkomstig zijn alle applicaties waarvan de database niet toegankelijk is eenvoudigweg uitgeschakeld en blijven ze in feite hangen in een verwaarloosde staat en wachten tot hun databases zijn hersteld. werk.

Als we een liveness-test hebben aangekondigd, stel je dan voor dat onze database kapot is en in jouw Kubernetes begint de helft van alles opnieuw op te starten omdat de liveness-test mislukt. Dit betekent dat u opnieuw moet opstarten. Dit is helemaal niet wat je wilt, ik heb zelfs persoonlijke ervaring in de praktijk gehad. We hadden een chatapplicatie die in JS was geschreven en in een Mongo-database werd ingevoerd. En het probleem was dat we aan het begin van mijn werk met Kubernetes de gereedheid en levendigheid van tests beschreven op basis van het principe dat Kubernetes het kan, dus we zullen het gebruiken. Dienovereenkomstig werd Mongo op een gegeven moment een beetje "saai" en begon het monster te falen. Dienovereenkomstig begonnen de peulen, volgens de regentest, te "doden".

Zoals je begrijpt, is dit een chat als ze worden "vermoord", dat wil zeggen dat er veel verbindingen van klanten aan hangen. Ze worden ook "gedood" - nee, geen klanten, alleen verbindingen - niet allemaal tegelijkertijd, en vanwege het feit dat ze niet tegelijkertijd worden gedood, sommige eerder, andere later, beginnen ze niet op hetzelfde moment tijd. Bovendien kunnen we standaard willekeurig de starttijd van de applicatie niet elke keer met millisecondennauwkeurigheid voorspellen, dus doen ze het exemplaar voor exemplaar. Eén infospot gaat omhoog, wordt toegevoegd aan de balancering, alle klanten komen daar, die kan zo'n last niet aan, omdat hij alleen is, en er werken er grofweg een tiental, en hij valt. De volgende staat op, de hele last rust op hem, hij valt ook. Welnu, deze watervallen blijven maar doorgaan. Hoe dit uiteindelijk werd opgelost: we hoefden alleen maar het gebruikersverkeer naar deze applicatie strikt te stoppen, alle instanties te laten stijgen en vervolgens al het gebruikersverkeer in één keer te starten, zodat het al over alle tien instanties werd verdeeld.

Als deze liveness-test niet was aangekondigd, waardoor alles opnieuw zou moeten worden opgestart, zou de applicatie het prima hebben afgehandeld. Maar alles van het balanceren is voor ons uitgeschakeld, omdat de databases ontoegankelijk zijn en alle gebruikers “eraf zijn gevallen”. Wanneer deze database vervolgens beschikbaar komt, wordt alles meegenomen in de balancering, maar hoeven applicaties niet opnieuw te starten en is het niet nodig om hier tijd en middelen aan te verspillen. Ze zijn er allemaal al, ze zijn klaar voor verkeer, dus het verkeer gaat gewoon open, alles is in orde - de applicatie is geïnstalleerd, alles blijft werken.

Daarom zijn de gereedheids- en liveness-tests verschillend, bovendien kun je theoretisch verschillende gezondheidscontroles uitvoeren, bijvoorbeeld één type radii, één type liv, en verschillende dingen controleren. Controleer tijdens gereedheidstests uw backends. En bij een liveness-test controleer je bijvoorbeeld niet vanuit het oogpunt dat de liveness-test over het algemeen slechts een applicatie is die reageert, als deze überhaupt kan reageren.

Omdat de levenstest over het algemeen plaatsvindt als we ‘vastzitten’. Er is een eindeloze lus gestart of iets anders - en er worden geen verzoeken meer verwerkt. Daarom is het logisch om ze zelfs te scheiden - en er een andere logica in te implementeren.

Over wat u moet antwoorden als u een test laat doen, als u een gezondheidscontrole doet. Het is gewoon echt pijn. Degenen die hiermee bekend zijn, zullen waarschijnlijk lachen - maar serieus, ik heb in mijn leven diensten gezien die in 200% van de gevallen "XNUMX" antwoordden. Dat wil zeggen, wie succesvol is. Maar tegelijkertijd schrijven ze in de hoofdtekst van het antwoord ‘die en die fout’.

Dat wil zeggen, de reactiestatus komt naar u toe - alles is succesvol. Maar tegelijkertijd moet je de hoofdtekst ontleden, omdat de hoofdtekst zegt: "Sorry, het verzoek eindigde met een fout" en dit is gewoon de realiteit. Ik heb dit in het echt gezien.

En zodat sommige mensen het niet grappig vinden, en anderen het erg pijnlijk vinden, is het nog steeds de moeite waard om je aan een eenvoudige regel te houden. Bij health checks, en in principe bij het werken met webapplicaties.

Als alles goed is gegaan, reageer dan met het tweehonderdste antwoord. In principe zal elk tweehonderdste antwoord bij u passen. Als je rassy heel goed leest en weet dat sommige antwoordstatussen anders zijn dan andere, antwoord dan met de juiste: 204, 5, 10, 15, wat dan ook. Als het niet erg goed is, dan gewoon ‘twee nul nul’. Als alles slecht gaat en de gezondheidscontrole niet reageert, antwoord dan met een vijfhonderdste. Nogmaals, als u begrijpt hoe u moet reageren, hoe verschillende antwoordstatussen van elkaar verschillen. Als u het niet begrijpt, kunt u via 502 reageren op een gezondheidscontrole als er iets misgaat.

Dit is een ander punt, ik wil nog even terugkomen op het controleren van de onderliggende services. Als u bijvoorbeeld begint met het controleren van alle onderliggende services die achter uw applicatie staan ​​- alles in het algemeen. Wat we krijgen vanuit het oogpunt van microservice-architectuur, is het concept van ‘lage koppeling’, dat wil zeggen wanneer uw services minimaal van elkaar afhankelijk zijn. Als een van hen uitvalt, blijven alle anderen zonder deze functionaliteit gewoon werken. Een deel van de functionaliteit werkt gewoon niet. Dienovereenkomstig, als je alle gezondheidscontroles aan elkaar koppelt, zul je eindigen met één ding dat in de infrastructuur valt, en omdat het viel, beginnen ook alle gezondheidscontroles van alle diensten te mislukken - en er is in het algemeen meer infrastructuur voor de volledige microservice-architectuur nr. Alles werd daar donker.

Daarom wil ik nogmaals herhalen dat u de onderliggende services moet controleren, zonder welke uw applicatie in honderd procent van de gevallen zijn werk niet kan doen. Dat wil zeggen, het is logisch dat als u een REST API heeft waarmee de gebruiker in de database opslaat of uit de database ophaalt, u bij het ontbreken van een database geen werk met uw gebruikers kunt garanderen.

Maar als uw gebruikers, wanneer u ze uit de database haalt, bovendien worden verrijkt met wat andere metadata, van een andere backend, die u invoert voordat u een antwoord naar de frontend stuurt - en deze backend is niet beschikbaar, betekent dit dat u uw antwoord zonder enig deel van de metadata.

Vervolgens hebben we ook een van de pijnlijke problemen bij het starten van applicaties.

In feite geldt dit niet alleen voor Kubernetes in het algemeen; het gebeurde zo dat de cultuur van een soort massaontwikkeling en DevOps in het bijzonder zich rond dezelfde tijd als Kubernetes begon te verspreiden. Daarom blijkt over het algemeen dat u uw applicatie netjes moet afsluiten zonder Kubernetes. Zelfs vóór Kubernetes deden mensen dit, maar met de komst van Kubernetes begonnen we er massaal over te praten.

Sierlijke afsluiting

Wat is Graceful Shutdown in het algemeen en waarom is het nodig? Dit gaat over wanneer uw applicatie om de een of andere reden crasht, wat u moet doen app stop - of u ontvangt bijvoorbeeld een signaal van het besturingssysteem, uw applicatie moet dit begrijpen en er iets aan doen. Het ergste scenario is natuurlijk wanneer uw aanvraag een SIGTERM ontvangt en zegt: "SIGTERM, laten we even volhouden, werken, niets doen." Dit is een ronduit slechte optie.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Een bijna net zo slechte optie is wanneer je applicatie een SIGTERM ontvangt en zegt: “ze zeiden segterm, dat betekent dat we eindigen, ik heb het niet gezien, ik ken geen gebruikersverzoeken, ik weet niet wat voor soort verzoeken waar ik nu aan werk, ze zeiden SIGTERM, dat betekent dat we eindigen " Dit is ook een slechte optie.

Welke optie is goed? Het eerste punt is om rekening te houden met de voltooiing van de operaties. Een goede optie is dat je server nog steeds rekening houdt met wat hij doet als hij een SIGTERM ontvangt.

SIGTERM is een zachte afsluiting, het is speciaal ontworpen, het kan worden onderschept op codeniveau, het kan worden verwerkt, zeg nu, wacht, we zullen eerst het werk afmaken dat we hebben, en dan zullen we afsluiten.

Vanuit Kubernetes-perspectief ziet het er zo uit. Wanneer we tegen een pod die in het Kubernetes-cluster draait zeggen: “stop alsjeblieft, ga weg”, of we worden opnieuw opgestart, of er vindt een update plaats wanneer Kubernetes de pods opnieuw maakt, stuurt Kubernetes precies hetzelfde SIGTERM-bericht naar de pod, wacht op enige tijd, en dit is de tijd dat hij wacht, het is ook geconfigureerd, er is zo'n speciale parameter in diploma's en deze heet Graceful ShutdownTimeout. Zoals je begrijpt heet het niet voor niets zo, en het is niet voor niets dat we het er nu over hebben.

Daar kunnen we specifiek zeggen hoe lang we moeten wachten tussen het moment dat we SIGTERM naar de applicatie sturen en het moment waarop we begrijpen dat de applicatie ergens gek op lijkt te zijn of "vastloopt" en niet zal eindigen - en we moeten stuur het SIGKILL, dat wil zeggen, voltooi zijn werk hard. Dat wil zeggen, dienovereenkomstig hebben we een soort daemon actief, deze verwerkt bewerkingen. We begrijpen dat onze handelingen waar de daemon aan werkt gemiddeld niet langer dan 30 seconden per keer duren. Dienovereenkomstig begrijpen we dat wanneer SIGTERM arriveert, onze daemon maximaal 30 seconden na SIGTERM kan eindigen. We schrijven het bijvoorbeeld 45 seconden voor het geval dat en zeggen dat SIGTERM. Daarna wachten we 45 seconden. In theorie zou de demon gedurende deze tijd zijn werk moeten hebben voltooid en een einde aan zichzelf moeten maken. Maar als het plotseling niet meer lukt, betekent dit dat het hoogstwaarschijnlijk vastloopt: het verwerkt onze verzoeken niet langer normaal. En binnen 45 seconden kun je hem veilig vastpinnen.

En hier kan in feite zelfs met 2 aspecten rekening worden gehouden. Begrijp allereerst dat als u een verzoek ontving, u er op de een of andere manier mee bent gaan werken en geen antwoord aan de gebruiker hebt gegeven, maar dat u bijvoorbeeld SIGTERM hebt ontvangen. Het is zinvol om het te verfijnen en een antwoord te geven aan de gebruiker. Dit is punt nummer één in dit verband. Punt nummer twee is dat als u uw eigen applicatie schrijft, u de architectuur over het algemeen zo bouwt dat u een verzoek voor uw applicatie ontvangt, u dan met wat werk begint, ergens bestanden begint te downloaden, een database downloadt, en dergelijke. Dat. Over het algemeen blijft uw verzoek van uw gebruiker een half uur hangen en wacht tot u hem beantwoordt - dan moet u hoogstwaarschijnlijk aan de architectuur werken. Dat wil zeggen, houd gewoon rekening met het gezonde verstand dat als uw activiteiten kort zijn, het zinvol is om SIGTERM te negeren en aan te passen. Als uw operaties lang duren, heeft het in dit geval geen zin om SIGTERM te negeren. Het is zinvol om de architectuur opnieuw te ontwerpen om zulke lange operaties te voorkomen. Zodat gebruikers niet alleen maar blijven hangen en wachten. Ik weet het niet, maak daar een soort websocket, maak reverse hooks die je server al naar de client zal sturen, of iets anders, maar dwing de gebruiker niet om een ​​half uur te blijven hangen en gewoon te wachten op een sessie totdat je antwoord hem. Omdat het onvoorspelbaar is waar het kan breken.

Wanneer uw toepassing wordt beëindigd, moet u een geschikte afsluitcode opgeven. Dat wil zeggen, als uw applicatie werd gevraagd om te sluiten, te stoppen en zichzelf normaal kon stoppen, dan hoeft u geen afsluitcode 1,5,255 enzovoort terug te geven. Alles wat geen zero-code is, tenminste in Linux-systemen, daar ben ik zeker van, wordt als niet succesvol beschouwd. Dat wil zeggen, er wordt van uitgegaan dat uw aanvraag in dit geval met een fout is geëindigd. Dienovereenkomstig, op een minnelijke manier, als uw aanvraag zonder fouten is voltooid, zegt u 0 op de uitvoer. Als uw toepassing om de een of andere reden mislukt, zegt u non-0 in de uitvoer. En met deze informatie kun je aan de slag.

En de laatste optie. Het is erg als uw gebruiker een verzoek verzendt en een half uur blijft hangen terwijl u het verwerkt. Maar in het algemeen zou ik ook willen zeggen wat de klant in het algemeen waard is. Het maakt niet uit of u een mobiele applicatie, front-end, etc. heeft. Houd er rekening mee dat de sessie van de gebruiker over het algemeen kan worden beëindigd en dat er van alles kan gebeuren. Een verzoek kan bijvoorbeeld te weinig worden verwerkt en er wordt geen antwoord teruggestuurd. Uw frontend of uw mobiele applicatie - elke frontend in het algemeen, laten we het zo zeggen - moet hier rekening mee houden. Als je met websockets werkt, is dit over het algemeen de ergste pijn die ik ooit heb gehad.

Wanneer de ontwikkelaars van sommige reguliere chats dat niet weten, blijkt dat de websocket kapot kan gaan. Voor hen, als er iets gebeurt bij de proxy, veranderen we gewoon de configuratie en wordt deze opnieuw geladen. Uiteraard worden in dit geval alle langlevende sessies verbroken. Ontwikkelaars komen naar ons toe rennen en zeggen: “Jongens, wat zijn jullie aan het doen, de chat is bij al onze klanten uitgevallen!” Wij zeggen tegen hen: “Wat ben je aan het doen? Kunnen uw klanten niet opnieuw verbinding maken? Ze zeggen: “Nee, we willen dat de sessies niet worden gescheurd.” Kortom, dit is eigenlijk onzin. Er moet rekening worden gehouden met de klantzijde. Vooral, zoals ik al zei, bij langlevende sessies zoals websockets kan het kapot gaan en moet je, ongemerkt door de gebruiker, dergelijke sessies opnieuw kunnen installeren. En dan is alles perfect.

Ресурсы

Eigenlijk vertel ik je hier gewoon een duidelijk verhaal. Opnieuw uit het echte leven. Het ziekste wat ik ooit over hulpbronnen heb gehoord.

In dit geval bedoel ik bronnen, een soort verzoeken, limieten die u kunt instellen op pods in uw Kubernetes-clusters. Het grappigste wat ik van een ontwikkelaar hoorde... Een van mijn collega-ontwikkelaars op een vorige werkplek zei ooit: "Mijn applicatie start niet in het cluster." Ik keek om te zien dat het niet op gang kwam, maar het paste niet in de middelen, of ze hadden heel kleine limieten gesteld. Kortom, de applicatie kan niet starten vanwege bronnen. Ik zeg: “Het start niet vanwege de middelen, jij bepaalt hoeveel je nodig hebt en stelt een adequate waarde in.” Hij zegt: “Wat voor middelen?” Ik begon hem uit te leggen dat Kubernetes, limieten voor verzoeken en bla, bla, bla moeten worden ingesteld. De man luisterde vijf minuten, knikte en zei: “Ik kwam hier om als ontwikkelaar te werken, ik wil niets weten over welke bronnen dan ook. Ik kwam hier om code te schrijven en dat was alles.” Het is zielig. Dit is een heel triest concept vanuit het perspectief van een ontwikkelaar. Vooral in de moderne wereld, om zo te zeggen, van progressieve devops.

Waarom zijn middelen überhaupt nodig? Er zijn 2 soorten bronnen in Kubernetes. Sommige worden verzoeken genoemd, andere limieten. Onder hulpmiddelen verstaan ​​we dat er in principe altijd slechts twee basisbeperkingen zijn. Dat wil zeggen, CPU-tijdslimieten en RAM-limieten voor een container die in Kubernetes draait.

Een limiet stelt een bovengrens aan de manier waarop een resource in uw toepassing kan worden gebruikt. Dat wil zeggen, als u 1 GB RAM binnen de limiet zegt, kan uw applicatie niet meer dan 1 GB RAM gebruiken. En als hij dit plotseling wil en probeert te doen, dan zal een proces genaamd oom killer, uit het geheugen, komen en uw applicatie doden - dat wil zeggen, het zal eenvoudigweg opnieuw opstarten. Applicaties worden niet opnieuw opgestart op basis van CPU. In termen van CPU: als een applicatie veel probeert te gebruiken, meer dan gespecificeerd in de limieten, wordt de CPU eenvoudigweg strikt geselecteerd. Dit leidt niet tot een herstart. Dit is de limiet - dit is de bovengrens.

En er is een verzoek. Een verzoek is hoe Kubernetes begrijpt hoe de knooppunten in uw Kubernetes-cluster worden gevuld met applicaties. Dat wil zeggen, een verzoek is een soort commit van uw aanvraag. Er staat wat ik wil gebruiken: "Ik zou graag willen dat je zoveel CPU en zoveel geheugen voor mij reserveert." Zo'n simpele analogie. Wat als we een knooppunt hebben met, ik weet het niet, in totaal 8 CPU's. En daar arriveert een pod, wiens verzoeken 1 CPU zeggen, wat betekent dat het knooppunt nog 7 CPU's over heeft. Dat wil zeggen dat zodra 8 pods bij dit knooppunt arriveren, die elk 1 CPU in hun verzoeken hebben, het knooppunt, alsof vanuit het oogpunt van Kubernetes, geen CPU meer heeft en er niet meer pods met verzoeken kunnen worden toegevoegd. gelanceerd op dit knooppunt. Als alle knooppunten geen CPU meer hebben, zal Kubernetes beginnen te zeggen dat er geen geschikte knooppunten in het cluster zijn om uw pods uit te voeren, omdat de CPU leeg is.

Waarom zijn verzoeken nodig en waarom denk ik dat er zonder verzoeken niets hoeft te worden gestart in Kubernetes? Laten we ons een hypothetische situatie voorstellen. Je start je applicatie zonder verzoeken, Kubernetes weet niet hoeveel van wat je hebt, naar welke knooppunten je het kunt pushen. Nou, hij duwt, schuift, schuift op de knooppunten. Op een gegeven moment zul je verkeer naar je applicatie krijgen. En een van de applicaties begint plotseling bronnen te gebruiken tot de limieten die hij heeft volgens de limieten. Het blijkt dat er een andere applicatie in de buurt is en deze heeft ook bronnen nodig. Het knooppunt begint feitelijk fysiek geen bronnen meer te hebben, bijvoorbeeld OP. Het knooppunt begint feitelijk fysiek zonder bronnen te komen te zitten, bijvoorbeeld Random Access Memory (RAM). Wanneer een knooppunt geen stroom meer heeft, reageert eerst de docker niet meer, dan de cubelet en vervolgens het besturingssysteem. Ze zullen gewoon bewusteloos raken en ALLES zal definitief stoppen met werken voor jou. Dat wil zeggen, dit zal ertoe leiden dat uw knooppunt vastloopt en dat u het opnieuw moet opstarten. Kortom: de situatie is niet erg goed.

En als je verzoeken hebt, zijn de limieten niet erg verschillend, althans niet vele malen meer dan de limieten of verzoeken, dan kun je zo'n normale, rationele vulling van applicaties hebben over de knooppunten van Kubernetes-clusters. Tegelijkertijd is Kubernetes zich er ongeveer van bewust hoeveel van wat het waar plaatst, hoeveel van wat waar wordt gebruikt. Dat wil zeggen, het is gewoon zo'n moment. Het is belangrijk om het te begrijpen. En het is belangrijk om te controleren of dit wordt aangegeven.

Data opslag

Ons volgende punt gaat over gegevensopslag. Wat moet je ermee doen en wat moet je in het algemeen doen met persistentie in Kubernetes?

Ik denk, nogmaals, binnen onze Avondschool, was er een onderwerp over de database in Kubernetes. En het lijkt mij dat ik zelfs ongeveer weet wat uw collega’s u vertelden toen hen werd gevraagd: “Is het mogelijk om een ​​database in Kubernetes te draaien?” Om de een of andere reden lijkt het mij dat je collega's je hadden moeten vertellen dat als je de vraag stelt of het mogelijk is om een ​​database in Kubernetes te draaien, dat onmogelijk is.

De logica hier is eenvoudig. Voor het geval dat, ik zal het nogmaals uitleggen: als je een heel coole kerel bent die een redelijk fouttolerant systeem van gedistribueerde netwerkopslag kan bouwen, begrijp dan hoe je een database in dit geval kunt inpassen, hoe cloud-native in containers zou moeten werken in een database in het algemeen. Hoogstwaarschijnlijk heeft u geen twijfel over hoe u het moet uitvoeren. Als je zo'n vraag hebt, en je wilt er zeker van zijn dat het zich allemaal ontvouwt en in de productie doodstaat en nooit valt, dan gebeurt dit niet. Met deze aanpak schiet je jezelf gegarandeerd in de voet. Het is dus beter om dat niet te doen.

Wat moeten we doen met de gegevens die onze applicatie wil opslaan, sommige foto's die gebruikers uploaden, sommige dingen die onze applicatie genereert tijdens de werking ervan, bij het opstarten bijvoorbeeld? Wat moet je ermee doen in Kubernetes?

Over het algemeen is Kubernetes idealiter, ja natuurlijk, zeer goed ontworpen en in eerste instantie bedoeld voor staatloze toepassingen. Dat wil zeggen, voor die applicaties die helemaal geen informatie opslaan. Dit is ideaal.

Maar de ideale optie bestaat natuurlijk niet altijd. Dus? Het eerste en eenvoudigste punt is om een ​​soort S3 te nemen, alleen niet een zelfgemaakt exemplaar, waarvan ook onduidelijk is hoe het werkt, maar van een of andere provider. Een goede, normale provider - en leer uw applicatie S3 gebruiken. Dat wil zeggen, wanneer uw gebruiker een bestand wil uploaden, zegt u "hier, upload het alstublieft naar S3." Als hij het wil ontvangen, zeg dan: "Hier is een link naar S3 terug en neem het vanaf hier over." Dit is ideaal.

Als deze ideale optie om een ​​of andere reden plotseling niet geschikt is, als je een applicatie hebt die je niet hebt geschreven, die je niet hebt ontwikkeld, of als het een vreselijke erfenis is, kan deze het S3-protocol niet gebruiken, maar moet hij werken met lokale mappen in lokale mappen. Neem iets min of meer eenvoudigs: implementeer Kubernetes. Dat wil zeggen, het lijkt mij een slecht idee om Ceph onmiddellijk af te schermen voor enkele minimale taken. Omdat Ceph natuurlijk goed en modieus is. Maar als je niet echt begrijpt wat je doet, kun je, als je eenmaal iets op Ceph hebt gezet, het daar heel gemakkelijk en simpelweg nooit meer uit krijgen. Omdat, zoals u weet, Ceph gegevens in zijn cluster opslaat in binaire vorm, en niet in de vorm van eenvoudige bestanden. Daarom, als het Ceph-cluster plotseling kapot gaat, is de kans groot dat u uw gegevens daar nooit meer vandaan zult halen.

Wij gaan een cursus Ceph geven, dat kan Maak uzelf vertrouwd met het programma en dien een aanvraag in.

Daarom is het beter om iets eenvoudigs te doen, zoals een NFS-server. Kubernetes kan ermee werken, u kunt een directory onder een NFS-server mounten - uw applicatie is net een lokale directory. Tegelijkertijd moet je natuurlijk begrijpen dat je opnieuw iets met je NFS moet doen, je moet begrijpen dat het soms ontoegankelijk kan worden en nadenken over de vraag wat je in dit geval gaat doen. Misschien moet er ergens een back-up van worden gemaakt op een aparte machine.

Het volgende punt waar ik het over had, is wat u moet doen als uw applicatie tijdens het gebruik enkele bestanden genereert. Wanneer het bijvoorbeeld start, genereert het een statisch bestand, dat gebaseerd is op bepaalde informatie die de applicatie pas ontvangt op het moment van opstarten. Wat een moment. Als er niet veel van dergelijke gegevens zijn, hoeft u zich helemaal geen zorgen te maken, installeer deze applicatie gewoon zelf en ga aan de slag. De enige vraag hier is wat, kijk. Heel vaak weten allerlei oudere systemen, zoals WordPress enzovoort, vooral met aangepaste slimme plug-ins, slimme PHP-ontwikkelaars vaak hoe ze het zo kunnen maken dat ze een soort bestand voor zichzelf genereren. Dienovereenkomstig genereert men één bestand, de tweede genereert een tweede bestand. Ze zijn verschillend. Het balanceren gebeurt eenvoudigweg bij toeval in het Kubernetes-cluster van de klant. Het blijkt dat ze bijvoorbeeld niet weten hoe ze moeten samenwerken. De ene geeft de ene informatie, de andere geeft de gebruiker andere informatie. Dit is iets dat je moet vermijden. Dat wil zeggen dat alles wat u start in Kubernetes gegarandeerd in meerdere instanties kan werken. Omdat Kubernetes een ontroerend iets is. Dienovereenkomstig kan hij alles verplaatsen, wanneer hij maar wil, zonder iemand te vragen. Daarom moet u hierop rekenen. Alles wat in één keer wordt gelanceerd, zal vroeg of laat mislukken. Hoe meer reserveringen u heeft, hoe beter. Maar nogmaals, ik zeg: als je een paar van dergelijke bestanden hebt, dan kun je ze direct onder je leggen, ze wegen een klein bedrag. Als er iets meer van zijn, moet u ze waarschijnlijk niet in de container duwen.

Ik zou willen zeggen dat er iets geweldigs in Kubernetes zit: je kunt volume gebruiken. In het bijzonder is er een volume van het type empty dir. Dat wil zeggen, het is gewoon zo dat Kubernetes automatisch een map aanmaakt in zijn servicemappen op de server waar u bent begonnen. En hij zal het je geven, zodat je het kunt gebruiken. Er is slechts één belangrijk punt. Dat wil zeggen dat uw gegevens niet in de container worden opgeslagen, maar op de host waarop u draait. Bovendien kan Kubernetes dergelijke lege mappen onder normale configuratie beheren en de maximale grootte ervan controleren en niet toestaan ​​dat deze wordt overschreden. Het enige punt is dat wat u in een lege map hebt geschreven, niet verloren gaat tijdens het opnieuw opstarten van de pod. Dat wil zeggen, als uw pod per ongeluk valt en weer opstaat, zal de informatie in de lege map nergens heen gaan. Hij kan het bij een nieuwe start weer gebruiken – en dat is goed. Als je pod ergens weggaat, dan vertrekt hij natuurlijk zonder gegevens. Dat wil zeggen: zodra de pod van het knooppunt waar deze met een lege map werd gestart, verdwijnt, wordt de lege map verwijderd.

Wat is er nog meer goed aan een lege map? Het kan bijvoorbeeld als cache worden gebruikt. Laten we ons voorstellen dat onze applicatie direct iets genereert, aan gebruikers geeft en dit gedurende een lange tijd doet. Daarom genereert de applicatie het bijvoorbeeld en geeft het aan gebruikers, en slaat het tegelijkertijd ergens op, zodat de volgende keer dat de gebruiker voor hetzelfde komt, het sneller zal zijn om het onmiddellijk gegenereerd te geven. Er kan aan Kubernetes worden gevraagd om een ​​lege map in het geheugen aan te maken. En dus kunnen uw caches over het algemeen razendsnel werken - in termen van schijftoegangssnelheid. Dat wil zeggen, je hebt een lege map in het geheugen, in het besturingssysteem wordt deze in het geheugen opgeslagen, maar voor jou, voor de gebruiker in de pod, lijkt het gewoon een lokale map. Je hebt de app niet nodig om specifiek magie te leren. U neemt uw bestand gewoon rechtstreeks in een map, maar in feite in het geheugen van het besturingssysteem. Ook qua Kubernetes is dit een erg handige feature.

Welke problemen heeft Minio? Het grootste probleem met Minio is dat om dit ding te laten werken, het ergens moet draaien, en dat er een soort bestandssysteem moet zijn, dat wil zeggen opslag. En hier komen we dezelfde problemen tegen als Ceph. Dat wil zeggen dat Minio zijn bestanden ergens moet opslaan. Het is gewoon een HTTP-interface voor uw bestanden. Bovendien is de functionaliteit duidelijk slechter dan die van Amazon's S3. Voorheen kon de gebruiker de gebruiker niet correct autoriseren. Voor zover ik weet kan het nu al buckets maken met verschillende autorisaties, maar nogmaals, het lijkt mij dat het grootste probleem op zijn minst het onderliggende opslagsysteem is.

Welke invloed heeft een lege map in het geheugen op de limieten? Heeft op geen enkele manier invloed op de grenzen. Het ligt in het geheugen van de host, en niet in het geheugen van uw container. Dat wil zeggen dat uw container de lege map in het geheugen niet ziet als onderdeel van het bezette geheugen. De gastheer ziet dit. Dienovereenkomstig, ja, vanuit het oogpunt van Kubernetes, zou het goed zijn om te begrijpen dat je, als je dit gaat gebruiken, een deel van je geheugen besteedt aan het leegmaken van dir. En begrijp daarom dat het geheugen niet alleen opraakt vanwege applicaties, maar ook omdat iemand naar deze lege mappen schrijft.

Cloudnativeiteit

En het laatste subonderwerp is wat Cloudnative is. Waarom is het nodig? Cloudnativeness enzovoort.

Dat wil zeggen, die applicaties die capabel en geschreven zijn om in een moderne cloudinfrastructuur te werken. Maar in feite heeft Cloudnative nog een ander dergelijk aspect. Dat dit niet alleen een applicatie is die rekening houdt met alle eisen van een moderne cloudinfrastructuur, maar ook weet hoe je met deze moderne cloudinfrastructuur moet werken, profiteer van de voor- en nadelen van het feit dat het in deze clouds werkt. Ga niet overboord en werk in de cloud, maar profiteer van de voordelen van werken in de cloud.

Vereisten voor het ontwikkelen van een applicatie in Kubernetes

Laten we Kubernetes als voorbeeld nemen. Uw applicatie draait in Kubernetes. Uw applicatie kan altijd, of beter gezegd de beheerders van uw applicatie, altijd een serviceaccount aanmaken. Dat wil zeggen, een account voor autorisatie in Kubernetes zelf op zijn server. Voeg daar enkele rechten toe die we nodig hebben. En u heeft vanuit uw applicatie toegang tot Kubernetes. Wat kun je op deze manier doen? Ontvang bijvoorbeeld vanuit de applicatie gegevens over waar uw andere applicaties en andere vergelijkbare instanties zich bevinden, en cluster op de een of andere manier bovenop Kubernetes, als daar behoefte aan is.

Nogmaals, we hadden onlangs letterlijk een zaak. We hebben één controller die de wachtrij bewaakt. En wanneer er nieuwe taken in deze wachtrij verschijnen, gaat deze naar Kubernetes - en binnen Kubernetes wordt een nieuwe pod gemaakt. Geeft deze pod een nieuwe taak en binnen het raamwerk van deze pod voert de pod de taak uit, stuurt een reactie naar de controller zelf, en de controller doet dan iets met deze informatie. Het voegt bijvoorbeeld een database toe. Dat is wederom een ​​pluspunt van het feit dat onze applicatie in Kubernetes draait. We kunnen de ingebouwde Kubernetes-functionaliteit zelf gebruiken om de functionaliteit van onze applicatie op de een of andere manier uit te breiden en handiger te maken. Dat wil zeggen, verberg geen magie over hoe je een applicatie start, hoe je een werker start. In Kubernetes stuur je eenvoudig een verzoek in de app als de applicatie in Python is geschreven.

Hetzelfde geldt als we verder gaan dan Kubernetes. We hebben onze Kubernetes ergens draaien - het is goed als het in een soort cloud staat. Nogmaals, we kunnen de mogelijkheden van de cloud zelf waar we actief zijn, gebruiken en moeten, denk ik, zelfs gebruik maken van de mogelijkheden van de cloud zelf. Van de elementaire dingen die de cloud ons biedt. Balanceren, dat wil zeggen dat we cloudbalancers kunnen maken en deze kunnen gebruiken. Dit is een direct voordeel van wat we kunnen gebruiken. Omdat cloudbalancering in de eerste plaats simpelweg op domme wijze de verantwoordelijkheid van ons wegneemt voor hoe het werkt en hoe het is geconfigureerd. Bovendien is het erg handig, omdat gewone Kubernetes kunnen worden geïntegreerd met clouds.

Hetzelfde geldt voor schaalvergroting. Reguliere Kubernetes kunnen integreren met cloudproviders. Weet hoe te begrijpen dat als het cluster geen knooppunten meer heeft, dat wil zeggen dat de knooppuntruimte op is, u moet toevoegen: Kubernetes zelf zal nieuwe knooppunten aan uw cluster toevoegen en er pods op gaan lanceren. Dat wil zeggen, wanneer uw lading komt, begint het aantal haarden toe te nemen. Wanneer de knooppunten in het cluster voor deze pods opraken, lanceert Kubernetes nieuwe knooppunten en dienovereenkomstig kan het aantal pods nog steeds toenemen. En het is erg handig. Dit is een directe kans om het cluster on-the-fly te schalen. Niet erg snel, in de zin dat het geen seconde duurt, het is meer een minuut om nieuwe knooppunten toe te voegen.

Maar vanuit mijn ervaring is dit nogmaals het coolste wat ik ooit heb gezien. Toen het Cloudnative-cluster schaalde op basis van het tijdstip van de dag. Het was een backend-service die werd gebruikt door mensen in de backoffice. Dat wil zeggen, ze komen om 9 uur naar hun werk, beginnen met inloggen op het systeem, en dienovereenkomstig begint het Cloudnative-cluster, waar het allemaal draait, te zwellen en nieuwe pods te lanceren zodat iedereen die naar het werk komt met de applicatie kan werken. Als ze om 8 of 6 uur het werk verlaten, merken de Kubernetes-clusters dat niemand de applicatie meer gebruikt en beginnen ze te krimpen. Besparingen tot 30 procent zijn gegarandeerd. Het werkte destijds bij Amazon; in die tijd was er niemand in Rusland die het zo goed kon.

Ik zeg het je eerlijk: de besparingen bedragen 30 procent, simpelweg omdat we Kubernetes gebruiken en profiteren van de mogelijkheden van de cloud. Nu kan dit in Rusland worden gedaan. Ik ga natuurlijk voor niemand adverteren, maar laten we zeggen dat er aanbieders zijn die dit kunnen doen, het direct uit de doos aanbieden met een knop.

Er is nog een laatste punt waar ik ook uw aandacht op wil vestigen. Om ervoor te zorgen dat uw applicatie, uw infrastructuur Cloudnative is, is het zinvol om eindelijk te beginnen met het aanpassen van de aanpak genaamd Infrastructure as a Code. Dat betekent dat uw applicatie, of beter gezegd uw infrastructuur, op precies dezelfde manier nodig is als de code Beschrijf uw applicatie, uw bedrijfslogica in de vorm van code. En werk ermee als code, dat wil zeggen, test het, rol het uit, sla het op in git, pas CICD erop toe.

En dit is precies wat u in de eerste plaats in staat stelt om altijd controle te hebben over uw infrastructuur, om altijd te begrijpen in welke staat deze zich bevindt. Ten tweede: vermijd handmatige handelingen die fouten veroorzaken. Ten derde: vermijd eenvoudigweg wat omzet wordt genoemd, wanneer u voortdurend dezelfde handmatige taken moet uitvoeren. Ten vierde kunt u hierdoor veel sneller herstellen in geval van een storing. Elke keer als ik hierover in Rusland praat, zijn er altijd een groot aantal mensen die zeggen: "Ja, het is duidelijk, maar je hebt benaderingen, kortom, het is niet nodig om iets op te lossen." Maar het is waar. Als er iets kapot is in uw infrastructuur, dan is het, vanuit het oogpunt van de Cloudnative-aanpak en vanuit het oogpunt van Infrastructuur als Code, gemakkelijker dan het te repareren, naar de server te gaan, uit te zoeken wat er kapot is en het te repareren. om de server te verwijderen en opnieuw aan te maken. En ik zal dit allemaal laten herstellen.

Al deze kwesties worden in meer detail besproken op Kubernetes videocursussen: Junior, Basic, Mega. Door de link te volgen kunt u kennismaken met het programma en de voorwaarden. Het handige is dat je Kubernetes onder de knie krijgt door 1-2 uur per dag thuis of op het werk te studeren.

Bron: www.habr.com

Voeg een reactie