De beste architectuur met Docker en Kubernetes - mythe of realiteit?

Hoe is de wereld van softwareontwikkeling veranderd in het tijdperk van Docker en Kubernetes? Is het mogelijk om voor eens en voor altijd een architectuur te bouwen met behulp van deze technologieën? Is het mogelijk om de ontwikkelings- en integratieprocessen te verenigen wanneer alles is "verpakt" in containers? Wat zijn de vereisten voor dergelijke beslissingen? Welke beperkingen brengen ze in het spel? Zullen ze het leven van ontwikkelaars gemakkelijker maken of er in plaats daarvan onnodige complicaties aan toevoegen?

Het is tijd om het licht te werpen op deze (en enkele andere) vragen! (In tekst en originele illustraties.)

Dit artikel neemt je mee op een reis van het echte leven naar ontwikkelingsprocessen naar architectuur en terug naar het echte leven, en geeft antwoorden op de belangrijkste vragen bij elk van deze stops onderweg. We zullen proberen een aantal componenten en principes te identificeren die onderdeel moeten worden van een architectuur en een paar voorbeelden demonstreren zonder in te gaan op de implementatie ervan.

De conclusie van het artikel kan van streek zijn of u bevallen. Het hangt allemaal af van je ervaring, je perceptie van dit drie hoofdstukken verhaal, en misschien zelfs je humeur op het moment van lezen. Laat me weten wat je denkt door hieronder opmerkingen of vragen te posten!

Van real life tot ontwikkelingsworkflows

Voor het grootste deel dienden alle ontwikkelingsprocessen die ik ooit heb gezien of geëerd om op te zetten een eenvoudig doel: de tijd verkorten tussen de geboorte van een idee en de levering ervan aan productie, met behoud van een zekere mate van codekwaliteit.

Het maakt niet uit of het idee goed of slecht is. Slechte ideeën komen en gaan snel - je probeert ze gewoon en wijst ze af om te desintegreren. Wat het vermelden waard is, is dat het terugdraaien van een slecht idee op de schouders van een robot valt die je workflow automatiseert.

Continue integratie en levering lijken een levensredder in de wereld van softwareontwikkeling. Wat is er eenvoudiger dan dat? Je hebt een idee, je hebt de code, dus ga ervoor! Zonder een klein probleem zou het perfect zijn geweest - het proces van integratie en levering is vrij moeilijk te formaliseren los van de technologie en bedrijfsprocessen die specifiek zijn voor uw bedrijf.

Ondanks de schijnbare complexiteit van de taak, werpt het leven echter voortdurend uitstekende ideeën in die ons (nou ja, zeker) een beetje dichter bij het bouwen van een foutloos mechanisme brengen dat in bijna elke gelegenheid nuttig kan zijn. De meest recente stap naar een dergelijk mechanisme voor mij zijn Docker en Kubernetes, waarvan het abstractieniveau en de ideologische benadering me deden denken dat 80% van de problemen nu met vrijwel dezelfde methoden kan worden opgelost.

De resterende 20% is duidelijk nergens naartoe gegaan. Maar dit is precies waar je je innerlijke creatieve genie kunt richten op interessant werk, in plaats van de repetitieve routinetaken aan te pakken. Als u slechts één keer voor het 'architecturale raamwerk' zorgt, kunt u 80% van de opgeloste problemen vergeten.

Wat betekent dit allemaal en hoe lost Docker precies de problemen van de ontwikkelingsworkflow op? Laten we eens kijken naar een eenvoudig proces, dat toevallig ook voldoende is voor de meeste werkomgevingen:

Met de juiste aanpak kunt u alles uit de onderstaande volgorde automatiseren en verenigen en het maandenlang vergeten.

Een ontwikkelomgeving opzetten

Een project moet een docker-compose.yml-bestand bevatten, waardoor u niet hoeft na te denken over wat en hoe u de toepassing / service op de lokale computer moet uitvoeren. Een eenvoudig docker-compose-commando zou uw applicatie moeten opstarten met al zijn afhankelijkheden, de database vullen met armaturen, de lokale code in de container uploaden, codetracing inschakelen voor compilatie ter plekke en uiteindelijk beginnen te reageren op de verwachte poort. Zelfs bij het opzetten van een nieuwe service hoeft u zich geen zorgen te maken over hoe u begint, waar u wijzigingen aanbrengt of welke kaders u moet gebruiken. Dit alles moet van tevoren worden beschreven in de standaardinstructies en worden bepaald door de servicesjablonen voor verschillende opstellingen: frontend, backend en werknemer.

Geautomatiseerd testen

Alles wat u wilt weten over de "zwarte doos" (meer over waarom ik container noem, dit volgt later in de tekst) is dat alles goed zit erin. Ja of nee. 1 of 0. Met een eindig aantal opdrachten dat in de container kan worden uitgevoerd en docker-compose.yml die alle afhankelijkheden beschrijft, kunt u eenvoudig testen automatiseren en unificeren zonder te veel te focussen op de implementatiedetails.

Bijvoorbeeld zoals dit!

Testen betekent hier niet alleen en niet zozeer unit-testen, maar ook functionele testen, integratietesten, testen van (codestijl) en dupliceren, controleren op verouderde afhankelijkheden, schending van licenties voor gebruikte pakketten, en vele andere dingen. Het punt is dat dit alles in je Docker-afbeelding moet worden ingekapseld.

Levering van systemen

Het maakt niet uit wanneer en waar u uw project wilt installeren. Het resultaat, net als het installatieproces, moet altijd hetzelfde zijn. Er is ook geen verschil uit welk deel van het hele ecosysteem je gaat installeren of van welke git-repo je het zult krijgen. Het belangrijkste onderdeel hier is idempotence. Het enige dat u moet opgeven, zijn de variabelen die de installatie besturen.

Dit is het algoritme dat mij vrij effectief lijkt te zijn om dit probleem op te lossen:

  1. Verzamel afbeeldingen van al uw Docker-bestanden (bijvoorbeeld als volgt)
  2. Lever deze afbeeldingen met behulp van een metaproject aan Kubernetes via Kube API. Het starten van een levering vereist meestal verschillende invoerparameters:
  • Kube API eindpunt
  • een "geheim" object dat varieert voor verschillende contexten (lokaal / showroom / enscenering / productie)
  • de namen van de weer te geven systemen en de tags van de Docker-afbeeldingen voor deze systemen (verkregen bij de vorige stap)
Als een voorbeeld van een metaproject dat alle systemen en services omvat (met andere woorden, een project dat beschrijft hoe het ecosysteem is ingericht en hoe updates eraan worden geleverd), gebruik ik bij voorkeur Ansible-playbooks met deze module voor integratie met Kube API. Geavanceerde automaten kunnen echter naar andere opties verwijzen en ik zal later bij mijn eigen keuzes stilstaan. U moet echter denken aan een gecentraliseerde / uniforme manier om de architectuur te beheren. Als je er een hebt, kun je alle services / systemen gemakkelijk en uniform beheren en eventuele complicaties neutraliseren die de opkomende jungle van technologieën en systemen met vergelijkbare functies op je zou kunnen werpen.

Doorgaans is een installatie van de omgeving vereist in:

  • "ShowRoom" - voor enkele handmatige controles of foutopsporing van het systeem
  • "Staging" - voor bijna live omgevingen en integraties met externe systemen (meestal in de DMZ in tegenstelling tot ShowRoom)
  • "Productie" - de werkelijke omgeving voor de eindgebruiker

Continuïteit in integratie en levering

Als je een uniforme manier hebt om Docker-afbeeldingen - of 'zwarte dozen' te testen - kun je ervan uitgaan dat je met de resultaten van dergelijke tests naadloos (en met een gerust geweten) feature-branch in de upstream- of master-branches van je git kunt integreren repository.

Misschien is de enige dealbreaker hier de volgorde van integratie en levering. Als er geen releases zijn, hoe voorkom je dan een 'race condition' op één systeem met een set parallelle feature-branches?

Daarom moet dit proces alleen worden gestart als er geen competitie is, anders blijft de "race condition" je rondspoken:

  1. Probeer de feature-branch bij te werken naar upstream (git rebase / merge)
  2. Bouw afbeeldingen van Dockerfiles
  3. Test alle ingebouwde afbeeldingen
  4. Begin en wacht tot de systemen met de afbeeldingen van stap 2 zijn afgeleverd
  5. Als de vorige stap is mislukt, rolt u het ecosysteem terug naar de vorige status
  6. Functie-branch in upstream samenvoegen en naar de repository verzenden

Elke fout in elke stap moet het leveringsproces beëindigen en de taak terugsturen naar de ontwikkelaar om de fout te verhelpen, of het nu een mislukte test of een samenvoegconflict is.

U kunt dit proces gebruiken om met meer dan één repository te werken. Voer gewoon elke stap uit voor alle opslagplaatsen in één keer (stap 1 voor opslagplaatsen A en B, stap 2 voor opslagplaatsen A en B, enzovoort), in plaats van het hele proces herhaaldelijk te doen voor elke afzonderlijke opslagplaats (stappen 1–6 voor opslagplaats A , stappen 1-6 voor repo B, enzovoort).

Bovendien kunt u met Kubernetes updates in delen uitrollen voor het uitvoeren van verschillende AB-tests en risicoanalyses. Kubernetes doet dit intern door services (toegangspunten) en applicaties te scheiden. U kunt de nieuwe en oude versies van een component altijd in een gewenste verhouding in evenwicht brengen om probleemanalyse te vergemakkelijken en plaats te maken voor een mogelijke terugdraaiing.

Rollback-systemen

Een van de verplichte vereisten voor een architectonisch raamwerk is de mogelijkheid om elke implementatie ongedaan te maken. Dit houdt op zijn beurt een aantal expliciete en impliciete nuances in. Hier zijn enkele van de belangrijkste:

  • Een service moet zijn omgeving kunnen instellen en wijzigingen kunnen ongedaan maken. Bijvoorbeeld databasemigratie, RabbitMQ-schema enzovoort.
  • Als het niet mogelijk is om de omgeving terug te draaien, moet de service polymorf zijn en zowel de oude als de nieuwe versie van de code ondersteunen. Bijvoorbeeld: databasemigraties mogen de oude versies van de service niet verstoren (meestal 2 of 3 eerdere versies)
  • Achterwaartse compatibiliteit van elke service-update. Meestal is dit API-compatibiliteit, berichtindelingen, enzovoort.
Het is vrij eenvoudig om statussen terug te draaien in een Kubernetes-cluster (voer kubectl-implementatie ongedaan maken / enige implementatie uit en Kubernetes herstelt de vorige "momentopname"), maar om dit te laten werken, moet uw metaproject informatie over deze momentopname bevatten. Meer complexe terugdraaialgoritmen voor de levering worden sterk afgeraden, hoewel ze soms nodig zijn.

Dit kan het terugdraaimechanisme activeren:

  • Hoog percentage applicatiefouten na een release
  • Signalen van belangrijke controlepunten
  • Mislukte rookproeven
  • Handmatige modus - menselijke factor

Zorgen voor informatiebeveiliging en audit

Er is geen enkele workflow die op magische wijze kogelvrije beveiliging kan "bouwen" en uw ecosysteem kan beschermen tegen zowel externe als interne bedreigingen, dus u moet ervoor zorgen dat uw architecturale raamwerk wordt uitgevoerd met het oog op de normen en het beveiligingsbeleid van het bedrijf bij elke niveau en in alle subsystemen.

Ik zal later alle drie niveaus van de voorgestelde oplossing behandelen, in het gedeelte over monitoring en alarmering, die zelf ook van cruciaal belang zijn voor de systeemintegriteit.

Kubernetes heeft een aantal goede ingebouwde mechanismen voor toegangscontrole, netwerkbeleid, audit van evenementen en andere krachtige tools met betrekking tot informatiebeveiliging, die kunnen worden gebruikt om een ​​uitstekende perimeter van bescherming te bouwen die aanvallen en datalekken kan weerstaan ​​en voorkomen .

Van ontwikkelingsworkflows tot architectuur

Een poging om een ​​nauwe integratie tussen de ontwikkelingsworkflows en het ecosysteem tot stand te brengen, moet serieus worden genomen. Het toevoegen van een vereiste voor een dergelijke integratie aan de traditionele set vereisten aan een architectuur (flexibiliteit, schaalbaarheid, beschikbaarheid, betrouwbaarheid, bescherming tegen bedreigingen, enzovoort) kan de waarde van uw architecturale raamwerk aanzienlijk verhogen. Het is een zo cruciaal aspect dat het heeft geleid tot de opkomst van een concept genaamd "DevOps" (Development Operation), wat een logische stap is in de richting van totale automatisering en optimalisatie van de infrastructuur. Met een goed ontworpen architectuur en betrouwbare subsystemen kunnen DevOps-taken echter worden geminimaliseerd.

Micro-service architectuur

Het is niet nodig om in details te treden over de voordelen van een servicegeoriënteerde architectuur - SOA, inclusief waarom services "micro" moeten zijn. Ik zal alleen zeggen dat als je hebt besloten Docker en Kubernetes te gebruiken, je waarschijnlijk begrijpt (en accepteert) dat het moeilijk en zelfs ideologisch verkeerd is om een ​​monolithische architectuur te hebben. Docker is ontworpen om een ​​enkel proces uit te voeren en met volharding te werken, en dwingt ons om te denken binnen het DDD-framework (Domain-Driven Development). In Docker wordt ingepakte code behandeld als een zwarte doos met enkele zichtbare poorten.

Kritieke componenten en oplossingen van het ecosysteem

Vanuit mijn ervaring met het ontwerpen van systemen met een verhoogde beschikbaarheid en betrouwbaarheid, zijn er verschillende componenten die cruciaal zijn voor de werking van microdiensten. Ik zal een lijst maken en later over elk van deze componenten praten, en hoewel ik ernaar zal verwijzen in de context van een Kubernetes-omgeving, kun je naar mijn lijst verwijzen als een checklist voor elk ander platform.

Als je (zoals ik) tot de conclusie bent gekomen dat het geweldig zou zijn om elk van deze componenten als een normale Kubernetes-service te beheren, dan raad ik je aan ze in een ander cluster te draaien dan "productie". Bijvoorbeeld een 'staging'-cluster, omdat het uw leven kan redden wanneer de productieomgeving onstabiel is en u wanhopig een bron van afbeeldingen, code of monitoringtools nodig hebt. Dat lost het probleem van kip en ei als het ware op.

Identiteitsservice

Zoals gewoonlijk begint het allemaal met toegang - tot servers, virtuele machines, applicaties, kantoormail, enzovoort. Als u klant bent of wilt worden van een van de belangrijkste enterprise-platforms (IBM, Google, Microsoft), wordt het toegangsprobleem behandeld door een van de services van de leverancier. Als u echter een eigen oplossing wilt, die alleen door u wordt beheerd en binnen uw budget?

Deze lijst moet u helpen bij het kiezen van de juiste oplossing en het schatten van de inspanningen die nodig zijn om deze op te zetten en te onderhouden. Natuurlijk moet uw keuze in overeenstemming zijn met het beveiligingsbeleid van het bedrijf en worden goedgekeurd door de afdeling informatiebeveiliging.

Geautomatiseerde dienstverlening

Hoewel Kubernetes slechts een handvol componenten nodig heeft op fysieke machines / cloud VM's (docker, kubelet, kube proxy, etcd cluster), moet u nog steeds de toevoeging van nieuwe machines en clusterbeheer automatiseren. Hier zijn een paar eenvoudige manieren om het te doen:

  • KOPS - met deze tool kunt u een cluster installeren op een van de twee cloudproviders - AWS of GCE
  • Teraform - hiermee kunt u de infrastructuur voor elke omgeving beheren en de ideologie van IAC volgen (Infrastructure as Code)
  • Ansible - veelzijdige tool voor elke automatisering
Persoonlijk geef ik de voorkeur aan de derde optie (met een kleine Kubernetes-integratiemodule), omdat ik hiermee met zowel servers als k8s-objecten kan werken en elke vorm van automatisering kan uitvoeren. Niets houdt u echter tegen om Teraform en de Kubernetes-module te gebruiken. KOPS werkt niet goed met het "blanke metaal" maar het is nog steeds een geweldig hulpmiddel om te gebruiken met AWS / GCE!

Git repository en een task tracker

Onnodig te zeggen dat je voor volwaardig werk van ontwikkelaars en andere gerelateerde rollen moet zorgen voor een plaats voor teamwork en discussies over codeopslag. Ik zou er hard op drukken om te bepalen welke service hiervoor het beste is, maar mijn persoonlijke gouden standaard voor het bijhouden van taken is Redmine (gratis) of Jira (betaald), en voor code repository - de 'old school' [gerrit] ( https://www.gerritcodereview.com/) (gratis) of bitbucket (betaald).

Het is de moeite waard om aandacht te besteden aan de twee meest consistente (hoewel commerciële) stapels voor samenwerking in een bedrijfsomgeving: Atlassian en Jetbrains. U kunt een van beide een zelfstandige oplossing gebruiken of verschillende componenten van beide combineren.

Overweeg hun integratiestrategie om het beste uit een combinatie van een tracker en repository te halen. Een paar tips om de integriteit van de code en gerelateerde taken te waarborgen (u kunt natuurlijk uw eigen aanpak kiezen):

  • De mogelijkheid om in een externe repository te 'pushen' moet alleen worden ingeschakeld als een branch waar men naar probeert te pushen het overeenkomstige taaknummer heeft (TASK-1 / feature-34)
  • Elke vertakking moet beschikbaar zijn om alleen samen te voegen na een bepaald aantal positieve codereview-iteraties
  • Elke vertakking moet worden geblokkeerd en uitgeschakeld voor toekomstige updates als de bijbehorende taak niet "In uitvoering" of een vergelijkbare status is
  • Alle stappen bedoeld voor automatisering zouden niet direct beschikbaar moeten zijn voor ontwikkelaars
  • Alleen geautoriseerde ontwikkelaars moeten in staat zijn om de master branch rechtstreeks te wijzigen - al het andere wordt bestuurd door een automatiseringsrobot
  • Een filiaal mag niet beschikbaar zijn voor samenvoeging als de bijbehorende taak een andere status heeft dan "Voor bezorging" of iets vergelijkbaars

Docker-register

Speciale aandacht moet worden besteed aan een Docker-beeldbeheersysteem, omdat dit van cruciaal belang is voor het opslaan en leveren van services. Bovendien moet dit systeem toegang voor gebruikers en gebruikersgroepen ondersteunen, in staat zijn om oude en onnodige afbeeldingen te verwijderen, een GUI en een RESTful API bieden.

U kunt een cloudoplossing (bijvoorbeeld hub.docker.com) of een particulier gehoste service gebruiken, die zelfs binnen uw zeer Kubernetes-cluster kan worden geïnstalleerd. Vmware Harbor, gepositioneerd als een bedrijfsoplossing voor Docker Registry, is een goed voorbeeld van dit laatste. In het ergste geval kunt u zelfs het goede oude Docker-register gebruiken als u alleen afbeeldingen wilt opslaan en geen behoefte hebt aan een complex systeem.

CI / CD en services leveringssysteem

Geen van de componenten die we eerder hebben besproken (git repo, task tracker, meta-project met Ansible Playbooks, externe afhankelijkheden) kunnen onafhankelijk van elkaar functioneren alsof ze in een vacuüm zijn opgehangen. Wat hen verbindt is de continue integratie- en bezorgservice.

CI - Continuous Integration CD - Continuous Delivery

De service moet redelijk eenvoudig zijn en elke logica met betrekking tot de systeemlevering of -configuratie missen. Het enige dat een CI / CD-service moet doen, is reageren op gebeurtenissen uit de buitenwereld (wijzigingen in de git-repository, taken verplaatsen rond de taakvolger) en de acties starten die in het metaproject worden beschreven. Bovendien is de servicecentrum een ​​controlepunt van alle repositories en een tool voor het beheer ervan (samenvoegen van filialen, updates van upstream / master).

Ik heb in het verleden een redelijk krachtig en toch heel eenvoudig hulpmiddel van Jetbrains gebruikt - TeamCity, maar ik zie geen probleem als je besluit om iets anders te proberen, bijvoorbeeld de gratis Jenkins.

In het schema dat we hierboven hebben beschreven, is de integratieservice in wezen verantwoordelijk voor het opstarten van de vier hoofdprocessen en een hulpproces, die als volgt zijn:

  • Automatische servicetests - meestal voor een enkele repository, wanneer een filiaalstatus is gewijzigd of wanneer de status is gewijzigd in "In afwachting van autotests" (of vergelijkbaar)
  • Servicelevering - meestal vanuit een metaproject en voor een aantal services (respectievelijk een aantal repositories), wanneer de status is gewijzigd in "Wachten op showroom" of "Wachten op levering" voor respectievelijk QA en productieomgeving
  • Terugdraaien - in de regel van een metaproject en voor een bepaald deel van een enkele service of een volledige service, veroorzaakt door een externe gebeurtenis of in geval van een mislukte levering
  • Serviceverwijdering - dit is vereist om het volledige ecosysteem volledig te verwijderen uit een enkele testomgeving (showroom), wanneer de In QA-status is verlopen of de omgeving niet langer nodig is
  • Image builder (het hulpproces) - kan worden geïntegreerd in het service delivery-proces of onafhankelijk worden gebruikt om Docker-images te compileren en naar Docker Registry te sturen. Behandelt vaak veelgebruikte afbeeldingen (DB, algemene services of services die geen frequente wijzigingen vereisen)

Systeem voor het verzamelen en analyseren van logboeken

De enige manier voor elke Docker-container om zijn logs toegankelijk te maken, is door ze naar STDOUT of STDERR te schrijven van het rootproces dat in de container wordt uitgevoerd. Serviceontwikkelaar kan het niet echt schelen wat er daarna gebeurt met de logboekgegevens, het belangrijkste is dat deze beschikbaar moeten zijn wanneer dat nodig is en bij voorkeur records tot een bepaald punt in het verleden bevatten. Alle verantwoordelijkheid voor het vervullen van deze verwachtingen ligt bij Kubernetes en de ingenieurs die het ecosysteem ondersteunen.

In de officiële documentatie vindt u een beschrijving van de basisstrategie (en een goede) voor het werken met logboeken, waarmee u een service kunt kiezen voor het verzamelen en opslaan van enorme tekstgegevens.

Onder de aanbevolen services voor een logsysteem vermeldt dezelfde documentatie vloeiend voor het verzamelen van gegevens (wanneer gestart als een agent op elk knooppunt van het cluster), en Elasticsearch voor het opslaan en indexeren van gegevens. Zelfs als de efficiëntie van een van beide U misschien niet eens bent met de efficiëntie van deze oplossing, maar het is betrouwbaar en gemakkelijk te gebruiken, dus ik denk dat het op zijn minst een goed begin is.

Elasticsearch is een resource-intensieve oplossing, maar het is goed schaalbaar en heeft kant-en-klare Docker-afbeeldingen om zowel een afzonderlijk knooppunt als een cluster van een vereiste grootte te gebruiken.

Tracing systeem

Hoe perfect je code ook is, er gebeuren fouten en dan wil je ze met een fijne kam bij de productie bestuderen en proberen te begrijpen "wat is er in hemelsnaam misgegaan als alles goed werkte op mijn lokale machine?". Trage databasequery's, onjuiste caching, trage schijven of connectiviteit met een externe bron, transacties in het ecosysteem, knelpunten en te weinig geschaalde computerservices zijn enkele van de redenen waarom u gedwongen zult worden om de tijd te volgen en te schatten die u hebt besteed aan het uitvoeren van uw code onder een echte lading.

Opentracing en Zipkin kunnen deze taak aan voor de meeste moderne programmeertalen en zonder extra belasting na het coderen van de code. Natuurlijk moeten alle verzamelde gegevens op een geschikte plaats worden opgeslagen, die als een van de componenten wordt gebruikt.

De complexiteit die zich voordoet bij het instrumenteren van de code en het doorsturen van "Trace Id" door alle services, berichtenwachtrijen, databases, enzovoort, wordt opgelost door de bovengenoemde ontwikkelingsstandaarden en servicesjablonen. Deze laatste zorgen ook voor uniformiteit van de aanpak.

Monitoring en alarmering

Prometheus is de de facto standaard geworden in moderne systemen en, nog belangrijker, het wordt bijna kant en klaar in Kubernetes ondersteund. U kunt de officiële Kubernetes-documentatie raadplegen voor meer informatie over monitoring en alarmering.

Monitoring is een van de weinige hulpsystemen die in een cluster moeten worden geïnstalleerd. En het cluster is een entiteit die wordt gecontroleerd. Maar monitoring van een monitoringsysteem (excuses voor de tautologie) kan alleen van buitenaf worden uitgevoerd (bijvoorbeeld vanuit dezelfde "staging" -omgeving). In dit geval is kruiscontrole handig als een handige oplossing voor elke gedistribueerde omgeving, die de architectuur van uw sterk verenigde ecosysteem niet zou compliceren.

Het hele bereik van monitoring is verdeeld in drie volledig logisch geïsoleerde niveaus. Dit zijn volgens mij de belangrijkste voorbeelden van trackingpunten op elk niveau:

  • Fysiek niveau: - Netwerkbronnen en hun beschikbaarheid - Schijven (i / o, beschikbare ruimte) - Basisbronnen van afzonderlijke knooppunten (CPU, RAM, LA)
  • Clusterniveau: - Beschikbaarheid van de belangrijkste clustersystemen op elk knooppunt (kubelet, kubeAPI, DNS, enzovoort) - Het aantal gratis bronnen en hun uniforme distributie - Monitoring van toegestaan ​​versus daadwerkelijk gebruik van bronnen door services - Herladen van pods
  • Serviceniveau: - Elke vorm van applicatiebewaking - van database-inhoud tot een frequentie van API-aanroepen - Aantal HTTP-fouten op de API-gateway - Grootte van de wachtrijen en het gebruik van de werknemers - Meerdere statistieken voor de database (replicatievertraging, tijd en aantal transacties, trage aanvragen en meer) - Foutanalyse voor niet-HTTP-processen - Monitoring van aanvragen die naar het logboeksysteem zijn verzonden (u kunt alle aanvragen omzetten in statistieken)

Wat betreft de waarschuwingsmeldingen op elk niveau, zou ik willen aanbevelen om een ​​van de talloze externe services te gebruiken die meldingen kunnen verzenden naar e-mail, sms of bellen naar een mobiel nummer. Ik zal ook een ander systeem noemen - OpsGenie - dat nauw is geïntegreerd met de alertmanager van Prometheus.

OpsGenie is een flexibel hulpmiddel voor alarmering dat helpt bij het omgaan met escalaties, de klok rond, selectie van meldingskanalen en nog veel meer. Het is ook gemakkelijk om meldingen onder teams te verspreiden. Verschillende monitoringniveaus moeten bijvoorbeeld meldingen naar verschillende teams / afdelingen sturen: fysiek - Infra + Devops, cluster - Devops, applicaties - elk naar een relevant team.

API-gateway en eenmalige aanmelding

Om taken als autorisatie, authenticatie, gebruikersregistratie (externe gebruikers-klanten van het bedrijf) en andere soorten toegangscontrole af te handelen, heeft u een zeer betrouwbare service nodig die een flexibele integratie met uw API-gateway kan behouden. Het is geen kwaad om dezelfde oplossing te gebruiken als voor de "Identity-service", maar u wilt misschien de twee bronnen scheiden om een ​​ander niveau van beschikbaarheid en betrouwbaarheid te bereiken.

De interservice-integratie mag niet ingewikkeld zijn en uw services moeten zich geen zorgen maken over autorisatie en authenticatie van gebruikers en elkaar. In plaats daarvan moeten de architectuur en het ecosysteem een ​​proxyservice hebben die alle communicatie en HTTP-verkeer afhandelt.

Laten we de meest geschikte manier van integratie met de API-gateway overwegen, dus met uw hele ecosysteem - tokens. Deze methode is goed voor alle drie toegangsscenario's: van de gebruikersinterface, van service tot service en van een extern systeem. De taak om een ​​token te ontvangen (op basis van de login en het wachtwoord) ligt dan bij de gebruikersinterface zelf of bij de serviceontwikkelaar. Het is ook zinvol om onderscheid te maken tussen de levensduur van tokens die worden gebruikt in de gebruikersinterface (kortere TTL) en in andere gevallen (langere en aangepaste TTL).

Hier zijn enkele problemen die de API-gateway oplost:

  • Toegang tot de services van het ecosysteem van buiten en binnen (services communiceren niet rechtstreeks met elkaar)
  • Integratie met een Single Sign-on-service: - Transformatie van tokens en het toevoegen van HTTPS-aanvragen met headers die gebruikersidentificatiegegevens (ID, rollen, andere details) voor de gevraagde service bevatten - Toegangsbeheer voor de gevraagde service inschakelen / uitschakelen op basis van de rollen ontvangen van de Single Sign-on-service
  • Eén monitoringpunt voor HTTP-verkeer
  • Combineren van API-documentatie van verschillende services (bijvoorbeeld het combineren van Swagger's json / yml-bestanden
  • Mogelijkheid om routing voor het hele ecosysteem te beheren op basis van de domeinen en aangevraagde URI's
  • Eén toegangspunt voor extern verkeer en integratie met de toegangsprovider

Evenementenbus en Enterprise Integration / Service-bus

Als uw ecosysteem honderden services bevat die werken in één macrodomein, zult u te maken krijgen met duizenden mogelijke manieren waarop de services kunnen communiceren. Om gegevensstromen te stroomlijnen, moet u denken aan de mogelijkheid om berichten over een groot aantal ontvangers te verspreiden bij het optreden van bepaalde gebeurtenissen, ongeacht de context van de gebeurtenissen. Met andere woorden, je hebt een evenementenbus nodig om evenementen te publiceren op basis van een standaardprotocol en je erop te abonneren.

Als evenementenbus kunt u elk systeem gebruiken dat een zogenaamde broker kan bedienen: RabbitMQ, Kafka, ActiveMQ en andere. Over het algemeen zijn hoge beschikbaarheid en consistentie van gegevens van cruciaal belang voor de microdiensten, maar je zult nog steeds iets moeten opofferen om een ​​goede distributie en clustering van de bus te bereiken, vanwege de CAP-stelling.

Natuurlijk moet de evenementenbus allerlei problemen van communicatie tussen services kunnen oplossen, maar naarmate het aantal services groeit van honderden tot duizenden tot tienduizenden, zal zelfs de beste op evenementenbus gebaseerde architectuur mislukken en zul je moet een andere oplossing zoeken. Een goed voorbeeld zou een integratiebusbenadering zijn, die de mogelijkheden van de hierboven beschreven "Dumb pipe - Smart consumer" -technieken kan uitbreiden.

Er zijn tientallen redenen om de "Enterprise Integration / Service Bus" -benadering te gebruiken, die tot doel heeft de complexiteit van een servicegeoriënteerde architectuur te verminderen. Hier zijn een paar van deze redenen:

  • Aggregatie van meerdere berichten
  • Opsplitsing van één evenement in meerdere evenementen
  • Synchrone / transactionele analyse van de systeemreactie op een gebeurtenis
  • Coördinatie van interfaces, wat vooral belangrijk is voor integratie met externe systemen
  • Geavanceerde logica van gebeurtenisrouting
  • Meerdere integratie met dezelfde services (van buiten en van binnen)
  • Niet-schaalbare centralisatie van de gegevensbus
Als open-source software voor een enterprise-integratiebus, wilt u misschien Apache ServiceMix overwegen, die verschillende componenten bevat die essentieel zijn voor het ontwerp en de ontwikkeling van dit soort SOA.

Databases en andere stateful diensten

Naast Kubernetes heeft Docker de spelregels voor eens en voor altijd gewijzigd voor services die gegevenspersistentie vereisen en nauw samenwerken met de schijf. Sommigen zeggen dat de services op de oude manier op fysieke servers of virtuele machines moeten 'leven'. Ik respecteer deze mening en ga niet in op argumenten over de voor- en nadelen, maar ik ben er vrij zeker van dat dergelijke verklaringen alleen bestaan ​​vanwege het tijdelijke gebrek aan kennis, oplossingen en ervaring in het beheren van stateful services in een Docker-omgeving.

Ik moet ook vermelden dat een database vaak de centrale plaats inneemt in de opslagwereld, en daarom moet de oplossing die u selecteert volledig voorbereid zijn om in een Kubernetes-omgeving te werken.

Op basis van mijn ervaring en de marktsituatie kan ik de volgende groepen stateful services onderscheiden, samen met voorbeelden van de meest geschikte Docker-georiënteerde oplossingen voor elk van hen:

  • Databasebeheersystemen - PostDock is een eenvoudige en betrouwbare oplossing voor PostgreSQL in elke Docker-omgeving
  • Wachtrij / berichtenmakelaars - RabbitMQ is een klassieke software voor het bouwen van een berichtenwachtrijsysteem en het routeren van de berichten. De parameter cluster_formation in de configuratie van RabbitMQ is onmisbaar voor een clusterinstallatie
  • Caching-services - Redis wordt beschouwd als een van de meest betrouwbare en flexibele oplossingen voor datacaching
  • Zoeken op volledige tekst - de Elasticsearch-stapel die ik hierboven al heb genoemd, oorspronkelijk gebruikt voor zoeken op volledige tekst, maar net zo goed in het opslaan van logboeken en voor elk soort werk met grote hoeveelheden tekstgegevens
  • Bestandsopslagservices - een algemene groep services voor elk type bestandsopslag en -levering (ftp, sftp, enzovoort)

Afhankelijkheid spiegelt

Als u nog nooit een situatie bent tegengekomen waarin de pakketten of afhankelijkheden die u nodig hebt, zijn verwijderd of tijdelijk niet beschikbaar zijn gemaakt op een openbare server, denk dan niet dat dit nooit zal gebeuren. Om ongewenste onbeschikbaarheid te voorkomen en de interne systemen te beveiligen, moet u ervoor zorgen dat voor het bouwen of leveren van uw services geen internetverbinding nodig is. Spiegelen en kopiëren van alle afhankelijkheden naar het interne netwerk configureren: Docker-afbeeldingen, rpm-pakketten, bronrepository's, python / go / js / php-modules.

Elk van deze en andere soorten afhankelijkheden hebben hun eigen oplossingen. De meest voorkomende kan worden gegoogled door de vraag "private afhankelijkheidsspiegel voor ..."

Van architectuur tot het echte leven

Of je het nu leuk vindt of niet, vroeg of laat is je hele architectuur gedoemd te mislukken. Het gebeurt altijd: technologieën worden snel verouderd (1-5 jaar), methoden en benaderingen - een beetje langzamer (5-10 jaar), ontwerpprincipes en basisprincipes - soms (10-20 jaar), maar onvermijdelijk.

Houd rekening met de veroudering van technologie, probeer uw ecosysteem altijd op het toppunt van technische innovaties te houden, plan en implementeer nieuwe services om te voldoen aan de behoeften van ontwikkelaars, bedrijven en eindgebruikers, promoot nieuwe hulpprogramma's aan uw stakeholders, lever kennis om uw team en het bedrijf vooruit.

Blijf op de hoogte van het spel door te integreren in de professionele gemeenschap, relevante literatuur te lezen en te socialiseren met collega's. Houd rekening met uw kansen en het juiste gebruik van nieuwe trends in uw project. Experimenteer en pas wetenschappelijke methoden toe om de resultaten van uw onderzoek te analyseren, of vertrouw op de conclusies van andere mensen die u vertrouwt en respecteert.

Het is moeilijk om je voor te bereiden op fundamentele veranderingen, maar toch mogelijk als je een expert bent in je vakgebied. We zullen allemaal slechts een paar belangrijke technologische veranderingen gedurende ons leven meemaken, maar het is niet de hoeveelheid kennis in ons hoofd die ons tot professionals maakt en ons naar de top brengt, het is de openheid van onze ideeën en het vermogen om metamorfose te accepteren.

Terugkerend naar de vraag uit de titel, "is het mogelijk om een ​​betere architectuur te bouwen?" Nee, niet "eens en voor altijd", maar zorg ervoor dat je ernaar streeft en op een gegeven moment "voor een korte tijd" zal zeker slagen!

PS:

Het originele artikel is in het Russisch geschreven, dus bedankt mijn collega in Lazada Sergey Rodin voor geweldige hulp bij het vertalen!