.NET Core op Linux, DevOps te paard

We hebben DevOps zo goed mogelijk ontwikkeld. We waren met z'n achten en Vasya was de coolste in Windows. Plotseling vertrok Vasya en ik had de taak een nieuw project te lanceren dat werd geleverd door Windows Development. Toen ik de hele Windows-ontwikkelstack op tafel gooide, besefte ik dat de situatie lastig was...

Dit is hoe het verhaal begint Alexandra Sinchinova op DevOpsConf. Toen de toonaangevende Windows-specialist het bedrijf verliet, vroeg Alexander zich af wat hij nu moest doen. Overstappen naar Linux natuurlijk! Alexander zal je vertellen hoe hij erin slaagde een precedent te scheppen en een deel van de Windows-ontwikkeling naar Linux over te brengen aan de hand van het voorbeeld van een voltooid project voor 100 eindgebruikers.

.NET Core op Linux, DevOps te paard

Hoe kun je eenvoudig en moeiteloos een project naar RPM opleveren met behulp van TFS, Puppet, Linux .NET core? Hoe kan het versiebeheer van een projectdatabase worden ondersteund als het ontwikkelteam voor het eerst de woorden Postgres en Flyway hoort en de deadline overmorgen is? Hoe te integreren met Docker? Hoe kunnen we .NET-ontwikkelaars motiveren om Windows en smoothies achterwege te laten ten gunste van Puppet en Linux? Hoe kunnen ideologische conflicten worden opgelost als er noch de kracht, noch de wens, noch de middelen zijn om Windows in productie te houden? Hierover, maar ook over Web Deploy, testen, CI, over de praktijken van het gebruik van TFS in bestaande projecten, en natuurlijk over kapotte krukken en werkende oplossingen, in het transcript van Alexanders rapport.


Dus Vasya vertrok, de taak ligt bij mij, de ontwikkelaars wachten ongeduldig met hooivorken. Toen ik eindelijk besefte dat Vasya niet kon worden teruggestuurd, ging ik aan de slag. Om te beginnen heb ik het percentage Win-VM's in onze vloot beoordeeld. De score was niet in het voordeel van Windows.

.NET Core op Linux, DevOps te paard

Omdat we actief bezig zijn met het ontwikkelen van DevOps, realiseerde ik me dat er iets moet veranderen in de aanpak voor het opleveren van een nieuwe applicatie. Er was maar één oplossing: zet, indien mogelijk, alles over naar Linux. Google heeft me geholpen - op dat moment was .Net al overgezet naar Linux, en ik besefte dat dit de oplossing was!

Waarom .NET core in combinatie met Linux?

Daar waren verschillende redenen voor. Tussen ‘geld betalen’ en ‘niet betalen’ zal de meerderheid – net als ik – voor het tweede kiezen. Een licentie voor MSDB kost ongeveer $1; het onderhouden van een vloot virtuele Windows-machines kost honderden dollars. Voor een groot bedrijf is dit een grote kostenpost. Daarom spaargeld - eerste reden:. Niet de belangrijkste, maar wel een van de belangrijkste.

Virtuele Windows-machines nemen meer bronnen in beslag dan hun Linux-broeders - zij zijn zwaar. Gezien de omvang van het grote bedrijf hebben wij voor Linux gekozen.

Het systeem wordt eenvoudig geïntegreerd in een bestaand CI. We beschouwen onszelf als vooruitstrevende DevOps, we gebruiken Bamboo, Jenkins en GitLab CI, dus het grootste deel van ons werk draait op Linux.

De laatste reden is handige begeleiding. We moesten de toegangsdrempel voor ‘escorts’ verlagen: de jongens die het technische gedeelte begrijpen, ononderbroken service garanderen en diensten vanaf de tweede lijn onderhouden. Ze waren al bekend met de Linux-stack, dus het is voor hen veel gemakkelijker om een ​​nieuw product te begrijpen, ondersteunen en onderhouden dan extra middelen te besteden om dezelfde functionaliteit van software voor het Windows-platform te begrijpen.

Eisen

Eerst en vooral - gemak van de nieuwe oplossing voor ontwikkelaars. Ze waren niet allemaal klaar voor verandering, vooral niet nadat het woord Linux was gesproken. Ontwikkelaars willen hun favoriete Visual Studio, TFS met autotests voor assemblages en smoothies. Hoe de levering aan de productie plaatsvindt, is voor hen niet belangrijk. Daarom hebben we besloten het gebruikelijke proces niet te veranderen en alles ongewijzigd te laten voor de Windows-ontwikkeling.

Nieuw project nodig integreren in bestaande CI. De rails lagen er al en bij al het werk moest rekening worden gehouden met de parameters van het configuratiemanagementsysteem, de geaccepteerde leveringsnormen en de monitoringsystemen.

Gemak van ondersteuning en bediening, als voorwaarde voor de minimale instapdrempel voor alle nieuwe deelnemers uit verschillende divisies en de ondersteunende afdeling.

Deadline - gisteren.

Win Ontwikkelingsgroep

Waar werkte het Windows-team toen mee?

.NET Core op Linux, DevOps te paard

Nu kan ik dat met zekerheid zeggen Identiteitsserver4 is een cool gratis alternatief voor ADFS met vergelijkbare mogelijkheden, of zoiets Entiteit Framework Kern - een paradijs voor een ontwikkelaar, waar je geen SQL-scripts hoeft te schrijven, maar queries in de database in OOP-termen moet beschrijven. Maar toen, tijdens de bespreking van het actieplan, bekeek ik deze stapel alsof het een Sumerisch spijkerschrift was, dat alleen PostgreSQL en Git herkende.

Destijds waren we er actief mee bezig Puppet als configuratiebeheersysteem. In de meeste van onze projecten gebruikten we GitLab-CI, Elastische, evenwichtige diensten met hoge belasting die gebruikmaken van HAProxy hield alles in de gaten Zabbix, ligamenten grafana и Prometheus, Jager, en dit alles draaide op stukjes ijzer HPESXi op VMware. Iedereen kent het - een klassieker van het genre.

.NET Core op Linux, DevOps te paard

Laten we eens kijken en proberen te begrijpen wat er gebeurde voordat we met al deze interventies begonnen.

Wat er is gebeurd

TFS is een redelijk krachtig systeem dat niet alleen code van de ontwikkelaar aan de uiteindelijke productiemachine levert, maar ook een set heeft voor zeer flexibele integratie met verschillende diensten - om CI op platformonafhankelijk niveau te leveren.

.NET Core op Linux, DevOps te paard
Voorheen waren dit massieve ramen. TFS gebruikte verschillende Build-agents, die werden gebruikt om veel projecten samen te stellen. Elke agent heeft 3-4 werknemers om taken te parallelliseren en het proces te optimaliseren. Vervolgens leverde TFS, volgens de releaseplannen, de vers gebakken build aan de Windows-applicatieserver.

Wat wilden we bereiken?

We gebruiken TFS voor levering en ontwikkeling, en draaien de applicatie op een Linux-applicatieserver, en er is een soort magie tussen hen. Dit Magische doos en daar zit het zout van het werk dat voor ons ligt. Voordat ik het uit elkaar haal, zal ik een stap opzij zetten en een paar woorden zeggen over de toepassing.

Project

De applicatie biedt functionaliteit voor het verwerken van prepaidkaarten.

.NET Core op Linux, DevOps te paard

CLIËNT

Er waren twee soorten gebruikers. Eerste toegang verkregen door in te loggen met een SSL SHA-2 certificaat. U de tweede er was toegang met een login en wachtwoord.

HAProxy

Vervolgens ging het klantverzoek naar HAProxy, wat de volgende problemen oploste:

  • primaire autorisatie;
  • SSL-beëindiging;
  • het afstemmen van HTTP-verzoeken;
  • uitzendverzoeken.

Het clientcertificaat werd gedurende de hele keten geverifieerd. Wij - autoriteit en dat kunnen we ons veroorloven, omdat we zelf certificaten uitgeven aan serviceklanten.

Let op het derde punt, we komen er later op terug.

backend

Ze waren van plan om de backend op Linux te maken. De backend communiceert met de database, laadt de benodigde lijst met rechten en biedt vervolgens, afhankelijk van de rechten die de geautoriseerde gebruiker heeft, toegang om financiële documenten te ondertekenen en ter uitvoering te verzenden, of om een ​​soort rapport te genereren.

Besparen met HAProxy

Naast de twee contexten waarin elke cliënt navigeerde, was er ook een identiteitscontext. Identiteitsserver4 Hiermee kunt u gewoon inloggen, dit is een gratis en krachtig analoog voor ADFS - Active Directory Federation-services.

Het identiteitsverzoek werd in verschillende stappen verwerkt. Eerste stap - cliënt kwam in de backend terecht, die met deze server communiceerde en de aanwezigheid van een token voor de client controleerde. Als het verzoek niet werd gevonden, werd het verzoek teruggestuurd naar de context waar het vandaan kwam, maar met een omleiding, en met de omleiding ging het naar identiteit.

Tweede stap: het verzoek is ontvangen naar de autorisatiepagina in IdentityServer, waar de client zich registreerde, en dat langverwachte token verscheen in de IdentityServer-database.

Derde stap - de klant werd teruggestuurd naar de context waaruit het kwam.

.NET Core op Linux, DevOps te paard

IdentityServer4 heeft een functie: het retourneert het antwoord op het retourverzoek via HTTP. Hoezeer we ook worstelden met het opzetten van de server, hoezeer we ons ook verdiepten met de documentatie, elke keer dat we een eerste clientverzoek ontvingen met een URL die via HTTPS kwam, retourneerde IdentityServer dezelfde context, maar dan met HTTP. We waren geschokt! En we hebben dit allemaal via de identiteitscontext overgedragen naar HAProxy, en in de headers moesten we het HTTP-protocol wijzigen naar HTTPS.

Wat is de verbetering en waar heb je bespaard?

We hebben geld bespaard door gebruik te maken van een gratis oplossing voor het autoriseren van een groep gebruikers, resources, aangezien we IdentityServer4 niet als aparte node in een apart segment hebben geplaatst, maar deze samen met de backend op dezelfde server hebben gebruikt waar de backend van de applicatie draait .

Hoe het zou moeten werken

Dus, zoals ik beloofde: Magic Box. We begrijpen al dat we gegarandeerd richting Linux zullen evolueren. Laten we specifieke taken formuleren waarvoor oplossingen nodig zijn.

.NET Core op Linux, DevOps te paard

Marionetten manifesteren. Om de service- en applicatieconfiguratie te kunnen leveren en beheren, moesten er coole recepten worden geschreven. Een rol potlood laat welsprekend zien hoe snel en efficiënt het is gedaan.

Leveringsmethode. De standaard is RPM. Iedereen begrijpt dat je in Linux niet zonder kunt, maar het project zelf was, na montage, een reeks uitvoerbare DLL-bestanden. Er waren er ongeveer 150, het project was behoorlijk moeilijk. De enige harmonieuze oplossing is om dit binaire bestand in RPM te verpakken en de applicatie daaruit te implementeren.

Versiebeheer. We moesten heel vaak vrijgeven en we moesten beslissen hoe we de pakketnaam vormden. Dit is een kwestie van het niveau van integratie met TFS. We hadden een build-agent op Linux. Wanneer TFS een taak naar een handler (werker) naar de Build-agent stuurt, geeft het ook een aantal variabelen door die in de omgeving van het handlerproces terechtkomen. Deze omgevingsvariabelen bevatten de buildnaam, versienaam en andere variabelen. Lees hierover meer in de paragraaf “Een RPM-pakket bouwen”.

TFS instellen kwam neer op het opzetten van Pipeline. Voorheen verzamelden we alle Windows-projecten op Windows-agents, maar nu verschijnt er een Linux-agent - een Build-agent, die moet worden opgenomen in de build-groep, verrijkt met enkele artefacten, en verteld welk type projecten op deze Build-agent zal worden gebouwd en wijzig op de een of andere manier de pijplijn.

Identiteitsserver. ADFS is niet onze weg, wij gaan voor Open Source.

Laten we de componenten doornemen.

Magische doos

Bestaat uit vier delen.

.NET Core op Linux, DevOps te paard

Linux Build-agent. Linux, omdat we ervoor bouwen - het is logisch. Dit onderdeel verliep in drie stappen.

  • Configureer werknemers en niet alleen, aangezien er gedistribueerd werk aan het project werd verwacht.
  • Installeer .NET Core 1.x. Waarom 1.x als 2.0 al beschikbaar is in de standaardrepository? Omdat toen we met de ontwikkeling begonnen, de stabiele versie 1.09 was, en er werd besloten om het project daarop te baseren.
  • Git 2.x.

RPM-repository. RPM-pakketten moesten ergens worden opgeslagen. Er werd aangenomen dat we dezelfde bedrijfs-RPM-repository zouden gebruiken die beschikbaar is voor alle Linux-hosts. Dat is wat ze deden. De repositoryserver is geconfigureerd webhook die het vereiste RPM-pakket van de opgegeven locatie heeft gedownload. De pakketversie is door de Build-agent aan de webhook gerapporteerd.

GitLab. Aandacht! GitLab wordt hier niet door ontwikkelaars gebruikt, maar door de operationele afdeling om applicatieversies en pakketversies te controleren, de status van alle Linux-machines te bewaken en het recept op te slaan - alle Puppet-manifesten.

Puppet — lost alle controversiële problemen op en levert precies de configuratie die we van Gitlab willen.

We beginnen te duiken. Hoe werkt DLL-levering aan RPM?

Levering DDL aan RPM

Laten we zeggen dat we een rockster op het gebied van .NET-ontwikkeling hebben. Het maakt gebruik van Visual Studio en creëert een releasebranch. Daarna uploadt het het naar Git, en Git is hier een TFS-entiteit, dat wil zeggen, het is de applicatierepository waarmee de ontwikkelaar werkt.

.NET Core op Linux, DevOps te paard

Waarna TFS ziet dat er een nieuwe commit is binnengekomen. Welke app? In de TFS-instellingen staat een label dat aangeeft welke bronnen een bepaalde Build-agent heeft. In dit geval ziet hij dat we een .NET Core-project aan het bouwen zijn en selecteert hij een Linux Build-agent uit de pool.

De Build-agent ontvangt de bronnen en downloadt de benodigde afhankelijkheden uit de .NET-repository, npm, enz. en na het bouwen van de applicatie zelf en het daaropvolgende verpakken, wordt het RPM-pakket naar de RPM-repository gestuurd.

Aan de andere kant gebeurt het volgende. De engineer van de operations afdeling is direct betrokken bij de uitrol van het project: hij wijzigt de versies van pakketten in Hiera in de repository waar het applicatierecept is opgeslagen, waarna Puppet wordt geactiveerd Yum, haalt het nieuwe pakket op uit de repository en de nieuwe versie van de applicatie is klaar voor gebruik.

.NET Core op Linux, DevOps te paard

Alles is eenvoudig in woorden, maar wat gebeurt er in de Build-agent zelf?

Verpakking DLL-RPM

Projectbronnen en bouwtaak ontvangen van TFS. Bouw agent begint het project zelf op te bouwen op basis van bronnen. Het samengestelde project is verkrijgbaar als set DLL-bestanden, die zijn verpakt in een zip-archief om de belasting van het bestandssysteem te verminderen.

Het ZIP-archief wordt weggegooid naar de RPM-pakketbuildmap. Vervolgens initialiseert het Bash-script de omgevingsvariabelen, vindt de Build-versie, de projectversie, het pad naar de build-directory en voert RPM-build uit. Zodra de build is voltooid, wordt het pakket gepubliceerd naar lokale opslagplaats, die zich op de Build-agent bevindt.

Vervolgens van de Build-agent naar de server in de RPM-repository JSON-verzoek is verzonden met vermelding van de naam van de versie en build. Webhook, waar ik het eerder over had, downloadt juist dit pakket uit de lokale repository op de Build-agent en maakt de nieuwe assembly beschikbaar voor installatie.

.NET Core op Linux, DevOps te paard

Waarom dit specifieke pakketbezorgschema naar de RPM-repository? Waarom kan ik het samengestelde pakket niet onmiddellijk naar de repository sturen? Feit is dat dit een voorwaarde is om de veiligheid te kunnen garanderen. Dit scenario beperkt de mogelijkheid dat onbevoegde personen RPM-pakketten uploaden naar een server die toegankelijk is voor alle Linux-machines.

Versiebeheer van databases

Bij overleg met het ontwikkelingsteam bleek dat de jongens dichter bij MS SQL stonden, maar in de meeste niet-Windows-projecten gebruikten we PostgreSQL al met alle macht. Omdat we al besloten hadden om al het betaalde achterwege te laten, zijn we ook hier PostgreSQL gaan gebruiken.

.NET Core op Linux, DevOps te paard

In dit deel wil ik je vertellen hoe we de databaseversie hebben aangepast en hoe we hebben gekozen tussen Flyway en Entity Framework Core. Laten we eens kijken naar hun voor- en nadelen.

Tegens

Flyway gaat maar één kant op, wij we kunnen niet terugdraaien - dit is een aanzienlijk nadeel. Je kunt het op andere manieren vergelijken met Entity Framework Core - in termen van ontwikkelaarsgemak. U herinnert zich dat we dit op de voorgrond plaatsten, en het belangrijkste criterium was om niets te veranderen aan de Windows-ontwikkeling.

Voor Flyway ons er was een soort verpakking nodigzodat de jongens niet schrijven SQL-query's. Ze zijn veel dichter bij het opereren in OOP-termen. We schreven instructies voor het werken met databaseobjecten, genereerden een SQL-query en voerden deze uit. De nieuwe versie van de database is klaar, getest - alles is in orde, alles werkt.

Enty Framework Core heeft een minpunt - onder zware belasting bouwt suboptimale SQL-query's, en de opname in de database kan aanzienlijk zijn. Maar omdat we geen service met hoge belasting hebben, berekenen we de belasting niet in honderden RPS, we hebben deze risico's geaccepteerd en het probleem aan ons in de toekomst gedelegeerd.

Voors

Entiteit Framework Kern werkt out-of-the-box en is eenvoudig te ontwikkelenen Vliegweg Kan eenvoudig worden geïntegreerd in bestaande CI. Maar we maken het gemakkelijk voor ontwikkelaars :)

Oprolprocedure

Puppet ziet dat er een verandering in de pakketversie aankomt, inclusief degene die verantwoordelijk is voor de migratie. Eerst installeert het een pakket dat migratiescripts en databasegerelateerde functionaliteit bevat. Hierna wordt de applicatie die met de database werkt opnieuw opgestart. Vervolgens komt de installatie van de resterende componenten. De volgorde waarin pakketten worden geïnstalleerd en applicaties worden gestart, wordt beschreven in het Puppet-manifest.

Applicaties gebruiken gevoelige gegevens, zoals tokens en databasewachtwoorden. Dit alles wordt vanuit Puppet Master in de configuratie gehaald, waar ze in gecodeerde vorm worden opgeslagen.

TFS-problemen

Nadat we hadden besloten en beseften dat alles echt voor ons werkte, besloot ik te kijken naar wat er aan de hand was met de assemblages in TFS als geheel voor de Win-ontwikkelingsafdeling bij andere projecten - of we nu snel aan het bouwen/vrijgeven waren of niet, en ontdekte aanzienlijke snelheidsproblemen.

Het in elkaar zetten van een van de hoofdprojecten duurt 12-15 minuten - dat is lang, zo kun je niet leven. Een snelle analyse toonde een vreselijke teruggang in I/O aan, en dit was op arrays.

Nadat ik het component voor component had geanalyseerd, identificeerde ik drie brandpunten. Eerst - "Kaspersky-antivirus", waarmee bronnen op alle Windows Build-agents worden gescand. Seconde - Dakramen en raamkozijnen Indexeerder. Het was niet uitgeschakeld en alles werd tijdens het implementatieproces in realtime geïndexeerd op de Build-agents.

Derde - Npm-installatie. Het bleek dat we in de meeste pijpleidingen exact dit scenario gebruikten. Waarom is hij slecht? De Npm-installatieprocedure wordt uitgevoerd wanneer de afhankelijkheidsboom wordt gevormd pakket-lock.json, waar de versies van pakketten die zullen worden gebruikt om het project te bouwen, worden vastgelegd. Het nadeel is dat Npm install elke keer de nieuwste versies van pakketten van internet haalt, en dit kost veel tijd in het geval van een groot project.

Ontwikkelaars experimenteren soms op een lokale machine om te testen hoe een bepaald onderdeel of een heel project werkt. Soms bleek dat alles lokaal cool was, maar ze hebben het in elkaar gezet, uitgerold en niets werkte. We beginnen erachter te komen wat het probleem is - ja, verschillende versies van pakketten met afhankelijkheden.

beslissing

  • Bronnen in AV-uitzonderingen.
  • Indexering uitschakelen.
  • Ga naar npm ci.

De voordelen van npm ci zijn dat wij We verzamelen de afhankelijkheidsboom één keer, en wij krijgen de mogelijkheid om de ontwikkelaar ter beschikking te stellen huidige lijst met pakketten, waarmee hij lokaal kan experimenteren zoveel hij wil. Dit bespaart tijd ontwikkelaars die code schrijven.

Configuratie

Nu iets over de configuratie van de repository. Historisch gezien gebruiken we Nexus voor het beheren van repositories, inclusief Interne REPO. Deze interne repository bevat alle componenten die wij voor interne doeleinden gebruiken, bijvoorbeeld zelfgeschreven monitoring.

.NET Core op Linux, DevOps te paard

Wij gebruiken ook NuGet, omdat het betere caching heeft in vergelijking met andere pakketbeheerders.

Resultaat

Nadat we de Build Agents hadden geoptimaliseerd, werd de gemiddelde bouwtijd teruggebracht van 12 minuten naar 7 minuten.

Als we alle machines tellen die we voor Windows hadden kunnen gebruiken, maar in dit project naar Linux zijn overgestapt, hebben we ongeveer $ 10 bespaard, en dat is alleen maar op licenties, en meer als we rekening houden met de inhoud.

Plannen

Voor het volgende kwartaal waren we van plan om te werken aan het optimaliseren van de levering van code.

Overschakelen naar een vooraf gebouwde Docker-installatiekopie. TFS is een cool ding met veel plug-ins waarmee je in Pipeline kunt integreren, inclusief trigger-gebaseerde assemblage van bijvoorbeeld een Docker-image. We willen deze trigger voor dezelfde maken pakket-lock.json. Als de samenstelling van de componenten die worden gebruikt om het project te bouwen op de een of andere manier verandert, bouwen we een nieuwe Docker-image. Het wordt later gebruikt om de container met de samengestelde applicatie in te zetten. Dit is nu niet het geval, maar we zijn van plan om over te stappen naar een microservice-architectuur in Kubernetes, die zich actief ontwikkelt in ons bedrijf en al lange tijd productieoplossingen bedient.

Beknopt

Ik moedig iedereen aan om Windows weg te gooien, maar dat is niet omdat ik niet weet hoe ik het moet koken. De reden is dat de meeste Opensource-oplossingen dat wel zijn Linux-stapel. ben je oke besparen op hulpbronnen. Naar mijn mening behoort de toekomst toe aan Open Source-oplossingen op Linux met een krachtige community.

Sprekerprofiel van Alexander Sinchinov op GitHub.

DevOps-conf is een conferentie over de integratie van ontwikkel-, test- en exploitatieprocessen voor professionals door professionals. Is dat de reden waarom het project waar Alexander het over had? geïmplementeerd en werkend, en op de dag van het optreden waren er twee succesvolle releases. Op DevOps Conf bij RIT++ Op 27 en 28 mei komen er nog meer soortgelijke gevallen van beoefenaars. Je kunt nog steeds in het laatste rijtuig springen en een rapport indienen of neem de tijd boek ticket. Ontmoet ons in Skolkovo!

Bron: www.habr.com

Voeg een reactie