.NET Core na Linuksie, DevOps na koniu

Rozwinęliśmy DevOps najlepiej jak potrafiliśmy. Było nas 8, a Vasya była najfajniejsza w Windowsie. Nagle Vasya odeszła, a ja otrzymałem zadanie uruchomienia nowego projektu, który został dostarczony przez rozwój systemu Windows. Kiedy rzuciłem na stół cały stos programistyczny systemu Windows, zdałem sobie sprawę, że sytuacja była uciążliwa…

Tak zaczyna się ta historia Aleksandra Sinchinova na Konf. DevOps. Kiedy czołowy specjalista Windows odszedł z firmy, Alexander zastanawiał się, co teraz zrobić. Oczywiście przejdź na Linuksa! Alexander opowie jak udało mu się stworzyć precedens i przenieść część rozwoju Windowsa na Linuksa na przykładzie zrealizowanego projektu dla 100 000 użytkowników końcowych.

.NET Core na Linuksie, DevOps na koniu

Jak łatwo i bez wysiłku dostarczyć projekt do RPM przy użyciu TFS, Puppet, Linux .NET core? Jak wesprzeć wersjonowanie bazy danych projektu, jeśli zespół programistów po raz pierwszy słyszy słowa Postgres i Flyway, a termin upływa pojutrze? Jak zintegrować się z Dockerem? Jak zmotywować programistów .NET do porzucenia Windowsa i smoothies na rzecz Puppet i Linux? Jak rozwiązywać konflikty ideologiczne, jeśli nie ma ani siły, ani chęci, ani zasobów, aby utrzymać Windows w produkcji? O tym, a także o Web Deploy, testowaniu, CI, o praktykach wykorzystania TFS w istniejących projektach i oczywiście o zepsutych kulach i działających rozwiązaniach, w transkrypcji raportu Alexandra.


Tak więc Vasya odeszła, zadanie spoczywa na mnie, programiści niecierpliwie czekają z widłami. Kiedy w końcu zdałem sobie sprawę, że Wasi nie da się zwrócić, zabrałem się do pracy. Na początek oceniłem procent maszyn wirtualnych Win VM w naszej flocie. Wynik nie był na korzyść systemu Windows.

.NET Core na Linuksie, DevOps na koniu

Ponieważ aktywnie rozwijamy DevOps, zdałem sobie sprawę, że trzeba coś zmienić w podejściu do dostarczania nowej aplikacji. Rozwiązanie było tylko jedno - jeśli to możliwe, przenieś wszystko na Linuksa. Google mi pomógł - w tamtym czasie .Net był już przeniesiony na Linuksa i zdałem sobie sprawę, że to jest rozwiązanie!

Dlaczego .NET core w połączeniu z Linuksem?

Powodów było kilka. Pomiędzy „zapłać pieniądze” a „nie płać” większość wybierze to drugie – tak jak ja. Licencja na MSDB kosztuje około 1 dolarów, a utrzymanie floty maszyn wirtualnych Windows kosztuje setki dolarów. Dla dużej firmy jest to duży wydatek. Dlatego oszczędności - pierwszy powód. Nie najważniejsze, ale jedno z najważniejszych.

Maszyny wirtualne z systemem Windows zużywają więcej zasobów niż ich bracia z systemem Linux - są ciężkie. Biorąc pod uwagę skalę dużej firmy, wybraliśmy Linuxa.

System można po prostu zintegrować z istniejącym CI. Uważamy się za progresywnych DevOps, używamy Bamboo, Jenkins i GitLab CI, więc większość naszej pracy działa na Linuksie.

Ostatnim powodem jest wygodny akompaniament. Musieliśmy obniżyć barierę wejścia dla „eskorty” – ludzi, którzy rozumieją część techniczną, zapewniają nieprzerwaną obsługę i utrzymują usługi z drugiej linii. Znali już stos Linuksa, więc znacznie łatwiej jest im zrozumieć, wspierać i utrzymywać nowy produkt, niż wydawać dodatkowe zasoby na zrozumienie tej samej funkcjonalności oprogramowania na platformę Windows.

Wymagania

Po pierwsze i najważniejsze - wygoda nowego rozwiązania dla programistów. Nie wszyscy byli gotowi na zmiany, zwłaszcza po tym, jak padło słowo Linux. Deweloperzy chcą swojego ulubionego Visual Studio, TFS z autotestami dla złożeń i koktajli. Sposób dostarczenia towaru na produkcję nie jest dla nich istotny. Dlatego postanowiliśmy nie zmieniać zwykłego procesu i pozostawić wszystko bez zmian na potrzeby rozwoju systemu Windows.

Potrzebny nowy projekt zintegrować z istniejącym CI. Szyny już były i wszystkie prace trzeba było wykonać z uwzględnieniem parametrów systemu zarządzania konfiguracją, przyjętych standardów dostaw i systemów monitorowania.

Łatwość wsparcia i obsługi, jako warunek minimalnego progu wejścia dla wszystkich nowych uczestników z różnych działów i działów wsparcia.

Termin - wczoraj.

Wygraj Grupę Rozwoju

Nad czym pracował wówczas zespół Windows?

.NET Core na Linuksie, DevOps na koniu

Teraz mogę śmiało to powiedzieć Serwer tożsamości4 to fajna, darmowa alternatywa dla ADFS z podobnymi możliwościami, czy co Rdzeń platformy Entity - raj dla programisty, w którym nie musisz zawracać sobie głowy pisaniem skryptów SQL, tylko opisywać zapytania w bazie danych w kategoriach OOP. Ale potem, podczas dyskusji nad planem działania, spojrzałem na ten stos, jakby był sumeryjskim pismem klinowym, rozpoznając tylko PostgreSQL i Git.

W tym czasie aktywnie korzystaliśmy Marionetka jako system zarządzania konfiguracją. W większości naszych projektów zastosowaliśmy GitLab CI, Elastyczna, zrównoważone usługi o dużym obciążeniu HAProxy monitorowałem wszystko za pomocą Zabbix, więzadła grafana и Prometheus, Jaeger, a wszystko to kręciło się na kawałkach żelaza HPESXi na VMware. Znają go wszyscy – klasyka gatunku.

.NET Core na Linuksie, DevOps na koniu

Przyjrzyjmy się i spróbujmy zrozumieć, co się wydarzyło, zanim rozpoczęliśmy te wszystkie interwencje.

Co się stało

TFS to dość potężny system, który nie tylko dostarcza kod od programisty do końcowej maszyny produkcyjnej, ale także posiada zestaw do bardzo elastycznej integracji z różnymi usługami - w celu zapewnienia CI na poziomie wieloplatformowym.

.NET Core na Linuksie, DevOps na koniu
Wcześniej były to okna solidne. TFS korzystał z kilku agentów Build, których używano do składania wielu projektów. Każdy agent ma 3-4 pracowników w celu zrównoleglenia zadań i optymalizacji procesu. Następnie, zgodnie z planami wydawniczymi, TFS dostarczył świeżo upieczony Build na serwer aplikacji Windows.

Co chcieliśmy osiągnąć?

Używamy TFS do dostarczania i programowania oraz uruchamiamy aplikację na serwerze aplikacji Linux i jest między nimi pewien rodzaj magii. Ten magiczne pudełko i jest sól do dalszej pracy. Zanim go rozbiorę, odsunę się na bok i powiem kilka słów na temat aplikacji.

Projekt

Aplikacja udostępnia funkcjonalność obsługi kart przedpłaconych.

.NET Core na Linuksie, DevOps na koniu

klientem

Były dwa typy użytkowników. pierwszy uzyskaliśmy dostęp logując się przy użyciu certyfikatu SSL SHA-2. U drugi był dostęp za pomocą loginu i hasła.

HAPROXY

Następnie żądanie klienta trafiło do HAProxy, co rozwiązało następujące problemy:

  • autoryzacja pierwotna;
  • Zakończenie protokołu SSL;
  • dostrajanie żądań HTTP;
  • żądania transmisji.

Certyfikat klienta został zweryfikowany w całym łańcuchu. My - władza i stać nas na to, gdyż sami wystawiamy certyfikaty do obsługi klientów.

Zwróć uwagę na trzeci punkt, wrócimy do niego nieco później.

Backend

Planowali stworzyć backend na Linuksie. Backend wchodzi w interakcję z bazą danych, ładuje niezbędną listę uprawnień, a następnie w zależności od uprawnień uprawnionego użytkownika umożliwia podpisanie dokumentów finansowych i przesłanie ich do realizacji lub wygenerowanie pewnego rodzaju raportu.

Oszczędności dzięki HAProxy

Oprócz dwóch kontekstów, po których poruszał się każdy klient, istniał również kontekst tożsamości. Serwer tożsamości4 pozwala po prostu się zalogować, jest to darmowy i potężny analog ADFS - Usługi federacyjne Active Directory.

Żądanie tożsamości zostało przetworzone w kilku etapach. Pierwszy krok - klient dostał się do backendu, który skomunikował się z tym serwerem i sprawdził obecność tokena dla klienta. Jeśli nie został znaleziony, żądanie wracało do kontekstu, z którego wyszło, ale z przekierowaniem, a wraz z przekierowaniem trafiało do tożsamości.

Krok drugi - otrzymano żądanie do strony autoryzacji w IdentityServer, gdzie klient się zarejestrował, a w bazie IdentityServer pojawił się długo oczekiwany token.

Trzeci krok - klient został przekierowany z powrotem do kontekstu, z którego pochodzi.

.NET Core na Linuksie, DevOps na koniu

IdentityServer4 ma funkcję: zwraca odpowiedź na żądanie zwrotu za pośrednictwem protokołu HTTP. Nieważne, jak bardzo męczyliśmy się z konfiguracją serwera, bez względu na to, jak bardzo oświeciliśmy się dokumentacją, za każdym razem, gdy otrzymywaliśmy początkowe żądanie klienta z adresem URL przychodzącym przez HTTPS, a IdentityServer zwracał ten sam kontekst, ale z HTTP. Byliśmy zszokowani! I przenieśliśmy to wszystko poprzez kontekst tożsamości do HAProxy, a w nagłówkach musieliśmy zmodyfikować protokół HTTP na HTTPS.

Jaka jest poprawa i gdzie zaoszczędziłeś?

Zaoszczędziliśmy pieniądze korzystając z darmowego rozwiązania do autoryzacji grupy użytkowników, zasobów, ponieważ nie umieściliśmy IdentityServer4 jako osobnego węzła w osobnym segmencie, ale używaliśmy go razem z backendem na tym samym serwerze, na którym działa backend aplikacji .

Jak to powinno działać

Tak jak obiecałem - Magic Box. Rozumiemy już, że mamy gwarancję przejścia w stronę Linuksa. Sformułujmy konkretne zadania, które wymagały rozwiązań.

.NET Core na Linuksie, DevOps na koniu

Manifest marionetki. Aby dostarczać i zarządzać konfiguracją usług i aplikacji, trzeba było napisać fajne przepisy. Rolka ołówka wymownie pokazuje, jak szybko i sprawnie zostało to zrobione.

Sposób dostawy. Standardem są obroty. Każdy rozumie, że w Linuksie nie można się bez tego obejść, ale sam projekt po złożeniu był zbiorem wykonywalnych plików DLL. Było ich około 150, projekt był dość trudny. Jedynym harmonijnym rozwiązaniem jest spakowanie tego pliku binarnego do RPM i wdrożenie z niego aplikacji.

Wersjonowanie. Musieliśmy bardzo często wypuszczać pakiety i decydować, jak uformować nazwę pakietu. To kwestia poziomu integracji z TFS. Mieliśmy agenta kompilacji na Linuksie. Kiedy TFS wysyła zadanie do procedury obsługi – procesu roboczego – do agenta kompilacji, przekazuje mu również kilka zmiennych, które trafiają do środowiska procesu obsługi. Te zmienne środowiskowe zawierają nazwę kompilacji, nazwę wersji i inne zmienne. Przeczytaj więcej na ten temat w sekcji „Tworzenie pakietu RPM”.

Konfigurowanie TFS sprowadziłem się do skonfigurowania Pipeline. Wcześniej zbieraliśmy wszystkie projekty Windows na agentach Windows, ale teraz pojawia się agent Linux - agent Build, którego należy uwzględnić w grupie build, wzbogacić o pewne artefakty i powiedzieć, jakiego rodzaju projekty będą budowane na tym agencie Build i w jakiś sposób zmodyfikuj Pipeline.

Serwer tożsamości. ADFS nie jest w naszym stylu, stawiamy na Open Source.

Przejdźmy do komponentów.

magiczne pudełko

Składa się z czterech części.

.NET Core na Linuksie, DevOps na koniu

Agent kompilacji systemu Linux. Linux, bo dla niego budujemy - to logiczne. Ta część została wykonana w trzech etapach.

  • Skonfiguruj pracowników i nie sam, gdyż oczekiwano rozproszonej pracy nad projektem.
  • Zainstaluj platformę .NET Core 1.x. Po co 1.x, skoro 2.0 jest już dostępne w standardowym repozytorium? Ponieważ kiedy zaczynaliśmy prace nad rozwojem, stabilną wersją była wersja 1.09 i zdecydowano się na nią oprzeć projekt.
  • Git 2.x.

Repozytorium RPM. Pakiety RPM musiały być gdzieś przechowywane. Założono, że będziemy korzystać z tego samego korporacyjnego repozytorium RPM, które jest dostępne dla wszystkich hostów Linux. To właśnie zrobili. Serwer repozytorium jest skonfigurowany hak sieciowy który pobrał wymagany pakiet RPM z określonej lokalizacji. Wersja pakietu została zgłoszona do elementu webhook przez agenta kompilacji.

GitLab. Uwaga! GitLab jest tutaj używany nie przez programistów, ale przez dział operacyjny do kontrolowania wersji aplikacji, wersji pakietów, monitorowania stanu wszystkich maszyn z Linuksem i przechowuje przepis - wszystkie manifesty Puppet.

Marionetka — rozwiązuje wszystkie kontrowersyjne kwestie i dostarcza dokładnie taką konfigurację, jakiej oczekujemy od Gitlaba.

Zaczynamy nurkować. Jak działa dostarczanie DLL do RPM?

Dostawa DDL do RPM

Załóżmy, że mamy gwiazdę rocka zajmującą się rozwojem .NET. Korzysta z Visual Studio i tworzy gałąź wydania. Następnie przesyła go do Gita, a Git tutaj jest jednostką TFS, czyli jest repozytorium aplikacji, z którym współpracuje programista.

.NET Core na Linuksie, DevOps na koniu

Po czym TFS widzi, że przybyło nowe zatwierdzenie. Która aplikacja? W ustawieniach TFS znajduje się etykieta wskazująca, jakie zasoby posiada dany agent Build. W tym przypadku widzi, że budujemy projekt .NET Core i wybiera z puli agenta Linux Build.

Agent kompilacji otrzymuje źródła i pobiera niezbędne Zależności z repozytorium .NET, npm itp. i po zbudowaniu samej aplikacji i późniejszym spakowaniu wysyła pakiet RPM do repozytorium RPM.

Z drugiej strony dzieje się, co następuje. Inżynier działu operacyjnego jest bezpośrednio zaangażowany w wdrożenie projektu: zmienia wersje pakietów w Hiera w repozytorium, w którym przechowywany jest przepis aplikacji, po czym uruchamia się Puppet Mniam, pobiera nowy pakiet z repozytorium i nowa wersja aplikacji jest gotowa do użycia.

.NET Core na Linuksie, DevOps na koniu

Wszystko jest proste w słowach, ale co dzieje się wewnątrz samego agenta Build?

Pakowanie DLL RPM

Otrzymano źródła projektu i zadanie kompilacji z TFS. Zbuduj agenta zaczyna budować sam projekt ze źródeł. Zmontowany projekt dostępny jest w zestawie Pliki DLL, które są spakowane w archiwum zip, aby zmniejszyć obciążenie systemu plików.

Archiwum ZIP zostało wyrzucone do katalogu kompilacji pakietu RPM. Następnie skrypt Bash inicjuje zmienne środowiskowe, znajduje wersję kompilacji, wersję projektu, ścieżkę do katalogu kompilacji i uruchamia RPM-build. Po zakończeniu kompilacji pakiet jest publikowany w lokalne repozytorium, który znajduje się w agencie kompilacji.

Następnie z agenta kompilacji do serwera w repozytorium RPM Żądanie JSON zostało wysłane wskazując nazwę wersji i kompilacji. Webhook, o którym mówiłem wcześniej, pobiera właśnie ten pakiet z lokalnego repozytorium na agencie Build i udostępnia nowy zestaw do instalacji.

.NET Core na Linuksie, DevOps na koniu

Dlaczego ten konkretny schemat dostarczania pakietów do repozytorium RPM? Dlaczego nie mogę od razu wysłać zmontowanej paczki do repozytorium? Faktem jest, że jest to warunek zapewnienia bezpieczeństwa. Ten scenariusz ogranicza możliwość przesyłania pakietów RPM przez nieupoważnione osoby na serwer dostępny dla wszystkich komputerów z systemem Linux.

Wersjonowanie bazy danych

Po konsultacjach z zespołem programistów okazało się, że chłopakom bliżej było do MS SQL, ale w większości projektów innych niż Windows korzystaliśmy już z PostgreSQL na pełnych obrotach. Ponieważ już zdecydowaliśmy się porzucić wszystko, co płatne, zaczęliśmy używać PostgreSQL i tutaj.

.NET Core na Linuksie, DevOps na koniu

W tej części chcę opowiedzieć, w jaki sposób wersjonowaliśmy bazę danych i jak wybraliśmy pomiędzy Flyway a Entity Framework Core. Przyjrzyjmy się ich zaletom i wadom.

Wady

Flyway działa tylko w jedną stronę, my nie możemy się wycofać - to istotna wada. Możesz porównać go z Entity Framework Core na inne sposoby - pod względem wygody programisty. Pamiętacie, że stawiamy to na pierwszym miejscu, a głównym kryterium było nie zmieniać niczego w rozwoju Windows.

Dla nas Flyway potrzebny był jakiś rodzaj opakowaniażeby chłopaki nie pisali Zapytania SQL. Dużo bliżej im do działania w kategoriach OOP. Napisaliśmy instrukcję pracy z obiektami bazy danych, wygenerowaliśmy zapytanie SQL i je wykonaliśmy. Nowa wersja bazy danych jest gotowa, przetestowana - wszystko gra, wszystko działa.

Entity Framework Core ma minus - przy dużych obciążeniach buduje suboptymalne zapytania SQL, a spadek w bazie danych może być znaczący. Ponieważ jednak nie mamy usługi o dużym obciążeniu, nie obliczamy obciążenia w setkach RPS, zaakceptowaliśmy to ryzyko i oddelegowaliśmy problem na przyszłość.

Plusy

Rdzeń platformy Entity działa od razu po wyjęciu z pudełka i jest łatwy w rozwojui Flyway Łatwo integruje się z istniejącym CI. Ale zapewniamy wygodę programistom :)

Procedura roll-upu

Puppet widzi, że nadchodzi zmiana wersji pakietu, w tym tej odpowiedzialnej za migrację. Najpierw instaluje pakiet zawierający skrypty migracji i funkcje związane z bazami danych. Następnie zostaje zrestartowana aplikacja współpracująca z bazą danych. Następnie następuje instalacja pozostałych komponentów. Kolejność instalowania pakietów i uruchamiania aplikacji jest opisana w manifeście Puppet.

Aplikacje wykorzystują wrażliwe dane, takie jak tokeny, hasła do baz danych, wszystko to jest pobierane do konfiguracji z Puppet Master, gdzie są przechowywane w zaszyfrowanej formie.

Problemy z TFSem

Kiedy już zdecydowaliśmy i zdaliśmy sobie sprawę, że wszystko u nas naprawdę działa, zdecydowałem się przyjrzeć, co dzieje się ze złożeniami w TFS jako całością dla działu rozwoju Win w innych projektach – niezależnie od tego, czy szybko budowaliśmy/wydawaliśmy, czy nie, i odkrył poważne problemy z szybkością.

Montaż jednego z głównych projektów zajmuje 12-15 minut - to dużo czasu, nie można tak żyć. Szybka analiza wykazała straszny spadek liczby wejść/wyjść, i to dotyczył tablic.

Analizując komponent po elemencie, zidentyfikowałem trzy ogniska. Pierwszy - „Antywirus Kaspersky”, który skanuje źródła we wszystkich agentach Windows Build. Drugi - Windows Indeksator. Nie zostało to wyłączone, a wszystko było indeksowane w czasie rzeczywistym na agentach Build podczas procesu wdrażania.

Trzeci - Instalacja Npm. Okazało się, że w większości Pipelines zastosowaliśmy dokładnie ten scenariusz. Dlaczego jest zły? Procedura instalacji Npm jest uruchamiana po utworzeniu drzewa zależności pakiet-lock.json, gdzie zapisywane są wersje pakietów, które zostaną użyte do zbudowania projektu. Minusem jest to, że Npm install za każdym razem pobiera najnowsze wersje pakietów z Internetu, co w przypadku dużego projektu zajmuje dużo czasu.

Programiści czasami eksperymentują na komputerze lokalnym, aby przetestować działanie określonej części lub całego projektu. Czasem okazywało się, że lokalnie wszystko jest spoko, ale montowali, rozkręcali i nic nie działało. Zaczynamy domyślać się, na czym polega problem - tak, różne wersje pakietów z zależnościami.

decyzja

  • Źródła w wyjątkach AV.
  • Wyłącz indeksowanie.
  • Przejście do npm ci.

Zaletami npm ci jest to, że my Drzewo zależności zbieramy raz, a my otrzymujemy możliwość dostarczenia deweloperowi aktualna lista pakietów, z którym może lokalnie eksperymentować tak bardzo, jak mu się podoba. Ten oszczędza czas programiści, którzy piszą kod.

Konfiguracja

Teraz trochę o konfiguracji repozytorium. Historycznie używamy Nexus do zarządzania repozytoriami, m.in Wewnętrzne REPO. To wewnętrzne repozytorium zawiera wszystkie komponenty, których używamy do celów wewnętrznych, na przykład samodzielnie pisany monitoring.

.NET Core na Linuksie, DevOps na koniu

Używamy również NuGeta, ponieważ ma lepsze buforowanie w porównaniu do innych menedżerów pakietów.

Doświadcz mocnych i skutecznych rezultatów

Po optymalizacji agentów kompilacji średni czas kompilacji został skrócony z 12 minut do 7.

Jeśli policzymy wszystkie maszyny, których moglibyśmy używać pod Windowsem, ale w tym projekcie przeszliśmy na Linuksa, zaoszczędziliśmy około 10 000 dolarów.I to tylko na licencjach, a jeśli weźmiemy pod uwagę treść, to więcej.

Plany

Na kolejny kwartał planowaliśmy pracować nad optymalizacją dostarczania kodu.

Przełączanie na wstępnie skompilowany obraz platformy Docker. TFS to fajna rzecz z wieloma wtyczkami, które pozwalają na integrację z Pipeline, w tym składanie oparte na wyzwalaczach, powiedzmy, obrazu Dockera. Chcemy, aby ten wyzwalacz był taki sam pakiet-lock.json. Jeśli skład komponentów użytych do zbudowania projektu w jakiś sposób ulegnie zmianie, budujemy nowy obraz Dockera. Służy później do wdrożenia kontenera ze zmontowaną aplikacją. Teraz tak nie jest, ale planujemy przejście na architekturę mikroserwisową w Kubernetesie, która w naszej firmie aktywnie się rozwija i od dłuższego czasu służy rozwiązaniom produkcyjnym.

Streszczenie

Zachęcam wszystkich do wyrzucenia Windowsa, ale nie dlatego, że nie umiem go ugotować. Powodem jest to, że większość rozwiązań Open Source jest Stos Linuksa. czy wszystko w porządku oszczędzaj na zasobach. Moim zdaniem przyszłość należy do rozwiązań Open Source na Linuksie z potężną społecznością.

Profil głośnika Aleksandra Sinchinowa na GitHubie.

Konf. DevOps to konferencja poświęcona integracji procesów rozwoju, testowania i obsługi dla profesjonalistów przez profesjonalistów. Dlatego projekt, o którym mówił Alexander? wdrożone i działające, a w dniu występu miały miejsce dwie udane premiery. NA Konferencja DevOps w RIT++ 27 i 28 maja podobnych spraw ze strony praktyków będzie jeszcze więcej. Nadal możesz wskoczyć do ostatniego wagonu i Prześlij raport lub nie spiesz się zarezerwować bilet. Spotkajmy się w Skołkowie!

Źródło: www.habr.com

Dodaj komentarz