.NET Core pe Linux, DevOps în armonie

Am dezvoltat DevOps cât am putut. Eram 8 oameni, iar Vasya era cel mai bun pe Windows. Dintr-o dată, Vasya a plecat, iar eu am avut de rezolvat sarcina de a lansa un nou proiect care să furnizeze dezvoltare Windows. Când am răsturnat pe masă întregul stack de dezvoltare Windows, am realizat că situația era dureroasă…

Așa începe povestea Alexandra Sinchinova pe DevOpsConf. Când specialistul nostru principal pe Windows a părăsit compania, Alexandra s-a întrebat ce ar trebui să facem acum. Să trecem pe Linux, desigur! Alexandra va vorbi despre cum a reușit să creeze un precedent și să transfere o parte a dezvoltării Windows pe Linux, folosind ca exemplu un proiect realizat pentru 100.000 de utilizatori finali.

.NET Core pe Linux, DevOps în armonie

Cum să livrăm un proiect în RPM, folosind TFS, Puppet, Linux .NET core, într-un mod simplu și fără stres? Cum să gestionăm versiunea bazei de date a proiectului, dacă dezvoltatorii auzit pentru prima dată cuvintele Postgres și Flyway, iar termenul limită este poimâine? Cum să integrăm cu Docker? Cum să motivăm dezvoltatorii .NET să renunțe la Windows și sucuri în favoarea Puppet și Linux? Cum să rezolvăm conflictele ideologice, dacă nu avem forță, dorință sau resurse pentru a menține Windows în producție? Despre asta, și despre Web Deploy, testare, CI, despre practicile de utilizare a TFS în proiectele existente, și, desigur, despre soluții improvizate și funcționale, ne va povesti Alexandra.

Redați video

Deci, Vasya a plecat, responsabilitatea este acum a mea, iar dezvoltatorii așteaptă cu nerăbdare. Când am realizat în cele din urmă că nu-l voi putea aduce înapoi pe Vasya, m-am apucat de treabă. Mai întâi, am evaluat procentul de Win VM din parcul nostru. Numărul nu era în favoarea Windows.

.NET Core pe Linux, DevOps în armonie

Deoarece dezvoltăm activ DevOps, am realizat că trebuie să schimbăm ceva în abordarea lansării noii aplicații. Decizia a fost clară — să transferăm totul pe Linux, pe cât posibil. Google m-a ajutat – în acel moment, .Net fusese deja portat pe Linux, iar eu am realizat că aceasta era soluția!

De ce .NET core în combinație cu Linux?

Existau câteva motive. Între "a plăti bani" și "a nu plăti", majoritatea aleg cea din urmă — la fel ca mine. Licența pentru MSDB costă aproximativ 1.000 $, iar întreținerea parcului de mașini virtuale Windows se ridică la sute de dolari. Pentru o companie mare, acestea sunt cheltuieli semnificative. Așadar, economia — este primul motiv. Nu este cel mai important, dar este unul dintre cele semnificative.

Mașinile virtuale Windows consumă mai multe resurse decât frații lor din Linux — sunt greoaie. Având în vedere dimensiunea unei companii mari, am ales Linux.

Sistemul se integrează ușor în CI existent. Ne considerăm DevOps progresivi, folosim Bamboo, Jenkins și GitLab CI, așa că cea mai mare parte a tot ce facem se desfășoară pe Linux.

Ultimul motiv este suportul convenabil. A trebuit să reducem pragul de intrare pentru „susținători” - persoanele care înțeleg partea tehnică, asigură continuitatea și întrețin serviciile de nivelul doi. Aceștia erau deja familiarizați cu stiva Linux, așa că le este mult mai ușor să înțeleagă noul produs, să-l susțină și să-l întrețină decât să investească resurse suplimentare pentru a învăța un software similar pentru platforma Windows.

Cerințe

Primul și cel mai important este comoditatea noii soluții pentru dezvoltatori. Nu toți dintre ei au fost pregătiți pentru schimbare, mai ales după ce au auzit cuvântul Linux. Dezvoltatorii doresc să folosească Visual Studio preferată, TFS cu teste automate de build și smoothie-uri. Cum se desfășoară livrarea în producție – nu le pasă. De aceea, am decis să nu schimbăm procesul familiar și să lăsăm totul neschimbat pentru dezvoltarea pe Windows.

Noul proiect trebuie să fie integrat în CI existent. Au existat deja căile, iar întreaga muncă a trebuit să fie realizată în conformitate cu parametrii sistemului de gestionare a configurației, standardele de livrare acceptate și sistemele de monitorizare.

Ușurința de suport și operare, ca o condiție pentru un prag minim de intrare pentru toți noii participanți din diferite departamente și din departamentul de suport.

Termenul limită a fost ieri.

Grupul de dezvoltare Win

Cu ce lucra echipa Windows?

.NET Core pe Linux, DevOps în armonie

Acum pot spune cu încredere că IdentityServer4 este o alternativă gratuită grozavă la ADFS cu capacități similare, sau că Entity Framework Core este un paradis pentru dezvoltatori, unde pot evita scrierea scripturilor SQL, descriind interogările în BD în termeni de OOP. Dar atunci, în timpul discuției planului de acțiune, am privit această stivă ca pe o scriere cuneiformă sumereană, recunoscând doar PostgreSQL și Git.

În acel moment foloseam activ Puppet ca sistem de gestionare a configurației. În majoritatea proiectelor noastre am utilizat GitLab CI, Elastic, am echilibrat servicii cu sarcină mare folosind HAProxy, am monitorizat totul cu ajutorul Zabbix, setul Grafana și Prometheus, Jaeger, și totul rula pe echipamentele HP c ESXi pe VMware. Toată lumea cunoaște - clasică.

.NET Core pe Linux, DevOps în armonie

Să vedem și să încercăm să înțelegem ce se întâmpla înainte de a începe toate aceste intervenții.

Ce a fost

TFS este un sistem destul de puternic, care nu doar livrează codul de la dezvoltator la serverul de producție final, ci are și un set de integrare foarte flexibil cu diferite servicii - pentru a asigura CI la un nivel multiplatformă.

.NET Core pe Linux, DevOps în armonie
În trecut, erau doar feronerie la fereastra. TFS folosea mai mulți agenți de construire, pe care se adunau multe proiecte. În fiecare agent erau 3-4 lucrători, pentru a paraleliza sarcinile și a optimiza procesul. Apoi, conform planurilor de lansare, TFS livra build-ul proaspăt pe serverul de aplicații Windows.

La ce voiam să ajungem

Pentru livrare și dezvoltare folosim TFS, iar aplicația este rulată pe un server de aplicații Linux, și între ele există o anumită magie. Acest Magic Box este sarea muncii viitoare. Înainte de a-l descompune în părți, voi face un pas în lateral și voi spune câteva cuvinte despre aplicație.

Proiect

Aplicația oferă funcționalitate pentru operarea cardurilor preplătite.

.NET Core pe Linux, DevOps în armonie

Client

Au existat două tipuri de utilizatori. Primul a avut acces autentificându-se printr-un certificat SSL SHA-2. Utilizatorul a doua a avut acces prin login și parolă.

HAProxy

Apoi, cererea clientului ajungea în HAProxy, care rezolva următoarele sarcini:

  • autentificarea inițială;
  • terminarea SSL;
  • optimizarea cererilor HTTP;
  • translatarea cererilor.

Verificarea certificatului clientului se realiza printr-un lanț. Noi - authority și ne putem permite asta, deoarece emitem noi înșine certificate clienților serviciului.

Rețineți punctul trei, ne vom întoarce la el puțin mai târziu.

Backend

Backend-ul era planificat să fie realizat pe Linux. Backend-ul interacționează cu baza de date, încarcă lista necesară de privilegii și apoi, în funcție de privilegii deținute de utilizatorul autentificat, oferă acces pentru semnarea documentelor financiare și trimiterea acestora pentru execuție sau generarea unui raport.

Economia cu HAProxy

Pe lângă cele două contexte prin care au trecut fiecare dintre clienți, mai exista un context de identitate. IdentityServer4 care permite autentificarea, acesta fiind un echivalent gratuit și puternic pentru ADFS — Active Directory Federation Services.

Cererea în identitate era procesată în câteva etape. Prima etapă - client ajungea în backend, care schimbă date cu acest server și verifica existența unui token pentru client. Dacă nu îl găsea – cererea era returnată înapoi la contextul din care a venit, dar deja cu un redirect, și cu redirectul mergea la identity.

Pasul doi – cererea ajungea pe pagina de autentificare în IdentityServer, unde clientul se înregistra, iar în baza de date a IdentityServer apărea acel așteptat token.

Pasul trei – clientul era redirecționat înapoi la contextul din care a venit.

.NET Core pe Linux, DevOps în armonie

IdentityServer4 are o particularitate: răspunsul la cererea inversă este returnat prin HTTP. Indiferent cât de mult ne-am chinuit cu configurarea serverului, cât de mult ne-am informat din documentație, de fiecare dată primeam cererea inițială a clientului cu URL-ul venit prin HTTPS, iar IdentityServer returna același context, dar cu HTTP. Eram șocați! Și am trecut totul prin contextul identity pe HAProxy, iar în headers a trebuit să modificăm protocolul HTTP în HTTPS.

Care este îmbunătățirea și unde am economisit?

Am economisit bani folosind o soluție gratuită pentru autentificarea unui grup de utilizatori, resurse, deoarece nu am desfășurat IdentityServer4 ca un nod separat într-un segment separat, ci l-am folosit împreună cu backend-ul pe același server pe care rulează backend-ul aplicației.

Cum ar trebui să funcționeze

Așadar, așa cum am promis – Magic Box. Deja înțelegem că ne îndreptăm garantat spre Linux. Să formulăm sarcinile concrete care necesitau soluționare.

.NET Core pe Linux, DevOps în armonie

Manifestele Puppet. Pentru a livra și gestiona configurația serviciului și aplicației, a fost necesar să scriem rețete excelente. Un mic rola cu un creion arată cât de repede și calitativ a fost realizat acest lucru.

Metoda de livrare. Standardul este RPM. Toată lumea înțelege că în Linux nu poți fără el, dar proiectul în sine, după compilare, consta dintr-un set de fișiere DLL executabile. Au fost aproximativ 150, proiectul destul de greu. Soluția harmonică unică este să împachetăm această binaritate în RPM și din ea să desfășurăm aplicația.

Versionare. A trebuit să lansăm foarte des și a fost necesar să decidă cum să formăm numele pachetului. Aceasta este o problemă la nivelul integrării cu TFS. Agentul de build l-am avut pe Linux. Când TFS trimite o sarcină către procesor - worker - pe agentul de build, el îi transmite și un set de variabile, care ajung în mediul procesului procesorului. În aceste variabile de mediu se transmite numele Build, numele versiunii și alte variabile. Mai multe detalii despre aceasta în secțiunea „construirea pachetului RPM”.

Configurarea TFS se concentra pe configurarea Pipeline-ului. În trecut, am construit toate proiectele Windows pe agenți Windows, iar acum apare agentul Linux - agentul de build, care trebuie inclus în grupul de construcție, îmbogățit cu anumite artefacte, să i se spună ce tip de proiecte vor fi create pe acest agent de build și să modifice Pipeline-ul.

IdentityServer. ADFS nu este calea noastră, susținem Open Source.

Haideți să trecem prin componente.

Magic Box

Se compune din patru părți.

.NET Core pe Linux, DevOps în armonie

Agent de build Linux. Linux, pentru că construim pentru el - este logic. Această parte a fost realizată în trei pași.

  • Configurează worker-ii și nu unul, deoarece era planificată o muncă distribuită asupra proiectului.
  • Instalează .NET Core 1.x. De ce exact 1.x, când 2.0 este deja disponibil în depozitul standard? Pentru că, atunci când am început dezvoltarea, versiunea stabilă era 1.09, iar proiectul a fost decis să fie realizat pentru aceasta.
  • Git 2.x.

Repository RPM. Pachetele RPM trebuiau stocate undeva. Se presupunea că vom folosi același repository RPM corporativ, care este disponibil pentru toate gazdele Linux. Așa am procedat. Pe serverul repository-ului a fost configurat webhook care descărca pachetul RPM necesar din locul specificat. Versiunea pachetului era comună webhook-ului de către agentul de build.

GitLab. Atenție! GitLab aici este folosit nu de dezvoltatori, ci de departamentul de exploatare pentru a controla versiunile aplicației, versiunile pachetelor, starea tuturor mașinilor Linux și aici se păstrează rețeta - toate manifestele Puppet.

Puppet - rezolvă toate problemele disputate și livrează exact configurația pe care o dorim, din GitLab.

Începem să ne aprofundăm. Cum se desfășoară livrarea DLL în RPM?

Livrarea DLL în RPM

Să presupunem că avem o stea a dezvoltării în .NET. El folosește Visual Studio și creează o ramură de lansare. După aceea, o încarcă în Git, iar Git aici este o entitate TFS, adică acesta este repository-ul aplicației cu care lucrează dezvoltatorul.

.NET Core pe Linux, DevOps în armonie

După care TFS vede că a sosit un nou commit. Ce aplicație? În setările TFS există o etichetă care indică resursele de care dispune fiecare Build-agent. În acest caz, el vede că adunăm un proiect .NET Core și alege Build-agent-ul Linux din pool.

Build-agentul primește sursele, descarcă necesarul dependencies din repositoriu .NET, npm etc. și, după construirea aplicației propriu-zise și pachetului ulterioare, trimite pachetul RPM în repositoriu RPM.

Pe de altă parte, se întâmplă următoarele. Inginerul din departamentul de exploatare se ocupă direct cu release-ul proiectului: modifică versiunile pachetelor în Hiera din repositoriu, unde se află rețeta aplicației, după care Puppet declanșează Yum, preia noul pachet din repositoriu, iar noua versiune a aplicației este gata de utilizare.

.NET Core pe Linux, DevOps în armonie

Pe hârtie totul este simplu, dar ce se întâmplă în interior, pe Build-agent?

Pachetizarea DLL RPM

S-au primit sursele proiectului și sarcina de construire de la TFS. Build-agentul inițiază construcția proiectului din surse. Proiectul construit este disponibil sub formă de multe fișiere DLL, care sunt pachetate într-un arhivă zip pentru a reduce sarcina pe sistemul de fișiere.

Arhiva ZIP este aruncată în directorul de construcție al pachetului RPM. Apoi, un script Bash inițiază variabilele de mediu, află versiunea Build, versiunea proiectului, calea către directorul de construcție și inițiază RPM-build. La finalizarea construcției, pachetul este publicat în repositorio local, care se află pe Build-agent.

Apoi, de pe Build-agent, pe serverul din repositoriile RPM se trimite o solicitare JSON cu indicația numelui versiunii și a build-ului. Webhook-ul despre care am vorbit mai devreme descarcă acest pachet din repositoriul local de pe Build-agent și face noua construcție disponibilă pentru instalare.

.NET Core pe Linux, DevOps în armonie

De ce tocmai acest sistem de livrare a pachetului în repositoriul RPM? De ce nu se poate trimite direct pachetul construit în repositoriu? Problema constă în faptul că aceasta este o condiție pentru asigurarea securității. Un astfel de scenariu limitează posibilitatea încărcării neautorizate a pachetelor RPM de către persoane străine pe serverul accesibil tuturor mașinilor Linux.

Versionarea Bazei de Date

În cadrul unei consilieri cu dezvoltarea, s-a aflat că echipei îi place mai mult MS SQL, dar în majoritatea proiectelor non-Windows foloseam deja PostgreSQL. Deoarece am decis să renunțăm la tot ce este plătit, am început să folosim PostgreSQL și aici.

.NET Core pe Linux, DevOps în armonie

În această secțiune vreau să explic cum am realizat versiunea bazei de date și cum am ales între Flyway și Entity Framework Core. Haideți să examinăm avantajele și dezavantajele lor.

Dezavantaje

Flyway funcționează într-o singură direcție, noi nu putem reveni înapoi — aceasta este o dezavantajare semnificativă. Compararea cu Entity Framework Core se poate face în funcție de alte criterii — din perspectiva confortului dezvoltatorului. Îți amintești că acesta a fost pus în prim-plan, iar criteriul principal a fost să nu modificăm nimic pentru dezvoltarea pe Windows.

Pentru Flyway, aveam nevoie de un fel de wrapper , astfel încât colegii să nu scrieinterogări SQL . Le este mult mai aproape să opereze în termeni de OOP. Am redactat instrucțiuni despre cum să lucrăm cu obiectele bazei de date, s-a format interogarea SQL și a fost executată. Noua versiune a bazei de date este gata, a fost testată — totul este bine, totul funcționează.Entity Framework Core are un dezavantaj — la sarcini mari, acesta

construiește interogări SQL suboptimale , iar impactul asupra bazei de date poate fi semnificativ. Dar, deoarece serviciul nostru nu este foarte solicitat, nu calculăm sarcina în sute de RPS, am acceptat aceste riscuri și am delegat problema viitorului nostru.funcționează din cutie și este convenabil pentru dezvoltare

Advantages

Entity Framework Core , iar Flywayse integrează ușor în CI existent . Dar noi ne străduim să facem viața dezvoltatorilor mai ușoară :)Procedura de executare

Puppet observă că a avut loc o modificare a versiunii pachetelor, inclusiv pachetul responsabil pentru migrare. În primul rând, instalează pachetul care conține scripturile de migrare și funcționalitatea legată de baza de date. După aceea, aplicația care lucrează cu baza de date este repornită. Apoi urmează instalarea celorlalte componente. Ordinea instalării pachetelor și a lansării aplicațiilor este descrisă în manifestul Puppet.

Aplicațiile utilizează date sensibile, cum ar fi token-uri, parole pentru baza de date, toate acestea fiind extrase din configurația de la Puppet master, unde sunt stocate în formă criptată.

Problemele TFS

După ce ne-am hotărât și am realizat că totul funcționează, am decis să verific ce se întâmplă cu construcțiile în TFS, în general pentru departamentul de dezvoltare Windows în cadrul altor proiecte — dacă ne compilăm/lansăm rapid sau nu, și am descoperit probleme semnificative cu viteza.

Unul dintre proiectele principale se compilează în 12-15 minute — acest lucru este prea mult, nu se poate trăi așa. O analiză rapidă a arătat o scădere drastică a I/O, și aceasta pe arii de stocare.

După o analiză detaliată, am identificat trei focare. Primul —

„Kaspersky antivirus” „Kaspersky antivirus”, care scanează sursele pe toate agenții de build Windows. Al doilea - Windows Indexer. Nu a fost dezactivat și pe agenții de build, totul a fost indexat în timp real în procesul de deploy.

Al treilea - Npm install. S-a dovedit că în majoritatea pipeline-urilor am folosit exact acest script. Ce este greșit? Procedura Npm install se lansează la formarea arborilor de dependențe în package-lock.json, unde sunt fixate versiunile pachetelor care vor fi folosite pentru construirea proiectului. Un dezavantaj este că Npm install trage de fiecare dată versiunile actualizate ale pachetelor din internet, iar aceasta ia un timp considerabil în cazul unui proiect mare.

Dezvoltatorii uneori experimentează pe mașina locală pentru a verifica funcționarea unei părți individuale sau a întregului proiect. Uneori se întâmpla ca local totul să fie grozav, dar la construirea și implementarea - nimic nu funcționa. Începem să investigăm problema - aha, versiuni diferite ale pachetelor cu dependențe.

Soluție

  • Sursele în excepții AV.
  • Dezactivarea indexării.
  • Trecerea la npm ci.

Avantajele npm ci sunt că construim o dată arborele de dependențe, și obținem oportunitatea de a oferi dezvoltatorului o listă actualizată de pachete, cu care poate experimenta local cât dorește. Aceasta economisește timp dezvoltatorilor care scriu cod.

Configurație

Acum puțin despre configurația depozitului. Istoric, folosim Nexus pentru gestionarea depozitelor, inclusiv Internal REPO. În acest depozit intern sunt livrate toate componentele pe care le folosim pentru scopuri interne, de exemplu, monitorizările scrise de noi.

.NET Core pe Linux, DevOps în armonie

Folosim de asemenea NuGet, deoarece acesta cache-uiește mai bine în comparație cu alți gestionari de pachete.

Rezultatul

După ce am optimizat agenții de build, timpul mediu de construire a fost redus de la 12 minute la 7.

Dacă am calcula toate mașinile pe care le-am putea folosi pentru Windows, dar le-am mutat la Linux în acest proiect, am economisit în jur de 10.000 $. Și aceasta este doar pe licențe; dacă includem costurile de întreținere - mai mult.

Planuri

Pentru următorul trimestru am planificat optimizarea livrării codului.

Trecerea la o imagine Docker preconstruită. TFS este o unealtă grozavă cu o mulțime de plugin-uri care permit integrarea în Pipeline, inclusiv construirea pe un trigger, de exemplu, al unei imagini Docker. Acest trigger vrem să-l facem pe acela. package-lock.json. Dacă somehow se schimbă compoziția componentelor folosite pentru a construi proiectul - ne construim o nouă imagine Docker. Ulterior, aceasta este folosită pentru desfășurarea unui container cu aplicația construită. Acum nu avem aceasta, dar plănuim să trecem la o arhitectură microservicii în Kubernetes, care se dezvoltă activ în compania noastră și deja susține soluții de producție.

Rezumat

Îndemn pe toți să renunțe la Windows, dar nu pentru că nu știu cum să o pregătesc. Motivul este că cea mai mare parte a soluțiilor Opensource este stiva Linux. Veți economisi bine resurse. În opinia mea, viitorul aparține soluțiilor Open Source pe Linux cu o comunitate puternică.

Profilul vorbitorului Alexandru Sinchinov pe GitHub.

DevOps Conf este o conferință dedicată integrării proceselor de dezvoltare, testare și operare pentru profesioniști de la profesioniști. De aceea, proiectul despre care a vorbit Alexandru? este realizat și funcționează, iar în ziua prezentării au avut loc două lansări de succes. La DevOps Conf la RIT++ pe 27 și 28 mai vor fi și mai multe cazuri similare de la practicieni. Încă mai poți să te urci în ultimul vagon și trimite un raport sau fără grabă rezerva bilet. Ne vedem la Skolkovo!

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster