.NET Core på Linux, DevOps på hesteryggen

Vi utviklet DevOps så godt vi kunne. Vi var 8, og Vasya var den kuleste i Windows. Plutselig dro Vasya, og jeg hadde i oppgave å lansere et nytt prosjekt som ble levert av Windows-utvikling. Da jeg dumpet hele Windows-utviklingsstabelen på bordet, skjønte jeg at situasjonen var en smerte ...

Slik begynner historien Alexandra SinchinovaDevOpsConf. Da den ledende Windows-spesialisten forlot selskapet, lurte Alexander på hva han skulle gjøre nå. Bytt til Linux, selvfølgelig! Alexander vil fortelle deg hvordan han klarte å skape en presedens og overføre deler av Windows-utviklingen til Linux ved å bruke eksemplet på et fullført prosjekt for 100 000 sluttbrukere.

.NET Core på Linux, DevOps på hesteryggen

Hvordan enkelt og uanstrengt levere et prosjekt til RPM ved å bruke TFS, Puppet, Linux .NET core? Hvordan støtte versjonering av en prosjektdatabase hvis utviklingsteamet hører ordene Postgres og Flyway for første gang, og fristen er i overmorgen? Hvordan integreres med Docker? Hvordan motivere .NET-utviklere til å forlate Windows og smoothies til fordel for Puppet og Linux? Hvordan løse ideologiske konflikter hvis det verken er styrken, lysten eller ressursene til å opprettholde Windows i produksjon? Om dette, så vel som om Web Deploy, testing, CI, om praksisen for bruk av TFS i eksisterende prosjekter, og, selvfølgelig, om ødelagte krykker og fungerende løsninger, i transkripsjonen av Alexanders rapport.


Så, Vasya dro, oppgaven er på meg, utviklerne venter utålmodig med høygafler. Da jeg endelig skjønte at Vasya ikke kunne returneres, satte jeg i gang. Til å begynne med vurderte jeg prosentandelen av Win VM-er i flåten vår. Poengsummen var ikke i favør av Windows.

.NET Core på Linux, DevOps på hesteryggen

Siden vi aktivt utvikler DevOps, innså jeg at noe må endres i tilnærmingen til å levere en ny applikasjon. Det var bare én løsning - hvis mulig, overfør alt til Linux. Google hjalp meg - på det tidspunktet var .Net allerede blitt portert til Linux, og jeg innså at dette var løsningen!

Hvorfor .NET core i forbindelse med Linux?

Det var flere årsaker til dette. Mellom "betale penger" og "ikke betale", vil flertallet velge den andre - som meg. En lisens for MSDB koster rundt 1 dollar; vedlikehold av en flåte av virtuelle Windows-maskiner koster hundrevis av dollar. For et stort selskap er dette en stor utgift. Derfor sparing - første grunn. Ikke den viktigste, men en av de betydelige.

Virtuelle Windows-maskiner tar opp mer ressurser enn Linux-brødrene deres - de er tunge. Gitt omfanget til det store selskapet, valgte vi Linux.

Systemet er ganske enkelt integrert i eksisterende CI. Vi anser oss selv som progressive DevOps, vi bruker Bamboo, Jenkins og GitLab CI, så det meste av arbeidet vårt kjører på Linux.

Den siste grunnen er praktisk akkompagnement. Vi trengte å senke inngangsbarrieren for «eskorte» – gutta som forstår den tekniske delen, sørger for uavbrutt service og vedlikeholder tjenester fra andre linje. De var allerede kjent med Linux-stakken, så det er mye lettere for dem å forstå, støtte og vedlikeholde et nytt produkt enn å bruke ekstra ressurser på å forstå den samme funksjonaliteten til programvaren for Windows-plattformen.

Krav

Først og fremst - bekvemmeligheten av den nye løsningen for utviklere. Ikke alle av dem var klare for endring, spesielt etter at ordet Linux ble sagt. Utviklere vil ha deres favoritt Visual Studio, TFS med autotester for sammenstillinger og smoothies. Hvordan levering til produksjon skjer er ikke viktig for dem. Derfor bestemte vi oss for å ikke endre den vanlige prosessen og la alt være uendret for Windows-utvikling.

Trenger nytt prosjekt integreres i eksisterende CI. Skinnene var der allerede, og alt arbeidet måtte gjøres med hensyn til parametrene til konfigurasjonsstyringssystemet, aksepterte leveringsstandarder og overvåkingssystemer.

Enkel støtte og betjening, som en betingelse for minste inngangsterskel for alle nye deltakere fra ulike divisjoner og støtteavdelingen.

Frist - i går.

Vinn utviklingsgruppe

Hva jobbet Windows-teamet med da?

.NET Core på Linux, DevOps på hesteryggen

Nå kan jeg trygt si det IdentityServer4 er et kult gratis alternativ til ADFS med lignende muligheter, eller hva Entity Framework Core - et paradis for en utvikler, hvor du ikke trenger å bry deg med å skrive SQL-skript, men beskrive spørringer i databasen i OOP-termer. Men så, under diskusjonen om handlingsplanen, så jeg på denne stabelen som om den var sumerisk kileskrift, og gjenkjente bare PostgreSQL og Git.

På den tiden brukte vi aktivt Puppet som et konfigurasjonsstyringssystem. I de fleste av våre prosjekter brukte vi GitLab CI, Elastisk, balanserte høybelastningstjenester ved hjelp av HAProxy overvåket alt med Zabbix, leddbånd grafana и Prometheus, Jaeger, og alt dette snurret på jernbiter HPESXi på VMware. Alle vet det - en klassiker i sjangeren.

.NET Core på Linux, DevOps på hesteryggen

La oss se og prøve å forstå hva som skjedde før vi startet alle disse intervensjonene.

Hva skjedde

TFS er et ganske kraftig system som ikke bare leverer kode fra utvikleren til den endelige produksjonsmaskinen, men som også har et sett for svært fleksibel integrasjon med ulike tjenester – for å gi CI på kryssplattformnivå.

.NET Core på Linux, DevOps på hesteryggen
Tidligere var dette solide vinduer. TFS brukte flere Build-agenter, som ble brukt til å sette sammen mange prosjekter. Hver agent har 3-4 arbeidere for å parallellisere oppgaver og optimalisere prosessen. Så, i henhold til utgivelsesplanene, leverte TFS den nybakte Build til Windows-applikasjonsserveren.

Hva ønsket vi å oppnå?

Vi bruker TFS for levering og utvikling, og kjører applikasjonen på en Linux applikasjonsserver, og det er en slags magi mellom dem. Dette Magisk boks og det er saltet av arbeidet som ligger foran oss. Før jeg tar den fra hverandre, tar jeg et skritt til side og sier noen ord om applikasjonen.

Prosjekt

Applikasjonen gir funksjonalitet for håndtering av forhåndsbetalte kort.

.NET Core på Linux, DevOps på hesteryggen

kunde

Det var to typer brukere. Første fått tilgang ved å logge på med et SSL SHA-2-sertifikat. U den andre det var tilgang med pålogging og passord.

HAProxy

Deretter gikk klientforespørselen til HAProxy, som løste følgende problemer:

  • primær autorisasjon;
  • SSL oppsigelse;
  • tuning av HTTP-forespørsler;
  • kringkastingsforespørsler.

Klientsertifikatet ble verifisert langs kjeden. Vi - myndighet og dette har vi råd til, siden vi selv utsteder sertifikater til servicekunder.

Vær oppmerksom på det tredje punktet, vi kommer tilbake til det litt senere.

Backend

De planla å lage backend på Linux. Backend samhandler med databasen, laster den nødvendige listen over privilegier og gir deretter, avhengig av hvilke privilegier den autoriserte brukeren har, tilgang til å signere økonomiske dokumenter og sende dem for utførelse, eller generere en slags rapport.

Besparelser med HAProxy

I tillegg til de to kontekstene som hver klient navigerte, var det også en identitetskontekst. IdentityServer4 lar deg bare logge inn, dette er en gratis og kraftig analog for ADFS - Active Directory Federation Services.

Identitetsforespørselen ble behandlet i flere trinn. Første skritt - kunde kom inn i backend, som kommuniserte med denne serveren og sjekket tilstedeværelsen av et token for klienten. Hvis den ikke ble funnet, ble forespørselen returnert tilbake til konteksten den kom fra, men med en omdirigering, og med viderekoblingen gikk den til identitet.

Andre trinn - forespørselen ble mottatt til autorisasjonssiden i IdentityServer, hvor klienten registrerte seg, og det etterlengtede tokenet dukket opp i IdentityServer-databasen.

Tredje trinn - klienten ble omdirigert tilbake til konteksten den kom fra.

.NET Core på Linux, DevOps på hesteryggen

IdentityServer4 har en funksjon: den returnerer svaret på returforespørselen via HTTP. Uansett hvor mye vi slet med å sette opp serveren, uansett hvor mye vi opplyste oss med dokumentasjonen, hver gang vi mottok en første klientforespørsel med en URL som kom via HTTPS, og IdentityServer returnerte samme kontekst, men med HTTP. Vi ble sjokkert! Og vi overførte alt dette gjennom identitetskonteksten til HAProxy, og i overskriftene måtte vi endre HTTP-protokollen til HTTPS.

Hva er forbedringen og hvor sparte du?

Vi sparte penger ved å bruke en gratis løsning for å autorisere en gruppe brukere, ressurser, siden vi ikke plasserte IdentityServer4 som en egen node i et eget segment, men brukte den sammen med backend på samme server der backend av applikasjonen kjører .

Hvordan det skal fungere

Så, som jeg lovet - Magic Box. Vi forstår allerede at vi garantert vil gå mot Linux. La oss formulere spesifikke oppgaver som krevde løsninger.

.NET Core på Linux, DevOps på hesteryggen

Dukke manifesterer seg. For å levere og administrere tjeneste- og applikasjonskonfigurasjon, måtte det skrives kule oppskrifter. En blyantrull viser veltalende hvor raskt og effektivt det ble gjort.

Leverings metode. Standarden er RPM. Alle forstår at i Linux kan du ikke klare deg uten det, men selve prosjektet, etter montering, var et sett med kjørbare DLL-filer. Det var rundt 150 av dem, prosjektet var ganske vanskelig. Den eneste harmoniske løsningen er å pakke denne binære filen inn i RPM og distribuere applikasjonen fra den.

Versjonskontroll. Vi måtte gi ut veldig ofte, og vi måtte bestemme hvordan vi skulle danne pakkenavnet. Dette er et spørsmål om nivået av integrasjon med TFS. Vi hadde en byggeagent på Linux. Når TFS sender en oppgave til en behandler - arbeider - til Build-agenten, sender den også en haug med variabler som havner i miljøet til behandlerprosessen. Disse miljøvariablene inneholder byggenavnet, versjonsnavnet og andre variabler. Les mer om dette i delen "Bygge en RPM-pakke".

Sette opp TFS kom ned til å sette opp Pipeline. Tidligere samlet vi alle Windows-prosjekter på Windows-agenter, men nå dukker det opp en Linux-agent - en Build-agent, som må inkluderes i byggegruppen, beriket med noen artefakter og fortalt hvilken type prosjekter som skal bygges på denne Build-agenten , og på en eller annen måte endre rørledningen.

IdentityServer. ADFS er ikke vår måte, vi går for åpen kildekode.

La oss gå gjennom komponentene.

Magisk boks

Består av fire deler.

.NET Core på Linux, DevOps på hesteryggen

Linux Build-agent. Linux, fordi vi bygger for det - det er logisk. Denne delen ble gjort i tre trinn.

  • Konfigurer arbeidere og ikke alene, siden det var forventet distribuert arbeid på prosjektet.
  • Installer .NET Core 1.x. Hvorfor 1.x når 2.0 allerede er tilgjengelig i standardlageret? For da vi startet utviklingen var den stabile versjonen 1.09, og det ble besluttet å lage prosjektet basert på den.
  • Git 2.x.

RPM-lager. RPM-pakker måtte lagres et sted. Det ble antatt at vi ville bruke det samme bedriftens RPM-lager som er tilgjengelig for alle Linux-verter. Det var det de gjorde. Lagringsserveren er konfigurert nettkrok som lastet ned den nødvendige RPM-pakken fra den angitte plasseringen. Pakkeversjonen ble rapportert til webhook av Build-agenten.

GitLab. Merk følgende! GitLab her brukes ikke av utviklere, men av driftsavdelingen for å kontrollere applikasjonsversjoner, pakkeversjoner, overvåke statusen til alle Linux-maskiner, og den lagrer oppskriften - alle Puppet-manifester.

Puppet — løser alle kontroversielle problemer og leverer akkurat den konfigurasjonen vi ønsker fra Gitlab.

Vi begynner å dykke. Hvordan fungerer DLL-levering til RPM?

Levering DDL til RPM

La oss si at vi har en .NET utviklingsrockestjerne. Den bruker Visual Studio og lager en utgivelsesgren. Etter det laster den det opp til Git, og Git her er en TFS-enhet, det vil si at det er applikasjonslageret som utvikleren jobber med.

.NET Core på Linux, DevOps på hesteryggen

Deretter ser TFS at en ny commit har kommet. Hvilken app? I TFS-innstillingene er det en etikett som indikerer hvilke ressurser en bestemt Build-agent har. I dette tilfellet ser han at vi bygger et .NET Core-prosjekt og velger en Linux Build-agent fra bassenget.

Build-agenten mottar kildene og laster ned de nødvendige avhengig fra .NET-lageret, npm osv. og etter å ha bygget selve applikasjonen og påfølgende pakking, sender RPM-pakken til RPM-lageret.

På den annen side skjer følgende. Driftsavdelingsingeniøren er direkte involvert i utrullingen av prosjektet: han endrer versjonene av pakkene inn Hiera i depotet hvor applikasjonsoppskriften er lagret, hvoretter Puppet trigger yum, henter den nye pakken fra depotet, og den nye versjonen av applikasjonen er klar til bruk.

.NET Core på Linux, DevOps på hesteryggen

Alt er enkelt i ord, men hva skjer inne i selve Build-agenten?

Emballasje DLL RPM

Mottatt prosjektkilder og byggeoppgave fra TFS. Byggeagent begynner å bygge prosjektet selv fra kilder. Det sammensatte prosjektet er tilgjengelig som et sett DLL-filer, som er pakket i et zip-arkiv for å redusere belastningen på filsystemet.

ZIP-arkivet blir kastet til RPM-pakkebyggekatalogen. Deretter initialiserer Bash-skriptet miljøvariablene, finner Build-versjonen, prosjektversjonen, banen til build-katalogen og kjører RPM-build. Når byggingen er fullført, publiseres pakken til lokalt depot, som er plassert på Build-agenten.

Deretter fra Build-agenten til serveren i RPM-lageret JSON-forespørsel er sendt angir navnet på versjonen og bygget. Webhook, som jeg snakket om tidligere, laster ned denne pakken fra det lokale depotet på Build-agenten og gjør den nye sammenstillingen tilgjengelig for installasjon.

.NET Core på Linux, DevOps på hesteryggen

Hvorfor denne spesielle pakkeleveringsordningen til RPM-lageret? Hvorfor kan jeg ikke umiddelbart sende den sammensatte pakken til depotet? Faktum er at dette er en betingelse for å ivareta sikkerheten. Dette scenariet begrenser muligheten for at uautoriserte personer laster opp RPM-pakker til en server som er tilgjengelig for alle Linux-maskiner.

Databaseversjon

På en konsultasjon med utviklingsteamet viste det seg at gutta var nærmere MS SQL, men i de fleste ikke-Windows-prosjekter brukte vi allerede PostgreSQL med all kraft. Siden vi allerede hadde bestemt oss for å forlate alt betalt, begynte vi å bruke PostgreSQL her også.

.NET Core på Linux, DevOps på hesteryggen

I denne delen vil jeg fortelle deg hvordan vi versjonerte databasen og hvordan vi valgte mellom Flyway og Entity Framework Core. La oss se på deres fordeler og ulemper.

Cons

Flyway går bare én vei, vi vi kan ikke rulle tilbake - Dette er en betydelig ulempe. Du kan sammenligne det med Entity Framework Core på andre måter - når det gjelder utviklervennlighet. Du husker at vi satte dette på spissen, og hovedkriteriet var å ikke endre noe for Windows-utvikling.

For Flyway oss en slags innpakning var nødvendigslik at gutta ikke skriver SQL-spørringer. De er mye nærmere å operere i OOP-termer. Vi skrev instruksjoner for arbeid med databaseobjekter, genererte en SQL-spørring og utførte den. Den nye versjonen av databasen er klar, testet - alt er bra, alt fungerer.

Entity Framework Core har et minus - under tung belastning bygger suboptimale SQL-spørringer, og nedtrekket i databasen kan være betydelig. Men siden vi ikke har en høybelastningstjeneste, beregner vi ikke belastningen i hundrevis av RPS, vi aksepterte disse risikoene og delegerte problemet til fremtidige oss.

Pros

Entity Framework Core fungerer ut av esken og er enkel å utvikle, og Flyway Integrerer enkelt i eksisterende CI. Men vi gjør det praktisk for utviklere :)

Roll-up prosedyre

Puppet ser at det kommer en endring i pakkeversjonen, inkludert den som er ansvarlig for migreringen. Først installerer den en pakke som inneholder migreringsskript og databaserelatert funksjonalitet. Etter dette startes programmet som fungerer med databasen på nytt. Deretter kommer installasjonen av de resterende komponentene. Rekkefølgen som pakker installeres og applikasjoner startes i, er beskrevet i Puppet-manifestet.

Applikasjoner bruker sensitive data, som tokens, databasepassord, alt dette trekkes inn i konfigurasjonen fra Puppet master, hvor de lagres i kryptert form.

TFS problemer

Etter at vi bestemte oss og skjønte at alt virkelig fungerte for oss, bestemte jeg meg for å se på hva som foregikk med monteringene i TFS som helhet for Win utviklingsavdelingen på andre prosjekter - enten vi bygget/slipper raskt eller ikke, og oppdaget betydelige problemer med hastigheten.

Et av hovedprosjektene tar 12-15 minutter å sette sammen - det er lang tid, du kan ikke leve slik. En rask analyse viste en forferdelig nedgang i I/O, og dette var på arrays.

Etter å ha analysert det komponent for komponent, identifiserte jeg tre foci. Først - "Kaspersky antivirus", som skanner kilder på alle Windows Build-agenter. Sekund - Windows Indekser. Den ble ikke deaktivert, og alt ble indeksert i sanntid på Build-agentene under distribusjonsprosessen.

Tredje - Npm installasjon. Det viste seg at vi i de fleste rørledninger brukte akkurat dette scenariet. Hvorfor er han dårlig? Npm-installasjonsprosedyren kjøres når avhengighetstreet dannes i package-lock.json, hvor versjonene av pakkene som skal brukes til å bygge prosjektet, registreres. Ulempen er at Npm install trekker opp de nyeste versjonene av pakker fra Internett hver gang, og dette tar mye tid i tilfelle et stort prosjekt.

Utviklere eksperimenterer noen ganger på en lokal maskin for å teste hvordan en bestemt del eller hele prosjektet fungerer. Noen ganger viste det seg at alt var kult lokalt, men de satte det sammen, rullet det ut, og ingenting fungerte. Vi begynner å finne ut hva problemet er - ja, forskjellige versjoner av pakker med avhengigheter.

beslutning

  • Kilder i AV-unntak.
  • Deaktiver indeksering.
  • Gå til npm ci.

Fordelene med npm ci er at vi Vi samler avhengighetstreet én gang, og vi får muligheten til å gi utvikleren gjeldende liste over pakker, som han kan eksperimentere lokalt med så mye han vil. Dette sparer tid utviklere som skriver kode.

Konfigurasjon

Nå litt om depotkonfigurasjonen. Historisk sett bruker vi Nexus for å administrere depoter, inkludert Intern REPO. Dette interne depotet inneholder alle komponentene vi bruker til interne formål, for eksempel selvskrevet overvåking.

.NET Core på Linux, DevOps på hesteryggen

Vi bruker også nuget, siden den har bedre caching sammenlignet med andre pakkebehandlere.

Resultat

Etter at vi optimaliserte byggeagentene, ble den gjennomsnittlige byggetiden redusert fra 12 minutter til 7.

Hvis vi teller alle maskinene som vi kunne ha brukt for Windows, men byttet til Linux i dette prosjektet, sparte vi rundt $10 000. Og det er bare på lisenser, og mer hvis vi tar hensyn til innholdet.

Planer

I neste kvartal planla vi å jobbe med å optimalisere kodelevering.

Bytter til et forhåndsbygget Docker-bilde. TFS er en kul ting med mange plugins som lar deg integrere i Pipeline, inkludert trigger-basert sammenstilling av for eksempel et Docker-bilde. Vi ønsker å gjøre denne triggeren for den samme package-lock.json. Hvis sammensetningen av komponentene som brukes til å bygge prosjektet på en eller annen måte endres, bygger vi et nytt Docker-bilde. Den brukes senere til å distribuere beholderen med den sammensatte applikasjonen. Dette er ikke tilfelle nå, men vi planlegger å bytte til en mikrotjenestearkitektur i Kubernetes, som aktivt utvikler seg i selskapet vårt og har betjent produksjonsløsninger i lang tid.

Oppsummering

Jeg oppfordrer alle til å kaste Windows, men det er ikke fordi jeg ikke vet hvordan jeg skal lage det. Årsaken er at de fleste Opensource-løsninger er det Linux-stabel. er du ok spare på ressurser. Etter min mening tilhører fremtiden Open Source-løsninger på Linux med et kraftig fellesskap.

Foredragsholderprofil til Alexander Sinchinov på GitHub.

DevOps Conf er en konferanse om integrering av utviklings-, test- og driftsprosesser for fagfolk av fagfolk. Det er derfor prosjektet som Alexander snakket om? implementert og fungerer, og på forestillingsdagen var det to vellykkede utgivelser. På DevOps Conf på RIT++ 27. og 28. mai kommer det enda flere lignende saker fra utøvere. Du kan fortsatt hoppe inn i siste vogn og Levere en rapport eller ta deg god tid å bestille billett. Møt oss i Skolkovo!

Kilde: www.habr.com

Legg til en kommentar