	{"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\/fr\/blog\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-part-2-2\/","title":{"rendered":"Servir des mod\u00e8les ML \u00e0 l'\u00e9chelle en utilisant Mlflow sur Kubernetes - Partie 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;\">Auteur<\/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>Scientifique senior Data \u00e0 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>Lisez notre article sur<\/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=\"Moyen 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>Cet article est la troisi\u00e8me partie d'une s\u00e9rie dans laquelle nous passons en revue le processus de journalisation des mod\u00e8les \u00e0 l'aide de Mlflow, de les servir sur le moteur Kubernetes et enfin de les mettre \u00e0 l'\u00e9chelle en fonction des besoins de notre application. Bien que cet article puisse \u00eatre utilis\u00e9 ind\u00e9pendamment pour tester n'importe quelle r\u00e9ponse d'API, nous vous recommandons de lire nos deux articles pr\u00e9c\u00e9dents (partie 1 et partie 2) sur la fa\u00e7on de d\u00e9ployer une instance de suivi et de servir un mod\u00e8le en tant qu'API avec Mlflow. Dans la suite de cet article, nous nous int\u00e9resserons \u00e0 la question de la scalabilit\u00e9 et nous l'aborderons avec quelques exp\u00e9riences pour comprendre le comportement du cluster k8s et donner des recommandations sur la fa\u00e7on de g\u00e9rer des charges \u00e9lev\u00e9es.<\/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;\">Partie 3 - Comment g\u00e9rer des charges \u00e9lev\u00e9es et rendre notre application \u00e9volutive ?<\/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;\">Introduction<\/h2><\/div><div class=\"fusion-text fusion-text-5\"><p>Dans un sc\u00e9nario classique o\u00f9 un mod\u00e8le d'apprentissage automatique est d\u00e9ploy\u00e9 derri\u00e8re une application ou un produit, plusieurs utilisateurs peuvent interagir avec lui simultan\u00e9ment pour g\u00e9n\u00e9rer des pr\u00e9dictions. Il est donc essentiel d'analyser les capacit\u00e9s de notre infrastructure et de la dimensionner en cons\u00e9quence. Cela devient particuli\u00e8rement int\u00e9ressant en ce qui concerne Kubernetes, car cela pourrait avoir un impact sur les d\u00e9cisions concernant l'utilisation ou non de l'autoscaling, le nombre maximum de n\u0153uds \u00e0 consid\u00e9rer....<\/p>\n<\/div><div class=\"fusion-text fusion-text-6\"><p>Dans ce contexte, les tests de charge permettent de simuler un nombre multiple de requ\u00eates simultan\u00e9es ou incr\u00e9mentales et de surveiller le comportement de l'infrastructure (temps de r\u00e9ponse, utilisation du CPU, utilisation de la m\u00e9moire..) afin de dimensionner correctement les ressources et d'\u00e9viter les goulets d'\u00e9tranglement. Ces tests seront r\u00e9alis\u00e9s ici \u00e0 l'aide d'un outil appel\u00e9 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;\">Pr\u00e9paration de l'environnement<\/h2><\/div><div class=\"fusion-text fusion-text-7\"><p>Les exigences pour ce Hands-on sont d\u00e9taill\u00e9es dans le premier article de cette s\u00e9rie mais en guise de r\u00e9sum\u00e9, voici les principaux \u00e9l\u00e9ments dont nous avons besoin sp\u00e9cifiquement pour cette partie en supposant que notre mod\u00e8le est d\u00e9j\u00e0 d\u00e9ploy\u00e9 en tant qu'API sur un cluster Kubernetes (mlflow-k8s).<\/p>\n<p>Pour cette partie de l'exercice pratique, nous aurons besoin de :<\/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 cluster GKE pour d\u00e9ployer Locust (nous le nommerons ici\u00a0<em class=\"jz\">load_testing<\/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\">Un poste de travail local configur\u00e9 (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 variable d'environnement suivante est export\u00e9e<\/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\">Le d\u00e9p\u00f4t<\/a>\u00a0o\u00f9 se trouve le code pratique<\/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;\">D\u00e9ploiement<\/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. Construire l'image docker de Locust et pousser l'image de Locust vers 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-example<\/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\nfichier 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. Pr\u00e9parez la t\u00e2che de test<\/h3><\/div><div class=\"fusion-text fusion-text-9\"><p>Les t\u00e2ches sont des fonctions python que Locust ex\u00e9cutera sur ses travailleurs dans le cadre du test de charge, dans l'exemple de code fourni sous la rubrique\u00a0<em>locust-tasks\/tasks.py<\/em>\u00a0il suffit d'envoyer une requ\u00eate POST \u00e0 l'API avec une ligne data pour obtenir des pr\u00e9dictions.<\/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>Dans cet extrait de code :<\/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\"> est\u00a0<\/em>ex\u00e9cut\u00e9 une seule fois lorsque le thread est lanc\u00e9 pour t\u00e9l\u00e9charger le 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>La fonction \/invocation : est le c\u0153ur de notre t\u00e2che de test, ici nous n'avons qu'une seule fonction qui envoie une ligne au point de terminaison \/invocation.<\/div><\/li><\/ul><div class=\"fusion-text fusion-text-11\"><p>Nous pouvons cr\u00e9er autant de fonctions que de tests que nous voulons effectuer. Par exemple, nous pouvons en ajouter une pour envoyer des lots de data. Nous pouvons \u00e9galement utiliser la fonction\u00a0<strong>@task()<\/strong>\u00a0pour donner la priorit\u00e9 aux diff\u00e9rentes t\u00e2ches.<\/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. D\u00e9ployez vers Kubernetes<\/h3><\/div><div class=\"fusion-text fusion-text-12\"><p>Il est maintenant temps de d\u00e9ployer l'image et d'ex\u00e9cuter Locust sur son cluster d\u00e9di\u00e9. Tout d'abord, assurez-vous que le contexte est d\u00e9fini sur le serveur\u00a0<em>load_testing<\/em>\u00a0en ex\u00e9cutant<\/p>\n<\/div><div class=\"fusion-text fusion-text-13\"><p>kubectl config get-contexts<br \/>\nkubectl config use-context NAME<\/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>Ensuite, nous pouvons mettre \u00e0 jour notre fichier de d\u00e9ploiement\u00a0<em>deployments\/locust_load_test.yaml\u00a0<\/em>en sp\u00e9cifiant\u00a0<strong>le chemin de l'image sur le GCR<\/strong>et<strong class=\"jh lj\">\u00a0<\/strong>en pointant le\u00a0<strong>TARGET_HOST<\/strong>\u00a0\u00e0 l'adresse de l'API.<\/p>\n<\/div><div class=\"fusion-text fusion-text-15\"><div class=\"code\">type : Contr\u00f4leur de r\u00e9plication<br \/>\napiVersion : v1<br \/>\nmetadata :<br \/>\nnom : locust-master<br \/>\nles \u00e9tiquettes :<br \/>\nnom : locuste<br \/>\nr\u00f4le : ma\u00eetre<br \/>\nsp\u00e9c :<br \/>\nr\u00e9pliques : 1<br \/>\ns\u00e9lecteur :<br \/>\nnom : locuste<br \/>\nr\u00f4le : ma\u00eetre<br \/>\nmod\u00e8le :<br \/>\nmetadata :<br \/>\nles \u00e9tiquettes :<br \/>\nnom : locuste<br \/>\nr\u00f4le : ma\u00eetre<br \/>\nsp\u00e9c :<br \/>\ndes conteneurs :<br \/>\n- nom : locuste<br \/>\nimage : GCR_REPO\/locust-tasks:v1 # Modifier ici<br \/>\nenv :<br \/>\n- nom : LOCUST_MODE<br \/>\nvaleur : ma\u00eetre<br \/>\n- nom : TARGET_HOST<br \/>\nvaleur : \u2018http:\/\/SERVING_IP:SERVING_PORT\u2019 # Modifier ici<br \/>\nports :<br \/>\n- nom : loc-master-web<br \/>\ncontainerPort : 8089<br \/>\nprotocole : TCP<br \/>\n- nom : loc-master-p1<br \/>\ncontainerPort : 5557<br \/>\nprotocole : TCP<br \/>\n- nom : loc-master-p2<br \/>\ncontainerPort : 5558<br \/>\nprotocole : TCP<br \/>\n-<br \/>\ntype : Contr\u00f4leur de r\u00e9plication<br \/>\napiVersion : v1<br \/>\nmetadata :<br \/>\nnom : ouvrier acridien<br \/>\nles \u00e9tiquettes :<br \/>\nnom : locuste<br \/>\nr\u00f4le : travailleur<br \/>\nsp\u00e9c :<br \/>\nr\u00e9pliques : 30<br \/>\ns\u00e9lecteur :<br \/>\nnom : locuste<br \/>\nr\u00f4le : travailleur<br \/>\nmod\u00e8le :<br \/>\nmetadata :<br \/>\nles \u00e9tiquettes :<br \/>\nnom : locuste<br \/>\nr\u00f4le : travailleur<br \/>\nsp\u00e9c :<br \/>\ndes conteneurs :<br \/>\n- nom : locuste<br \/>\nimage : GCR_REPO\/locust-tasks:v1 # Modifier ici<br \/>\nenv :<br \/>\n- nom : LOCUST_MODE<br \/>\nvaleur : travailleur<br \/>\n- nom : LOCUST_MASTER<br \/>\nvaleur : ma\u00eetre des sauterelles<br \/>\n- nom : TARGET_HOST<br \/>\nvaleur : \u2018http:\/\/SERVING_IP:SERVING_PORT\u2019 # Modifier ici<br \/>\n-<br \/>\ngenre : Service<br \/>\napiVersion : v1<br \/>\nmetadata :<br \/>\nnom : locust-master<br \/>\nles \u00e9tiquettes :<br \/>\nnom : locuste<br \/>\nr\u00f4le : ma\u00eetre<br \/>\nsp\u00e9c :<br \/>\nports :<br \/>\n- port : 8089<br \/>\ntargetPort : loc-master-web<br \/>\nprotocole : TCP<br \/>\nnom : loc-master-web<br \/>\n- port : 5557<br \/>\ntargetPort : loc-master-p1<br \/>\nprotocole : TCP<br \/>\nnom : loc-master-p1<br \/>\n- port : 5558<br \/>\ntargetPort : loc-master-p2<br \/>\nprotocole : TCP<br \/>\nnom : loc-master-p2<br \/>\ns\u00e9lecteur :<br \/>\nnom : locuste<br \/>\nr\u00f4le : ma\u00eetre<br \/>\ntype : LoadBalancer<\/div>\n<\/div>\ntype : ReplicationController\napiVersion : v1\nmetadata :\n  name : locust-master\n  labels :\n    name : locust\n    role : master\nspec :\n  replicas : 1\n  selector :\n    name : locust\n    role : master\n  mod\u00e8le :\n    metadata :\n      \u00e9tiquettes :\n        nom : criquet\n        r\u00f4le : master\n    spec :\n      conteneurs :\n        - name : locust\n          image : GCR_REPO\/locust-tasks:v1 # Modifier ici\n          env :\n            - name : LOCUST_MODE\n              value : master\n            - name : TARGET_HOST\n              value : 'http:\/\/SERVING_IP:SERVING_PORT' # Modifier ici\n          ports :\n            - name : loc-master-web\n              containerPort : 8089\n              protocole : TCP\n            - name : loc-master-p1\n              containerPort : 5557\n              protocol : TCP\n            - nom : loc-master-p2\n              containerPort : 5558\n              protocol : TCP\n---\nkind : ReplicationController\napiVersion : v1\nmetadata :\n  name : locust-worker\n  labels :\n    name : locust\n    role : worker\nspec :\n  r\u00e9pliques : 30\n  selector :\n    name : locust\n    role : worker\n  mod\u00e8le :\n    metadata :\n      \u00e9tiquettes :\n        nom : criquet\n        r\u00f4le : travailleur\n    spec :\n      conteneurs :\n        - name : locust\n          image : GCR_REPO\/locust-tasks:v1 # Modifier ici\n          env :\n            - name : LOCUST_MODE\n              value : worker\n            - name : LOCUST_MASTER\n              valeur : locust-master\n            - name : TARGET_HOST\n              valeur : 'http:\/\/SERVING_IP:SERVING_PORT' # Modifier ici\n---\nkind : Service\napiVersion : v1\nmetadata :\n  name : locust-master\n  labels :\n    name : locust\n    role : master\nspec :\n  ports :\n    - port : 8089\n      targetPort : loc-master-web\n      protocole : TCP\n      name : loc-master-web\n    - port : 5557\n      targetPort : loc-master-p1\n      protocole : TCP\n      name : loc-master-p1\n    - port : 5558\n      targetPort : loc-master-p2\n      protocole : TCP\n      name : loc-master-p2\n  selector :\n    nom : locust\n    r\u00f4le : master\n  type : LoadBalancer<div class=\"fusion-text fusion-text-16\"><p>Enfin, d\u00e9ployons-le \u00e0 l'aide de la commande suivante.<\/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>L'instance de Locust devrait maintenant \u00eatre en place et un nouvel \u00e9quilibreur de charge devrait avoir \u00e9t\u00e9 cr\u00e9\u00e9. Nous pouvons trouver son IP en tapant <em>kubectl get services\u00a0<\/em>et acc\u00e9dez \u00e0 l'interface \u00e0 l'aide de 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;\">Exp\u00e9rimentation<\/h2><\/div><div class=\"fusion-text fusion-text-17\"><p>L'id\u00e9e est d'utiliser Locust pour simuler des requ\u00eates parall\u00e8les sur notre API de service et d'analyser le comportement du cluster et le temps de r\u00e9ponse (m\u00e9diane en vert et 95\u00e8me percentile en orange). Ceci est fait \u00e0 des fins \u00e9ducatives pour mettre en \u00e9vidence deux fonctionnalit\u00e9s offertes par Kubernetes, \u00e0 savoir la mise \u00e0 l'\u00e9chelle horizontale et verticale (auto)-mise \u00e0 l'\u00e9chelle.<\/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. Mise \u00e0 l'\u00e9chelle manuelle<\/h3><\/div><div class=\"fusion-text fusion-text-18\"><p>Dans la premi\u00e8re exp\u00e9rience, nous essayons de comprendre l'effet des\u00a0<strong>avoir plus de gousses <\/strong>pour servir nos mod\u00e8les. Nous commen\u00e7ons avec un pod et essayons d'augmenter le nombre de requ\u00eates. Dans le graphique ci-dessous, nous pouvons diff\u00e9rencier 4 phases avec diff\u00e9rentes configurations et charges.<\/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>D'une mani\u00e8re g\u00e9n\u00e9rale, nous pouvons constater qu'il est important de toujours surveiller les mesures des ressources (CPU, RAM..) pour identifier les goulots d'\u00e9tranglement et les probl\u00e8mes de configuration. Dans notre cas, le fait de n'avoir qu'un seul pod ne nous a pas permis de profiter de la puissance de traitement disponible. Ainsi, lors du d\u00e9ploiement d'une application, il est essentiel de d\u00e9finir un nombre ad\u00e9quat de pods et de d\u00e9finir suffisamment de ressources par pod pour maximiser l'utilisation de la machine en tenant compte des services syst\u00e8me ex\u00e9cut\u00e9s dans le backend. Nous vous recommandons donc de ne pas d\u00e9passer 80-90% pour l'utilisation du CPU des n\u0153uds.<\/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. Mise \u00e0 l'\u00e9chelle automatique horizontale<\/h3><\/div><div class=\"fusion-text fusion-text-20\"><p>Heureusement, Kubernetes dispose d'un syst\u00e8me de gestion de l'information.\u00a0<strong>fonction de mise \u00e0 l'\u00e9chelle horizontale automatique<\/strong>\u00a0pour surveiller automatiquement l'utilisation du CPU et cr\u00e9er de nouveaux pods si n\u00e9cessaire pour r\u00e9partir la charge. Ceci peut \u00eatre simplement activ\u00e9 par la commande suivante.<\/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>Nous pouvons ensuite surveiller le nombre et l'\u00e9tat des pods en utilisant la fonction\u00a0<em>kubectl get hpa mlflow-serving<\/em>, Le syst\u00e8me d'information sur la gestion de l'environnement permet d'analyser le temps de r\u00e9ponse de la grappe et la consommation de ressources.<br \/>\nL'objectif de l'exp\u00e9rience suivante est d'observer comment Kubernetes peut ajouter automatiquement des pods afin d'optimiser l'utilisation des ressources et d'obtenir un meilleur temps de r\u00e9ponse. Nous pouvons diviser cette exp\u00e9rience en trois phases, comme le montre le graphique ci-dessous.<\/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>Dans cette deuxi\u00e8me exp\u00e9rience, nous avons remarqu\u00e9 que l'auto-scaling horizontal nous permettait de r\u00e9duire le temps de r\u00e9ponse en cr\u00e9ant de nouveaux pods et en allouant plus de ressources au cluster. Cependant, lorsque la capacit\u00e9 du cluster est atteinte (phase 3), les nouveaux pods restent en attente et notre temps de r\u00e9ponse augmente \u00e0 nouveau.<\/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. Mise \u00e0 l'\u00e9chelle automatique verticale<\/h3><\/div><div class=\"fusion-text fusion-text-22\"><p>Dans une telle situation, nous pouvons explorer une autre fonctionnalit\u00e9 de Kubernetes connue sous le nom de\u00a0<strong>mise \u00e0 l'\u00e9chelle automatique verticale\u00a0<\/strong>qui consiste \u00e0 allouer plus de n\u0153uds chaque fois que cela est n\u00e9cessaire. Cette fonctionnalit\u00e9 peut \u00eatre activ\u00e9e \u00e0 l'aide de la commande suivante qui sp\u00e9cifie le nombre de n\u0153uds minimum et maximum que Kubernetes peut allouer.<\/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>Enfin, dans cette derni\u00e8re exp\u00e9rience r\u00e9sum\u00e9e dans le graphique ci-dessous, l'activation de la fonction d'auto-scaling vertical a permis \u00e0 Kubernetes d'ajouter automatiquement deux nouveaux n\u0153uds et de cr\u00e9er de nouveaux pods pour r\u00e9partir la charge et garantir un temps de r\u00e9ponse plus faible. En fait, il a fallu environ 1 minute \u00e0 Kubernetes pour d\u00e9tecter le besoin et cr\u00e9er les ressources (phase 2). De plus, avec une charge plus faible (phase 3), Kubernetes a r\u00e9ussi \u00e0 lib\u00e9rer les deux nouveaux n\u0153uds en tuant les pods et \u00e0 r\u00e9duire le cluster \u00e0 un minimum de trois n\u0153uds en 15 minutes environ.<\/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. Estimation de la taille des grappes<\/h3><\/div><div class=\"fusion-text fusion-text-23\"><p>Maintenant que nous avons compris comment Kubernetes se comporte en r\u00e9ponse \u00e0 diff\u00e9rents niveaux de charge en utilisant les fonctionnalit\u00e9s d'auto-scaling vertical et horizontal, l'\u00e9tape ultime consiste \u00e0 effectuer des tests de performance avec diff\u00e9rentes ressources, en tenant compte des exigences de notre application et de l'estimation du nombre de ses utilisateurs. Imaginons que, pour satisfaire aux exigences de notre accord de niveau de service, notre temps de r\u00e9ponse au 95e percentile doit \u00eatre inf\u00e9rieur \u00e0 1 seconde. Dans ce cas, nous pouvons tracer le graphique ci-dessous montrant le temps de r\u00e9ponse de l'API pour diff\u00e9rents nombres de c\u0153urs et nous faire une id\u00e9e de la performance de notre application dans diff\u00e9rentes conditions.<\/p>\n<p>En particulier, pour notre mod\u00e8le ML servi avec Mlflow, nous pouvons avoir environ 120 utilisateurs simultan\u00e9s sur un cluster Kubernetes de 12 c\u0153urs et garantir un temps de r\u00e9ponse inf\u00e9rieur \u00e0 1 seconde.<\/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;\">Conclusion<\/h2><\/div><div class=\"fusion-text fusion-text-24\"><p>Dans cette s\u00e9rie d'articles, nous avons parcouru l'ensemble du processus de d\u00e9ploiement de l'instance de suivi de Mlflow et de service d'un mod\u00e8le en tant qu'API sur le moteur Kubernetes en tirant parti de sa capacit\u00e9 \u00e0 s'adapter facilement et \u00e0 g\u00e9rer des charges \u00e9lev\u00e9es. Nous avons \u00e9galement exp\u00e9riment\u00e9 deux fonctionnalit\u00e9s int\u00e9ressantes offertes par Kubernetes, \u00e0 savoir l'auto-scaling horizontal et vertical, et nous avons montr\u00e9 qu'il est toujours int\u00e9ressant de surveiller nos ressources pour s'assurer que nous les utilisons de mani\u00e8re efficace. Enfin, nous avons montr\u00e9 comment nous pouvions tester notre application et prendre des d\u00e9cisions concernant l'infrastructure en fonction de sa r\u00e9ponse \u00e0 diff\u00e9rents sc\u00e9narios de test.<\/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=\"moyen\" 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;\">Moyen Blog par Artefact.<\/h3><\/div><div class=\"fusion-text fusion-text-25\" style=\"--awb-content-alignment:center;\"><p>Cet article a \u00e9t\u00e9 initialement publi\u00e9 sur <strong>Medium.com<\/strong>.<br \/>\nSuivez-nous sur notre 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\">Lire notre article<\/span><\/a><\/div><\/div><\/div><\/div><\/div><\/p>","protected":false},"excerpt":{"rendered":"<p>Cet article est la troisi\u00e8me partie d'une s\u00e9rie dans laquelle nous passons en revue le processus de journalisation des mod\u00e8les \u00e0 l'aide de Mlflow, de les servir sur le moteur Kubernetes et enfin de les mettre \u00e0 l'\u00e9chelle en fonction des besoins de notre application. Bien que cet article puisse \u00eatre utilis\u00e9 ind\u00e9pendamment pour tester n'importe quelle r\u00e9ponse d'API, nous vous recommandons de lire nos deux articles pr\u00e9c\u00e9dents (partie 1 et partie 2) sur la fa\u00e7on de d\u00e9ployer une instance de suivi et de servir un mod\u00e8le en tant qu'API avec Mlflow. Dans la suite de cet article, nous nous int\u00e9resserons \u00e0 la question de la scalabilit\u00e9 et nous l'aborderons avec quelques exp\u00e9riences pour comprendre le comportement du cluster k8s et donner des recommandations sur la fa\u00e7on de g\u00e9rer des charges \u00e9lev\u00e9es.<\/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\/fr\/wp-json\/wp\/v2\/blog\/64449","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.artefact.com\/fr\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.artefact.com\/fr\/wp-json\/wp\/v2\/types\/blog"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.artefact.com\/fr\/wp-json\/wp\/v2\/media\/68688"}],"wp:attachment":[{"href":"https:\/\/www.artefact.com\/fr\/wp-json\/wp\/v2\/media?parent=64449"}],"wp:term":[{"taxonomy":"blog-category","embeddable":true,"href":"https:\/\/www.artefact.com\/fr\/wp-json\/wp\/v2\/blog-category?post=64449"},{"taxonomy":"blog-language","embeddable":true,"href":"https:\/\/www.artefact.com\/fr\/wp-json\/wp\/v2\/blog-language?post=64449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}