{"id":32217,"date":"2019-10-31T21:45:43","date_gmt":"2019-10-31T18:45:43","guid":{"rendered":"https:\/\/prohoster.info\/blog\/net-core-na-linux-devops-na-kone\/"},"modified":"2019-10-31T21:45:43","modified_gmt":"2019-10-31T18:45:43","slug":"net-core-na-linux-devops-na-kone","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","title":{"rendered":".NET Core na Linux, DevOps na szczycie.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Rozwijali\u015bmy DevOps, jak mogli\u015bmy. By\u0142o nas 8 os\u00f3b, a Wasya by\u0142 najlepszy w Windows. Nagle Wasya odszed\u0142, a ja musia\u0142em zaj\u0105\u0107 si\u0119 nowym projektem, kt\u00f3ry dostarcza\u0142by rozw\u00f3j Windows. Kiedy wy\u0142o\u017cy\u0142em na st\u00f3\u0142 ca\u0142y stos technologii Windows, zrozumia\u0142em, \u017ce sytuacja to b\u00f3l\u2026<\/p>\n<p>Tak zaczyna si\u0119 historia <b>Aleksandr Sinchinov<\/b> na <noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOpsConf<\/a><\/noindex>. Kiedy z firmy odszed\u0142 g\u0142\u00f3wny specjalista od Windows, Aleksandr zada\u0142 sobie pytanie, co teraz robi\u0107. Oczywi\u015bcie przej\u015b\u0107 na Linux! Aleksandr opowie, jak uda\u0142o mu si\u0119 stworzy\u0107 precedens i przenie\u015b\u0107 cz\u0119\u015b\u0107 rozwoju Windows na Linux na przyk\u0142adzie zrealizowanego projektu dla 100 000 u\u017cytkownik\u00f3w ko\u0144cowych.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/3c944351864df95217e133236542c9b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJak \u0142atwo i niewymuszenie dostarczy\u0107 projekt w RPM, u\u017cywaj\u0105c TFS, Puppet, Linux .NET core? Jak utrzyma\u0107 wersjonowanie BD projektu, je\u015bli zesp\u00f3\u0142 deweloperski po raz pierwszy s\u0142yszy s\u0142owa Postgres i Flyway, a deadline jest na pojutrze? Jak zintegrowa\u0107 z Dockerem? Jak zmotywowa\u0107 programist\u00f3w .NET do porzucenia Windows i smoothies na rzecz Puppet i Linux? Jak rozwi\u0105zywa\u0107 konflikty ideologiczne, gdy nie ma si\u0142y, woli ani zasob\u00f3w do obs\u0142ugi Windows w produkcji? O tym, oraz o Web Deploy, testowaniu, CI, praktykach u\u017cywania TFS w istniej\u0105cych projektach, a tak\u017ce o z\u0142amanych ko\u015bciach i dzia\u0142aj\u0105cych rozwi\u0105zaniach w transkrypcji wyk\u0142adu Aleksandra.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<center><div class=\"youtube-placeholder\" data-id=\"tZH9Ro9j9KQ\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/tZH9Ro9j9KQ\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nWi\u0119c Wasya odszed\u0142, zadanie spad\u0142o na mnie, programi\u015bci czekaj\u0105 z niecierpliwo\u015bci\u0105. Kiedy w ko\u0144cu zrozumia\u0142em, \u017ce nie mog\u0119 ju\u017c przywr\u00f3ci\u0107 Wasya - zabra\u0142em si\u0119 do pracy. Na pocz\u0105tek oceni\u0142em procent Win VM w naszym parku. Wynik nie by\u0142 na korzy\u015b\u0107 Windows.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/836e47372126b6ba369ac494b91c7d3c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPoniewa\u017c aktywnie rozwijamy DevOps, zrozumia\u0142em, \u017ce musimy zmieni\u0107 podej\u015bcie do wydania nowej aplikacji. Jedynym rozwi\u0105zaniem by\u0142o przenie\u015b\u0107 wszystko na Linux, je\u015bli to mo\u017cliwe. Google mi pom\u00f3g\u0142 - w tamtym czasie .Net by\u0142 ju\u017c portowany na Linux, wi\u0119c zrozumia\u0142em, \u017ce to jest rozwi\u0105zanie!<\/p>\n<h2>Dlaczego .NET core w po\u0142\u0105czeniu z Linux?<\/h2>\n<p>\nNa to by\u0142o kilka powod\u00f3w. Wi\u0119kszo\u015b\u0107 ludzi wybierze opcj\u0119 \u201enie p\u0142aci\u0107\u201d, zamiast \u201ep\u0142aci\u0107\u201d - tak jak ja. Licencja na MSDB kosztuje oko\u0142o 1000 $, a koszty utrzymania parku wirtualnych maszyn Windows liczone s\u0105 w setkach dolar\u00f3w. Dla du\u017cej firmy to ogromne wydatki. Dlatego <b>oszcz\u0119dno\u015b\u0107\u00a0<\/b>\u2014<b> to pierwszy pow\u00f3d<\/b>. Nie jest to najwa\u017cniejsze, ale jeden z istotnych.<\/p>\n<p>Maszyny wirtualne Windows zajmuj\u0105 wi\u0119cej zasob\u00f3w ni\u017c ich odpowiedniki w Linuxie - <b>s\u0105 ci\u0119\u017ckie<\/b>. Bior\u0105c pod uwag\u0119 skal\u0119 du\u017cej firmy, wybrali\u015bmy Linux.<\/p>\n<p><b>System wbudowuje si\u0119 w istniej\u0105cy CI<\/b>. Uwa\u017camy si\u0119 za nowoczesnych DevOps, u\u017cywamy Bamboo, Jenkins i GitLab CI, dlatego wi\u0119kszo\u015b\u0107 dzia\u0142a na Linuxie.<\/p>\n<p>Ostatni pow\u00f3d to <b>wygodne wsparcie. <\/b>Musieli\u015bmy obni\u017cy\u0107 pr\u00f3g wej\u015bcia dla \u201ewsparcia\u201d \u2013 ludzi, kt\u00f3rzy rozumiej\u0105 cz\u0119\u015b\u0107 techniczn\u0105, zapewniaj\u0105 ci\u0105g\u0142o\u015b\u0107 i obs\u0142uguj\u0105 us\u0142ugi na drugim poziomie. Byli ju\u017c zaznajomieni z ekosystemem Linux, wi\u0119c \u0142atwiej im zrozumie\u0107 nowy produkt, wspiera\u0107 i go obs\u0142ugiwa\u0107 zamiast inwestowa\u0107 dodatkowe zasoby, aby zrozumie\u0107 analogiczny funkcjonalno\u015bci oprogramowania dla platform Windows.<\/p>\n<h2>Wymagania<\/h2>\n<p>\nPierwsze i najwa\u017cniejsze to <b>wygoda nowego rozwi\u0105zania dla programist\u00f3w<\/b>. Nie wszyscy byli gotowi na zmiany, zw\u0142aszcza po wyra\u017conym s\u0142owie Linux. Programi\u015bci chc\u0105 swojej ulubionej Visual Studio, TFS z automatycznymi testami dla kompilacji i smoothiem. Jak odbywa si\u0119 dostawa do produkcji - dla nich to nie ma znaczenia. Dlatego zdecydowali\u015bmy si\u0119 nie zmienia\u0107 ustalonego procesu i pozostawi\u0107 wszystko bez zmian dla programist\u00f3w Windows. <\/p>\n<p>Nowy projekt musi by\u0107 <b>wbudowany w istniej\u0105cy CI<\/b>. Rails ju\u017c by\u0142y i ca\u0142\u0105 prac\u0119 nale\u017ca\u0142o wykona\u0107 z uwzgl\u0119dnieniem parametr\u00f3w systemu zarz\u0105dzania konfiguracj\u0105, przyj\u0119tych standard\u00f3w dostarczania i system\u00f3w monitorowania.<\/p>\n<p><b>Prostota w utrzymaniu i eksploatacji<\/b>, jako warunek minimalnego progu wej\u015bcia dla wszystkich nowych uczestnik\u00f3w z r\u00f3\u017cnych dzia\u0142\u00f3w i zespo\u0142u wsparcia.<\/p>\n<p><b>Termin - wczoraj<\/b>.<\/p>\n<h2>Zesp\u00f3\u0142 Win development<\/h2>\n<p>\nCzym wtedy zajmowa\u0142 si\u0119 zesp\u00f3\u0142 Windows?<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/6e6e128ef3d49410c260d05114f819a4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTeraz mog\u0119 spokojnie powiedzie\u0107, \u017ce <b>IdentityServer4<\/b>\u00a0to \u015bwietna darmowa alternatywa dla ADFS z podobnymi mo\u017cliwo\u015bciami, czy \u017ce <b>Entity Framework Core<\/b>\u00a0to raj dla programisty, gdzie nie trzeba si\u0119 martwi\u0107 pisaniem skrypt\u00f3w SQL, ale mo\u017cna opisywa\u0107 zapytania w bazie danych w terminach OOP. Ale wtedy, podczas omawiania planu dzia\u0142ania, patrzy\u0142em na ten stos jak na sumeryjski klin, znaj\u0105c jedynie PostgreSQL i Git.<\/p>\n<p>W tamtym czasie aktywnie u\u017cywali\u015bmy <b>Puppet<\/b> jako systemu zarz\u0105dzania konfiguracj\u0105. W wi\u0119kszo\u015bci naszych projekt\u00f3w stosowali\u015bmy <b>GitLab CI<\/b>, <b>Elastic<\/b>, zbalansowali\u015bmy wysoko obci\u0105\u017cone us\u0142ugi przy pomocy <b>HAProxy,<\/b> monitorowali\u015bmy wszystko przy pomocy <b>Zabbix<\/b>, zestawu <b>Grafana<\/b> i\u00a0<b>Prometheus<\/b>, <b>Jaeger<\/b>, i to wszystko dzia\u0142a\u0142o na sprz\u0119cie\u00a0<b>HP<\/b> c\u00a0<b>ESXi.<\/b> na\u00a0<b>VMware<\/b>Wszystkim znane - klasyka gatunku.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/f4ffcac7a7fbb4fa48d47f07bed52610.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZobaczmy i spr\u00f3bujmy zrozumie\u0107, co dzia\u0142o si\u0119 przed tym, jak zacz\u0119li\u015bmy wszystkie te interwencje.<\/p>\n<h2>Co by\u0142o<\/h2>\n<p>\nTFS to do\u015b\u0107 pot\u0119\u017cny system, kt\u00f3ry nie tylko dostarcza kod od programisty do finalnej maszyny produkcyjnej, ale r\u00f3wnie\u017c posiada zestaw do bardzo elastycznej integracji z r\u00f3\u017cnymi us\u0142ugami - w celu zapewnienia CI na poziomie wieloplatformowym.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/ea448b38e321a8350468d69f3e45e429.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDawniej by\u0142y to jedynie okna. TFS korzysta\u0142 z kilku agent\u00f3w Build, na kt\u00f3rych zbierano wiele projekt\u00f3w. W ka\u017cdym agencie by\u0142o po 3-4 worker\u00f3w, aby zr\u00f3wnolegli\u0107 zadania i zoptymalizowa\u0107 proces. Nast\u0119pnie, zgodnie z planami wydania, TFS dostarcza\u0142 \u015bwie\u017co upieczony Build na serwerze aplikacji Windows.<\/p>\n<h2>Do czego chcieli\u015bmy doj\u015b\u0107<\/h2>\n<p>\nDo dostarczania i rozwijania u\u017cywamy TFS, uruchamiamy aplikacj\u0119 na serwerze aplikacji Linux, a mi\u0119dzy nimi dzieje si\u0119 jaka\u015b magia. Ta <b>Magiczna skrzynka<\/b> jest istot\u0105 nadchodz\u0105cej pracy. Zanim roz\u0142o\u017c\u0119 j\u0105 na cz\u0119\u015bci, zrobi\u0119 krok w bok i powiem kilka s\u0142\u00f3w o aplikacji.<\/p>\n<h2>Projekt<\/h2>\n<p>\nAplikacja zapewnia funkcjonalno\u015b\u0107 do operowania kartami przedp\u0142aconymi. <\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/c93aa67b340c45ad279330466fc4f776.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Client<\/h3>\n<p>\nIstnia\u0142y dwa typy u\u017cytkownik\u00f3w. <b>Pierwszy<\/b> uzyskiwa\u0142 dost\u0119p, autoryzuj\u0105c si\u0119 certyfikatem SSL SHA-2. Drugi\u00a0<b>posiada\u0142 dost\u0119p za pomoc\u0105 loginu i has\u0142a.<\/b> Nast\u0119pnie zapytanie klienta trafia\u0142o do HAProxy, kt\u00f3re rozwi\u0105zywa\u0142o nast\u0119puj\u0105ce zadania:<\/p>\n<h3>HAProxy<\/h3>\n<p>\npodstawowa autoryzacja;<\/p>\n<ul>\n<li>terminowanie SSL;\n<\/li>\n<li>dostosowywanie zapyta\u0144 HTTP;\n<\/li>\n<li>translacja zapyta\u0144.\n<\/li>\n<li>Weryfikacja certyfikatu klienta odbywa\u0142a si\u0119 w oparciu o \u0142a\u0144cuch. My jeste\u015bmy\n<\/li>\n<\/ul>\n<p>\nauthority <b>i mo\u017cemy sobie na to pozwoli\u0107, poniewa\u017c sami wydajemy certyfikaty klientom us\u0142ugi. <\/b>Zwr\u00f3\u0107 uwag\u0119 na trzeci punkt, wr\u00f3cimy do niego za chwil\u0119.<\/p>\n<p>Backend planowano zrealizowa\u0107 na Linuxie. Backend wsp\u00f3\u0142pracuje z baz\u0105 danych, \u0142adowa\u0142 niezb\u0119dn\u0105 list\u0119 uprawnie\u0144, a nast\u0119pnie, w zale\u017cno\u015bci od tego, jakie uprawnienia posiada autoryzuj\u0105cy si\u0119 u\u017cytkownik, zapewnia\u0142 dost\u0119p do podpisywania dokument\u00f3w finansowych i ich wysy\u0142ania, b\u0105d\u017a generowania jakiego\u015b raportu.<\/p>\n<h3>Backend<\/h3>\n<p>\nOszcz\u0119dno\u015bci z HAProxy<\/p>\n<h2>Opr\u00f3cz dw\u00f3ch kontekst\u00f3w, w ramach kt\u00f3rych porusza\u0142 si\u0119 ka\u017cdy z klient\u00f3w, istnia\u0142 jeszcze kontekst identity.<\/h2>\n<p>\nkt\u00f3ry umo\u017cliwia autoryzacj\u0119, to bezp\u0142atny i pot\u0119\u017cny odpowiednik dla <b>IdentityServer4<\/b> ADFS <b>Active Directory Federation Services\u00a0<\/b>\u2014<b> Zapytanie w identity by\u0142o przetwarzane w kilku krokach. Pierwszy krok -<\/b>.<\/p>\n<p>trafia\u0142o do backendu <b>\u5ba2\u6237\u7aef<\/b> <b>trafia\u0107 do backendu<\/b>, kt\u00f3ry wymienia\u0142 dane z\u00a0tym serwerem i\u00a0sprawdza\u0142 obecno\u015b\u0107 tokenu dla klienta. Je\u015bli go nie\u00a0znajdowa\u0142,\u00a0\u2014 zapytanie wraca\u0142o do\u00a0kontekstu, z\u00a0kt\u00f3rego przysz\u0142o, ale\u00a0ju\u017c z\u00a0przekierowaniem, i\u00a0z\u00a0przekierowaniem kierowa\u0142o na\u00a0identity.<\/p>\n<p>Drugi krok\u00a0\u2014 zapytanie trafia\u0142o <b>na stron\u0119 logowania w\u00a0IdentityServer,<\/b> gdzie klient si\u0119 rejestrowa\u0142, a w\u00a0bazie danych IdentityServer pojawia\u0142 si\u0119 ten d\u0142ugo wyczekiwany token. <\/p>\n<p>Trzeci krok\u00a0\u2014 <b>klient by\u0142 przekierowywany z powrotem <\/b>na kontekst, z\u00a0kt\u00f3rego przyszed\u0142.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/e052c408d67485ab9aa10d0fd25df57e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIdentityServer4 ma pewn\u0105 w\u0142a\u015bciwo\u015b\u0107: <b>odpowied\u017a na\u00a0zapytanie zwrotne zwraca przez HTTP<\/b>. Jak bardzo starali\u015bmy si\u0119 z\u00a0konfiguracj\u0105 serwera, jak bardzo przestudiowali\u015bmy dokumentacj\u0119, to\u00a0za ka\u017cdym razem otrzymywali\u015bmy pocz\u0105tkowe zapytanie klienta z\u00a0URL, kt\u00f3ry przyszed\u0142 przez HTTPS, a\u00a0IdentityServer zwraca\u0142 ten sam kontekst, ale\u00a0przez HTTP. Byli\u015bmy w\u00a0szoku! I\u00a0przekierowali\u015bmy to wsz\u0119dzie przez kontekst identity na\u00a0HAProxy, a\u00a0w\u00a0nag\u0142\u00f3wkach musieli\u015bmy zmodyfikowa\u0107 protok\u00f3\u0142 HTTP na\u00a0HTTPS. <\/p>\n<p>Gdzie tkwi poprawa i\u00a0gdzie zaoszcz\u0119dzili\u015bmy?<\/p>\n<blockquote><p>Zaoszcz\u0119dzili\u015bmy pieni\u0105dze, korzystaj\u0105c z\u00a0bezp\u0142atnego rozwi\u0105zania do\u00a0autoryzacji grupy u\u017cytkownik\u00f3w, zasoby, poniewa\u017c nie\u00a0wyodr\u0119bniali\u015bmy IdentityServer4 jako osobnej nody w\u00a0oddzielnym segmencie, lecz\u00a0u\u017cywali\u015bmy go wsp\u00f3lnie z\u00a0backendem na\u00a0tym samym serwerze, gdzie dzia\u0142a backend aplikacji.<\/p><\/blockquote>\n<p><\/p>\n<h2>Jak powinno dzia\u0142a\u0107<\/h2>\n<p>\nA zatem, jak obieca\u0142em\u00a0\u2014 Magic Box. Ju\u017c rozumiemy, \u017ce\u00a0gwarantowanie poruszamy si\u0119 w\u00a0kierunku Linux. Formu\u0142ujmy konkretne zadania, kt\u00f3re wymaga\u0142y rozwi\u0105zania.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/cc59632aa0e5c65fe0efc754311ecf5e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Manifesty Puppet. <\/b>Aby dostarcza\u0107 i\u00a0zarz\u0105dza\u0107 konfiguracj\u0105 us\u0142ugi i\u00a0aplikacji, trzeba by\u0142o napisa\u0107 \u015bwietne przepisy. Rolka z\u00a0o\u0142\u00f3wkiem wymownie pokazuje, jak szybko i\u00a0jako\u015bciowo to by\u0142o zrobione.<\/p>\n<p><b>Spos\u00f3b dostawy. <\/b>Standard\u00a0\u2014 to\u00a0RPM. Wszyscy rozumiej\u0105, \u017ce w\u00a0Linuxie bez niego si\u0119 nie\u00a0obejdzie, ale\u00a0sam projekt po\u00a0zbi\u00f3rce stanowi\u0142 zestaw wykonywalnych plik\u00f3w DLL. By\u0142o ich oko\u0142o 150, projekt by\u0142 dosy\u0107 ci\u0119\u017cki. Jedynym harmonijnym rozwi\u0105zaniem by\u0142o spakowanie tej binari\u00f3w w\u00a0RPM i\u00a0ju\u017c z\u00a0niej wdra\u017canie aplikacji.<\/p>\n<p><b>Wersjonowanie. <\/b>Musieli\u015bmy cz\u0119sto wydawa\u0107 nowe wersje, dlatego musieli\u015bmy zdecydowa\u0107, jak formowa\u0107 nazw\u0119 pakietu. To jest kwestia integracji z TFS. Nasz agent budowy dzia\u0142a\u0142 na Linuxie. Kiedy TFS wysy\u0142a zadanie do wykonawcy - worker - na agenta budowy, przekazuje r\u00f3wnie\u017c zestaw zmiennych, kt\u00f3re trafiaj\u0105 do \u015brodowiska procesu wykonawczego. W tych zmiennych przekazywana jest nazwa budowy, nazwa wersji i inne zmienne. Wi\u0119cej informacji w sekcji \u201ebudowanie pakietu RPM\u201d.<\/p>\n<p><b>Konfiguracja TFS<\/b> polega\u0142a na ustawieniu Pipeline. Wcze\u015bniej zbierali\u015bmy wszystkie projekty Windows na agentach Windows, a teraz pojawia si\u0119 agent Linux - agent budowy, kt\u00f3ry nale\u017cy w\u0142\u0105czy\u0107 do grupy budowy, wzbogaci\u0107 o jakie\u015b artefakty i okre\u015bli\u0107, jakie projekty b\u0119d\u0105 zbierane na tym agencie budowy oraz jak zmodyfikowa\u0107 Pipeline.<\/p>\n<p><b>IdentityServer. <\/b>ADFS nie jest dla nas, wspieramy Open Source.<\/p>\n<p>Przejd\u017amy do komponent\u00f3w.<\/p>\n<h2>Magiczna skrzynka<\/h2>\n<p>\nSk\u0142ada si\u0119 z czterech cz\u0119\u015bci.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/22ea63bcf184046c15e034ec093352bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Agent budowy Linux. <\/b>Linux, poniewa\u017c to dla niego zbieramy - logiczne. Ta cz\u0119\u015b\u0107 by\u0142a wykonywana w trzech krokach.<\/p>\n<ul>\n<li><b>Skonfigurowa\u0107 worker\u00f3w<\/b> i nie tylko jednego, poniewa\u017c przewidywano rozproszon\u0105 prac\u0119 nad projektem.\n<\/li>\n<li><b>Zainstalowa\u0107 .NET Core 1.x<\/b>. Dlaczego 1.x, mimo \u017ce ju\u017c dost\u0119pna jest 2.0 w standardowym repozytorium? Poniewa\u017c, gdy zaczynali\u015bmy rozw\u00f3j, stabiln\u0105 wersj\u0105 by\u0142a 1.09, a projekt postanowiono zrobi\u0107 pod ni\u0105.\n<\/li>\n<li><b>Git 2.x<\/b>.\n<\/li>\n<\/ul>\n<p>\n<b>RPM-repozytorium. <\/b>Pakiety RPM musia\u0142y by\u0107 gdzie\u015b przechowywane. Zak\u0142adano, \u017ce b\u0119dziemy korzysta\u0107 z tej samej korporacyjnej bazy danych RPM, kt\u00f3ra jest dost\u0119pna dla wszystkich host\u00f3w Linux. Tak w\u0142a\u015bnie zrobili\u015bmy. Na serwerze repozytorium ustawiono <b>webhook<\/b> kt\u00f3ry pobiera\u0142 wymagany pakiet RPM z danego miejsca. Wersj\u0119 pakietu przekazywa\u0142 agent budowy do webhooka.<\/p>\n<p><b>GitLab. <\/b>Uwaga! GitLab jest u\u017cywany nie przez programist\u00f3w, a przez dzia\u0142 eksploatacji do kontroli wersji aplikacji, wersji pakiet\u00f3w, monitorowania stanu wszystkich maszyn Linux, a przechowuje w nim receptur\u0119 - wszystkie manifesty Puppet. <\/p>\n<p><b>Puppet<\/b>\u00a0\u2014 rozwi\u0105zuj\u0105c wszystkie sporne kwestie i dostarczaj\u0105c dok\u0142adnie t\u0119 konfiguracj\u0119, kt\u00f3rej chcemy, z Gitlab.<\/p>\n<p>Zaczynamy zanurzenie. Jak odbywa si\u0119 dostawa DLL w RPM?<\/p>\n<h3>Dostawa DLL w RPM<\/h3>\n<p>\nZa\u0142\u00f3\u017cmy, \u017ce mamy gwiazd\u0119 rocka programowania w .NET. U\u017cywa Visual Studio i tworzy ga\u0142\u0105\u017a wydania. Nast\u0119pnie \u0142aduje j\u0105 do Gita, a Git w tym przypadku jest bytem TFS, czyli to jest repozytorium aplikacji, z kt\u00f3rym pracuje programista.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/978240886981d41fc6d7b17d0a4fcb05.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPo czym TFS widzi, \u017ce nadesz\u0142o nowe zatwierdzenie. Jak\u0105 aplikacj\u0119? W ustawieniach TFS znajduje si\u0119 etykieta, jakimi zasobami dysponuje dany agent kompilacji. W tym przypadku widzi, \u017ce kompilujemy projekt .NET Core i wybiera agenta kompilacji Linux z puli. <\/p>\n<p>Agent kompilacji otrzymuje \u017ar\u00f3d\u0142a, pobiera niezb\u0119dne <b>dependencies<\/b> z repozytorium .NET, npm itd. i po skompilowaniu samej aplikacji oraz nast\u0119pnej paczki wysy\u0142a paczk\u0119 RPM do repozytorium RPM.<\/p>\n<p>Z drugiej strony dzieje si\u0119 nast\u0119puj\u0105ce. In\u017cynier dzia\u0142u eksploatacji zajmuje si\u0119 bezpo\u015brednim wprowadzeniem projektu: zmienia wersje pakiet\u00f3w w\u00a0<b>Hiera<\/b> w repozytorium, gdzie przechowywana jest receptura aplikacji, po czym Puppet wyzwala <b>Yum<\/b>, pobiera nowy pakiet z repozytorium, a nowa wersja aplikacji jest gotowa do u\u017cycia.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/6c2db3ce4bd7d4268e88c6c3d3ecbeba.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNa s\u0142owach wszystko jest proste, ale co dzieje si\u0119 wewn\u0105trz samego agenta kompilacji?<\/p>\n<h3>Pakowanie DLL RPM<\/h3>\n<p>\nOtrzymano \u017ar\u00f3d\u0142a projektu i zadanie na kompilacj\u0119 od TFS. Agent kompilacji <b>uruchamia kompilacj\u0119 samego projektu z \u017ar\u00f3de\u0142.<\/b>Skompilowany projekt jest dost\u0119pny w postaci wielu <b>plik\u00f3w DLL<\/b>, kt\u00f3re s\u0105 pakowane w archiwum zip, aby zmniejszy\u0107 obci\u0105\u017cenie systemu plik\u00f3w.<\/p>\n<p>Archiwum ZIP jest umieszczane <b>w katalogu kompilacji paczki RPM.<\/b> Nast\u0119pnie skrypt Bash inicjalizuje zmienne \u015brodowiskowe, znajduje wersj\u0119 Build, wersj\u0119 projektu, \u015bcie\u017ck\u0119 do katalogu kompilacji i uruchamia RPM-build. Po zako\u0144czeniu kompilacji paczka jest publikowana w\u00a0<b>lokalnym repozytorium<\/b>, kt\u00f3re znajduje si\u0119 na agencie kompilacji.<\/p>\n<p>Nast\u0119pnie, z agenta kompilacji na serwer do repozytori\u00f3w RPM <b>wysy\u0142ane jest \u017c\u0105danie JSON<\/b> z okre\u015bleniem nazwy wersji i numeru kompilacji. Webhook, o kt\u00f3rym wcze\u015bniej m\u00f3wi\u0142em, pobiera ten pakiet z lokalnego repozytorium na agencie kompilacji i udost\u0119pnia now\u0105 kompilacj\u0119 do zainstalowania.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/b69cacdadd171f4cbc9913b2ff4b7a79.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDlaczego w\u0142a\u015bnie taki schemat dostarczania pakietu do repozytorium RPM? Dlaczego nie mo\u017cna od razu wys\u0142a\u0107 skompilowanego pakietu do repozytorium? Chodzi o to, \u017ce jest to warunek dla zapewnienia bezpiecze\u0144stwa. Taki scenariusz ogranicza mo\u017cliwo\u015b\u0107 nieautoryzowanego przesy\u0142ania pakiet\u00f3w RPM przez osoby trzecie na serwer, kt\u00f3ry jest dost\u0119pny dla wszystkich maszyn Linux.<\/p>\n<h2>Wersjonowanie Bazy Danych<\/h2>\n<p>\nNa konsylium z zespo\u0142em deweloperskim okaza\u0142o si\u0119, \u017ce zespo\u0142owi bli\u017cej do MS SQL, ale w wi\u0119kszo\u015bci projekt\u00f3w non-Windows ju\u017c w pe\u0142ni u\u017cywali\u015bmy PostgreSQL. Poniewa\u017c ju\u017c postanowili\u015bmy zrezygnowa\u0107 ze wszystkiego, co p\u0142atne, zacz\u0119li\u015bmy u\u017cywa\u0107 PostgreSQL i tutaj.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/6b6c081344f2408c399248a70a63dccc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW tej cz\u0119\u015bci chc\u0119 opowiedzie\u0107, jak przeprowadzali\u015bmy wersjonowanie bazy danych i jak wybierali\u015bmy mi\u0119dzy Flyway a Entity Framework Core. Przyjrzymy si\u0119 ich zaletom i wadom.<\/p>\n<h3>Minusy<\/h3>\n<p>\nFlyway dzia\u0142a tylko w jedn\u0105 stron\u0119, nie\u00a0<b>mo\u017cemy cofn\u0105\u0107 si\u0119 wstecz<\/b>\u00a0\u2014 to istotna wada. Por\u00f3wnuj\u0105c z Entity Framework Core, mo\u017cna to oceni\u0107 pod wzgl\u0119dem wygody programisty. Pami\u0119tacie, \u017ce to postawili\u015bmy na pierwszym miejscu i g\u0142\u00f3wnym kryterium by\u0142o nie wprowadza\u0107 \u017cadnych zmian w programowaniu dla Windows.<\/p>\n<p>Do Flyway potrzebowali\u015bmy jakiego\u015b opakowania, <b>aby ch\u0142opaki nie pisali,<\/b>. Dla nich znacznie bardziej naturalne jest operowanie w terminach OOP. Przygotowali\u015bmy instrukcje dotycz\u0105ce pracy z obiektami bazy danych, powsta\u0142o zapytanie SQL i zosta\u0142o wykonane. Nowa wersja bazy danych gotowa, przesz\u0142a testy \u2014 wszystko dobrze, wszystko dzia\u0142a. <b>zapytania SQL<\/b>Entity Framework Core ma wad\u0119 \u2014 przy du\u017cych obci\u0105\u017ceniach generuje<\/p>\n<p>nieoptymalne zapytania SQL,\u00a0<b>a spadek wydajno\u015bci bazy danych mo\u017ce by\u0107 znaczny. Ale poniewa\u017c nasza us\u0142uga nie jest obci\u0105\u017cona, nie mierzymy obci\u0105\u017cenia setkami RPS, zaakceptowali\u015bmy te ryzyka i przekazali\u015bmy problemy przysz\u0142ym nam.<\/b>dzia\u0142a od razu i jest wygodny dla programist\u00f3w,<\/p>\n<h3>Zalety<\/h3>\n<p>\nEntity Framework Core <b>a Flyway<\/b>\u0142atwo integruje si\u0119 z istniej\u0105cym CI. <b>Ale robimy, aby to by\u0142o wygodne dla deweloper\u00f3w :)<\/b>Procedura wdro\u017cenia<\/p>\n<h3>Puppet widzi, \u017ce przychodzi zmiana wersji pakiet\u00f3w, w\u015br\u00f3d kt\u00f3rych jest ten odpowiedzialny za migracj\u0119. Najpierw instaluje pakiet, w kt\u00f3rym znajduj\u0105 si\u0119 skrypty migracyjne i funkcjonalno\u015b\u0107 zwi\u0105zana z baz\u0105 danych. Nast\u0119pnie aplikacja, kt\u00f3ra pracuje z baz\u0105 danych, jest restartowana. Kolejne pakiety s\u0105 instalowane po tym kroku. Kolejno\u015b\u0107 instalacji pakiet\u00f3w i uruchamiania aplikacji jest opisana w manife\u015bcie Puppet.<\/h3>\n<p>\nAplikacje wykorzystuj\u0105 dane wra\u017cliwe, takie jak tokeny, has\u0142a do bazy danych, wszystko to jest pobierane w konfiguracji z Puppet master, gdzie s\u0105 przechowywane w zaszyfrowanej formie.<\/p>\n<p>Problemy z TFS<\/p>\n<h2>Po tym, jak ustalili\u015bmy i zrozumieli\u015bmy, \u017ce naprawd\u0119 wszystko dzia\u0142a, postanowi\u0142em sprawdzi\u0107, co dzieje si\u0119 ze sk\u0142adkami w TFS w og\u00f3le dla dzia\u0142u Win-rozwoju w innych projektach \u2014 czy szybko si\u0119 budujemy\/wydajemy, i odkry\u0142em istotne problemy z pr\u0119dko\u015bci\u0105.<\/h2>\n<p>\nJeden z g\u0142\u00f3wnych projekt\u00f3w buduje si\u0119 12-15 minut \u2014 to d\u0142ugo, tak \u017cy\u0107 nie mo\u017cna. Szybka analiza wykaza\u0142a ogromny spadek wydajno\u015bci I\/O, a to na macierzach.<\/p>\n<p>Analizuj\u0105c sk\u0142adnikami, wyr\u00f3\u017cni\u0142em trzy ogniska. Pierwsze \u2014<\/p>\n<p>\u00abKaspersky antivirus\u00bb <b>\u00abAntywirus Kaspersky\u00bb<\/b>, kt\u00f3ry skanuje \u017ar\u00f3d\u0142a na wszystkich agentach Windows Build. Drugi - <b>Windows<\/b> <b>Indeksator.<\/b> Nie zosta\u0142 wy\u0142\u0105czony, a na agentach Build wszystko by\u0142o indeksowane w czasie rzeczywistym podczas procesu wdra\u017cania. <\/p>\n<p>Trzeci - <b>Npm install. <\/b>Okaza\u0142o si\u0119, \u017ce w wi\u0119kszo\u015bci Pipelines u\u017cywali\u015bmy dok\u0142adnie tego skryptu. Co w nim jest z\u0142ego? Procedura Npm install uruchamia si\u0119 podczas tworzenia drzewa zale\u017cno\u015bci w\u00a0<b>package-lock.json<\/b>, gdzie s\u0105 zapisywane wersje pakiet\u00f3w, kt\u00f3re b\u0119d\u0105 u\u017cyte do budowy projektu. Minusem jest to, \u017ce Npm install za ka\u017cdym razem pobiera aktualne wersje pakiet\u00f3w z internetu, co zajmuje sporo czasu w przypadku du\u017cego projektu.<\/p>\n<blockquote><p>Programi\u015bci czasami eksperymentuj\u0105 na lokalnej maszynie, aby sprawdzi\u0107 dzia\u0142anie pojedynczej cz\u0119\u015bci lub ca\u0142ego projektu. Czasami zdarza\u0142o si\u0119, \u017ce lokalnie wszystko dzia\u0142a\u0142o \u015bwietnie, ale podczas budowy, wdra\u017cania - nic nie dzia\u0142a\u0142o. Zaczynamy si\u0119 zastanawia\u0107, gdzie le\u017cy problem - aha, r\u00f3\u017cne wersje pakiet\u00f3w z zale\u017cno\u015bciami.<\/p><\/blockquote>\n<p><\/p>\n<h3>Rozwi\u0105zanie<\/h3>\n<p><\/p>\n<ul>\n<li>\u0179r\u00f3d\u0142a w wykluczeniach AV.\n<\/li>\n<li>Wy\u0142\u0105czenie indeksacji.\n<\/li>\n<li>Przej\u015bcie na\u00a0<b>npm ci<\/b>.\n<\/li>\n<\/ul>\n<p>\nZalety npm ci s\u0105 takie, \u017ce\u00a0<b>budujemy drzewo zale\u017cno\u015bci tylko raz<\/b>, i mo\u017cemy dostarczy\u0107 programi\u015bcie <b>aktualn\u0105 list\u0119 pakiet\u00f3w<\/b>, z kt\u00f3r\u0105 mo\u017ce eksperymentowa\u0107 lokalnie. To <b>oszcz\u0119dza czas<\/b> programist\u00f3w, kt\u00f3rzy pisz\u0105 kod.<\/p>\n<h3>Konfiguracja<\/h3>\n<p>\nTeraz troch\u0119 o konfiguracji repozytorium. Historycznie u\u017cywamy <b>Nexus<\/b> do zarz\u0105dzania repozytoriami, w tym <b>Internal REPO<\/b>. Do tego wewn\u0119trznego repozytorium dostarczane s\u0105 wszystkie komponenty, kt\u00f3re wykorzystujemy do cel\u00f3w wewn\u0119trznych, na przyk\u0142ad samodzielnie napisane narz\u0119dzia monitoruj\u0105ce.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core na Linux, DevOps na szczycie.\" src=\"\/wp-content\/uploads\/2019\/04\/147d7e80bf20e03a232f8b533be316eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nU\u017cywamy r\u00f3wnie\u017c <b>NuGet<\/b>, poniewa\u017c dobrze cache'uje w por\u00f3wnaniu do innych mened\u017cer\u00f3w pakiet\u00f3w.<\/p>\n<h3>Wynik<\/h3>\n<p>\nPo optymalizacji agencji Build \u015bredni czas budowy skr\u00f3ci\u0142 si\u0119 z 12 minut do 7.<\/p>\n<blockquote><p>Licz\u0105c wszystkie maszyny, kt\u00f3re mogliby\u015bmy wykorzysta\u0107 dla Windows, ale w tym projekcie przenie\u015bli\u015bmy na Linux, zaoszcz\u0119dzili\u015bmy oko\u0142o 10 000 dolar\u00f3w. I to tylko na licencjach, a je\u015bli uwzgl\u0119dni\u0107 utrzymanie - wi\u0119cej.<\/p><\/blockquote>\n<p><\/p>\n<h2>Plany<\/h2>\n<p>\nNa nast\u0119pny kwarta\u0142 w planach mamy prac\u0119 nad optymalizacj\u0105 dostarczania kodu.<\/p>\n<p><b>Przej\u015bcie na prebuild Docker-image<\/b>. TFS to \u015bwietna rzecz z wieloma wtyczkami, kt\u00f3re pozwalaj\u0105 integrowa\u0107 w Pipeline, w tym budow\u0119 na podstawie triggera, na przyk\u0142ad, obrazu Docker. Ten trigger chcemy ustawi\u0107 na ten w\u0142a\u015bnie sam. <b>package-lock.json<\/b>. Je\u015bli w jakikolwiek spos\u00f3b zmienia si\u0119 sk\u0142ad komponent\u00f3w u\u017cywanych do budowy projektu \u2013 tworzony jest nowy obraz Docker. W dalszej kolejno\u015bci jest on u\u017cywany do wdro\u017cenia kontenera z zbudowan\u0105 aplikacj\u0105. Obecnie tego nie ma, ale planujemy przej\u015b\u0107 na architektur\u0119 mikrous\u0142ug w Kubernetes, kt\u00f3ra aktywnie rozwija si\u0119 w naszej firmie i od dawna obs\u0142uguje rozwi\u0105zania produkcyjne.<\/p>\n<h2>Podsumowanie<\/h2>\n<p>\nZach\u0119cam wszystkich do porzucenia Windows, ale nie dlatego, \u017ce nie potrafi\u0119 go u\u017cywa\u0107. Pow\u00f3d jest taki, \u017ce wi\u0119kszo\u015b\u0107 rozwi\u0105za\u0144 typu Opensource to <b>stak Linux<\/b>. Dobrze <b>zaoszcz\u0119dzicie na zasobach<\/b>. Moim zdaniem przysz\u0142o\u015b\u0107 nale\u017cy do rozwi\u0105za\u0144 Open Source na Linux z siln\u0105 spo\u0142eczno\u015bci\u0105.<\/p>\n<p><i>Profil prelegenta Aleksandra Sinczinowa <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/alextuning\">na GitHubie<\/a><\/noindex>.<\/i><\/p>\n<blockquote><p><noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOps Conf<\/a><\/noindex>\u00a0to konferencja dotycz\u0105ca integracji proces\u00f3w tworzenia, testowania i eksploatacji dla profesjonalist\u00f3w od profesjonalist\u00f3w. Dlatego projekt, o kt\u00f3rym opowiada\u0142 Aleksander, zosta\u0142 zrealizowany i dzia\u0142a, a w dniu wyst\u0105pienia przeprowadzono dwa udane wydania. Na\u00a0<noindex><a rel=\"nofollow\" href=\"http:\/\/devopsconf.io\/moscow-rit\/2019\">DevOps Conf na RIT++<\/a><\/noindex> 27 i 28 maja b\u0119dzie jeszcze wi\u0119cej podobnych przypadk\u00f3w od praktyk\u00f3w. Mo\u017cna jeszcze wskoczy\u0107 do ostatniego wagonu i <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/lectures\/propose\/?conference=dc2019-rit\">zg\u0142osi\u0107 referat<\/a><\/noindex> lub na spokojnie <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/conference\/join\/rit2019.html?popup=3\">zarezerwowa\u0107<\/a><\/noindex> bilet. Do zobaczenia w Skolkowie!<\/p><\/blockquote>\n<p>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/448496\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u044b\u00a0\u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8\u00a0\u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438\u00a0\u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e\u00a0Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430\u00a0\u0443\u00a0\u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430. \u041a\u043e\u0433\u0434\u0430 \u044f\u00a0\u0432\u044b\u0441\u044b\u043f\u0430\u043b \u043d\u0430\u00a0\u0441\u0442\u043e\u043b \u0432\u0435\u0441\u044c \u0441\u0442\u0435\u043a Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u043e\u00a0\u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u00a0\u2014 \u0431\u043e\u043b\u044c\u2026 \u0422\u0430\u043a \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u043d\u0447\u0438\u043d\u043e\u0432\u0430 \u043d\u0430 DevOpsConf. \u041a\u043e\u0433\u0434\u0430 \u0438\u0437\u00a0\u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0443\u0448\u0435\u043b \u0432\u0435\u0434\u0443\u0449\u0438\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442 \u043f\u043e\u00a0Windows, \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440 \u0437\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0442\u044c. \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430\u00a0Linux, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24043,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32217","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u044b \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438 \u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47.NET Core \u043d\u0430 Linux, DevOps \u043d\u0430 \u043a\u043e\u043d\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u044b \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438 \u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:45:43+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:45:43+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47.NET Core na Linuxie, DevOps na koniu | ProHoster","description":"Rozwijali\u015bmy DevOps jak mogli\u015bmy. By\u0142o nas 8 os\u00f3b, a Wania by\u0142 najlepszy w Windows. Nagle Wania odszed\u0142, a ja mia\u0142em zadanie wprowadzenia nowego projektu, kt\u00f3ry dostarcza rozw\u00f3j Windows.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47.NET Core \u043d\u0430 Linux, DevOps \u043d\u0430 \u043a\u043e\u043d\u0435 | ProHoster","og:description":"\u041c\u044b \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438 \u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:45:43+00:00","article:modified_time":"2019-10-31T18:45:43+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32217","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 09:49:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:02:47","updated":"2026-01-21 09:49:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/32217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=32217"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/32217\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/24043"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=32217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=32217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=32217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}