.NET Core pe Linux, DevOps pe cal

Am dezvoltat DevOps cât de bine am putut. Eram 8, iar Vasya era cel mai tare din Windows. Brusc, Vasya a plecat și am avut sarcina de a lansa un nou proiect care a fost furnizat de dezvoltarea Windows. Când am aruncat toată stiva de dezvoltare Windows pe masă, mi-am dat seama că situația era o durere...

Așa începe povestea Alexandra Sinchinova pe DevOpsConf. Când principalul specialist Windows a părăsit compania, Alexander s-a întrebat ce să facă acum. Treceți la Linux, desigur! Alexander vă va spune cum a reușit să creeze un precedent și să transfere o parte din dezvoltarea Windows pe Linux, folosind exemplul unui proiect finalizat pentru 100 de utilizatori finali.

.NET Core pe Linux, DevOps pe cal

Cum să livrezi ușor și fără efort un proiect către RPM folosind TFS, Puppet, Linux .NET core? Cum să sprijiniți versiunea unei baze de date de proiect dacă echipa de dezvoltare aude cuvintele Postgres și Flyway pentru prima dată, iar termenul limită este poimâine? Cum se integrează cu Docker? Cum să motivezi dezvoltatorii .NET să abandoneze Windows și smoothie-urile în favoarea Puppet și Linux? Cum să rezolvi conflictele ideologice dacă nu există nici puterea, nici dorința, nici resursele pentru a menține Windows în producție? Despre aceasta, precum și despre Web Deploy, testare, CI, despre practicile de utilizare a TFS în proiectele existente și, bineînțeles, despre cârjele sparte și soluțiile de lucru, în transcrierea raportului lui Alexander.


Deci, Vasya a plecat, sarcina este pe mine, dezvoltatorii așteaptă cu nerăbdare cu furci. Când în sfârșit mi-am dat seama că Vasya nu poate fi returnat, m-am apucat de treabă. Pentru început, am evaluat procentul de VM-uri Win din flota noastră. Scorul nu a fost în favoarea Windows.

.NET Core pe Linux, DevOps pe cal

Deoarece dezvoltăm în mod activ DevOps, mi-am dat seama că trebuie schimbat ceva în abordarea furnizării unei noi aplicații. A existat o singură soluție - dacă este posibil, transferați totul pe Linux. Google m-a ajutat - la acel moment .Net fusese deja portat pe Linux și mi-am dat seama că aceasta era soluția!

De ce .NET core împreună cu Linux?

Au fost mai multe motive pentru aceasta. Între „plătește bani” și „nu plătește”, majoritatea îl va alege pe al doilea - ca mine. O licență pentru MSDB costă aproximativ 1 USD; întreținerea unei flote de mașini virtuale Windows costă sute de dolari. Pentru o companie mare, aceasta este o cheltuială mare. De aceea economie - primul motiv. Nu cel mai important, dar unul dintre cele semnificative.

Mașinile virtuale Windows ocupă mai multe resurse decât frații lor Linux - sunt grele. Având în vedere dimensiunea marii companii, am ales Linux.

Sistemul este pur și simplu integrat în CI existent. Ne considerăm DevOps progresiv, folosim Bamboo, Jenkins și GitLab CI, așa că cea mai mare parte a muncii noastre rulează pe Linux.

Ultimul motiv este acompaniament convenabil. Trebuia să reducem bariera de intrare pentru „escorte” – băieții care înțeleg partea tehnică, asigură servicii neîntrerupte și mențin serviciile de pe a doua linie. Erau deja familiarizați cu stiva Linux, așa că le este mult mai ușor să înțeleagă, să susțină și să întrețină un nou produs decât să cheltuiască resurse suplimentare pentru a înțelege aceeași funcționalitate a software-ului pentru platforma Windows.

Cerințe

Primul si cel mai important - comoditatea noii soluții pentru dezvoltatori. Nu toți erau pregătiți pentru schimbare, mai ales după ce a fost rostit cuvântul Linux. Dezvoltatorii își doresc Visual Studio preferat, TFS cu autotestare pentru ansambluri și smoothie-uri. Modul în care are loc livrarea către producție nu este important pentru ei. Prin urmare, am decis să nu schimbăm procesul obișnuit și să lăsăm totul neschimbat pentru dezvoltarea Windows.

Este nevoie de un nou proiect se integrează în CI existent. Șinele erau deja acolo și toată munca trebuia făcută ținând cont de parametrii sistemului de management al configurației, standardele de livrare acceptate și sistemele de monitorizare.

Ușurință de asistență și operare, ca o condiție pentru pragul minim de intrare pentru toți participanții noi din diferite divizii și departamentul de asistență.

Termen limită - ieri.

Win Development Group

Cu ce ​​lucra atunci echipa Windows?

.NET Core pe Linux, DevOps pe cal

Acum pot spune asta cu încredere IdentityServer4 este o alternativă gratuită la ADFS cu capabilități similare, sau ce Entity Framework Core - un paradis pentru un dezvoltator, unde nu trebuie să vă deranjați să scrieți scripturi SQL, ci să descrieți interogările din baza de date în termeni OOP. Dar apoi, în timpul discuției despre planul de acțiune, m-am uitat la această stivă ca și cum ar fi cuneiform sumerian, recunoscând doar PostgreSQL și Git.

La acea vreme folosim activ Marionetă ca sistem de management al configurației. În majoritatea proiectelor noastre am folosit GitLab CI, Elastic, servicii echilibrate de mare sarcină folosind HAProxy monitorizat totul cu Zabbix, ligamentele grafana и Prometeu, Jaeger, și toate acestea se învârteau pe bucăți de fier HPESXi pe VMware. Toată lumea o știe - un clasic al genului.

.NET Core pe Linux, DevOps pe cal

Să ne uităm și să încercăm să înțelegem ce s-a întâmplat înainte să începem toate aceste intervenții.

Ce s-a întâmplat

TFS este un sistem destul de puternic care nu numai că furnizează cod de la dezvoltator la mașina de producție finală, dar are și un set pentru integrare foarte flexibilă cu diverse servicii - pentru a oferi CI la nivel multiplatformă.

.NET Core pe Linux, DevOps pe cal
Anterior, acestea erau ferestre solide. TFS a folosit mai mulți agenți Build, care au fost folosiți pentru a asambla multe proiecte. Fiecare agent are 3-4 lucrători pentru a paraleliza sarcinile și a optimiza procesul. Apoi, conform planurilor de lansare, TFS a livrat Build-ul proaspăt copt pe serverul de aplicații Windows.

Ce ne-am dorit să realizăm?

Folosim TFS pentru livrare și dezvoltare și rulăm aplicația pe un server de aplicații Linux și există un fel de magie între ele. Acest cutie magica și acolo este sarea lucrării înainte. Înainte de a o demonta, voi face un pas deoparte și voi spune câteva cuvinte despre aplicație.

Proiect

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

.NET Core pe Linux, DevOps pe cal

Client

Au fost două tipuri de utilizatori. în primul rând a obținut acces prin autentificare folosind un certificat SSL SHA-2. U a doua a existat acces folosind un login și o parolă.

HAProxy

Apoi, cererea clientului a mers la HAProxy, care a rezolvat următoarele probleme:

  • autorizare primară;
  • terminare SSL;
  • reglarea cererilor HTTP;
  • cereri de difuzare.

Certificatul de client a fost verificat de-a lungul lanțului. Noi - autoritate și ne putem permite acest lucru, deoarece noi înșine eliberăm certificate clienților de servicii.

Atenție la al treilea punct, vom reveni asupra lui puțin mai târziu.

Backend

Au plănuit să facă backend-ul pe Linux. Backend-ul interacționează cu baza de date, încarcă lista necesară de privilegii și apoi, în funcție de ce privilegii are utilizatorul autorizat, oferă acces pentru a semna documente financiare și a le trimite spre execuție sau pentru a genera un fel de raport.

Economii cu HAProxy

Pe lângă cele două contexte pe care le-a navigat fiecare client, a existat și un context identitar. IdentityServer4 vă permite doar să vă conectați, acesta este un analog gratuit și puternic pentru ADFS - Servicii de federație Active Directory.

Cererea de identitate a fost procesată în mai multe etape. Primul pas - client a intrat în backend, care a comunicat cu acest server și a verificat prezența unui token pentru client. Dacă nu a fost găsit, cererea a fost returnată în contextul din care a venit, dar cu o redirecționare, iar odată cu redirecționarea s-a trecut la identitate.

Al doilea pas - cererea a fost primită la pagina de autorizare din IdentityServer, unde s-a înregistrat clientul și acel token mult așteptat a apărut în baza de date IdentityServer.

Al treilea pas - clientul a fost redirecționat înapoi la contextul din care provine.

.NET Core pe Linux, DevOps pe cal

IdentityServer4 are o caracteristică: returnează răspunsul la cererea de returnare prin HTTP. Oricât ne-am chinuit cu configurarea serverului, oricât ne-am luminat cu documentația, de fiecare dată am primit o cerere inițială de client cu un URL care venea prin HTTPS, iar IdentityServer a returnat același context, dar cu HTTP. Am fost șocați! Și am transferat toate acestea prin contextul de identitate către HAProxy, iar în anteturi a trebuit să modificăm protocolul HTTP în HTTPS.

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

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

Cum ar trebui să funcționeze

Deci, așa cum am promis - Magic Box. Înțelegem deja că suntem garantați să ne îndreptăm către Linux. Să formulăm sarcini specifice care au necesitat soluții.

.NET Core pe Linux, DevOps pe cal

Păpuși se manifestă. Pentru a livra și gestiona configurarea serviciului și a aplicațiilor, au trebuit scrise rețete interesante. O rolă de creion arată în mod elocvent cât de rapid și eficient a fost făcut.

Metoda de livrare. Standardul este RPM. Toată lumea înțelege că în Linux nu puteți face fără el, dar proiectul în sine, după asamblare, a fost un set de fișiere DLL executabile. Au fost vreo 150, proiectul a fost destul de dificil. Singura soluție armonioasă este să împachetați acest binar în RPM și să implementați aplicația din acesta.

Versiune. A trebuit să lansăm foarte des și a trebuit să decidem cum să formăm numele pachetului. Aceasta este o problemă a nivelului de integrare cu TFS. Aveam un agent de compilare pe Linux. Când TFS trimite o sarcină unui handler - lucrător - către agentul Build, îi transmite și o mulțime de variabile care ajung în mediul procesului de handler. Aceste variabile de mediu conțin numele Build, numele versiunii și alte variabile. Citiți mai multe despre acest lucru în secțiunea „Crearea unui pachet RPM”.

Configurarea TFS a ajuns la înființarea Pipeline. Anterior, colectam toate proiectele Windows pe agenți Windows, dar acum apare un agent Linux - un agent Build, care trebuie inclus în grupul de build, îmbogățit cu unele artefacte și a spus ce tip de proiecte vor fi construite pe acest agent Build și modificați cumva Pipeline.

IdentityServer. ADFS nu este drumul nostru, mergem spre Open Source.

Să trecem prin componente.

cutie magica

Constă din patru părți.

.NET Core pe Linux, DevOps pe cal

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

  • Configurați lucrătorii și nu singur, deoarece era de așteptat lucru distribuit la proiect.
  • Instalați .NET Core 1.x. De ce 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 și s-a decis să facem proiectul pe baza ei.
  • Git 2.x.

Depozitul RPM. Pachetele RPM trebuiau stocate undeva. S-a presupus că vom folosi același depozit RPM corporativ care este disponibil pentru toate gazdele Linux. Asta au făcut. Serverul de depozit este configurat cârlig web care a descărcat pachetul RPM necesar din locația specificată. Versiunea pachetului a fost raportată la webhook de către agentul Build.

GitLab. Atenţie! GitLab aici este folosit nu de dezvoltatori, ci de departamentul de operațiuni pentru a controla versiunile de aplicații, versiunile de pachete, pentru a monitoriza starea tuturor mașinilor Linux și stochează rețeta - toate manifestele Puppet.

Marionetă — rezolvă toate problemele controversate și oferă exact configurația pe care o dorim de la Gitlab.

Începem să ne scufundăm. Cum funcționează livrarea DLL către RPM?

Livrare DDL la RPM

Să presupunem că avem un rockstar de dezvoltare .NET. Utilizează Visual Studio și creează o ramură de lansare. După aceea, îl încarcă în Git, iar Git aici este o entitate TFS, adică este depozitul de aplicații cu care lucrează dezvoltatorul.

.NET Core pe Linux, DevOps pe cal

După care TFS vede că a sosit un nou commit. Care aplicație? În setările TFS există o etichetă care indică ce resurse are un anumit agent Build. În acest caz, vede că construim un proiect .NET Core și selectează un agent Linux Build din pool.

Agentul Build primește sursele și descarcă cele necesare dependențe din depozitul .NET, npm etc. și după construirea aplicației în sine și ambalarea ulterioară, trimite pachetul RPM la depozitul RPM.

Pe de altă parte, se întâmplă următoarele. Inginerul departamentului de operațiuni este implicat direct în lansarea proiectului: schimbă versiunile pachetelor în Hiera în depozitul în care este stocată rețeta aplicației, după care se declanșează Puppet Yum, preia noul pachet din depozit, iar noua versiune a aplicației este gata de utilizare.

.NET Core pe Linux, DevOps pe cal

Totul este simplu în cuvinte, dar ce se întâmplă în interiorul agentului Build însuși?

Ambalarea DLL RPM

Surse de proiect primite și sarcină de construcție de la TFS. Agent de construcție începe să construiască proiectul în sine din surse. Proiectul asamblat este disponibil ca set fișiere DLL, care sunt ambalate într-o arhivă zip pentru a reduce încărcarea sistemului de fișiere.

Arhiva ZIP este aruncată în directorul de compilare a pachetului RPM. Apoi, scriptul Bash inițializează variabilele de mediu, găsește versiunea Build, versiunea proiectului, calea către directorul build și rulează RPM-build. Odată ce construirea este completă, pachetul este publicat în depozit local, care se află în agentul Build.

Apoi, de la agentul Build la serverul din depozitul RPM Solicitarea JSON este trimisă indicând numele versiunii și al build-ului. Webhook, despre care am vorbit mai devreme, descarcă chiar acest pachet din depozitul local de pe agentul Build și face noul ansamblu disponibil pentru instalare.

.NET Core pe Linux, DevOps pe cal

De ce această schemă specială de livrare a pachetelor către depozitul RPM? De ce nu pot trimite imediat pachetul asamblat la depozit? Cert este că aceasta este o condiție pentru asigurarea siguranței. Acest scenariu limitează posibilitatea ca persoanele neautorizate să încarce pachete RPM pe un server care este accesibil tuturor mașinilor Linux.

Versiune baze de date

La o consultare cu echipa de dezvoltare, s-a dovedit că băieții erau mai aproape de MS SQL, dar în majoritatea proiectelor non-Windows folosim deja PostgreSQL cu toată puterea lor. Deoarece am decis deja să renunțăm la tot ce se plătea, am început să folosim și aici PostgreSQL.

.NET Core pe Linux, DevOps pe cal

În această parte vreau să vă spun cum am versiunea baza de date și cum am ales între Flyway și Entity Framework Core. Să ne uităm la avantajele și dezavantajele lor.

Contra

Flyway merge doar într-un singur sens, noi nu putem deplasa înapoi - acesta este un dezavantaj semnificativ. Îl puteți compara cu Entity Framework Core în alte moduri - în ceea ce privește confortul dezvoltatorului. Vă amintiți că am pus acest lucru în prim-plan, iar criteriul principal a fost să nu schimbăm nimic pentru dezvoltarea Windows.

Pentru Flyway noi era nevoie de un fel de ambalajca să nu scrie băieții interogări SQL. Sunt mult mai aproape de operare în termeni OOP. Am scris instrucțiuni pentru lucrul cu obiectele bazei de date, am generat o interogare SQL și am executat-o. Noua versiune a bazei de date este gata, testată - totul este în regulă, totul funcționează.

Entity Framework Core are un minus - sub sarcini grele construiește interogări SQL suboptimale, iar reducerea în baza de date poate fi semnificativă. Dar din moment ce nu avem un serviciu de sarcină mare, nu calculăm sarcina în sute de RPS, am acceptat aceste riscuri și am delegat problema viitorilor nouă.

Pro

Entity Framework Core funcționează din cutie și este ușor de dezvoltat, și Flyway Se integrează cu ușurință în CI existent. Dar îl facem convenabil pentru dezvoltatori :)

Procedura de rulare

Puppet vede că urmează o schimbare în versiunea pachetului, inclusiv cea care este responsabilă de migrare. În primul rând, instalează un pachet care conține scripturi de migrare și funcționalități legate de bazele de date. După aceasta, aplicația care funcționează cu baza de date este repornită. Urmează instalarea componentelor rămase. Ordinea în care sunt instalate pachetele și sunt lansate aplicațiile este descrisă în manifestul Puppet.

Aplicațiile folosesc date sensibile, cum ar fi token-uri, parole de baze de date, toate acestea sunt introduse în configurația din Puppet master, unde sunt stocate în formă criptată.

Probleme TFS

După ce ne-am hotărât și am realizat că totul funcționează cu adevărat pentru noi, am decis să mă uit la ceea ce se întâmplă cu ansamblurile din TFS în ansamblu pentru departamentul de dezvoltare Win pe alte proiecte - indiferent dacă construim/lansam rapid sau nu, și a descoperit probleme semnificative cu viteza .

Unul dintre proiectele principale durează 12-15 minute pentru a asambla - asta este mult timp, nu poți trăi așa. O analiză rapidă a arătat o reducere teribilă a I/O, iar aceasta a fost pe matrice.

După ce l-am analizat component cu component, am identificat trei focare. În primul rând - „Antivirus Kaspersky”, care scanează sursele pe toți agenții Windows Build. Al doilea - ferestre din Indexator. Nu a fost dezactivat și totul a fost indexat în timp real pe agenții Build în timpul procesului de implementare.

Al treilea - Instalare Npm. S-a dovedit că în majoritatea conductelor am folosit exact acest scenariu. De ce este rău? Procedura de instalare Npm este rulată atunci când arborele de dependență este format în Pachet-lock.json, unde sunt înregistrate versiunile pachetelor care vor fi utilizate pentru construirea proiectului. Dezavantajul este că Npm install trage cele mai recente versiuni de pachete de pe Internet de fiecare dată, iar acest lucru necesită mult timp în cazul unui proiect mare.

Dezvoltatorii experimentează uneori pe o mașină locală pentru a testa modul în care funcționează o anumită parte sau întreg proiectul. Uneori s-a dovedit că totul era cool la nivel local, dar l-au asamblat, l-au rulat și nimic nu a funcționat. Începem să ne dăm seama care este problema - da, diferite versiuni de pachete cu dependențe.

decizie

  • Surse în excepții AV.
  • Dezactivați indexarea.
  • Mergi la npm ci.

Avantajele npm ci sunt că noi Colectăm arborele de dependență o datăși avem posibilitatea de a oferi dezvoltatorului lista curentă de pachete, cu care poate experimenta local cât de mult îi place. Acest Salveaza timp dezvoltatori care scriu cod.

configurație

Acum puțin despre configurația depozitului. Din punct de vedere istoric, folosim Nexus pentru gestionarea depozitelor, inclusiv REPO intern. Acest depozit intern conține toate componentele pe care le folosim în scopuri interne, de exemplu, monitorizarea scrisă de sine.

.NET Core pe Linux, DevOps pe cal

De asemenea, folosim NuGet, deoarece are o memorie cache mai bună în comparație cu alți manageri de pachete.

Rezultat

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

Dacă numărăm toate mașinile pe care le-am fi putut folosi pentru Windows, dar am trecut la Linux în acest proiect, am economisit aproximativ 10 000 de dolari. Și asta e doar pe licențe și mai mult dacă luăm în considerare conținutul.

Planuri

Pentru trimestrul următor, am plănuit să lucrăm la optimizarea livrării codului.

Trecerea la o imagine Docker preconstruită. TFS este un lucru grozav cu multe plugin-uri care vă permit să vă integrați în Pipeline, inclusiv asamblarea bazată pe declanșare, de exemplu, a unei imagini Docker. Vrem să facem acest declanșator pentru același Pachet-lock.json. Dacă compoziția componentelor utilizate pentru construirea proiectului se schimbă cumva, construim o nouă imagine Docker. Este folosit ulterior pentru a implementa containerul cu aplicația asamblată. Nu este cazul acum, dar plănuim să trecem la o arhitectură de microservicii în Kubernetes, care se dezvoltă activ în compania noastră și deservește soluții de producție de mult timp.

Rezumat

Îi încurajez pe toată lumea să arunce Windows, dar nu pentru că nu știu să-l gătesc. Motivul este că majoritatea soluțiilor Opensource sunt Stiva Linux. te simți bine economisiți resurse. În opinia mea, viitorul aparține soluțiilor Open Source pe Linux cu o comunitate puternică.

Profilul vorbitorului lui Alexander Sinchinov pe GitHub.

DevOps Conf este o conferință despre integrarea proceselor de dezvoltare, testare și operare pentru profesioniști de către profesioniști. De aceea proiectul despre care a vorbit Alexandru? implementat și funcțional, iar în ziua spectacolului au fost două versiuni de succes. Pe DevOps Conf la RIT++ Pe 27 și 28 mai vor fi și mai multe cazuri similare de la practicanți. Încă poți sări în ultima trăsură și Trimite un raport sau ia-ți timp A rezerva bilet. Ne întâlnim în Skolkovo!

Sursa: www.habr.com

Adauga un comentariu