{"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\/pt\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","title":{"rendered":".NET Core no Linux, DevOps no comando","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>N\u00f3s desenvolvemos DevOps da melhor maneira que pudemos. \u00c9ramos 8 pessoas, e o Vasya era o melhor em Windows. De repente, o Vasya saiu, e eu fiquei encarregado de lan\u00e7ar um novo projeto que fornece desenvolvimento em Windows. Quando joguei no escrit\u00f3rio toda a pilha de desenvolvimento em Windows, percebi que a situa\u00e7\u00e3o era dolorosa...<\/p>\n<p>Assim come\u00e7a a hist\u00f3ria <b>Alexandra Sinchinova<\/b> para <noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOpsConf<\/a><\/noindex>. Quando o especialista l\u00edder em Windows deixou a empresa, Alexander se questionou sobre o que fazer agora. Mudar para Linux, claro! Alexander contar\u00e1 como conseguiu criar um precedente e transferir parte do desenvolvimento em Windows para Linux, usando como exemplo um projeto realizado para 100.000 usu\u00e1rios finais.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/3c944351864df95217e133236542c9b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nComo entregar um projeto em RPM de forma f\u00e1cil e descontra\u00edda, usando TFS, Puppet e Linux .NET Core? Como manter o versionamento do banco de dados do projeto se os desenvolvedores ouviram falar pela primeira vez sobre Postgres e Flyway, e o prazo \u00e9 depois de amanh\u00e3? Como integrar com Docker? Como motivar os desenvolvedores .NET a abandonarem o Windows e os smoothies em favor do Puppet e do Linux? Como resolver conflitos ideol\u00f3gicos se atender ao Windows em produ\u00e7\u00e3o n\u00e3o \u00e9 vi\u00e1vel nem desejado? Faremos isso, assim como sobre Web Deploy, testes, CI, as pr\u00e1ticas de uso do TFS em projetos existentes e, claro, sobre pernas quebradas e solu\u00e7\u00f5es funcionais, na transcri\u00e7\u00e3o da palestra de Alexander.<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=\"Por que no hosting comum a administra\u00e7\u00e3o do PrestaShop \u00e9 lenta, e no seu n\u00e3o \u00e9?\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nEnt\u00e3o, o Vasya saiu, a tarefa ficou comigo, e os desenvolvedores esperam ansiosamente. Quando percebi que n\u00e3o conseguiria trazer o Vasya de volta, comecei a trabalhar. Primeiro, avaliei a porcentagem de VMs Windows em nosso parque. A contagem era desfavor\u00e1vel para o Windows.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/836e47372126b6ba369ac494b91c7d3c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nComo estamos desenvolvendo ativamente o DevOps, percebi que era preciso mudar a abordagem de implementa\u00e7\u00e3o do novo aplicativo. A solu\u00e7\u00e3o era clara: transferir tudo para Linux, se poss\u00edvel. O Google me ajudou \u2013 naquele momento, o .NET j\u00e1 havia sido portado para Linux, e percebi que essa era a solu\u00e7\u00e3o!<\/p>\n<h2>Por que .NET Core em conjunto com Linux?<\/h2>\n<p>\nHavia v\u00e1rias raz\u00f5es para isso. Entre \"pagar\" e \"n\u00e3o pagar\", a maioria escolher\u00e1 a segunda op\u00e7\u00e3o \u2013 assim como eu. A licen\u00e7a do MSDB custa cerca de 1.000 $, e a manuten\u00e7\u00e3o de um parque de m\u00e1quinas virtuais Windows gera custos na casa das centenas de d\u00f3lares. Para uma grande empresa, s\u00e3o altos gastos. Portanto, <b>a economia\u00a0<\/b>\u2014<b> \u00e9 a primeira raz\u00e3o<\/b>. N\u00e3o \u00e9 a mais importante, mas \u00e9 uma das mais significativas.<\/p>\n<p>As m\u00e1quinas virtuais Windows consomem mais recursos do que suas irm\u00e3s Linux \u2013 <b>elas s\u00e3o pesadas<\/b>. Considerando a escala de uma grande empresa, escolhemos o Linux.<\/p>\n<p><b>O sistema integra-se facilmente ao CI existente<\/b>. N\u00f3s nos consideramos DevOps progressivos, utilizamos Bamboo, Jenkins e GitLab CI, portanto, a maior parte do nosso trabalho gira em torno do Linux.<\/p>\n<p>A \u00faltima raz\u00e3o \u00e9 <b>a conveni\u00eancia do suporte. <\/b>Precis\u00e1vamos reduzir a barreira de entrada para os 'suportadores' - pessoas que entendem a parte t\u00e9cnica, garantem a continuidade e mant\u00eam os servi\u00e7os de um n\u00edvel secund\u00e1rio. Eles j\u00e1 estavam familiarizados com o stack Linux, ent\u00e3o era muito mais f\u00e1cil para eles entenderem o novo produto, manter e dar suporte, do que gastar recursos adicionais para se familiarizarem com uma funcionalidade semelhante de software para a plataforma Windows.<\/p>\n<h2>Requisitos<\/h2>\n<p>\nPrimeiro e mais importante - <b>a facilidade da nova solu\u00e7\u00e3o para os desenvolvedores<\/b>. Nem todos estavam prontos para a mudan\u00e7a, especialmente ap\u00f3s a men\u00e7\u00e3o do Linux. Os desenvolvedores querem o Visual Studio que amam, TFS com testes automatizados e smoothies. Como a entrega acontece em produ\u00e7\u00e3o - n\u00e3o lhes importa. Portanto, decidimos n\u00e3o mudar o processo familiar e deixar tudo inalterado para o desenvolvimento no Windows. <\/p>\n<p>O novo projeto precisa <b>ser integrado ao CI existente<\/b>. As trilhas j\u00e1 estavam estabelecidas e todo o trabalho precisava ser realizado considerando os par\u00e2metros do sistema de gerenciamento de configura\u00e7\u00e3o, os padr\u00f5es de entrega aceitos e os sistemas de monitoramento.<\/p>\n<p><b>A simplicidade no suporte e opera\u00e7\u00e3o<\/b>, como uma condi\u00e7\u00e3o para a m\u00ednima barreira de entrada para todos os novos participantes de diferentes departamentos e da equipe de suporte.<\/p>\n<p><b>O prazo era ontem<\/b>.<\/p>\n<h2>A equipe de desenvolvimento do Win<\/h2>\n<p>\nCom o que a equipe do Windows estava trabalhando ent\u00e3o?<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/6e6e128ef3d49410c260d05114f819a4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAgora posso afirmar com confian\u00e7a que <b>IdentityServer4<\/b>\u00a0\u00e9 uma \u00f3tima alternativa gratuita ao ADFS com funcionalidades semelhantes, ou que <b>Entity Framework Core<\/b>\u00a0\u00e9 um para\u00edso para o desenvolvedor, onde ele n\u00e3o precisa se preocupar em escrever scripts SQL, mas pode descrever consultas ao banco de dados em termos de POO. Mas naquela \u00e9poca, na discuss\u00e3o do plano de a\u00e7\u00e3o, eu via aquele stack como uma escrita cuneiforme sum\u00e9ria, reconhecendo apenas PostgreSQL e Git.<\/p>\n<p>Naquele momento, est\u00e1vamos utilizando ativamente <b>Puppet<\/b> como sistema de gerenciamento de configura\u00e7\u00e3o. Na maioria dos nossos projetos, aplic\u00e1vamos <b>GitLab CI<\/b>, <b>Elastic<\/b>, equilibrando servi\u00e7os de alta carga com <b>HAProxy,<\/b> monitorando tudo com <b>Zabbix<\/b>, uma combina\u00e7\u00e3o de <b>Grafana<\/b> e\u00a0<b>Prometheus<\/b>, <b>Jaeger<\/b>, e tudo isso funcionava em\u00a0<b>HP<\/b> c\u00a0<b>ESXi<\/b> para\u00a0<b>VMware<\/b>. Todo mundo conhece - um cl\u00e1ssico.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/f4ffcac7a7fbb4fa48d47f07bed52610.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVamos analisar e tentar entender o que aconteceu antes de come\u00e7armos todas essas interven\u00e7\u00f5es.<\/p>\n<h2>O que aconteceu<\/h2>\n<p>\nO TFS \u00e9 um sistema bastante poderoso, que n\u00e3o apenas entrega c\u00f3digo do desenvolvedor \u00e0 m\u00e1quina de produ\u00e7\u00e3o final, mas tamb\u00e9m possui um conjunto para uma integra\u00e7\u00e3o muito flex\u00edvel com diversos servi\u00e7os \u2013 para garantir CI em um n\u00edvel multiplataforma.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/ea448b38e321a8350468d69f3e45e429.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAntes, eram apenas caixas cont\u00ednuas. O TFS usava v\u00e1rios agentes de Build, onde muitos projetos eram compilados. Em cada agente, havia de 3 a 4 workers, para paralelizar tarefas e otimizar o processo. Em seguida, de acordo com os planos de lan\u00e7amento, o TFS entregava o Build rec\u00e9m-preparado em um servidor Windows de aplicativos.<\/p>\n<h2>A que quer\u00edamos chegar<\/h2>\n<p>\nPara entrega e desenvolvimento, usamos o TFS, e executamos o aplicativo em um servidor de aplica\u00e7\u00e3o Linux, com alguma m\u00e1gica entre eles. Esse <b>Caixa M\u00e1gica<\/b> \u00e9 o cerne do trabalho futuro. Antes de desmont\u00e1-lo em partes, vou fazer uma pausa e dizer algumas palavras sobre o aplicativo.<\/p>\n<h2>Projeto<\/h2>\n<p>\nO aplicativo oferece funcionalidades para operar cart\u00f5es pr\u00e9-pagos. <\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/c93aa67b340c45ad279330466fc4f776.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Cliente<\/h3>\n<p>\nExistiam dois tipos de usu\u00e1rios. <b>Primeiro<\/b> acessava o sistema, autenticando-se com um certificado SSL SHA-2. O\u00a0<b>segundo<\/b> tinha acesso com login e senha.<\/p>\n<h3>HAProxy<\/h3>\n<p>\nDepois, a solicita\u00e7\u00e3o do cliente chegava ao HAProxy, que resolvia as seguintes tarefas:<\/p>\n<ul>\n<li>autentica\u00e7\u00e3o inicial;\n<\/li>\n<li>termina\u00e7\u00e3o SSL;\n<\/li>\n<li>ajuste de requisi\u00e7\u00f5es HTTP;\n<\/li>\n<li>transmiss\u00e3o de requisi\u00e7\u00f5es.\n<\/li>\n<\/ul>\n<p>\nA verifica\u00e7\u00e3o do certificado do cliente seguia por uma cadeia. N\u00f3s somos a <b>autoridade <\/b>e podemos nos dar ao luxo, pois emitimos certificados aos clientes do servi\u00e7o.<\/p>\n<p>Preste aten\u00e7\u00e3o ao terceiro ponto, voltaremos a ele mais tarde.<\/p>\n<h3>Backend<\/h3>\n<p>\nO backend foi planejado para ser feito em Linux. O backend interage com o BD, carrega a lista necess\u00e1ria de privil\u00e9gios e, ent\u00e3o, dependendo dos privil\u00e9gios do usu\u00e1rio autenticado, fornece acesso para assinar documentos financeiros e envi\u00e1-los para execu\u00e7\u00e3o, ou gerar algum relat\u00f3rio.<\/p>\n<h2>Economia com HAProxy<\/h2>\n<p>\nAl\u00e9m dos dois contextos que cada um dos clientes percorria, havia tamb\u00e9m o contexto de identidade. <b>IdentityServer4<\/b> \u00e9 o que permite a autentica\u00e7\u00e3o, um an\u00e1logo gratuito e poderoso para <b>ADFS\u00a0<\/b>\u2014<b> Active Directory Federation Services<\/b>.<\/p>\n<p>A solicita\u00e7\u00e3o de identidade era processada em v\u00e1rias etapas. A primeira etapa \u2013 <b>leve<\/b> <b>chegava ao backend.<\/b>, que trocava dados com este servidor e verificava a exist\u00eancia de um token para o cliente. Se n\u00e3o fosse encontrado, a solicita\u00e7\u00e3o retornava ao contexto de onde veio, mas j\u00e1 com um redirecionamento, e com o redirecionamento ia para identity.<\/p>\n<p>O segundo passo - a solicita\u00e7\u00e3o chegava <b>\u00e0 p\u00e1gina de autoriza\u00e7\u00e3o no IdentityServer,<\/b> onde o cliente estava registrado e, no banco de dados do IdentityServer, o t\u00e3o aguardado token aparecia. <\/p>\n<p>O terceiro passo - <b>o cliente era redirecionado de volta <\/b>ao contexto de onde veio.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/e052c408d67485ab9aa10d0fd25df57e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nO IdentityServer4 tem uma particularidade: <b>a resposta \u00e0 solicita\u00e7\u00e3o de volta \u00e9 retornada via HTTP<\/b>. Por mais que tent\u00e1ssemos configurar o servidor e busc\u00e1ssemos na documenta\u00e7\u00e3o, cada vez receb\u00edamos a solicita\u00e7\u00e3o original do cliente com uma URL que vinha via HTTPS, e o IdentityServer retornava o mesmo contexto, mas com HTTP. Fomos pegos de surpresa! E passamos todo esse processo atrav\u00e9s do contexto identity no HAProxy, tendo que modificar o protocolo HTTP para HTTPS nos headers. <\/p>\n<p>Qual \u00e9 a melhoria e onde economizamos?<\/p>\n<blockquote><p>Economizamos dinheiro usando uma solu\u00e7\u00e3o gratuita para a autoriza\u00e7\u00e3o de grupo de usu\u00e1rios, recursos, pois n\u00e3o colocamos o IdentityServer4 como um n\u00f3 separado em um segmento distinto, mas o utilizamos juntamente com o backend no mesmo servidor onde o backend da aplica\u00e7\u00e3o est\u00e1 em execu\u00e7\u00e3o.<\/p><\/blockquote>\n<p><\/p>\n<h2>Como deve funcionar<\/h2>\n<p>\nEnt\u00e3o, como prometi - Magic Box. J\u00e1 entendemos que estamos avan\u00e7ando com garantia em dire\u00e7\u00e3o ao Linux. Vamos formular as tarefas espec\u00edficas que requeriam solu\u00e7\u00e3o.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/cc59632aa0e5c65fe0efc754311ecf5e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Manifestos Puppet. <\/b>Para entregar e gerenciar a configura\u00e7\u00e3o do servi\u00e7o e da aplica\u00e7\u00e3o, foi necess\u00e1rio escrever boas receitas. Um rolo com um l\u00e1pis ilustra claramente como isso foi feito de forma r\u00e1pida e eficiente.<\/p>\n<p><b>M\u00e9todo de entrega. <\/b>O padr\u00e3o \u00e9 RPM. Todos entendem que no Linux isso \u00e9 fundamental, mas o pr\u00f3prio projeto, ap\u00f3s a compila\u00e7\u00e3o, consistia em um conjunto de arquivos DLL execut\u00e1veis. Eram cerca de 150, o projeto \u00e9 bastante pesado. A \u00fanica solu\u00e7\u00e3o harmoniosa foi empacotar este bin\u00e1rio em RPM e ent\u00e3o desplegar a aplica\u00e7\u00e3o a partir dele.<\/p>\n<p><b>Versionamento. <\/b>N\u00f3s precis\u00e1vamos lan\u00e7ar com bastante frequ\u00eancia e foi necess\u00e1rio decidir como formar o nome do pacote. Essa \u00e9 uma quest\u00e3o de integra\u00e7\u00e3o com o TFS. O agente de Build estava em Linux. Quando o TFS envia uma tarefa para o processador - worker - no agente de Build, ele tamb\u00e9m passa um conjunto de vari\u00e1veis que entram no ambiente do processo do processador. Nesse conjunto de vari\u00e1veis de ambiente, o nome do Build, nome da vers\u00e3o e outras vari\u00e1veis s\u00e3o transmitidas. Detalhes sobre isso podem ser encontrados na se\u00e7\u00e3o 'constru\u00e7\u00e3o do pacote RPM'.<\/p>\n<p><b>Configura\u00e7\u00e3o do TFS<\/b> resumia-se \u00e0 configura\u00e7\u00e3o do Pipeline. Antes, colet\u00e1vamos todos os projetos do Windows em agentes Windows, mas agora temos um agente Linux - o agente de Build - que precisa ser inclu\u00eddo no grupo de constru\u00e7\u00e3o, enriquecido com alguns artefatos, especificar que tipo de projetos ser\u00e3o constru\u00eddos nesse agente de Build, e modificar de alguma forma o Pipeline.<\/p>\n<p><b>IdentityServer. <\/b>ADFS n\u00e3o \u00e9 o nosso caminho, n\u00f3s apoiamos o Open Source.<\/p>\n<p>Vamos passar pelos componentes.<\/p>\n<h2>Caixa M\u00e1gica<\/h2>\n<p>\nConsiste em quatro partes.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/22ea63bcf184046c15e034ec093352bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Agente de Build Linux. <\/b>Linux, porque estamos construindo para ele - \u00e9 l\u00f3gico. Essa parte foi realizada em tr\u00eas etapas.<\/p>\n<ul>\n<li><b>Configurar workers<\/b> e n\u00e3o apenas um, pois esperava-se um trabalho distribu\u00eddo no projeto.\n<\/li>\n<li><b>Instalar .NET Core 1.x<\/b>. Por que especificamente 1.x, quando j\u00e1 est\u00e1 dispon\u00edvel 2.0 no reposit\u00f3rio padr\u00e3o? Porque, quando come\u00e7amos o desenvolvimento, a vers\u00e3o est\u00e1vel era 1.09, e decidiu-se que o projeto seria feito com ela.\n<\/li>\n<li><b>Git 2.x<\/b>.\n<\/li>\n<\/ul>\n<p>\n<b>Reposit\u00f3rio RPM. <\/b>Os pacotes RPM precisavam ser armazenados em algum lugar. Supunha-se que usar\u00edamos o mesmo reposit\u00f3rio RPM corporativo, que est\u00e1 dispon\u00edvel para todos os hosts Linux. E assim fizemos. No servidor do reposit\u00f3rio, foi configurado <b>webhook<\/b> que baixava do local especificado o pacote RPM necess\u00e1rio. A vers\u00e3o do pacote era informada ao webhook pelo agente de Build.<\/p>\n<p><b>GitLab. <\/b>Aten\u00e7\u00e3o! O GitLab aqui \u00e9 utilizado n\u00e3o pelos desenvolvedores, mas pelo departamento de opera\u00e7\u00f5es para controle de vers\u00f5es do aplicativo, vers\u00f5es dos pacotes, controle do estado de todas as m\u00e1quinas Linux e nele \u00e9 armazenada a receita - todos os manifests do Puppet. <\/p>\n<p><b>Puppet<\/b>\u00a0resolve todas as quest\u00f5es controversas e entrega exatamente a configura\u00e7\u00e3o que desejamos, do GitLab.<\/p>\n<p>Vamos nos aprofundar. Como ocorre a entrega do DLL no RPM?<\/p>\n<h3>Entrega do DLL no RPM<\/h3>\n<p>\nSuponha que temos uma estrela do rock do desenvolvimento em .NET. Ele usa o Visual Studio e cria um ramo de release. Depois disso, ele o carrega no Git, e o Git aqui \u00e9 uma entidade do TFS, ou seja, \u00e9 o reposit\u00f3rio do aplicativo com o qual o desenvolvedor trabalha.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/978240886981d41fc6d7b17d0a4fcb05.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDepois disso, o TFS percebe que um novo commit foi enviado. Qual aplicativo? Nas configura\u00e7\u00f5es do TFS, existe uma etiqueta que indica quais recursos cada agente de constru\u00e7\u00e3o possui. Neste caso, ele v\u00ea que estamos compilando um projeto .NET Core e seleciona um agente de constru\u00e7\u00e3o Linux do pool. <\/p>\n<p>O agente de constru\u00e7\u00e3o recebe os c\u00f3digos-fonte, baixa os necess\u00e1rios <b>dependencies<\/b> do reposit\u00f3rio .NET, npm, etc., e ap\u00f3s a compila\u00e7\u00e3o do pr\u00f3prio aplicativo e o empacotamento subsequente, envia o pacote RPM para o reposit\u00f3rio RPM.<\/p>\n<p>Por outro lado, o seguinte acontece. O engenheiro da equipe de opera\u00e7\u00f5es est\u00e1 lidando diretamente com a implementa\u00e7\u00e3o do projeto: ele altera as vers\u00f5es dos pacotes no\u00a0<b>Hiera<\/b> no reposit\u00f3rio onde a receita do aplicativo est\u00e1 armazenada, ap\u00f3s o que o Puppet dispara <b>Yum<\/b>, busca o novo pacote do reposit\u00f3rio e a nova vers\u00e3o do aplicativo est\u00e1 pronta para uso.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/6c2db3ce4bd7d4268e88c6c3d3ecbeba.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEm teoria, tudo \u00e9 simples, mas o que acontece internamente no agente de constru\u00e7\u00e3o?<\/p>\n<h3>Empacotamento DLL RPM<\/h3>\n<p>\nOs c\u00f3digos-fonte do projeto foram recebidos e a tarefa de compila\u00e7\u00e3o do TFS. O agente de constru\u00e7\u00e3o <b>inicia a compila\u00e7\u00e3o do pr\u00f3prio projeto a partir dos c\u00f3digos-fonte.<\/b>O projeto compilado est\u00e1 dispon\u00edvel na forma de v\u00e1rios <b>arquivos DLL<\/b>, que s\u00e3o empacotados em um arquivo zip para reduzir a carga no sistema de arquivos.<\/p>\n<p>O arquivo ZIP \u00e9 enviado <b>para o diret\u00f3rio de constru\u00e7\u00e3o do pacote RPM.<\/b> Em seguida, um script Bash inicializa vari\u00e1veis de ambiente, encontra a vers\u00e3o da constru\u00e7\u00e3o, a vers\u00e3o do projeto, o caminho para o diret\u00f3rio de constru\u00e7\u00e3o e inicia o RPM-build. Ap\u00f3s a conclus\u00e3o da constru\u00e7\u00e3o, o pacote \u00e9 publicado no\u00a0<b>reposit\u00f3rio local<\/b>, que est\u00e1 localizado no agente de constru\u00e7\u00e3o.<\/p>\n<p>Depois, do agente de constru\u00e7\u00e3o para o servidor em reposit\u00f3rios RPM <b>\u00e9 enviado um pedido JSON<\/b> especificando o nome da vers\u00e3o e da constru\u00e7\u00e3o. O Webhook, do qual falei anteriormente, baixa esse pacote do reposit\u00f3rio local no agente de constru\u00e7\u00e3o e torna uma nova constru\u00e7\u00e3o dispon\u00edvel para instala\u00e7\u00e3o.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/b69cacdadd171f4cbc9913b2ff4b7a79.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPor que essa l\u00f3gica de entrega do pacote ao reposit\u00f3rio RPM? Por que n\u00e3o enviar o pacote compilado diretamente para o reposit\u00f3rio? A quest\u00e3o \u00e9 que esta \u00e9 uma condi\u00e7\u00e3o para garantir a seguran\u00e7a. Esse cen\u00e1rio limita a possibilidade de upload n\u00e3o autorizado de pacotes RPM por pessoas n\u00e3o autorizadas para o servidor, que est\u00e1 acess\u00edvel a todas as m\u00e1quinas Linux.<\/p>\n<h2>Versionamento do BD<\/h2>\n<p>\nNa reuni\u00e3o de desenvolvimento, ficou claro que a equipe preferia o MS SQL, mas na maioria dos projetos n\u00e3o-Windows j\u00e1 est\u00e1vamos usando PostgreSQL. Como j\u00e1 decidimos abrir m\u00e3o de tudo que \u00e9 pago, come\u00e7amos a usar PostgreSQL aqui tamb\u00e9m.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/6b6c081344f2408c399248a70a63dccc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNesta parte, quero falar sobre como realizamos o versionamento do banco de dados e como escolhemos entre Flyway e Entity Framework Core. Vamos analisar os pr\u00f3s e contras deles.<\/p>\n<h3>Desvantagens<\/h3>\n<p>\nO Flyway funciona apenas em uma dire\u00e7\u00e3o, n\u00f3s\u00a0<b>n\u00e3o podemos reverter altera\u00e7\u00f5es<\/b>\u00a0\u2014 esse \u00e9 um ponto negativo significativo. Comparar com o Entity Framework Core pode ser feito por outros crit\u00e9rios \u2014 do ponto de vista da conveni\u00eancia para o desenvolvedor. Voc\u00ea se lembra que isso foi o que priorizamos, e o crit\u00e9rio principal foi n\u00e3o alterar nada para o desenvolvimento no Windows.<\/p>\n<p>Para o Flyway, n\u00f3s <b>precis\u00e1vamos de algum wrapper<\/b>, para que a equipe n\u00e3o precisasse escrever <b>consultas SQL<\/b>. \u00c9 muito mais familiar para eles trabalhar em termos de OOP. Escrevemos instru\u00e7\u00f5es para trabalhar com os objetos do banco de dados, uma consulta SQL foi formada e executada. A nova vers\u00e3o do banco de dados est\u00e1 pronta, testada \u2014 tudo bem, tudo funcionando.<\/p>\n<p>O Entity Framework Core tem um ponto fraco \u2014 sob alta carga, ele\u00a0<b>gera consultas SQL n\u00e3o otimizadas<\/b>, e a queda no banco de dados pode ser significativa. No entanto, como nosso servi\u00e7o n\u00e3o \u00e9 de alta carga, n\u00e3o medimos a carga em centenas de RPS, aceitamos esses riscos e delegamos o problema para o nosso futuro.<\/p>\n<h3>Pr\u00f3s<\/h3>\n<p>\nEntity Framework Core <b>funciona pronto para uso e \u00e9 conveniente para desenvolvimento<\/b>, enquanto o Flyway <b>integra-se facilmente ao CI existente<\/b>. Mas estamos tornando tudo mais conveniente para os desenvolvedores :)<\/p>\n<h3>O processo de aplica\u00e7\u00e3o<\/h3>\n<p>\nO Puppet verifica as atualiza\u00e7\u00f5es de vers\u00e3o dos pacotes, entre os quais est\u00e1 o respons\u00e1vel pela migra\u00e7\u00e3o. Primeiro, instala o pacote que cont\u00e9m os scripts de migra\u00e7\u00e3o e a funcionalidade relacionada ao banco de dados. Ap\u00f3s isso, o aplicativo que trabalha com o banco de dados \u00e9 reiniciado. Depois vem a instala\u00e7\u00e3o dos componentes restantes. A ordem de instala\u00e7\u00e3o dos pacotes e o in\u00edcio dos aplicativos est\u00e3o descritos no manifesto do Puppet.<\/p>\n<p>Os aplicativos utilizam dados sens\u00edveis, como tokens, senhas para o banco de dados, tudo isso \u00e9 puxado na configura\u00e7\u00e3o do Puppet master, onde s\u00e3o armazenados de forma criptografada.<\/p>\n<h2>Problemas no TFS<\/h2>\n<p>\nDepois que confirmamos que tudo realmente funcionava, decidi investigar como estavam as compila\u00e7\u00f5es no TFS de forma geral para o departamento de desenvolvimento em Windows para outros projetos \u2014 se est\u00e1vamos compilando\/lan\u00e7ando rapidamente ou n\u00e3o, e encontrei problemas significativos com a velocidade.<\/p>\n<p>Um dos principais projetos est\u00e1 levando de 12 a 15 minutos para compilar \u2014 isso \u00e9 muito, n\u00e3o podemos viver assim. Uma an\u00e1lise r\u00e1pida mostrou uma queda extremamente ruim em I\/O, e isso em arrays.<\/p>\n<p>Analisando por componentes, identifiquei tr\u00eas focos. O primeiro \u2014 <b>\u00abKaspersky antivirus\u00bb<\/b>, que escaneia o c\u00f3digo-fonte em todos os agentes de Build do Windows. O segundo \u2014 <b>Windows<\/b> <b>Indexer.<\/b> Ele n\u00e3o foi desativado e tudo foi indexado em tempo real nos agentes de Build durante o processo de deployment. <\/p>\n<p>O terceiro \u2014 <b>Npm install. <\/b>Descobrimos que na maioria dos Pipelines n\u00f3s us\u00e1vamos exatamente esse script. O que h\u00e1 de errado com isso? O procedimento Npm install \u00e9 executado durante a forma\u00e7\u00e3o da \u00e1rvore de depend\u00eancias em\u00a0<b>package-lock.json<\/b>, onde as vers\u00f5es dos pacotes que ser\u00e3o usadas para a constru\u00e7\u00e3o do projeto s\u00e3o registradas. O problema \u00e9 que o Npm install puxa a vers\u00e3o mais recente dos pacotes da internet a cada vez, o que consome um tempo consider\u00e1vel em um projeto grande.<\/p>\n<blockquote><p>Os desenvolvedores \u00e0s vezes experimentam em suas m\u00e1quinas locais para verificar o funcionamento de uma parte espec\u00edfica ou do projeto como um todo. \u00c0s vezes, tudo funcionava perfeitamente localmente, mas ao construir e implantar \u2014 nada funcionava. Come\u00e7amos a investigar qual era o problema \u2014 ah, diferentes vers\u00f5es de pacotes e suas depend\u00eancias.<\/p><\/blockquote>\n<p><\/p>\n<h3>Solu\u00e7\u00e3o<\/h3>\n<p><\/p>\n<ul>\n<li>C\u00f3digos-fonte em exce\u00e7\u00f5es AV.\n<\/li>\n<li>Desativa\u00e7\u00e3o da indexa\u00e7\u00e3o.\n<\/li>\n<li>Mudan\u00e7a para\u00a0<b>npm ci<\/b>.\n<\/li>\n<\/ul>\n<p>\nAs vantagens do npm ci s\u00e3o que n\u00f3s\u00a0<b>constru\u00edmos a \u00e1rvore de depend\u00eancias uma \u00fanica vez<\/b>, e obtemos a chance de fornecer ao desenvolvedor <b>uma lista atualizada de pacotes<\/b>, com a qual ele pode experimentar \u00e0 vontade localmente. Isso <b>economiza tempo<\/b> dos desenvolvedores que escrevem c\u00f3digo.<\/p>\n<h3>Configura\u00e7\u00e3o<\/h3>\n<p>\nAgora, um pouco sobre a configura\u00e7\u00e3o do reposit\u00f3rio. Historicamente, usamos <b>Nexus<\/b> para gerenciar reposit\u00f3rios, incluindo <b>Internal REPO<\/b>. Nesse reposit\u00f3rio interno, todos os componentes que usamos para finalidades internas s\u00e3o fornecidos, como monitoramentos feitos em casa.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core no Linux, DevOps no comando\" src=\"\/wp-content\/uploads\/2019\/04\/147d7e80bf20e03a232f8b533be316eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nN\u00f3s tamb\u00e9m usamos <b>NuGet<\/b>, pois ele faz um cache melhor em compara\u00e7\u00e3o com outros gerenciadores de pacotes.<\/p>\n<h3>Resultado<\/h3>\n<p>\nAp\u00f3s otimizarmos os agentes de Build, o tempo m\u00e9dio de constru\u00e7\u00e3o foi reduzido de 12 minutos para 7.<\/p>\n<blockquote><p>Se contarmos todas as m\u00e1quinas que poder\u00edamos ter usado para Windows, mas que migramos para Linux neste projeto, economizamos cerca de $10.000. E isso s\u00f3 em licen\u00e7as, e se levarmos em conta os custos de manuten\u00e7\u00e3o \u2014 \u00e9 mais.<\/p><\/blockquote>\n<p><\/p>\n<h2>Planos<\/h2>\n<p>\nPara o pr\u00f3ximo trimestre, planejamos trabalhar na otimiza\u00e7\u00e3o da entrega de c\u00f3digo.<\/p>\n<p><b>Mudan\u00e7a para a pr\u00e9-build da imagem Docker<\/b>. O TFS \u00e9 uma ferramenta incr\u00edvel com muitos plugins que permitem integrar ao Pipeline, incluindo a constru\u00e7\u00e3o por um trigger, por exemplo, de uma imagem Docker. Este trigger que queremos implementar \u00e9 exatamente esse <b>package-lock.json<\/b>. Se a composi\u00e7\u00e3o dos componentes utilizados para construir o projeto mudar de alguma forma, um novo Docker image ser\u00e1 criado. Este, posteriormente, \u00e9 usado para a implanta\u00e7\u00e3o de um cont\u00eainer com o aplicativo constru\u00eddo. No momento, isso n\u00e3o acontece, mas planejamos migrar para uma arquitetura de microservi\u00e7os no Kubernetes, que est\u00e1 se desenvolvendo ativamente em nossa empresa e h\u00e1 muito suporta solu\u00e7\u00f5es de produ\u00e7\u00e3o.<\/p>\n<h2>Resumo<\/h2>\n<p>\nEu incentivo todos a abandonarem o Windows, mas n\u00e3o porque eu n\u00e3o saiba como prepar\u00e1-lo. A raz\u00e3o \u00e9 que a maior parte das solu\u00e7\u00f5es Opensource \u00e9 <b>pilha Linux<\/b>. Voc\u00ea economizar\u00e1 <b>recursos.<\/b>Na minha opini\u00e3o, o futuro est\u00e1 em solu\u00e7\u00f5es Open Source no Linux com uma comunidade forte.<\/p>\n<p><i>Perfil do palestrante Alexandre Sinchino <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/alextuning\">no GitHub<\/a><\/noindex>.<\/i><\/p>\n<blockquote><p><noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOps Conf<\/a><\/noindex>\u00a0\u00e9 uma confer\u00eancia sobre integra\u00e7\u00e3o de processos de desenvolvimento, teste e opera\u00e7\u00f5es para profissionais por profissionais. \u00c9 por isso que o projeto sobre o qual Alexandre falou foi implementado e est\u00e1 em funcionamento, e no dia da sua apresenta\u00e7\u00e3o, duas libera\u00e7\u00f5es bem-sucedidas foram realizadas.\u00a0<noindex><a rel=\"nofollow\" href=\"http:\/\/devopsconf.io\/moscow-rit\/2019\">No DevOps Conf em RIT++<\/a><\/noindex> nos dias 27 e 28 de maio haver\u00e1 ainda mais casos como esses apresentados por praticantes. Voc\u00ea ainda pode embarcar no \u00faltimo trem e <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/lectures\/propose\/?conference=dc2019-rit\">submeter uma proposta<\/a><\/noindex> ou com calma <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/conference\/join\/rit2019.html?popup=3\">reservar<\/a><\/noindex> um ingresso. Nos encontramos em Skolkovo!<\/p><\/blockquote>\n<p>Fonte: <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.3 - 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\/pt\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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 no Linux, DevOps na crista da onda | ProHoster","description":"Desenvolvemos o DevOps como pudemos. \u00c9ramos 8 pessoas, e o Vasya era o melhor em Windows. De repente, Vasya saiu, e eu tive a tarefa de lan\u00e7ar um novo projeto que oferece desenvolvimento em Windows.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/32217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=32217"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/32217\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/24043"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=32217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=32217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=32217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}