{"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\/es\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","title":{"rendered":".NET Core en Linux, DevOps al mando","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Desarrollamos DevOps lo mejor que pudimos. \u00c9ramos 8 personas, y Vasya era el mejor en Windows. De repente, Vasya se fue, y me encontr\u00e9 con la tarea de lanzar un nuevo proyecto que entregara desarrollo de Windows. Cuando volqu\u00e9 sobre la mesa todo el stack de desarrollo en Windows, comprend\u00ed que la situaci\u00f3n era dolorosa...<\/p>\n<p>As\u00ed comienza la historia <b>Alexandra Sinchinova<\/b> en <noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOpsConf<\/a><\/noindex>. Cuando el principal especialista en Windows de la empresa se fue, Alexander se pregunt\u00f3 qu\u00e9 hacer a continuaci\u00f3n. \u00a1Por supuesto, cambiar a Linux! Alexander explicar\u00e1 c\u00f3mo logr\u00f3 crear un precedente y trasladar parte del desarrollo de Windows a Linux usando como ejemplo un proyecto implementado para 100,000 usuarios finales.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/3c944351864df95217e133236542c9b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00bfC\u00f3mo entregar un proyecto en RPM de manera f\u00e1cil y sin complicaciones, utilizando TFS, Puppet, Linux .NET Core? \u00bfC\u00f3mo mantener el versionado de la base de datos del proyecto si los desarrolladores oyen por primera vez palabras como Postgres y Flyway, y la fecha l\u00edmite es pasado ma\u00f1ana? \u00bfC\u00f3mo integrarse con Docker? \u00bfC\u00f3mo motivar a los desarrolladores .NET a abandonar Windows y los batidos en favor de Puppet y Linux? \u00bfC\u00f3mo resolver conflictos ideol\u00f3gicos si no hay fuerzas, ni deseos, ni recursos para mantener Windows en producci\u00f3n? Sobre esto, as\u00ed como sobre Web Deploy, pruebas, CI, pr\u00e1cticas de uso de TFS en proyectos existentes, y, por supuesto, sobre muletas rotas y soluciones efectivas, se discutir\u00e1 en la transcripci\u00f3n de la presentaci\u00f3n 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=\"Reproducir video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nAs\u00ed que, Vasya se fue, la tarea est\u00e1 sobre m\u00ed, los desarrolladores esperan con ansias. Cuando finalmente me di cuenta de que no pod\u00eda recuperar a Vasya, me puse a trabajar. Primero evalu\u00e9 el porcentaje de VM de Windows en nuestro parque. La cuenta no era favorable para Windows.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/836e47372126b6ba369ac494b91c7d3c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nComo estamos desarrollando activamente DevOps, entend\u00ed que era necesario cambiar el enfoque para implementar la nueva aplicaci\u00f3n. La soluci\u00f3n fue simple: trasladar todo a Linux cuando fuera posible. Google me ayud\u00f3: en ese momento ya se hab\u00eda portado .Net a Linux, y entend\u00ed que esa era la soluci\u00f3n.<\/p>\n<h2>\u00bfPor qu\u00e9 .NET Core en combinaci\u00f3n con Linux?<\/h2>\n<p>\nHubo varias razones. Entre 'pagar dinero' y 'no pagar', la mayor\u00eda elegir\u00e1 la segunda opci\u00f3n, al igual que yo. La licencia para MSDB cuesta alrededor de 1,000 $, y el mantenimiento de un parque de m\u00e1quinas virtuales Windows se cuenta por cientos de d\u00f3lares. Para una gran empresa, estos son costos significativos. Por eso, <b>el ahorro\u00a0<\/b>\u2014<b> es la primera raz\u00f3n<\/b>. No es la m\u00e1s importante, pero s\u00ed una de las m\u00e1s relevantes.<\/p>\n<p>Las m\u00e1quinas virtuales de Windows consumen m\u00e1s recursos que sus contrapartes de Linux, <b>son pesadas<\/b>. Considerando la escala de una gran empresa, elegimos Linux.<\/p>\n<p><b>El sistema se integra f\u00e1cilmente en CI existente<\/b>. Nos consideramos DevOps progresistas, utilizamos Bamboo, Jenkins y GitLab CI, por lo que gran parte de nuestro trabajo se realiza en Linux.<\/p>\n<p>La \u00faltima raz\u00f3n es <b>el soporte conveniente. <\/b>Necesit\u00e1bamos reducir la barrera de entrada para los \"soportantes\" \u2014 chicos que entienden la parte t\u00e9cnica, garantizan la continuidad y atienden los servicios de segunda l\u00ednea. Ya estaban familiarizados con el stack de Linux, por lo que les resulta mucho m\u00e1s f\u00e1cil entender el nuevo producto, mantenerlo y soportarlo, en lugar de gastar recursos adicionales para familiarizarse con funcionalidades similares en software para la plataforma Windows.<\/p>\n<h2>Requisitos<\/h2>\n<p>\nLo primero y m\u00e1s importante es <b>la conveniencia de la nueva soluci\u00f3n para los desarrolladores<\/b>. No todos estaban listos para el cambio, especialmente despu\u00e9s de mencionar la palabra Linux. Los desarrolladores quieren su Visual Studio favorito, TFS con pruebas autom\u00e1ticas en compilaciones y smoothies. C\u00f3mo se realiza la entrega a producci\u00f3n no les preocupa. Por eso decidimos no cambiar el proceso habitual y dejar todo igual para el desarrollo en Windows. <\/p>\n<p>El nuevo proyecto debe <b>integrarse en CI existente<\/b>. Las herramientas ya estaban en su lugar y todo el trabajo deb\u00eda realizarse teniendo en cuenta los par\u00e1metros del sistema de gesti\u00f3n de configuraciones, los est\u00e1ndares de entrega aprobados y los sistemas de monitoreo.<\/p>\n<p><b>La simplicidad en el soporte y operaci\u00f3n<\/b>, como condici\u00f3n para una m\u00ednima barrera de entrada para todos los nuevos participantes de diferentes departamentos y del equipo de soporte.<\/p>\n<p><b>El plazo era ayer<\/b>.<\/p>\n<h2>El grupo de desarrollo de Win<\/h2>\n<p>\n\u00bfCon qu\u00e9 estaba trabajando el equipo de Windows entonces?<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/6e6e128ef3d49410c260d05114f819a4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAhora puedo decir con confianza que <b>IdentityServer4<\/b>\u00a0es una excelente alternativa gratuita a ADFS con capacidades similares, o que <b>Entity Framework Core<\/b>\u00a0es un para\u00edso para los desarrolladores, donde no hay necesidad de preocuparse por escribir scripts SQL, sino que se pueden describir consultas a la base de datos en t\u00e9rminos de OOP. Pero en ese momento, en la discusi\u00f3n del plan de acci\u00f3n, ve\u00eda este stack como una escritura cuneiforme sumeria, reconociendo solo PostgreSQL y Git.<\/p>\n<p>En ese momento utiliz\u00e1bamos activamente <b>Puppet<\/b> como sistema de gesti\u00f3n de configuraciones. En la mayor\u00eda de nuestros proyectos aplic\u00e1bamos <b>GitLab CI<\/b>, <b>Elastic<\/b>, balance\u00e1bamos servicios de alta carga usando <b>HAProxy,<\/b> monitore\u00e1bamos todo con <b>Zabbix<\/b>, la combinaci\u00f3n de <b>Grafana<\/b> y\u00a0<b>Prometheus<\/b>, <b>Jaeger<\/b>, y todo esto funcionaba en hardware\u00a0<b>HP<\/b> c\u00a0<b>ESXi<\/b> en\u00a0<b>VMware<\/b>. Es bien conocido \u2014 la cl\u00e1sica.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/f4ffcac7a7fbb4fa48d47f07bed52610.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVamos a ver y tratar de entender qu\u00e9 sucedi\u00f3 antes de que comenz\u00e1ramos todas estas intervenciones.<\/p>\n<h2>\u00bfQu\u00e9 pas\u00f3?<\/h2>\n<p>\nTFS es un sistema bastante potente que no solo transporta el c\u00f3digo del desarrollador a la m\u00e1quina de producci\u00f3n final, sino que tambi\u00e9n tiene un conjunto para una integraci\u00f3n muy flexible con varios servicios para garantizar CI a nivel multiplataforma.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/ea448b38e321a8350468d69f3e45e429.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAntes, eran solo ventanillas. TFS utilizaba varios agentes de compilaci\u00f3n, en los cuales se compilaban numerosos proyectos. En cada agente hay de 3 a 4 trabajadores para paralelizar tareas y optimizar el proceso. Luego, de acuerdo con los planes de lanzamiento, TFS entregaba la compilaci\u00f3n reci\u00e9n horneada en un servidor de aplicaciones de Windows.<\/p>\n<h2>A lo que quer\u00edamos llegar<\/h2>\n<p>\nUsamos TFS para la entrega y desarrollo, y lanzamos la aplicaci\u00f3n en un servidor de aplicaciones Linux, y entre ellos hay una especie de magia. Esta <b>Magic Box<\/b> es la esencia del trabajo futuro. Antes de descomponerlo en partes, har\u00e9 un paso al lado y dir\u00e9 un par de palabras sobre la aplicaci\u00f3n.<\/p>\n<h2>Proyecto<\/h2>\n<p>\nLa aplicaci\u00f3n proporciona funcionalidad para manejar tarjetas prepagadas. <\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/c93aa67b340c45ad279330466fc4f776.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Cliente<\/h3>\n<p>\nExist\u00edan dos tipos de usuarios. <b>Primero<\/b> acced\u00eda autentic\u00e1ndose con un certificado SSL SHA-2. El\u00a0<b>segundo<\/b> ten\u00eda acceso con login y contrase\u00f1a.<\/p>\n<h3>HAProxy<\/h3>\n<p>\nLuego, la solicitud del cliente llegaba a HAProxy, que resolv\u00eda las siguientes tareas:<\/p>\n<ul>\n<li>autenticaci\u00f3n primaria;\n<\/li>\n<li>terminaci\u00f3n de SSL;\n<\/li>\n<li>ajuste de solicitudes HTTP;\n<\/li>\n<li>transmisi\u00f3n de solicitudes.\n<\/li>\n<\/ul>\n<p>\nLa verificaci\u00f3n del certificado del cliente se realizaba en cadena. Nosotros somos <b>authority <\/b>y podemos permitirnos esto, ya que nosotros mismos emitimos certificados a los clientes del servicio.<\/p>\n<p>Presta atenci\u00f3n al tercer punto, regresaremos a \u00e9l m\u00e1s tarde.<\/p>\n<h3>Backend<\/h3>\n<p>\nPlaneamos hacer el backend en Linux. El backend interact\u00faa con la base de datos, carga la lista necesaria de privilegios y luego, dependiendo de los privilegios del usuario autenticado, proporciona acceso para la firma de documentos financieros y su env\u00edo para su ejecuci\u00f3n, o la generaci\u00f3n de alg\u00fan informe.<\/p>\n<h2>Ahorro con HAProxy<\/h2>\n<p>\nAdem\u00e1s de los dos contextos que segu\u00eda cada uno de los clientes, hab\u00eda otro contexto de identidad. <b>IdentityServer4<\/b> que precisamente permite la autenticaci\u00f3n, es un equivalente gratuito y potente de <b>ADFS\u00a0<\/b>\u2014<b> Servicios de Federaci\u00f3nde Active Directory<\/b>.<\/p>\n<p>La solicitud en identity se procesaba en varios pasos. El primer paso - <b>cliente<\/b> <b>llegaba al backend<\/b>, que intercambiaba datos con este servidor y verificaba la existencia del token para el cliente. Si no lo encontraba, la solicitud se devolv\u00eda al contexto desde el cual hab\u00eda venido, pero ya con una redirecci\u00f3n, y la redirecci\u00f3n iba a identity.<\/p>\n<p>El segundo paso \u2014 la solicitud llegaba <b>a la p\u00e1gina de autorizaci\u00f3n en IdentityServer,<\/b> donde el cliente se registraba, y en la base de datos de IdentityServer aparec\u00eda ese tan esperado token. <\/p>\n<p>El tercer paso \u2014 <b>el cliente se redirig\u00eda de vuelta <\/b>al contexto desde el cual hab\u00eda venido.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/e052c408d67485ab9aa10d0fd25df57e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIdentityServer4 tiene una particularidad: <b>la respuesta a la solicitud inversa se devuelve por HTTP<\/b>. Por m\u00e1s que intentamos configurar el servidor, por m\u00e1s que nos iluminamos con la documentaci\u00f3n, cada vez recib\u00edamos la solicitud original del cliente con una URL que hab\u00eda llegado por HTTPS, y IdentityServer devolv\u00eda el mismo contexto, pero con HTTP. \u00a1Est\u00e1bamos en shock! Y trasladamos todo esto a trav\u00e9s del contexto identity en HAProxy, y en los headers tuvimos que modificar el protocolo HTTP a HTTPS. <\/p>\n<p>\u00bfCu\u00e1l es la mejora y d\u00f3nde ahorramos?<\/p>\n<blockquote><p>Ahorramos dinero usando una soluci\u00f3n gratuita para la autorizaci\u00f3n de un grupo de usuarios, recursos, ya que no llevamos IdentityServer4 como un nodo separado en un segmento separado, sino que lo utilizamos junto con el backend en el mismo servidor donde est\u00e1 funcionando el backend de la aplicaci\u00f3n.<\/p><\/blockquote>\n<p><\/p>\n<h2>C\u00f3mo deber\u00eda funcionar<\/h2>\n<p>\nAs\u00ed que, como promet\u00ed \u2014 Magic Box. Ya entendemos que nos movemos garantizadamente hacia Linux. Vamos a formular tareas concretas que requer\u00edan soluci\u00f3n.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/cc59632aa0e5c65fe0efc754311ecf5e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Manifiestos de Puppet. <\/b>Para entregar y gestionar la configuraci\u00f3n del servicio y la aplicaci\u00f3n, era necesario escribir recetas adecuadas. Un rollo con un l\u00e1piz muestra elocuente c\u00f3mo se hizo esto de manera r\u00e1pida y de calidad.<\/p>\n<p><b>M\u00e9todo de entrega. <\/b>El est\u00e1ndar es RPM. Todos entienden que en Linux no se puede sin \u00e9l, pero el proyecto despu\u00e9s de la construcci\u00f3n era un conjunto de archivos DLL ejecutables. Eran alrededor de 150, el proyecto es bastante pesado. La \u00fanica soluci\u00f3n armoniosa fue empaquetar esta binaria en RPM y desde all\u00ed desplegar la aplicaci\u00f3n.<\/p>\n<p><b>Versionado. <\/b>Ten\u00edamos que lanzar muy frecuentemente y necesit\u00e1bamos decidir c\u00f3mo formar el nombre del paquete. Esta es una cuesti\u00f3n a nivel de integraci\u00f3n con TFS. Ten\u00edamos un agente de compilaci\u00f3n en Linux. Cuando TFS env\u00eda una tarea al procesador - worker - en el agente de compilaci\u00f3n, tambi\u00e9n le pasa un mont\u00f3n de variables que llegan al entorno del proceso del procesador. En estas variables de entorno se transmite el nombre de la compilaci\u00f3n, el nombre de la versi\u00f3n y otras variables. M\u00e1s detalles sobre esto en la secci\u00f3n 'compilaci\u00f3n de paquetes RPM'.<\/p>\n<p><b>Configuraci\u00f3n de TFS<\/b> se centraba en la configuraci\u00f3n del Pipeline. Antes recopil\u00e1bamos todos los proyectos de Windows en agentes de Windows, y ahora aparece un agente de Linux - el agente de compilaci\u00f3n, que debe ser incluido en el grupo de compilaci\u00f3n, enriquecido con alg\u00fan artefacto, indicado qu\u00e9 tipo de proyectos se compilar\u00e1n en este agente de compilaci\u00f3n y modificar el Pipeline de alguna manera.<\/p>\n<p><b>IdentityServer. <\/b>ADFS no es nuestro camino, apoyamos el Open Source.<\/p>\n<p>Vamos a revisar los componentes.<\/p>\n<h2>Magic Box<\/h2>\n<p>\nConsiste en cuatro partes.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/22ea63bcf184046c15e034ec093352bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Agente de compilaci\u00f3n en Linux. <\/b>Linux, porque estamos compilando para \u00e9l - es l\u00f3gico. Esta parte se llev\u00f3 a cabo en tres pasos.<\/p>\n<ul>\n<li><b>Configurar los workers<\/b> y no uno solo, ya que se supon\u00eda que habr\u00eda trabajo distribuido en el proyecto.\n<\/li>\n<li><b>Instalar .NET Core 1.x<\/b>. \u00bfPor qu\u00e9 1.x, cuando ya est\u00e1 disponible 2.0 en el repositorio est\u00e1ndar? Porque cuando comenzamos el desarrollo, la versi\u00f3n estable era 1.09, y se decidi\u00f3 hacer el proyecto para esa versi\u00f3n.\n<\/li>\n<li><b>Git 2.x<\/b>.\n<\/li>\n<\/ul>\n<p>\n<b>Repositorio RPM. <\/b>Los paquetes RPM necesitaban ser almacenados en alg\u00fan lugar. Se esperaba que utiliz\u00e1ramos el mismo repositorio RPM corporativo que estaba disponible para todos los hosts de Linux. As\u00ed lo hicimos. En el servidor del repositorio se configur\u00f3 <b>webhook<\/b> que descargaba el paquete RPM requerido desde el lugar indicado. La versi\u00f3n del paquete fue informada al webhook por el agente de compilaci\u00f3n.<\/p>\n<p><b>GitLab. <\/b>\u00a1Atenci\u00f3n! GitLab aqu\u00ed es utilizado no por los desarrolladores, sino por el departamento de operaciones para el control de versiones de la aplicaci\u00f3n, versiones de paquetes, control del estado de todas las m\u00e1quinas Linux y en \u00e9l se almacena la receta - todos los manifiestos de Puppet. <\/p>\n<p><b>Puppet<\/b>\u00a0resuelve todos los puntos conflictivos y proporciona exactamente la configuraci\u00f3n que queremos, desde GitLab.<\/p>\n<p>Comenzamos a profundizar. \u00bfC\u00f3mo se entrega DLL en RPM?<\/p>\n<h3>Entrega de DDL en RPM<\/h3>\n<p>\nSupongamos que tenemos una estrella de rock del desarrollo en .NET. Utiliza Visual Studio y crea una rama de lanzamiento. Despu\u00e9s de eso, la sube a Git, y Git aqu\u00ed es una entidad de TFS, es decir, es el repositorio de la aplicaci\u00f3n con el que trabaja el desarrollador.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/978240886981d41fc6d7b17d0a4fcb05.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDespu\u00e9s de lo cual TFS ve que ha llegado un nuevo commit. \u00bfQu\u00e9 aplicaci\u00f3n? En la configuraci\u00f3n de TFS hay una etiqueta que indica qu\u00e9 recursos tiene cada agente de compilaci\u00f3n. En este caso, ve que estamos compilando un proyecto .NET Core y elige un agente de compilaci\u00f3n de Linux del grupo. <\/p>\n<p>El agente de compilaci\u00f3n recibe los fuentes, descarga lo necesario <b>dependencies<\/b> del repositorio .NET, npm, etc. y despu\u00e9s de compilar la aplicaci\u00f3n y empaquetarla, env\u00eda el paquete RPM al repositorio RPM.<\/p>\n<p>Por otro lado, ocurre lo siguiente. El ingeniero del departamento de operaciones se encarga directamente de desplegar el proyecto: cambia las versiones de los paquetes en\u00a0<b>Hiera<\/b> en el repositorio donde se almacena la receta de la aplicaci\u00f3n, despu\u00e9s de lo cual Puppet activa <b>Yum<\/b>, recoge el nuevo paquete del repositorio y la nueva versi\u00f3n de la aplicaci\u00f3n est\u00e1 lista para ser utilizada.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/6c2db3ce4bd7d4268e88c6c3d3ecbeba.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn teor\u00eda todo es simple, pero \u00bfqu\u00e9 ocurre dentro del propio agente de compilaci\u00f3n?<\/p>\n<h3>Empaquetado de DLL RPM<\/h3>\n<p>\nSe han obtenido los fuentes del proyecto y la tarea de compilaci\u00f3n de TFS. El agente de compilaci\u00f3n <b>inicia la compilaci\u00f3n del proyecto a partir de los fuentes<\/b>. El proyecto compilado est\u00e1 disponible en forma de m\u00faltiples <b>archivos DLL<\/b>, que se empaquetan en un archivo zip para reducir la carga en el sistema de archivos.<\/p>\n<p>El archivo ZIP se lanza <b>en el directorio de construcci\u00f3n del paquete RPM.<\/b> Luego, un script Bash inicializa las variables de entorno, encuentra la versi\u00f3n de Build, la versi\u00f3n del proyecto, la ruta al directorio de construcci\u00f3n y lanza RPM-build. Al finalizar la compilaci\u00f3n, el paquete se publica en\u00a0<b>el repositorio local<\/b>, que se encuentra en el agente de compilaci\u00f3n.<\/p>\n<p>Luego, desde el agente de compilaci\u00f3n al servidor en el repositorio RPM <b>se env\u00eda una solicitud JSON<\/b> con la especificaci\u00f3n del nombre de la versi\u00f3n y la compilaci\u00f3n. El webhook, del que habl\u00e9 antes, descarga ese paquete del repositorio local en el agente de compilaci\u00f3n y hace que una nueva compilaci\u00f3n est\u00e9 disponible para instalaci\u00f3n.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/b69cacdadd171f4cbc9913b2ff4b7a79.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00bfPor qu\u00e9 este esquema de entrega del paquete al repositorio RPM? \u00bfPor qu\u00e9 no se puede enviar el paquete compilado directamente al repositorio? Se debe a que es una condici\u00f3n para garantizar la seguridad. Este escenario limita la posibilidad de cargas no autorizadas de paquetes RPM por parte de personas ajenas en el servidor, que est\u00e1 accesible para todas las m\u00e1quinas Linux.<\/p>\n<h2>Versionado de la base de datos<\/h2>\n<p>\nEn el consejo con el desarrollo se aclar\u00f3 que a los chicos les gusta m\u00e1s MS SQL, pero en la mayor\u00eda de los proyectos no Windows ya est\u00e1bamos usando PostgreSQL. Dado que ya decidimos alejarnos de todo lo de pago, comenzamos a usar PostgreSQL aqu\u00ed tambi\u00e9n.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/6b6c081344f2408c399248a70a63dccc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn esta parte quiero hablar sobre c\u00f3mo realizamos la versi\u00f3n de la base de datos y c\u00f3mo elegimos entre Flyway y Entity Framework Core. Veamos sus ventajas y desventajas.<\/p>\n<h3>Desventajas<\/h3>\n<p>\nFlyway solo va en una direcci\u00f3n, nosotros\u00a0<b>no podemos retroceder<\/b>\u00a0\u2014 esta es una desventaja significativa. La comparaci\u00f3n con Entity Framework Core puede hacerse seg\u00fan otros par\u00e1metros, desde el punto de vista de la comodidad del desarrollador. Recuerden que esto es lo que pusimos en primer plano, y el principal criterio fue no cambiar nada para el desarrollo en Windows.<\/p>\n<p>Para Flyway necesit\u00e1bamos alg\u00fan tipo de envoltura <b>, para que los chicos no tuvieran que escribir<\/b>consultas SQL <b>. A ellos les resulta mucho m\u00e1s f\u00e1cil operar en t\u00e9rminos de OOP. Escribimos instrucciones sobre c\u00f3mo trabajar con los objetos de la base de datos, se form\u00f3 la consulta SQL y se ejecut\u00f3. La nueva versi\u00f3n de la base de datos est\u00e1 lista, ha funcionado \u2014 todo bien, todo funciona.<\/b>Entity Framework Core tiene un inconveniente \u2014 bajo altas cargas<\/p>\n<p>genera consultas SQL no \u00f3ptimas\u00a0<b>, y la ca\u00edda en la base de datos puede ser significativa. Sin embargo, dado que nuestro servicio no est\u00e1 sometido a alta carga, no contamos la carga por cientos de RPS, asumimos estos riesgos y delegamos el problema a nuestro futuro.<\/b>funciona fuera de la caja y es conveniente para el desarrollo<\/p>\n<h3>Ventajas<\/h3>\n<p>\nEntity Framework Core <b>, mientras que Flyway<\/b>se integra f\u00e1cilmente en el CI existente <b>. Pero hacemos todo para que sea conveniente para los desarrolladores :)<\/b>El procedimiento de implementaci\u00f3n<\/p>\n<h3>Puppet ve que llega un cambio de versi\u00f3n de los paquetes, entre los cuales est\u00e1 el que se encarga de la migraci\u00f3n. Primero instala el paquete que contiene los scripts de migraci\u00f3n y la funcionalidad relacionada con la base de datos. Despu\u00e9s de esto, se reinicia la aplicaci\u00f3n que trabaja con la base de datos. Luego se realiza la instalaci\u00f3n de los componentes restantes. El orden de instalaci\u00f3n de los paquetes y el inicio de las aplicaciones est\u00e1 descrito en el manifiesto de Puppet.<\/h3>\n<p>\nLas aplicaciones utilizan datos sensibles, como tokens, contrase\u00f1as para la base de datos, todo esto se extrae en la configuraci\u00f3n desde el Puppet master, donde se almacenan en forma cifrada.<\/p>\n<p>Problemas en TFS<\/p>\n<h2>Despu\u00e9s de que nos decidimos y entendimos que efectivamente todo funciona, decid\u00ed observar c\u00f3mo iban las compilaciones en TFS en general para el departamento de desarrollo en Windows para otros proyectos \u2014 si r\u00e1pidamente o no nos estamos compilando\/lanzando, y encontr\u00e9 problemas significativos con la velocidad.<\/h2>\n<p>\nUno de los principales proyectos se compila en 12-15 minutos \u2014 esto es largo, no se puede vivir as\u00ed. Un r\u00e1pido an\u00e1lisis mostr\u00f3 una terrible ca\u00edda en el I\/O, y eso en matrices.<\/p>\n<p>Al analizar componente por componente, identifiqu\u00e9 tres focos. El primero \u2014<\/p>\n<p>\u00abKaspersky antivirus\u00bb <b>\u00abAntivirus Kaspersky\u00bb<\/b>, que escanea el c\u00f3digo fuente en todos los agentes de construcci\u00f3n de Windows. El segundo \u2014 <b>Windows<\/b> <b>Indexador.<\/b> No fue desactivado, y en los agentes de construcci\u00f3n se indexaba todo en tiempo real durante el proceso de despliegue. <\/p>\n<p>El tercero \u2014 <b>Npm install. <\/b>Result\u00f3 que en la mayor\u00eda de los Pipelines utiliz\u00e1bamos exactamente este script. \u00bfCu\u00e1l es su desventaja? El procedimiento Npm install se activa al formar el \u00e1rbol de dependencias en\u00a0<b>package-lock.json<\/b>, donde se registran las versiones de los paquetes que se utilizar\u00e1n para compilar el proyecto. La desventaja es que Npm install cada vez descarga las versiones actuales de los paquetes desde internet, lo cual consume bastante tiempo en el caso de un proyecto grande.<\/p>\n<blockquote><p>Los desarrolladores a veces experimentan en su m\u00e1quina local para verificar el funcionamiento de una parte espec\u00edfica o de todo el proyecto. A veces suced\u00eda que localmente todo funcionaba genial, pero al compilar y desplegar, nada funcionaba. Comenzamos a investigar cu\u00e1l es el problema \u2014 ah, diferentes versiones de paquetes con dependencias.<\/p><\/blockquote>\n<p><\/p>\n<h3>Soluci\u00f3n<\/h3>\n<p><\/p>\n<ul>\n<li>C\u00f3digos fuente en excepciones AV.\n<\/li>\n<li>Desactivaci\u00f3n de la indexaci\u00f3n.\n<\/li>\n<li>Cambio a\u00a0<b>npm ci<\/b>.\n<\/li>\n<\/ul>\n<p>\nLas ventajas de npm ci son que\u00a0<b>creamos el \u00e1rbol de dependencias una vez<\/b>, y obtenemos la posibilidad de proporcionar al desarrollador <b>una lista actualizada de paquetes<\/b>, con la que puede experimentar localmente tanto como quiera. Esto <b>ahorra tiempo<\/b> a los desarrolladores que escriben c\u00f3digo.<\/p>\n<h3>Configuraci\u00f3n<\/h3>\n<p>\nAhora un poco sobre la configuraci\u00f3n del repositorio. Hist\u00f3ricamente hemos utilizado <b>Nexus<\/b> para gestionar repositorios, incluyendo el <b>REPO Interno<\/b>. En este repositorio interno se suministran todos los componentes que usamos para fines internos, por ejemplo, monitoreos personalizados.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core en Linux, DevOps al mando\" src=\"\/wp-content\/uploads\/2019\/04\/147d7e80bf20e03a232f8b533be316eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTambi\u00e9n utilizamos <b>NuGet<\/b>, ya que tiene un mejor sistema de cach\u00e9 en comparaci\u00f3n con otros gestores de paquetes.<\/p>\n<h3>Resultado<\/h3>\n<p>\nDespu\u00e9s de optimizar los agentes de construcci\u00f3n, el tiempo medio de compilaci\u00f3n se redujo de 12 minutos a 7.<\/p>\n<blockquote><p>Si contamos todas las m\u00e1quinas que podr\u00edamos haber utilizado para Windows, pero que convertimos a Linux en este proyecto, hemos ahorrado alrededor de $10,000. Y eso solo en licencias, y si consideramos el mantenimiento, m\u00e1s.<\/p><\/blockquote>\n<p><\/p>\n<h2>Planes<\/h2>\n<p>\nEn el pr\u00f3ximo trimestre hemos planeado trabajar en la optimizaci\u00f3n de la entrega de c\u00f3digo.<\/p>\n<p><b>Transici\u00f3n a la imagen Docker precompilada<\/b>. TFS es una herramienta genial con muchos complementos que permiten integrarse en el Pipeline, incluyendo la compilaci\u00f3n por trigger, por ejemplo, de una imagen Docker. Queremos crear este trigger para esa misma. <b>package-lock.json<\/b>. Si de alguna manera cambia la composici\u00f3n de los componentes que se utilizan para construir el proyecto, se genera una nueva imagen de Docker. Posteriormente, se utiliza para desplegar un contenedor con la aplicaci\u00f3n ensamblada. En este momento no est\u00e1 disponible, pero planeamos migrar a una arquitectura de microservicios en Kubernetes, que se est\u00e1 desarrollando activamente en nuestra empresa y que hace tiempo que gestiona soluciones en producci\u00f3n.<\/p>\n<h2>Curr\u00edculum<\/h2>\n<p>\nExorto a todos a deshacerse de Windows, pero no porque no sepa usarla. La raz\u00f3n es que la mayor\u00eda de las soluciones de c\u00f3digo abierto son <b>el stack de Linux.<\/b>Ahorrar\u00e1s <b>en recursos.<\/b>En mi opini\u00f3n, el futuro pertenece a las soluciones de c\u00f3digo abierto en Linux con una s\u00f3lida comunidad.<\/p>\n<p><i>Perfil del ponente Alexander Sinchinov <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/alextuning\">en GitHub.<\/a><\/noindex>.<\/i><\/p>\n<blockquote><p><noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOps Conf<\/a><\/noindex>\u00a0es una conferencia sobre la integraci\u00f3n de procesos de desarrollo, pruebas y operaci\u00f3n para profesionales por profesionales. Es por eso que el proyecto del que habl\u00f3 Alexander est\u00e1 implementado y funcionando, y en el d\u00eda de su presentaci\u00f3n se realizaron dos lanzamientos exitosos.\u00a0<noindex><a rel=\"nofollow\" href=\"http:\/\/devopsconf.io\/moscow-rit\/2019\">En DevOps Conf en RIT++<\/a><\/noindex> el 27 y 28 de mayo habr\u00e1 a\u00fan m\u00e1s casos similares de practicantes. A\u00fan puedes subirte al \u00faltimo tren y <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/lectures\/propose\/?conference=dc2019-rit\">presentar una ponencia.<\/a><\/noindex> O, sin prisa, <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/conference\/join\/rit2019.html?popup=3\">reservar<\/a><\/noindex> un boleto. \u00a1Nos vemos en Skolkovo!<\/p><\/blockquote>\n<p>Fuente: <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.2 - 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\/es\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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 en Linux, DevOps a la vanguardia | ProHoster","description":"Desarrollamos DevOps lo mejor que pudimos. \u00c9ramos 8 personas, y Vasya era el mejor en Windows. De repente, Vasya se fue, y yo tuve la tarea de lanzar un nuevo proyecto que entrega el desarrollo en Windows.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/32217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=32217"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/32217\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/24043"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=32217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=32217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=32217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}