	{"id":64449,"date":"2021-10-26T16:06:03","date_gmt":"2021-10-26T15:06:03","guid":{"rendered":"https:\/\/www.artefact.com\/?post_type=news&#038;p=64449"},"modified":"2024-09-20T17:45:46","modified_gmt":"2024-09-20T16:45:46","slug":"serving-ml-models-at-scale-using-mlflow-on-kubernetes-part-2-2","status":"publish","type":"blog","link":"https:\/\/www.artefact.com\/es\/blog\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-part-2-2\/","title":{"rendered":"Servir modelos ML a escala utilizando Mlflow en Kubernetes - Parte 3"},"content":{"rendered":"<p><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-1 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling article-author\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-background-color:#ffffff;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-0 fusion_builder_column_1_2 1_2 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:50%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:50%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-title title fusion-title-1 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Autor<\/h2><\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27150%27%20height%3D%270%27%20viewBox%3D%270%200%20150%200%27%3E%3Crect%20width%3D%27150%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/kais-laribi.jpeg\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left article-author-image\" style=\"width: 150px; border-radius: 54% 46% 77% 23% \/ 74% 40% 60% 26%; overflow: hidden;\" width=\"150\" height=\"auto\" \/><div class=\"fusion-title title fusion-title-2 fusion-sep-none fusion-title-text fusion-title-size-three article-author-name-title\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Kais Laribi<\/h3><\/div><div class=\"fusion-text fusion-text-1 article-author-description\"><p>Cient\u00edfico Senior Data en Artefact<\/p>\n<\/div><\/div><\/div><\/div><\/div><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-2 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-margin-top:40px;--awb-margin-bottom:40px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-center fusion-flex-justify-content-center fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-1 fusion_builder_column_1_1 1_1 fusion-flex-column fusion-flex-align-self-center fusion-column-inner-bg-wrapper\" style=\"--awb-padding-top:20px;--awb-padding-right:20px;--awb-padding-bottom:20px;--awb-padding-left:20px;--awb-overflow:hidden;--awb-inner-bg-size:cover;--awb-border-color:rgba(10,17,40,0.1);--awb-border-top:1px;--awb-border-right:1px;--awb-border-bottom:1px;--awb-border-left:1px;--awb-border-style:solid;--awb-border-radius:4px 4px 4px 4px;--awb-inner-bg-border-radius:4px 4px 4px 4px;--awb-inner-bg-overflow:hidden;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><span class=\"fusion-column-inner-bg hover-type-none\"><a class=\"fusion-column-anchor\" href=\"https:\/\/medium.com\/artefact-engineering-and-data-science\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-a83390718a92\" rel=\"noopener noreferrer\" target=\"_blank\"><span class=\"fusion-column-inner-bg-image\"><\/span><\/a><\/span><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-center fusion-content-layout-row fusion-flex-align-items-center\"><div class=\"fusion-text fusion-text-2\"><p><u>Lea nuestro art\u00edculo sobre<\/u><\/p>\n<\/div><div class=\"fusion-image-element\" style=\"--awb-margin-right:20px;--awb-margin-left:20px;--awb-max-width:150px;--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);\"><span class=\"fusion-imageframe imageframe-none imageframe-1 hover-type-none\"><img decoding=\"async\" width=\"4000\" height=\"992\" title=\"Mediano Blog\" src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog.png\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog.png\" alt class=\"lazyload img-responsive wp-image-60582\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%274000%27%20height%3D%27992%27%20viewBox%3D%270%200%204000%20992%27%3E%3Crect%20width%3D%274000%27%20height%3D%27992%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog-200x50.png 200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog-400x99.png 400w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog-600x149.png 600w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog-800x198.png 800w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog-1200x298.png 1200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/04\/Medium-Blog.png 4000w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 640px) 100vw, 4000px\" \/><\/span><\/div><div class=\"fusion-text fusion-text-3\"><p>.<\/p>\n<\/div><\/div><\/div><\/div><\/div><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-3 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-2 fusion_builder_column_1_1 1_1 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-text fusion-text-4 description\"><p>Este art\u00edculo es la tercera parte de una serie en la que recorremos el proceso de registrar modelos utilizando Mlflow, servirlos en el motor Kubernetes y finalmente escalarlos seg\u00fan las necesidades de nuestra aplicaci\u00f3n. Aunque este art\u00edculo podr\u00eda utilizarse de forma independiente para probar cualquier respuesta de API, recomendamos la lectura de nuestros dos art\u00edculos anteriores (parte1 y parte2) sobre c\u00f3mo desplegar una instancia de seguimiento y servir un modelo como API con Mlflow. A continuaci\u00f3n, nos interesaremos por la cuesti\u00f3n de la escalabilidad y la abordaremos con algunos experimentos para comprender el comportamiento del cl\u00faster k8s y dar recomendaciones sobre c\u00f3mo manejar cargas elevadas.<\/p>\n<\/div><\/div><\/div><\/div><\/div><article class=\"fusion-fullwidth fullwidth-box fusion-builder-row-4 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-justify-content-center fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-3 fusion_builder_column_1_1 1_1 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-title title fusion-title-3 fusion-sep-none fusion-title-text fusion-title-size-one\" style=\"--awb-margin-bottom-small:8px;\"><h1 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:70;line-height:1;\">Parte 3 - \u00bfC\u00f3mo manejar cargas elevadas y hacer que nuestra aplicaci\u00f3n sea escalable?<\/h1><\/div><div class=\"fusion-title title fusion-title-4 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Introducci\u00f3n<\/h2><\/div><div class=\"fusion-text fusion-text-5\"><p>En un escenario cl\u00e1sico en el que se despliega un modelo de aprendizaje autom\u00e1tico detr\u00e1s de una aplicaci\u00f3n o un producto, varios usuarios podr\u00edan interactuar con \u00e9l simult\u00e1neamente para generar predicciones. Por lo tanto, es esencial analizar las capacidades de nuestra infraestructura y dimensionarla en consecuencia. Esto resulta especialmente interesante en lo que respecta a Kubernetes, ya que podr\u00eda influir en las decisiones sobre si utilizar o no el autoescalado, el n\u00famero m\u00e1ximo de nodos a considerar...<\/p>\n<\/div><div class=\"fusion-text fusion-text-6\"><p>En este contexto, las pruebas de carga permiten simular m\u00faltiples n\u00fameros simult\u00e1neos o incrementales de peticiones y monitorizar el comportamiento de la infraestructura (tiempo de respuesta, uso de CPU, uso de memoria..) con el fin de dimensionar correctamente los recursos y evitar cuellos de botella. Estas pruebas se realizar\u00e1n aqu\u00ed utilizando una herramienta llamada Locust.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-5 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Preparaci\u00f3n del entorno<\/h2><\/div><div class=\"fusion-text fusion-text-7\"><p>Los requisitos para este Hands-on se detallan en el primer art\u00edculo de esta serie, pero a modo de resumen, aqu\u00ed est\u00e1n los principales elementos que necesitamos espec\u00edficamente para esta parte suponiendo que nuestro modelo ya est\u00e1 desplegado como una API en un cl\u00faster Kubernetes (mlflow-k8s).<\/p>\n<p>Para esta parte de la pr\u00e1ctica, necesitaremos:<\/p>\n<\/div><ul style=\"--awb-line-height:27.2px;--awb-icon-width:27.2px;--awb-icon-height:27.2px;--awb-icon-margin:11.2px;--awb-content-margin:38.4px;\" class=\"fusion-checklist fusion-checklist-1 fusion-checklist-default type-icons\"><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">Un cl\u00faster GKE para desplegar Locust (aqu\u00ed lo llamaremos\u00a0<em class=\"jz\">carga_prueba<\/em>)<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">Una estaci\u00f3n de trabajo local configurada (gcloud, kubectl)<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">La siguiente variable de entorno exportada<\/p>\n<pre class=\"hp hq hr hs ht lb gv be\"><span id=\"c4c0\" class=\"ej lc ii dm ld b le lf lg s lh\" data-selectable-paragraph=\"\">export GCR_REPO=eu.gcr.io\/mlflow-on-k8s\/repo<\/span><\/pre>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\"><a class=\"bv ig\" href=\"https:\/\/github.com\/artefactory-global\/mlflow-serving-example\" target=\"_blank\" rel=\"noopener ugc nofollow\">El dep\u00f3sito<\/a>\u00a0d\u00f3nde vive el c\u00f3digo pr\u00e1ctico<\/div><\/li><\/ul><div class=\"fusion-title title fusion-title-6 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Despliegue<\/h2><\/div><div class=\"fusion-title title fusion-title-7 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">1. Construya la imagen Locust docker y empuje la imagen Locust a GCR<\/h3><\/div><div class=\"fusion-text fusion-text-8\"><pre class=\"hp hq hr hs ht lb gv be\"><span id=\"df7b\" class=\"ej lc ii dm ld b le lf lg s lh\" data-selectable-paragraph=\"\">cd mlflow-serving-ejemplo<\/span><span id=\"f519\" class=\"ej lc ii dm ld b le lk ll lm ln lo lg s lh\" data-selectable-paragraph=\"\">docker build --tag $\/locust-tasks:v1\narchivo dockerfile_locust .<\/span><span id=\"dcc8\" class=\"ej lc ii dm ld b le lk ll lm ln lo lg s lh\" data-selectable-paragraph=\"\">docker push $\/locust-tasks:v1<\/span><\/pre>\n<\/div><div class=\"fusion-title title fusion-title-8 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">2. Prepare la tarea de prueba<\/h3><\/div><div class=\"fusion-text fusion-text-9\"><p>Las tareas son funciones python que Locust ejecutar\u00e1 en sus trabajadores como parte de la prueba de carga, en el c\u00f3digo de ejemplo proporcionado en\u00a0<em>locust-tareas\/tareas.py<\/em>\u00a0s\u00f3lo tenemos que enviar una solicitud POST a la API con una fila data para obtener predicciones.<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27667%27%20height%3D%270%27%20viewBox%3D%270%200%20667%200%27%3E%3Crect%20width%3D%27667%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/Capture-de\u0301cran-2021-10-26-a\u0300-18.11.10.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 667px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"667\" height=\"auto\" \/><div class=\"fusion-text fusion-text-10\"><p>En este fragmento de c\u00f3digo :<\/p>\n<\/div><ul style=\"--awb-line-height:27.2px;--awb-icon-width:27.2px;--awb-icon-height:27.2px;--awb-icon-margin:11.2px;--awb-content-margin:38.4px;\" class=\"fusion-checklist fusion-checklist-2 fusion-checklist-default type-icons\"><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p><em><strong>on_start<\/strong><strong>:<\/strong><\/em><em class=\"jz\"> es\u00a0<\/em>se ejecuta una sola vez cuando se lanza el hilo para descargar el dataset.<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\"><em><strong>post_metrics<\/strong><\/em>: es el n\u00facleo de nuestra tarea de prueba, aqu\u00ed s\u00f3lo tenemos una funci\u00f3n que env\u00eda una fila al punto final \/invocaci\u00f3n.<\/div><\/li><\/ul><div class=\"fusion-text fusion-text-11\"><p>Podemos crear tantas funciones como pruebas queramos realizar. Por ejemplo, podemos a\u00f1adir una para enviar lotes de data. Adem\u00e1s, podemos utilizar la funci\u00f3n\u00a0<strong>@tarea()<\/strong>\u00a0decorador para dar prioridad a las distintas tareas.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-9 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">3. Despliegue en Kubernetes<\/h3><\/div><div class=\"fusion-text fusion-text-12\"><p>Ahora es el momento de desplegar la imagen y ejecutar Locust en su cl\u00faster dedicado. En primer lugar, aseg\u00farese de que el contexto est\u00e1 establecido en el\u00a0<em>carga_prueba<\/em>\u00a0cluster ejecutando<\/p>\n<\/div><div class=\"fusion-text fusion-text-13\"><p>kubectl config get-contexts<br \/>\nkubectl config use-context NOMBRE<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27667%27%20height%3D%270%27%20viewBox%3D%270%200%20667%200%27%3E%3Crect%20width%3D%27667%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-2.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 667px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"667\" height=\"auto\" \/><div class=\"fusion-text fusion-text-14\"><p>A continuaci\u00f3n, podemos actualizar nuestro archivo de despliegue\u00a0<em>deployments\/locust_load_test.yaml\u00a0<\/em>especificando\u00a0<strong>la ruta de la imagen en GCR<\/strong>y<strong class=\"jh lj\">\u00a0<\/strong>se\u00f1alando el\u00a0<strong>TARGET_HOST<\/strong>\u00a0a la direcci\u00f3n API.<\/p>\n<\/div><div class=\"fusion-text fusion-text-15\"><div class=\"code\">tipo: ReplicationController<br \/>\napiVersion: v1<br \/>\nmetadata:<br \/>\nnombre: locust-master<br \/>\netiquetas:<br \/>\nnombre: langosta<br \/>\npapel: maestro<br \/>\nespec:<br \/>\nr\u00e9plicas: 1<br \/>\nselector:<br \/>\nnombre: langosta<br \/>\npapel: maestro<br \/>\nplantilla:<br \/>\nmetadata:<br \/>\netiquetas:<br \/>\nnombre: langosta<br \/>\npapel: maestro<br \/>\nespec:<br \/>\ncontenedores:<br \/>\n- nombre: langosta<br \/>\nimagen: GCR_REPO\/locust-tasks:v1 # Cambiar aqu\u00ed<br \/>\nenv:<br \/>\n- nombre: LOCUST_MODE<br \/>\nvalor: maestro<br \/>\n- nombre: TARGET_HOST<br \/>\nvalor: \u2018http:\/\/SERVING_IP:SERVING_PORT\u2019 # Cambie aqu\u00ed<br \/>\npuertos:<br \/>\n- nombre: loc-master-web<br \/>\ncontainerPort: 8089<br \/>\nprotocolo: TCP<br \/>\n- nombre: loc-master-p1<br \/>\ncontainerPort: 5557<br \/>\nprotocolo: TCP<br \/>\n- nombre: loc-master-p2<br \/>\ncontainerPort: 5558<br \/>\nprotocolo: TCP<br \/>\n-<br \/>\ntipo: ReplicationController<br \/>\napiVersion: v1<br \/>\nmetadata:<br \/>\nnombre: trabajador de la langosta<br \/>\netiquetas:<br \/>\nnombre: langosta<br \/>\npapel: trabajador<br \/>\nespec:<br \/>\nr\u00e9plicas: 30<br \/>\nselector:<br \/>\nnombre: langosta<br \/>\npapel: trabajador<br \/>\nplantilla:<br \/>\nmetadata:<br \/>\netiquetas:<br \/>\nnombre: langosta<br \/>\npapel: trabajador<br \/>\nespec:<br \/>\ncontenedores:<br \/>\n- nombre: langosta<br \/>\nimagen: GCR_REPO\/locust-tasks:v1 # Cambiar aqu\u00ed<br \/>\nenv:<br \/>\n- nombre: LOCUST_MODE<br \/>\nvalor: trabajador<br \/>\n- nombre: LOCUST_MASTER<br \/>\nvalor: locust-master<br \/>\n- nombre: TARGET_HOST<br \/>\nvalor: \u2018http:\/\/SERVING_IP:SERVING_PORT\u2019 # Cambie aqu\u00ed<br \/>\n-<br \/>\nTipo: Servicio<br \/>\napiVersion: v1<br \/>\nmetadata:<br \/>\nnombre: locust-master<br \/>\netiquetas:<br \/>\nnombre: langosta<br \/>\npapel: maestro<br \/>\nespec:<br \/>\npuertos:<br \/>\n- puerto: 8089<br \/>\ntargetPort: loc-master-web<br \/>\nprotocolo: TCP<br \/>\nnombre: loc-master-web<br \/>\n- puerto 5557<br \/>\ntargetPort: loc-master-p1<br \/>\nprotocolo: TCP<br \/>\nnombre: loc-master-p1<br \/>\n- puerto 5558<br \/>\ntargetPort: loc-master-p2<br \/>\nprotocolo: TCP<br \/>\nnombre: loc-master-p2<br \/>\nselector:<br \/>\nnombre: langosta<br \/>\npapel: maestro<br \/>\ntipo: LoadBalancer<\/div>\n<\/div>\ntipo: ReplicationController\napiVersion: v1\nmetadata:\n  name: locust-master\n  etiquetas:\n    nombre: langosta\n    rol: maestro\nespecificaci\u00f3n:\n  r\u00e9plicas: 1\n  selector:\n    nombre: langosta\n    rol: maestro\n  plantilla:\n    metadata:\n      etiquetas:\n        nombre: langosta\n        rol: maestro\n    especificaci\u00f3n:\n      contenedores:\n        - nombre: langosta\n          imagen: GCR_REPO\/locust-tasks:v1 # Cambie aqu\u00ed\n          env:\n            - nombre: LOCUST_MODE\n              valor: master\n            - nombre: TARGET_HOST\n              valor: 'http:\/\/SERVING_IP:SERVING_PORT' # Cambie aqu\u00ed\n          puertos:\n            - nombre: loc-master-web\n              puertoContenedor: 8089\n              protocolo TCP\n            - nombre: loc-master-p1\n              puertoContenedor: 5557\n              protocolo: TCP\n            - nombre: loc-master-p2\n              puertoContenedor: 5558\n              protocolo: TCP\n---\ntipo: ReplicationController\napiVersion: v1\nmetadata:\n  nombre: locust-worker\n  etiquetas:\n    nombre: langosta\n    rol: trabajador\nspec:\n  r\u00e9plicas: 30\n  selector:\n    nombre: langosta\n    rol: trabajador\n  plantilla:\n    metadata:\n      etiquetas:\n        nombre: langosta\n        rol: trabajador\n    especificaci\u00f3n:\n      contenedores:\n        - nombre: langosta\n          imagen: GCR_REPO\/locust-tasks:v1 # Cambie aqu\u00ed\n          env:\n            - nombre: LOCUST_MODE\n              valor: worker\n            - nombre: LOCUST_MASTER\n              valor: locust-master\n            - nombre: TARGET_HOST\n              valor: 'http:\/\/SERVING_IP:SERVING_PORT' # Cambie aqu\u00ed\n---\ntipo: Service\napiVersion: v1\nmetadata\n  name: locust-master\n  etiquetas:\n    nombre: langosta\n    rol: maestro\nspec:\n  puertos:\n    - puerto 8089\n      targetPort: loc-master-web\n      protocolo: TCP\n      nombre: loc-master-web\n    - puerto 5557\n      targetPort: loc-master-p1\n      protocolo TCP\n      nombre: loc-master-p1\n    - puerto 5558\n      targetPort: loc-master-p2\n      protocolo TCP\n      nombre: loc-master-p2\n  selector\n    nombre: locust\n    rol: maestro\n  tipo: equilibrador de carga<div class=\"fusion-text fusion-text-16\"><p>Por \u00faltimo, vamos a desplegarlo utilizando el siguiente comando.<\/p>\n<pre class=\"hp hq hr hs ht lb gv be\"><span id=\"30de\" class=\"ej lc ii dm ld b le lf lg s lh\" data-selectable-paragraph=\"\">kubectl create -f deployments\/locust_load_test.yaml<\/span><\/pre>\n<p>La instancia de Langosta deber\u00eda estar ahora en marcha y se deber\u00eda haber creado un nuevo equilibrador de carga. Podemos encontrar su IP escribiendo <em>kubectl obtener servicios\u00a0<\/em>y acceder a la interfaz utilizando el LoadbalancerIP:8089<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27701%27%20height%3D%270%27%20viewBox%3D%270%200%20701%200%27%3E%3Crect%20width%3D%27701%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-3.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 701px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"701\" height=\"auto\" \/><div class=\"fusion-title title fusion-title-10 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Experimentaci\u00f3n<\/h2><\/div><div class=\"fusion-text fusion-text-17\"><p>La idea es utilizar Locust para simular consultas paralelas en nuestra API de servicio y analizar el comportamiento del cl\u00faster y el tiempo de respuesta (mediana en verde y percentil 95 en naranja). Esto se hace con fines educativos para destacar dos caracter\u00edsticas que ofrece Kubernetes que son el (auto)escalado horizontal y vertical.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-11 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">1. Escalado manual<\/h3><\/div><div class=\"fusion-text fusion-text-18\"><p>En el primer experimento, intentamos comprender el efecto de\u00a0<strong>tener m\u00e1s vainas <\/strong>sirviendo nuestros modelos. Empezamos con un pod e intentamos aumentar el n\u00famero de peticiones. En el gr\u00e1fico siguiente, podemos diferenciar 4 fases con distintas configuraciones y cargas.<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27707%27%20height%3D%270%27%20viewBox%3D%270%200%20707%200%27%3E%3Crect%20width%3D%27707%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-4.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 707px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"707\" height=\"auto\" \/><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27686%27%20height%3D%270%27%20viewBox%3D%270%200%20686%200%27%3E%3Crect%20width%3D%27686%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-5.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 686px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"686\" height=\"auto\" \/><div class=\"fusion-text fusion-text-19\"><p>Como conclusi\u00f3n general, podemos ver que es importante monitorizar siempre las m\u00e9tricas de recursos (CPU, RAM..) para identificar cuellos de botella y problemas de configuraci\u00f3n. En nuestro caso, disponer de un solo pod no nos permit\u00eda aprovechar la potencia de procesamiento disponible. Por lo tanto, al desplegar una aplicaci\u00f3n, es esencial establecer un n\u00famero adecuado de pods y fijar suficientes recursos por pod para maximizar el uso de la m\u00e1quina teniendo en cuenta los servicios del sistema que se ejecutan en el backend. As\u00ed pues, recomendamos no forzar el uso de la CPU de los nodos por encima de 80-90%.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-12 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">2. Autoescalado horizontal<\/h3><\/div><div class=\"fusion-text fusion-text-20\"><p>Bueno, afortunadamente, Kubernetes tiene un\u00a0<strong>funci\u00f3n de escala horizontal autom\u00e1tica<\/strong>\u00a0para supervisar autom\u00e1ticamente el uso de la CPU y crear nuevos pods cuando sea necesario para distribuir la carga. Esto podr\u00eda activarse simplemente con el siguiente comando.<\/p>\n<pre class=\"hp hq hr hs ht lb gv be\"><span id=\"a7cd\" class=\"ej lc ii dm ld b le lf lg s lh\" data-selectable-paragraph=\"\">kubectl autoscale deployment mlflow-serving --cpu-percent=80 --min=1 --max=12<\/span><\/pre>\n<p>A continuaci\u00f3n, podemos supervisar el n\u00famero y los estados de los pods utilizando\u00a0<em>kubectl get hpa mlflow-serving<\/em>, analizar el tiempo de respuesta del cluster y el consumo de recursos.<br \/>\nEl objetivo del siguiente experimento es observar c\u00f3mo Kubernetes puede a\u00f1adir pods autom\u00e1ticamente para optimizar el uso de recursos y tener un mejor tiempo de respuesta. Podemos dividir este experimento en tres fases como se muestra en el siguiente gr\u00e1fico.<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27686%27%20height%3D%270%27%20viewBox%3D%270%200%20686%200%27%3E%3Crect%20width%3D%27686%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-6.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 686px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"686\" height=\"auto\" \/><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27671%27%20height%3D%270%27%20viewBox%3D%270%200%20671%200%27%3E%3Crect%20width%3D%27671%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-7.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 671px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"671\" height=\"auto\" \/><div class=\"fusion-text fusion-text-21\"><p>En este segundo experimento, observamos que el autoescalado horizontal nos permit\u00eda reducir el tiempo de respuesta mediante la creaci\u00f3n de nuevos pods y la asignaci\u00f3n de m\u00e1s recursos de cl\u00faster. Sin embargo, al alcanzar la capacidad del cl\u00faster (fase3) los nuevos pods permanecen en estado pendiente y nuestro tiempo de respuesta vuelve a aumentar.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-13 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">3. Autoescalado vertical<\/h3><\/div><div class=\"fusion-text fusion-text-22\"><p>En tal situaci\u00f3n, podemos explorar otra caracter\u00edstica de Kubernetes conocida como\u00a0<strong>autoescalado vertical\u00a0<\/strong>que consiste en asignar m\u00e1s nodos siempre que sea necesario. Esta funci\u00f3n puede activarse mediante el siguiente comando que especifica el n\u00famero m\u00ednimo y m\u00e1ximo de nodos que Kubernetes puede asignar.<\/p>\n<pre class=\"hp hq hr hs ht lb gv be\"><span id=\"7f33\" class=\"ej lc ii dm ld b le lf lg s lh\" data-selectable-paragraph=\"\">gcloud container clusters update mlflow-k8s\n--enable-autoscaling --min-nodes 3 --max-nodes 5 --node-pool POOL_NAME<\/span><\/pre>\n<p>Finalmente, en este \u00faltimo experimento resumido en el gr\u00e1fico siguiente, habilitar la funci\u00f3n de autoescalado vertical, permiti\u00f3 a Kubernetes a\u00f1adir autom\u00e1ticamente dos nuevos nodos y crear nuevos pods para despachar la carga y garantizar un menor tiempo de respuesta. En realidad, Kubernetes tard\u00f3 alrededor de 1 minuto en detectar la necesidad y crear los recursos (fase 2). Adem\u00e1s, con una carga menor (fase 3) Kubernetes consigui\u00f3 liberar los dos nuevos nodos matando pods y reducir el cl\u00faster a un m\u00ednimo de tres nodos en unos 15 min.<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27661%27%20height%3D%270%27%20viewBox%3D%270%200%20661%200%27%3E%3Crect%20width%3D%27661%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-8.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 661px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"661\" height=\"auto\" \/><div class=\"fusion-title title fusion-title-14 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">4. Estimaci\u00f3n del tama\u00f1o de los conglomerados<\/h3><\/div><div class=\"fusion-text fusion-text-23\"><p>Ahora que hemos comprendido c\u00f3mo se comporta Kubernetes en respuesta a diferentes niveles de carga utilizando las funciones de autoescalado vertical y horizontal, el \u00faltimo paso es realizar pruebas de rendimiento con diferentes recursos, teniendo en cuenta los requisitos de nuestra aplicaci\u00f3n y la estimaci\u00f3n de su n\u00famero de usuarios. Imaginemos que, para cumplir los requisitos de nuestro SLA, nuestro tiempo de respuesta del percentil 95 debe ser inferior a 1 s. En este caso, podemos trazar el gr\u00e1fico siguiente mostrando el tiempo de respuesta de la API para diferentes n\u00fameros de n\u00facleos y hacernos una idea del rendimiento de nuestra aplicaci\u00f3n en diferentes condiciones.<\/p>\n<p>En concreto, para nuestro modelo ML servido con Mlflow, podemos tener unos 120 usuarios simult\u00e1neos en un cl\u00faster Kubernetes de 12 n\u00facleos y garantizar un tiempo de respuesta inferior a 1 s.<\/p>\n<\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27625%27%20height%3D%270%27%20viewBox%3D%270%200%20625%200%27%3E%3Crect%20width%3D%27625%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/10\/article-kais-part3-9.png\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left hover-enable\" style=\"width: 625px; border-radius: 59% 41% 41% 59% \/ 29% 48% 52% 71%; overflow: hidden;\" width=\"625\" height=\"auto\" \/><div class=\"fusion-title title fusion-title-15 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Conclusi\u00f3n<\/h2><\/div><div class=\"fusion-text fusion-text-24\"><p>En una serie de art\u00edculos, recorrimos todo el proceso para desplegar una instancia de seguimiento de Mlflow y servir un modelo como API en el motor Kubernetes aprovechando su capacidad para escalar f\u00e1cilmente y manejar cargas elevadas. Tambi\u00e9n experimentamos con dos interesantes caracter\u00edsticas que ofrece Kubernetes que son el autoescalado horizontal y vertical y demostramos que siempre es interesante monitorizar nuestros recursos para asegurarnos de que los estamos utilizando eficientemente. Por \u00faltimo, mostramos c\u00f3mo pod\u00edamos probar nuestra aplicaci\u00f3n y tomar decisiones sobre la infraestructura en funci\u00f3n de su respuesta a diferentes escenarios de prueba.<\/p>\n<\/div><\/div><\/div><\/div><\/article><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-5 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-margin-top:40px;--awb-margin-bottom:40px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-center fusion-flex-justify-content-center fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-4 fusion_builder_column_1_1 1_1 fusion-flex-column fusion-flex-align-self-center fusion-column-inner-bg-wrapper\" style=\"--awb-padding-top:40px;--awb-padding-right:40px;--awb-padding-bottom:40px;--awb-padding-left:40px;--awb-overflow:hidden;--awb-inner-bg-position:left center;--awb-inner-bg-size:cover;--awb-border-color:rgba(10,17,40,0.1);--awb-border-style:solid;--awb-border-radius:4px 4px 4px 4px;--awb-inner-bg-border-radius:4px 4px 4px 4px;--awb-inner-bg-overflow:hidden;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><span class=\"fusion-column-inner-bg hover-type-none\"><a class=\"fusion-column-anchor\" href=\"https:\/\/medium.com\/artefact-engineering-and-data-science\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-a83390718a92\" target=\"_blank\" rel=\"noopener\"><span class=\"fusion-column-inner-bg-image lazyload\" data-bg=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/03\/background.jpg\"><\/span><\/a><\/span><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-center fusion-content-layout-column fusion-column-has-bg-image\" data-bg-url=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/03\/background.jpg\"><div class=\"fusion-image-element\" style=\"text-align:center;--awb-margin-right:20px;--awb-margin-left:20px;--awb-max-width:150px;--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);\"><span class=\"fusion-imageframe imageframe-none imageframe-2 hover-type-none\"><img decoding=\"async\" width=\"72\" height=\"41\" title=\"medio\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2772%27%20height%3D%2741%27%20viewBox%3D%270%200%2072%2041%27%3E%3Crect%20width%3D%2772%27%20height%3D%2741%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/03\/medium.png\" alt class=\"lazyload img-responsive wp-image-60927\"\/><\/span><\/div><div class=\"fusion-title title fusion-title-16 fusion-sep-none fusion-title-center fusion-title-text fusion-title-size-three\" style=\"--awb-margin-top:20px;--awb-margin-bottom:0px;--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-center fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Medio Blog por Artefact.<\/h3><\/div><div class=\"fusion-text fusion-text-25\" style=\"--awb-content-alignment:center;\"><p>Este art\u00edculo se public\u00f3 inicialmente en <strong>Medium.com<\/strong>.<br \/>\n\u00a1S\u00edganos en nuestro Medium Blog !<\/p>\n<\/div><div style=\"text-align:center;\"><a class=\"fusion-button button-flat button-medium button-default fusion-button-default button-1 fusion-button-default-span fusion-button-default-type\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"https:\/\/medium.com\/artefact-engineering-and-data-science\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-a83390718a92\" aria-label=\"https:\/\/medium.com\/artefact-engineering-and-data-science\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-a83390718a92\" href=\"https:\/\/medium.com\/artefact-engineering-and-data-science\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-bf27258775e7\"><span class=\"fusion-button-text awb-button__text awb-button__text--default\">Lea nuestro art\u00edculo<\/span><\/a><\/div><\/div><\/div><\/div><\/div><\/p>","protected":false},"excerpt":{"rendered":"<p>Este art\u00edculo es la tercera parte de una serie en la que recorremos el proceso de registrar modelos utilizando Mlflow, servirlos en el motor Kubernetes y finalmente escalarlos seg\u00fan las necesidades de nuestra aplicaci\u00f3n. Aunque este art\u00edculo podr\u00eda utilizarse de forma independiente para probar cualquier respuesta de API, recomendamos la lectura de nuestros dos art\u00edculos anteriores (parte1 y parte2) sobre c\u00f3mo desplegar una instancia de seguimiento y servir un modelo como API con Mlflow. A continuaci\u00f3n, nos interesaremos por la cuesti\u00f3n de la escalabilidad y la abordaremos con algunos experimentos para comprender el comportamiento del cl\u00faster k8s y dar recomendaciones sobre c\u00f3mo manejar cargas elevadas.<\/p>","protected":false},"featured_media":68688,"parent":0,"template":"","meta":{"_acf_changed":false,"ep_exclude_from_search":false},"blog-category":[21939],"blog-language":[2991],"class_list":["post-64449","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog-category-medium","blog-language-en"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/blog\/64449","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/types\/blog"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/media\/68688"}],"wp:attachment":[{"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/media?parent=64449"}],"wp:term":[{"taxonomy":"blog-category","embeddable":true,"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/blog-category?post=64449"},{"taxonomy":"blog-language","embeddable":true,"href":"https:\/\/www.artefact.com\/es\/wp-json\/wp\/v2\/blog-language?post=64449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}