.NET Core en Linux, DevOps a cabalo

Desenvolvemos DevOps como puidemos. Eramos 8, e Vasya era o máis xenial de Windows. De súpeto, Vasya marchou e tiven a tarefa de lanzar un novo proxecto que foi proporcionado polo desenvolvemento de Windows. Cando botei toda a pila de desenvolvemento de Windows sobre a mesa, decateime de que a situación era unha dor...

Así comeza a historia Alexandra Sinchinova en DevOpsConf. Cando o principal especialista en Windows deixou a empresa, Alexander preguntouse que facer agora. Cambia a Linux, por suposto! Alexander contarache como conseguiu crear un precedente e transferir parte do desenvolvemento de Windows a Linux usando o exemplo dun proxecto rematado para 100 usuarios finais.

.NET Core en Linux, DevOps a cabalo

Como entregar facilmente e sen esforzo un proxecto a RPM usando TFS, Puppet, Linux .NET core? Como admitir a versión dunha base de datos de proxecto se o equipo de desenvolvemento escoita as palabras Postgres e Flyway por primeira vez e a data límite é pasado mañá? Como integrarse con Docker? Como motivar aos desenvolvedores de .NET para que abandonen Windows e os smoothies en favor de Puppet e Linux? Como resolver os conflitos ideolóxicos se non hai nin a forza, nin o desexo, nin os recursos para manter Windows en produción? Sobre isto, así como sobre Web Deploy, probas, CI, sobre as prácticas de uso de TFS en proxectos existentes e, por suposto, sobre muletas rotas e solucións de traballo, na transcrición do informe de Alexander.


Entón, Vasya deixou, a tarefa corre por min, os desenvolvedores están esperando impacientes con forcos. Cando finalmente me decatei de que Vasya non podía ser devolto, púxenme ao negocio. Para comezar, avaliei a porcentaxe de máquinas virtuales Win na nosa flota. A puntuación non foi a favor de Windows.

.NET Core en Linux, DevOps a cabalo

Dado que estamos desenvolvendo activamente DevOps, decateime de que hai que cambiar algo no enfoque para ofrecer unha nova aplicación. Só había unha solución: se é posible, transferir todo a Linux. Google axudoume: nese momento .Net xa fora portado a Linux, e decateime de que esta era a solución!

Por que .NET core xunto con Linux?

Houbo varias razóns para iso. Entre "pagar diñeiro" e "non pagar", a maioría escollerá o segundo, coma min. Unha licenza para MSDB custa uns 1 dólares; manter unha flota de máquinas virtuais Windows custa centos de dólares. Para unha gran empresa isto é un gran gasto. Por iso aforro - primeira razón. Non o máis importante, pero si un dos significativos.

As máquinas virtuais Windows ocupan máis recursos que os seus irmáns Linux. son pesados. Dada a escala da gran empresa, escollemos Linux.

O sistema simplemente está integrado no CI existente. Consideramos DevOps progresivos, usamos Bamboo, Jenkins e GitLab CI, polo que a maior parte do noso traballo funciona en Linux.

A última razón é acompañamento conveniente. Necesitabamos rebaixar a barreira de entrada das "escoltas", os mozos que entenden a parte técnica, aseguran un servizo ininterrompido e manteñen os servizos desde a segunda liña. Xa estaban familiarizados coa pila de Linux, polo que é moito máis fácil para eles comprender, apoiar e manter un produto novo que gastar recursos adicionais para comprender a mesma funcionalidade do software para a plataforma Windows.

Requisitos

Primeiro e máis importante - conveniencia da nova solución para desenvolvedores. Non todos estaban preparados para o cambio, especialmente despois de que se falase a palabra Linux. Os desenvolvedores queren o seu Visual Studio favorito, TFS con autotests para montaxes e batidos. Como se produce a entrega á produción non é importante para eles. Por iso, decidimos non cambiar o proceso habitual e deixar todo sen cambios para o desenvolvemento de Windows.

Necesítase novo proxecto integrar no CI existente. Os carrís xa estaban alí e todo o traballo había que facerse tendo en conta os parámetros do sistema de xestión da configuración, as normas de entrega aceptadas e os sistemas de vixilancia.

Facilidade de apoio e operación, como condición para o limiar mínimo de entrada para todos os novos participantes das distintas divisións e do departamento de apoio.

Prazo - onte.

Win Development Group

Con que traballaba entón o equipo de Windows?

.NET Core en Linux, DevOps a cabalo

Agora podo dicir iso con confianza IdentityServer 4 é unha alternativa gratuíta a ADFS con capacidades similares, ou que Entity Framework Core - un paraíso para un programador, onde non tes que molestarte en escribir scripts SQL, pero describir consultas na base de datos en termos de POO. Pero despois, durante a discusión do plan de acción, mirei esta pila coma se fose cuneiforme sumerio, recoñecendo só PostgreSQL e Git.

Nese momento estabamos usando activamente Títere como un sistema de xestión de configuración. Na maioría dos nosos proxectos utilizamos GitLab CI, Elástico, servizos equilibrados de alta carga utilizando HAProxy supervisado todo con Zabbix, ligamentos grafana и Prometeu, Jaeger, e todo isto estaba xirando sobre anacos de ferro HPESXi en VMware. Todo o mundo sábeo - un clásico do xénero.

.NET Core en Linux, DevOps a cabalo

Vexamos e intentemos comprender o que pasou antes de comezar todas estas intervencións.

Que pasou

TFS é un sistema bastante potente que non só entrega código do programador á máquina de produción final, senón que tamén ten un conxunto para unha integración moi flexible con varios servizos, para proporcionar CI a nivel multiplataforma.

.NET Core en Linux, DevOps a cabalo
Anteriormente, estas eran fiestras sólidas. TFS utilizou varios axentes de compilación, que se utilizaron para montar moitos proxectos. Cada axente ten 3-4 traballadores para paralelizar tarefas e optimizar o proceso. Despois, segundo os plans de lanzamento, TFS entregou o Build recén cocido ao servidor de aplicacións de Windows.

Que queriamos conseguir?

Usamos TFS para entrega e desenvolvemento, e executamos a aplicación nun servidor de aplicacións Linux, e hai algún tipo de maxia entre eles. Isto Caixa máxica e aí está o sal do traballo por diante. Antes de desmontalo, vou dar un paso a un lado e dicir algunhas palabras sobre a aplicación.

Proxecto

A aplicación ofrece funcionalidades para manexar tarxetas prepago.

.NET Core en Linux, DevOps a cabalo

Cliente

Había dous tipos de usuarios. Primeiro obtivo acceso iniciando sesión mediante un certificado SSL SHA-2. U o segundo houbo acceso mediante un inicio de sesión e un contrasinal.

HAProxy

A continuación, a solicitude do cliente foi a HAProxy, que resolveu os seguintes problemas:

  • autorización primaria;
  • Terminación SSL;
  • axustar solicitudes HTTP;
  • solicitudes de emisión.

Verificouse o certificado do cliente ao longo da cadea. Nós - autoridade e podemos pagar isto, xa que nós mesmos emitimos certificados para os clientes de servizo.

Prestade atención ao terceiro punto, volveremos sobre el un pouco máis tarde.

motor

Planearon facer o backend en Linux. O backend interactúa coa base de datos, carga a lista de privilexios necesaria e despois, dependendo de que privilexios teña o usuario autorizado, proporciona acceso para asinar documentos financeiros e envialos para a súa execución ou xerar algún tipo de informe.

Aforro con HAProxy

Ademais dos dous contextos que navegaba cada cliente, tamén había un contexto de identidade. IdentityServer 4 só che permite iniciar sesión, este é un análogo gratuíto e potente para ADFS - Servizos de federación de Active Directory.

A solicitude de identidade procesouse en varios pasos. Primeiro paso - cliente entrou no backend, que se comunicou con este servidor e comprobou a presenza dun token para o cliente. Se non se atopaba, a solicitude volvíase ao contexto do que procedía, pero cunha redirección, e coa redirección pasaba a identidade.

Segundo paso: recibiuse a solicitude á páxina de autorización en IdentityServer, onde se rexistrou o cliente e ese token tan esperado apareceu na base de datos IdentityServer.

Terceiro paso - o cliente foi redirixido de volta ao contexto do que procede.

.NET Core en Linux, DevOps a cabalo

IdentityServer4 ten unha característica: devolve a resposta á solicitude de devolución a través de HTTP. Por moito que nos esforzaramos coa configuración do servidor, por moito que nos iluminaramos coa documentación, cada vez que recibíamos unha solicitude inicial de cliente cunha URL que chegaba a través de HTTPS, e IdentityServer devolvía o mesmo contexto, pero con HTTP. ¡Quedamos impresionados! E transferimos todo isto a través do contexto de identidade a HAProxy, e nas cabeceiras tivemos que modificar o protocolo HTTP a HTTPS.

Cal é a mellora e onde aforraches?

Aforramos diñeiro usando unha solución gratuíta para autorizar un grupo de usuarios, recursos, xa que non colocamos IdentityServer4 como un nodo separado nun segmento separado, senón que o utilizamos xunto co backend no mesmo servidor onde se executa o backend da aplicación. .

Como debería funcionar

Entón, como prometín - Magic Box. Xa entendemos que temos a garantía de avanzar cara a Linux. Formulemos tarefas específicas que requiran solucións.

.NET Core en Linux, DevOps a cabalo

Manifestos de títeres. Para ofrecer e xestionar a configuración do servizo e da aplicación, houbo que escribir receitas interesantes. Un rolo de lapis mostra de forma elocuente o rápido e eficiente que se fixo.

Método de entrega. O estándar é RPM. Todo o mundo entende que en Linux non se pode prescindir del, pero o proxecto en si, despois da montaxe, era un conxunto de ficheiros DLL executables. Foron uns 150, o proxecto foi bastante difícil. A única solución harmoniosa é empaquetar este binario en RPM e despregar a aplicación desde el.

Versionado. Tivemos que lanzar moi a miúdo, e tivemos que decidir como formar o nome do paquete. Esta é unha cuestión do nivel de integración con TFS. Tivemos un axente de compilación en Linux. Cando TFS envía unha tarefa a un controlador (traballador) ao axente de compilación, tamén lle pasa unha morea de variables que acaban no entorno do proceso do controlador. Estas variables de ambiente conteñen o nome da compilación, o nome da versión e outras variables. Lea máis sobre isto na sección "Creación dun paquete RPM".

Configuración de TFS chegou a configurar Pipeline. Anteriormente, recompilamos todos os proxectos de Windows nos axentes de Windows, pero agora aparece un axente de Linux: un axente de compilación, que debe incluírse no grupo de compilación, enriquecerse con algúns artefactos e indicar que tipo de proxectos se crearán neste axente de compilación. , e dalgún xeito modificar o Pipeline.

IdentityServer. ADFS non é o noso camiño, imos polo código aberto.

Imos pasar polos compoñentes.

Caixa máxica

Consta de catro partes.

.NET Core en Linux, DevOps a cabalo

Axente de compilación de Linux. Linux, porque construímos para iso, é lóxico. Esta parte realizouse en tres pasos.

  • Configurar traballadores e non só, xa que se esperaba traballo repartido no proxecto.
  • Instalar .NET Core 1.x. Por que 1.x cando 2.0 xa está dispoñible no repositorio estándar? Porque cando comezamos o desenvolvemento, a versión estable era a 1.09, e decidiuse facer o proxecto baseado nela.
  • Git 2.x.

Repositorio RPM. Os paquetes RPM debían ser almacenados nalgún lugar. Supoñíase que usaríamos o mesmo repositorio RPM corporativo que está dispoñible para todos os hosts Linux. Iso foi o que fixeron. O servidor do repositorio está configurado gancho web que descargou o paquete RPM necesario desde a localización especificada. O axente de compilación informou da versión do paquete ao webhook.

GitLab. Atención! GitLab aquí non é usado polos desenvolvedores, senón polo departamento de operacións para controlar as versións das aplicacións, as versións dos paquetes, supervisar o estado de todas as máquinas Linux e almacena a receita: todos os manifestos de Puppet.

Títere — resolve todos os problemas controvertidos e ofrece exactamente a configuración que queremos de Gitlab.

Comezamos a mergullar. Como funciona a entrega de DLL a RPM?

Entrega DDL a RPM

Digamos que temos unha estrela de rock de desenvolvemento .NET. Usa Visual Studio e crea unha rama de versión. Despois diso, súbeo a Git, e Git aquí é unha entidade TFS, é dicir, é o repositorio de aplicacións co que traballa o programador.

.NET Core en Linux, DevOps a cabalo

Despois diso, TFS ve que chegou un novo commit. Que aplicación? Na configuración de TFS hai unha etiqueta que indica que recursos ten un determinado axente de compilación. Neste caso, ve que estamos a construír un proxecto .NET Core e selecciona un axente de compilación de Linux do grupo.

O axente de compilación recibe as fontes e descarga o necesario dependencias dende o repositorio .NET, npm, etc. e despois de construír a propia aplicación e o empaquetado posterior, envía o paquete RPM ao repositorio de RPM.

Por outra banda, ocorre o seguinte. O enxeñeiro do departamento de operacións está directamente implicado no lanzamento do proxecto: cambia as versións dos paquetes Hiera no repositorio onde se almacena a receita da aplicación, despois de que se activa Puppet Yum, obtén o novo paquete do repositorio e a nova versión da aplicación está lista para usar.

.NET Core en Linux, DevOps a cabalo

Todo é sinxelo en palabras, pero que pasa dentro do propio axente Build?

Embalaxe DLL RPM

Recibiu fontes do proxecto e tarefa de compilación de TFS. Axente de construción comeza a construír o propio proxecto a partir das fontes. O proxecto montado está dispoñible como conxunto ficheiros DLL, que se empaquetan nun arquivo zip para reducir a carga do sistema de ficheiros.

O arquivo ZIP bótase ao directorio de compilación do paquete RPM. A continuación, o script Bash inicializa as variables de ambiente, atopa a versión de compilación, a versión do proxecto, o camiño ao directorio de compilación e executa RPM-build. Unha vez completada a compilación, o paquete publícase en repositorio local, que se atopa no axente de compilación.

A continuación, desde o axente de compilación ata o servidor do repositorio RPM Enviouse a solicitude JSON indicando o nome da versión e compilación. Webhook, do que falei anteriormente, descarga este mesmo paquete desde o repositorio local do axente de compilación e fai que o novo conxunto estea dispoñible para a súa instalación.

.NET Core en Linux, DevOps a cabalo

Por que este esquema particular de entrega de paquetes ao repositorio RPM? Por que non podo enviar inmediatamente o paquete ensamblado ao repositorio? O caso é que esta é unha condición para garantir a seguridade. Este escenario limita a posibilidade de que persoas non autorizadas carguen paquetes RPM a un servidor accesible para todas as máquinas Linux.

Versionado de bases de datos

Nunha consulta co equipo de desenvolvemento, resultou que os mozos estaban máis preto de MS SQL, pero na maioría dos proxectos que non eran de Windows xa estabamos usando PostgreSQL con todas as súas forzas. Como xa decidimos abandonar todo o que se pagaba, comezamos a usar PostgreSQL tamén aquí.

.NET Core en Linux, DevOps a cabalo

Nesta parte quero contarvos como versionamos a base de datos e como eliximos entre Flyway e Entity Framework Core. Vexamos os seus pros e contras.

Contra

O Flyway só vai nun sentido, nós non podemos retroceder - Esta é unha desvantaxe importante. Podes comparalo con Entity Framework Core doutras formas, en termos de comodidade para o programador. Lembrades que puxemos isto á vangarda, e o criterio principal era non cambiar nada para o desenvolvemento de Windows.

Para Flyway nós facía falta algún tipo de envoltoriopara que os rapaces non escriban Consultas SQL. Están moito máis preto de operar en termos de POO. Escribimos instrucións para traballar con obxectos de base de datos, xeramos unha consulta SQL e executámola. A nova versión da base de datos está lista, probada: todo está ben, todo funciona.

Entity Framework Core ten un inconveniente: baixo cargas pesadas crea consultas SQL subóptimas, e a retirada na base de datos pode ser significativa. Pero como non temos un servizo de alta carga, non calculamos a carga en centos de RPS, aceptamos estes riscos e delegamos o problema para nós.

Pros

Entity Framework Core funciona fóra da caixa e é fácil de desenvolver, e Flyway Intégrase facilmente no CI existente. Pero facémolo cómodo para os desenvolvedores :)

Procedemento de enrolamento

Puppet ve que se achega un cambio na versión do paquete, incluído o responsable da migración. En primeiro lugar, instala un paquete que contén scripts de migración e funcións relacionadas coa base de datos. Despois diso, reiniciarase a aplicación que traballa coa base de datos. A continuación vén a instalación dos restantes compoñentes. A orde na que se instalan os paquetes e se inician as aplicacións descríbese no manifesto de Puppet.

As aplicacións usan datos sensibles, como tokens, contrasinais de bases de datos, todo isto incorpórase á configuración desde Puppet master, onde se almacenan en forma cifrada.

Problemas de TFS

Despois de que decidimos e nos demos conta de que todo funcionaba realmente para nós, decidín analizar o que estaba a suceder coas montaxes en TFS no seu conxunto para o departamento de desenvolvemento de Win noutros proxectos, se estabamos construíndo/lanzando rapidamente ou non, e descubriu problemas significativos coa velocidade.

Un dos proxectos principais leva entre 12 e 15 minutos en montar: é moito tempo, non podes vivir así. Unha análise rápida mostrou un descenso terrible na E/S, e isto foi nas matrices.

Despois de analizalo compoñente por compoñente, identificei tres focos. Primeira - "antivirus Kaspersky", que analiza as fontes en todos os axentes de Windows Build. segundo - Windows Indexador. Non se desactivou e todo se indexou en tempo real nos axentes de compilación durante o proceso de implantación.

Terceiro - Instalación de npm. Resultou que na maioría dos Pipelines utilizamos este escenario exacto. Por que é malo? O procedemento de instalación de Npm execútase cando se forma a árbore de dependencias package-lock.json, onde se rexistran as versións dos paquetes que se utilizarán para construír o proxecto. A desvantaxe é que Npm install saca as últimas versións dos paquetes de Internet cada vez, e isto leva moito tempo no caso dun proxecto grande.

Ás veces, os desenvolvedores experimentan nunha máquina local para probar como funciona unha parte concreta ou un proxecto completo. Ás veces resultou que todo estaba xenial localmente, pero montaron, desenrolaron e nada funcionou. Comezamos a descubrir cal é o problema: si, diferentes versións de paquetes con dependencias.

decisión

  • Fontes en excepcións AV.
  • Desactivar a indexación.
  • Ir a npm ci.

As vantaxes de npm ci son que nós Recollemos a árbore de dependencias unha vez, e temos a oportunidade de proporcionarlle ao programador lista actual de paquetes, co que pode experimentar localmente tanto como queira. Isto aforra tempo desenvolvedores que escriben código.

Configuración

Agora un pouco sobre a configuración do repositorio. Historicamente usamos Nexo para xestionar repositorios, incluíndo REPO interno. Este repositorio interno contén todos os compoñentes que usamos para fins internos, por exemplo, o seguimento escrito por si mesmo.

.NET Core en Linux, DevOps a cabalo

Tamén usamos NuGet, xa que ten mellor caché en comparación con outros xestores de paquetes.

Resultado

Despois de optimizar os axentes de compilación, o tempo medio de construción reduciuse de 12 minutos a 7.

Se contamos todas as máquinas que puidemos usar para Windows, pero cambiamos a Linux neste proxecto, aforramos uns 10 dólares, e iso só en licenzas, e máis se temos en conta o contido.

Plans

Para o próximo trimestre, planeamos traballar na optimización da entrega do código.

Cambiando a unha imaxe de Docker preconstruída. TFS é unha cousa interesante con moitos complementos que che permiten integrar en Pipeline, incluíndo a montaxe baseada en disparadores, por exemplo, dunha imaxe de Docker. Queremos facer este disparador para o mesmo package-lock.json. Se a composición dos compoñentes utilizados para construír o proxecto cambia dalgún xeito, construímos unha nova imaxe de Docker. Máis tarde úsase para despregar o contedor coa aplicación ensamblada. Este non é o caso agora, pero estamos a planear cambiar a unha arquitectura de microservizos en Kubernetes, que se está a desenvolver activamente na nosa empresa e leva moito tempo atendendo solucións de produción.

Resumo

Animo a todos a tirar as fiestras, pero non é porque non saiba cociñar. A razón é que a maioría das solucións Opensource son pila de linux. estás ben aforrar recursos. Na miña opinión, o futuro pertence ás solucións de código aberto en Linux cunha comunidade poderosa.

Perfil do orador de Alexander Sinchinov en GitHub.

DevOps Conf é unha xornada sobre a integración de procesos de desenvolvemento, proba e operación para profesionais por parte de profesionais. Por iso o proxecto do que falou Alexander? implementado e funcionando, e o día da actuación houbo dous lanzamentos exitosos. Activado DevOps Conf en RIT++ Os días 27 e 28 de maio haberá aínda máis casos similares de practicantes. Aínda podes saltar ao último carro e presentar un informe ou tómate o teu tempo Reservar billete. Reunímonos en Skolkovo!

Fonte: www.habr.com

Engadir un comentario