[{"data":1,"prerenderedAt":691},["ShallowReactive",2],{"/fr-fr/blog/kubernetes-overview-operate-cluster-data-on-the-frontend":3,"navigation-fr-fr":27,"banner-fr-fr":446,"footer-fr-fr":459,"":670,"next-steps-fr-fr":671,"footer-source-/fr-fr/blog/kubernetes-overview-operate-cluster-data-on-the-frontend/":686},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":13,"config":17,"_id":20,"_type":21,"title":22,"_source":23,"_file":24,"_stem":25,"_extension":26},"/fr-fr/blog/kubernetes-overview-operate-cluster-data-on-the-frontend","blog",false,"",{"config":9,"title":10,"description":11,"ogImage":12},{"noIndex":6},"Kubernetes : gérer les données du cluster côté frontend","Découvrez dans ce guide tout ce que vous devez savoir sur la solution intégrée de GitLab pour surveiller l'état de vos clusters Kubernetes.","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1750099045/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2816%29_3L7ZP4GxJrShu6qImuS4Wo_1750099045397.png",{"title":10,"description":11,"heroImage":12,"date":14,"body":15,"category":16},"2025-10-13","Un accès aux informations relatives au cluster en temps réel est essentiel pour vérifier le succès des déploiements logiciels et lancer les processus de dépannage. Dans cet article, vous découvrirez l'intégration Kubernetes améliorée de GitLab et notamment comment exploiter l'API Watch pour obtenir des informations en temps réel sur l'état des déploiements et les fonctionnalités de dépannage optimisées.\n\n\n## Quelles sont les ressources Kubernetes de GitLab ?\n\n\nGitLab propose un [tableau de bord](https://gitlab.com/groups/gitlab-org/-/epics/2493 \"Afficher l'état des cluster dans GitLab\") dédié à [Kubernetes](https://about.gitlab.com/fr-fr/blog/kubernetes-the-container-orchestration-solution/ \"Qu'est-ce que Kubernetes ?\") afin de mieux visualiser l'état des clusters connectés grâce à une interface intuitive. Intégré à la page Détails de l'environnement, il permet d'afficher les ressources pertinentes de l'environnement.\n\n\nTrois types de ressources Kubernetes sont actuellement disponibles :\n\n* Les pods filtrés par espace de nommage Kubernetes\n* Les services\n* Les ressources Flux ([HelmRelease](https://fluxcd.io/flux/components/helm/helmreleases/) ou [Kustomization](https://fluxcd.io/flux/components/kustomize/kustomizations/))\n\n\nNous fournissons des informations générales telles que le nom, le statut, l'espace de nommage, l'âge, etc., pour ces ressources. Les données sont présentées de manière similaire à ce que la commande [kubectl](https://kubernetes.io/docs/reference/kubectl/) afficherait lorsqu'elle est exécutée depuis le cluster Kubernetes. Il est possible de cliquer sur n'importe quelle ressource pour obtenir plus de détails. Le panneau latéral affiche la liste des labels, des annotations, le statut détaillé et les informations de spécification présentées sous forme de blocs de code YAML en lecture seule, et diffuse en temps réel les événements Kubernetes filtrés pour cette ressource spécifique. En ce qui concerne les pods, les utilisateurs peuvent accéder à une vue dédiée des logs et sélectionner un conteneur afin de diffuser ses logs en temps réel et d'obtenir des informations cruciales pour le débogage.\n\n\nLes informations fournies aident à visualiser l'état du cluster, à repérer d'éventuels problèmes et à déboguer immédiatement les déploiements problématiques. Les utilisateurs peuvent également agir immédiatement (supprimer les pods en échec, déclencher la réconciliation Flux ou suspendre/reprendre la synchronisation), le tout depuis la même interface sans avoir besoin de basculer vers des outils en ligne de commande.\n\n\n## Communication frontend-cluster : la solution GitLab\n\n\nNous avons développé une gamme d'outils et de solutions pour garantir une connexion et une gestion fluides des clusters Kubernetes dans GitLab. L'[agent GitLab pour Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/install/) est l'un des principaux composants de ce système et offre une connexion bidirectionnelle sécurisée entre une instance GitLab et un cluster Kubernetes. Cet outil puissant est composé de deux composants clés : **agentk** et **KAS** (GitLab Agent Server for Kubernetes).\n\n\n![Graphique du flux Kubernetes](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099055229.png)\n\n\nagentk est un composant léger côté cluster qui établit une connexion à une instance KAS et attend les requêtes à traiter. Il sert de proxy pour les requêtes KAS vers l'API Kubernetes. Il peut également envoyer activement des informations sur les événements du cluster à KAS.\n\n\nAlors qu'agentk communique activement avec le cluster, KAS est un composant côté serveur GitLab qui :\n\n\n* Accepte les requêtes d'agentk\n\n* Authentifie les requêtes d'agentk en interrogeant le backend GitLab\n\n* Récupère la configuration de l'agent depuis un dépôt [Git](https://about.gitlab.com/fr-fr/blog/what-is-git/ \"Qu'est-ce que Git ?\") correspondant en utilisant Gitaly\n\n* Interroge les dépôts de manifestes pour la prise en charge de [GitOps](https://about.gitlab.com/fr-fr/topics/gitops/ \"Qu'est-ce que Gitops ?\")\n\n\nNous avons implémenté la fonctionnalité relative aux droits d'accès de l'agent pour fournir un accès du frontend GitLab au cluster de manière sécurisée et fiable. Pour activer cette fonctionnalité, l'utilisateur doit mettre à jour le fichier de configuration de l'agent en ajoutant la section [user_access](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html) avec les paramètres `projects`, `groups` et `access_as` afin de préciser les projets qui peuvent accéder aux informations du cluster via l'agent et la manière dont il doit s'authentifier.\n\n\nLe frontend peut ensuite se connecter au cluster en envoyant une requête au contrôleur Rails, qui doit définir un cookie `gitlab_kas`. Ce cookie est ensuite ajouté à la requête envoyée à KAS avec l'ID de l'agent et le token Cross-Site Request Forgery (CSRF). À la réception de la requête, KAS vérifie l'autorisation de l'utilisateur et la transmet à agentk, qui effectue une requête réelle à l'API Kubernetes. Ensuite, la réponse remonte et passe par agentk et KAS avant de finalement arriver au client GitLab.\n\n\n![Aperçu du fonctionnement de Kubernetes overview](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099055229.png)\n\n\nPour intégrer cette logique dans le frontend GitLab et l'utiliser dans l'application Vue, nous avons développé une bibliothèque JavaScript ([@gitlab/cluster-client](https://gitlab.com/gitlab-org/cluster-integration/javascript-client)) générée à partir de la spécification OpenAPI Kubernetes au moyen du générateur typescript-fetch. Elle fournit toutes les API Kubernetes qui peuvent être utilisées dans un navigateur web, ainsi que notre classe `WebSocketWatchManager` qui gère l'API Watch Aggregator et fournit des mises à jour efficaces en temps réel.\n\n\n## Présentation de l'API Watch\n\n\nLes **mises à jour en temps réel** représentent le défi le plus important du tableau de bord Kubernetes. Dans Kubernetes, le concept de commandes watch est une extension des requêtes GET qui permet d'afficher le contenu du corps sous forme de [flux lisible](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams). Une fois connecté au flux, l'API Kubernetes transmet les mises à jour de l'état du cluster de manière similaire à la commande `kubectl get \u003Cresource> --watch`. Le mécanisme de surveillance permet au client de récupérer l'état actuel de la ressource (ou de la liste de ressources) puis de s'abonner aux changements ultérieurs afin de ne rien manquer. Chaque événement contient un type de modification (ajout, modification ou suppression) et l'objet concerné.\n\n\nAu sein de la classe `WatchApi` de la bibliothèque `@gitlab/cluster-client`, nous avons développé une approche systématique pour interagir avec l'API Kubernetes, qui consiste à récupérer un flux continu de données, à le traiter ligne par ligne et à gérer les événements en fonction de leurs types. Explorons les principaux composants et fonctionnalités de cette approche :\n\n\n1. Extension de l'API Kubernetes : au sein de la classe `WatchApi`, nous étendons les fonctionnalités de base de l'API Kubernetes pour récupérer un flux continu de données avec un chemin et des paramètres de requête spécifiés. Cette extension permet une gestion efficace des grands ensembles de données, car le flux est traité ligne par ligne.\n\n2. Décodage et catégorisation des événements : à la réception du flux, chaque ligne, qui représente généralement un objet JSON, est décodée. Ce processus extrait les informations pertinentes et catégorise les événements en fonction de leurs types.\n\n3. Gestion interne des données : la classe `WatchApi` maintient un tableau de données interne pour indiquer l'état actuel des données diffusées. Elle le met à jour en conséquence à mesure que de nouvelles données arrivent ou que des modifications se produisent.\n\n4. Enregistrement d'écouteurs d'événements : la classe `WatchApi` implémente des méthodes pour enregistrer des écouteurs d'événements, tels que `onData`, `onError`, `onTimeout`, et `onTerminate`. Ces méthodes permettent aux équipes de développement de personnaliser la réponse de leur application aux événements tels que les mises à jour de données, les erreurs et les délais d'attente dépassés.\n\n\nLe code gère également des scénarios tels que les types de contenu non valides, les délais d'attente dépassés et les erreurs du serveur, pour lesquels il émet des événements correspondants afin que les clients puissent les traiter de manière appropriée. **Cette approche simple et axée sur les événements de la classe `WatchApi` permet aux équipes de développement de créer en toute efficacité des applications réactives en temps réel.**\n\n\n![Aperçu du flux Kubernetes overview](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099055231.png)\n\n\n## Évolution vers l'agrégation WebSocket\n\n\nNous nous sommes basés sur l'API Watch et avons introduit le `WebSocketWatchManager` pour répondre aux limitations des flux lisibles : le sous-protocole WebSocket `gitlab-agent-watch-api` agrège plusieurs commandes watch de ressources au sein d'une seule connexion persistante. \n\n\nCette approche apporte plusieurs améliorations :\n\n\n* **Plusieurs commandes watch via une connexion unique :** au lieu d'ouvrir des flux HTTP séparés pour chaque ressource Kubernetes, elles partagent toutes une seule connexion WebSocket. Les problèmes de connexion côté client et serveur sont ainsi considérablement réduits, un aspect particulièrement important lors de la surveillance de nombreuses ressources dans différents espaces de nommage.\n\n* **Gestion dynamique des commandes watch :** le protocole prend en charge le démarrage et l'arrêt de commandes watch individuelles à la demande via des messages `watch` et `unwatch`. La fonctionnalité `unwatch` n'est pas encore implémentée dans le client JavaScript, mais une fois ajoutée, elle arrêtera les commandes watch inutiles lorsque les utilisateurs quittent les vues de ressources.\n\n* **Connexions plus fiables :** les connexions WebSocket maintiennent des sessions stables et durables sans les interruptions imprévisibles que nous avons rencontrées avec le streaming basé sur HTTP de l'API Watch. Ces connexions de streaming s'interrompaient parfois de manière inattendue, nécessitaient une logique de reconnexion et risquaient potentiellement de manquer des événements pendant la fenêtre de reconnexion.\n\n\nLors de l'établissement d'une connexion, le client doit d'abord demander un token d'authentification, car les connexions WebSocket ne peuvent pas envoyer d'en-têtes personnalisés (comme les tokens CSRF ou les cookies) après la communication initiale. Ce token, obtenu via une requête HTTP standard avec des en-têtes d'authentification complets, est ensuite intégré dans l'en-tête du sous-protocole WebSocket lors de l'établissement de la connexion. Une fois connecté au point de terminaison `/watch`, le client démarre des commandes watch individuelles en envoyant des messages avec des paramètres de ressource, et le serveur renvoie en continu les événements watch à mesure que les ressources Kubernetes changent.\n\n\nLe système revient à l'implémentation `WatchApi` d'origine lorsque les connexions WebSocket échouent pour une raison quelconque, que ce soit en raison de limitations d'infrastructure réseau, d'échecs de connexion ou de problèmes d'authentification. Cette double approche offre les avantages de performance WebSocket lorsque ceux-ci sont disponibles et maintient une fonctionnalité complète grâce à la méthode de streaming de l'API Watch si nécessaire. Le basculement se fait automatiquement et garantit une fonctionnalité en temps réel et cohérente qui ne requiert aucune connaissance ni intervention de l'utilisateur.\n\n\n## Comment la vue d'ensemble Kubernetes est-elle intégrée au frontend GitLab ?\n\n\nNous avons actuellement deux intégrations Kubernetes dans le produit : la section Vue d'ensemble Kubernetes pour les Environnements et le tableau de bord Kubernetes complet comme vue séparée. Ce dernier représente le fruit de nos efforts en vue d'afficher toutes les ressources Kubernetes disponibles avec des fonctionnalités de filtrage et de tri, et une vue détaillée avec des informations complètes sur les métadonnées, les spécifications et le statut de la ressource. Ce projet est actuellement en pause, car nous sommes en train d'explorer comment afficher les ressources Kubernetes liées à un environnement de la façon la plus utile possible.\n\n\nLa [vue d'ensemble Kubernetes](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html) sur la page Environnements représente une vue détaillée des ressources Kubernetes liées à un environnement spécifique. Pour accéder à la vue de l'état du cluster, l'utilisateur doit sélectionner un agent installé dans le cluster avec les droits d'accès appropriés, fournir un espace de nommage (facultatif) et sélectionner une ressource Flux associée.\n\n\nLa vue affiche une liste de pods et de services Kubernetes filtrés par l'espace de nommage avec leurs statuts et le statut de synchronisation Flux. Cliquer sur chaque ressource ouvre une vue détaillée avec plus d'informations pour faciliter la détection des problèmes et le débogage de haut niveau.\n\n\n![Aperçu de Kubernetes, liste des pods et services Kubernetes](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099055233.png)\n\n\nNous devons paramétrer un objet de configuration correct qui sera utilisé pour toutes les requêtes API. Dans la configuration, nous devons préciser l'URL fournie par le KAS, qui sert de proxy pour les API Kubernetes, l'ID de l'agent GitLab auquel se connecter et le token CSRF. Nous devons inclure les cookies pour que le `kas_cookie` soit récupéré et envoyé dans la requête.\n\n\n```javascript\n\ncreateK8sAccessConfig({ kasTunnelUrl, gitlabAgentId }) {\n  return {\n    basePath: kasTunnelUrl,\n    headers: {\n      'GitLab-Agent-Id': gitlabAgentId,\n      ...csrf.headers,\n    },\n    credentials: 'include',\n  };\n}\n\n```\n\n\nCet objet de configuration sert de base pour toutes les interactions avec l'API Kubernetes via KAS, que ce soit en utilisant des appels API standard, le streaming de l'API Watch ou les connexions WebSocket. Chaque méthode de connexion s'appuie sur cette configuration de base avec ses exigences spécifiques.\n\n\nToutes les requêtes API sont implémentées sous forme de requêtes client GraphQL pour une meilleure efficacité, flexibilité et facilité de développement. La structure de requête permet aux clients de récupérer des données provenant de diverses sources en une seule requête. Grâce à des définitions de schéma claires, GraphQL minimise les erreurs et renforce l'efficacité des équipes de développement. L'implémentation WebSocket complète cette approche avec une gestion des mises à jour en temps réel via une connexion unique persistante, ce qui réduit le besoin de multiples connexions de streaming parallèles et maintient la même structure de requête GraphQL pour les mises à jour de données.\n\n\nLors du premier affichage de la vue d'ensemble Kubernetes, le frontend demande des listes statiques de pods, services et ressources Flux (HelmRelease ou Kustomization). La requête de récupération est nécessaire pour afficher correctement la vue vide. Si le frontend essayait de s'abonner au flux de l'API Watch et qu'une des listes de ressources était vide, il faudrait alors attendre les mises à jour indéfiniment, et le résultat réel, soit 0 ressource, ne serait jamais affiché. Dans le cas des pods et services, après la requête initiale, nous nous abonnons au flux même si une liste vide a été reçue afin de refléter tout changement d'état du cluster. En ce qui concerne la ressource Flux, la probabilité que l'utilisateur s'attende à ce qu'une ressource apparaisse après la requête initiale est faible. Nous utilisons la réponse vide ici en vue de fournir plus d'informations sur la fonctionnalité et sa configuration.\n\n\n![Aperçu de Kubernetes, synchronisation du statut du flux non disponible](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099055235.png)\n\n\nAprès avoir affiché le résultat initial, le frontend établit des connexions en temps réel pour surveiller les changements. L'implémentation tente d'abord la connexion WebSocket et se rabat sur le streaming de l'API Watch lorsqu'elle n'est pas disponible. Avec les connexions WebSocket, une seule connexion gère toutes les commandes watch de ressources, maintient des flux internes pour chaque ressource et les met à jour en fonction des événements entrants (`ADDED`, `MODIFIED`, `DELETED`). En mode de solution alternative API Watch, le frontend effectue des requêtes avec le paramètre de requête `?watch=true` et crée des watchers séparés pour chaque type d'événement :\n\n\n```javascript\n\nwatcher.on(EVENT_DATA, (data) => {\n  result = data.map(mapWorkloadItem);\n  client.writeQuery({\n    query,\n    variables: { configuration, namespace },\n    data: { [queryField]: result },\n  });\n\n  updateConnectionStatus(client, {\n    configuration,\n    namespace,\n    resourceType: queryField,\n    status: connectionStatus.connected,\n  });\n});\n\n```\n\n\nLes deux approches suivent le même modèle de traitement des données :\n\n\n* Transformer les données pour assurer une structure cohérente\n\n* Mettre à jour le cache Apollo pour déclencher les mises à jour de l'interface utilisateur\n\n* Exécuter une mutation pour mettre à jour l'indicateur d'état de connexion\n\n\nÉtant donné que les informations détaillées sont affichées pour chaque ressource, nous devons pouvoir consulter les champs statut, spécifications et métadonnées avec annotations et labels. L'API Kubernetes n'envoie pas toujours ces informations, ce qui pourrait mettre à mal l'interface utilisateur et générer des erreurs du client GraphQL. Il faut d'abord transformer les données reçues pour éviter ces problèmes, et ajouter `__typename` afin de mieux définir les types de données et simplifier les requêtes en réutilisant les fragments partagés.\n\n\nAprès la stabilisation des données, nous mettons à jour le cache Apollo pour que le frontend puisse afficher de nouveau les vues afin de refléter les changements d'état du cluster. Il est intéressant de constater que nous pouvons visualiser exactement ce qui se passe dans le cluster : par exemple, lors de la suppression des pods, Kubernetes en crée de nouveaux avec un état en attente, puis il supprime les anciens pods. Ainsi, il est possible de voir deux fois plus de pods qu'escompté pendant un bref instant. Nous pouvons également vérifier comment les pods passent d'un état à un autre en temps réel. Pour ce faire, il nous suffit de combiner les événements ajoutés, supprimés et modifiés reçus des API Kubernetes et traités soit par le `WebSocketWatchManager`, soit par la classe `WatchApi` de la bibliothèque `@gitlab/cluster-client`.\n\n\n![Aperçu de Kubernetes, états des statuts de connexion](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099055236.gif)\n\n\nL'indicateur d'état de connexion est un élément important pour les deux types de connexion, bien que pour des raisons différentes. Même si les connexions WebSocket sont plus stables et durables, les utilisateurs doivent pouvoir savoir si la connexion est interrompue en raison de problèmes réseau ou d'authentifications expirées. Avec le streaming de l'API Watch, les connexions ont des limitations dues aux délais d'attente dépassés et sont davantage sujettes à la déconnexion. Pour obtenir une meilleure visibilité à ce sujet, nous avons introduit une requête `k8sConnection` avec la mutation `reconnectToCluster`. L'interface utilisateur affiche un badge avec une infobulle qui indique trois états de connexion :\n\n\n* Connexion en cours : défini lors de l'initiation de l'une ou l'autre connexion\n\n* Connecté : mis à jour lorsque les premières données arrivent via l'une ou l'autre connexion\n\n* Déconnecté : déclenché en cas d'échec de connexion WebSocket, d'expiration des flux API Watch, ou d'erreur de connexion\n\n\nEn cas de déconnexion, les utilisateurs peuvent cliquer pour se reconnecter sans actualiser le navigateur. En comptant sur l'utilisateur pour se reconnecter au flux, nous pouvons économiser des ressources et ne demander que les données nécessaires tout en garantissant que l'état précis du cluster est disponible pour l'utilisateur à tout moment.\n\n\n## Et maintenant ? \n\n\nLa fonctionnalité intégrée de Kubernetes pour surveiller le flux lisible nous a aidés à développer rapidement cette fonctionnalité et à fournir une solution d'interface utilisateur Kubernetes à nos clients, à obtenir des retours précoces et à ajuster le produit. Bien que l'approche initiale de l'API Watch présente des défis comme les délais d'attente dépassés de connexion et les besoins de reconnexion, elle nous a donné des informations précieuses sur les modèles d'utilisation réels. L'implémentation WebSocket a résolu bon nombre de ces défis initiaux et a offert des connexions plus stables ainsi qu'une meilleure efficacité des ressources grâce aux commandes watch multiplexées. Les deux approches API Watch et WebSocket continueront d'évoluer en fonction des besoins des utilisateurs.\n\n\nIl existe des solutions qui pourraient améliorer davantage l'expérience utilisateur. Le protocole WebSocket prend déjà en charge les messages `unwatch` pour la gestion dynamique des commandes watch, même s'il n'est pas encore implémenté dans le client JavaScript. Une gestion des erreurs plus complète et la prise en charge de types de ressources Kubernetes supplémentaires pourraient également renforcer les fonctionnalités du tableau de bord.\n\n\n> Vous souhaitez contribuer à la fonctionnalité du tableau de bord Kubernetes, explorer les possibilités d'amélioration ou partager vos cas d'utilisation ? Partagez vos retours dans notre [epic Tableau de bord Kubernetes](https://gitlab.com/groups/gitlab-org/-/epics/2493).\n","engineering",{"featured":6,"template":18,"slug":19},"BlogPost","kubernetes-overview-operate-cluster-data-on-the-frontend","content:fr-fr:blog:kubernetes-overview-operate-cluster-data-on-the-frontend.yml","yaml","Kubernetes Overview Operate Cluster Data On The Frontend","content","fr-fr/blog/kubernetes-overview-operate-cluster-data-on-the-frontend.yml","fr-fr/blog/kubernetes-overview-operate-cluster-data-on-the-frontend","yml",{"_path":28,"_dir":29,"_draft":6,"_partial":6,"_locale":7,"data":30,"_id":442,"_type":21,"title":443,"_source":23,"_file":444,"_stem":445,"_extension":26},"/shared/fr-fr/main-navigation","fr-fr",{"logo":31,"freeTrial":36,"sales":41,"login":46,"items":51,"search":383,"minimal":419,"duo":433},{"config":32},{"href":33,"dataGaName":34,"dataGaLocation":35},"/fr-fr/","gitlab logo","header",{"text":37,"config":38},"Commencer un essai gratuit",{"href":39,"dataGaName":40,"dataGaLocation":35},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":42,"config":43},"Contacter l'équipe commerciale",{"href":44,"dataGaName":45,"dataGaLocation":35},"/fr-fr/sales/","sales",{"text":47,"config":48},"Connexion",{"href":49,"dataGaName":50,"dataGaLocation":35},"https://gitlab.com/users/sign_in/","sign in",[52,96,194,199,304,364],{"text":53,"config":54,"cards":56,"footer":79},"Plateforme",{"dataNavLevelOne":55},"platform",[57,63,71],{"title":53,"description":58,"link":59},"La plateforme DevSecOps alimentée par l'IA la plus complète",{"text":60,"config":61},"Découvrir notre plateforme",{"href":62,"dataGaName":55,"dataGaLocation":35},"/fr-fr/platform/",{"title":64,"description":65,"link":66},"GitLab Duo (IA)","Créez des logiciels plus rapidement en tirant parti de l'IA à chaque étape du développement",{"text":67,"config":68},"Découvrez GitLab Duo",{"href":69,"dataGaName":70,"dataGaLocation":35},"/fr-fr/gitlab-duo/","gitlab duo ai",{"title":72,"description":73,"link":74},"Choisir GitLab","10 raisons pour lesquelles les entreprises choisissent GitLab",{"text":75,"config":76},"En savoir plus",{"href":77,"dataGaName":78,"dataGaLocation":35},"/fr-fr/why-gitlab/","why gitlab",{"title":80,"items":81},"Démarrer avec",[82,87,92],{"text":83,"config":84},"Ingénierie de plateforme",{"href":85,"dataGaName":86,"dataGaLocation":35},"/fr-fr/solutions/platform-engineering/","platform engineering",{"text":88,"config":89},"Expérience développeur",{"href":90,"dataGaName":91,"dataGaLocation":35},"/fr-fr/developer-experience/","Developer experience",{"text":93,"config":94},"MLOps",{"href":95,"dataGaName":93,"dataGaLocation":35},"/fr-fr/topics/devops/the-role-of-ai-in-devops/",{"text":97,"left":98,"config":99,"link":101,"lists":105,"footer":176},"Produit",true,{"dataNavLevelOne":100},"solutions",{"text":102,"config":103},"Voir toutes les solutions",{"href":104,"dataGaName":100,"dataGaLocation":35},"/fr-fr/solutions/",[106,132,154],{"title":107,"description":108,"link":109,"items":114},"Automatisation","CI/CD et automatisation pour accélérer le déploiement",{"config":110},{"icon":111,"href":112,"dataGaName":113,"dataGaLocation":35},"AutomatedCodeAlt","/fr-fr/solutions/delivery-automation/","automated software delivery",[115,119,123,128],{"text":116,"config":117},"CI/CD",{"href":118,"dataGaLocation":35,"dataGaName":116},"/fr-fr/solutions/continuous-integration/",{"text":120,"config":121},"Développement assisté par l'IA",{"href":69,"dataGaLocation":35,"dataGaName":122},"AI assisted development",{"text":124,"config":125},"Gestion du code source",{"href":126,"dataGaLocation":35,"dataGaName":127},"/fr-fr/solutions/source-code-management/","Source Code Management",{"text":129,"config":130},"Livraison de logiciels automatisée",{"href":112,"dataGaLocation":35,"dataGaName":131},"Automated software delivery",{"title":133,"description":134,"link":135,"items":140},"Securité","Livrez du code plus rapidement sans compromettre la sécurité",{"config":136},{"href":137,"dataGaName":138,"dataGaLocation":35,"icon":139},"/fr-fr/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[141,145,150],{"text":142,"config":143},"Application Security Testing",{"href":137,"dataGaName":144,"dataGaLocation":35},"Application security testing",{"text":146,"config":147},"Sécurité de la chaîne d'approvisionnement logicielle",{"href":148,"dataGaLocation":35,"dataGaName":149},"/fr-fr/solutions/supply-chain/","Software supply chain security",{"text":151,"config":152},"Software Compliance",{"href":153,"dataGaName":151,"dataGaLocation":35},"/fr-fr/solutions/software-compliance/",{"title":155,"link":156,"items":161},"Mesures",{"config":157},{"icon":158,"href":159,"dataGaName":160,"dataGaLocation":35},"DigitalTransformation","/fr-fr/solutions/visibility-measurement/","visibility and measurement",[162,166,171],{"text":163,"config":164},"Visibilité et mesures",{"href":159,"dataGaLocation":35,"dataGaName":165},"Visibility and Measurement",{"text":167,"config":168},"Gestion de la chaîne de valeur",{"href":169,"dataGaLocation":35,"dataGaName":170},"/fr-fr/solutions/value-stream-management/","Value Stream Management",{"text":172,"config":173},"Données d'analyse et informations clés",{"href":174,"dataGaLocation":35,"dataGaName":175},"/fr-fr/solutions/analytics-and-insights/","Analytics and insights",{"title":177,"items":178},"GitLab pour",[179,184,189],{"text":180,"config":181},"Entreprises",{"href":182,"dataGaLocation":35,"dataGaName":183},"/fr-fr/enterprise/","enterprise",{"text":185,"config":186},"PME",{"href":187,"dataGaLocation":35,"dataGaName":188},"/fr-fr/small-business/","small business",{"text":190,"config":191},"Secteur public",{"href":192,"dataGaLocation":35,"dataGaName":193},"/fr-fr/solutions/public-sector/","public sector",{"text":195,"config":196},"Tarifs",{"href":197,"dataGaName":198,"dataGaLocation":35,"dataNavLevelOne":198},"/fr-fr/pricing/","pricing",{"text":200,"config":201,"link":203,"lists":207,"feature":291},"Ressources",{"dataNavLevelOne":202},"resources",{"text":204,"config":205},"Afficher toutes les ressources",{"href":206,"dataGaName":202,"dataGaLocation":35},"/fr-fr/resources/",[208,241,263],{"title":209,"items":210},"Premiers pas",[211,216,221,226,231,236],{"text":212,"config":213},"Installation",{"href":214,"dataGaName":215,"dataGaLocation":35},"/fr-fr/install/","install",{"text":217,"config":218},"Guides de démarrage rapide",{"href":219,"dataGaName":220,"dataGaLocation":35},"/fr-fr/get-started/","quick setup checklists",{"text":222,"config":223},"Apprentissage",{"href":224,"dataGaLocation":35,"dataGaName":225},"https://university.gitlab.com/","learn",{"text":227,"config":228},"Documentation sur le produit",{"href":229,"dataGaName":230,"dataGaLocation":35},"https://docs.gitlab.com/","product documentation",{"text":232,"config":233},"Vidéos sur les bonnes pratiques",{"href":234,"dataGaName":235,"dataGaLocation":35},"/fr-fr/getting-started-videos/","best practice videos",{"text":237,"config":238},"Intégrations",{"href":239,"dataGaName":240,"dataGaLocation":35},"/fr-fr/integrations/","integrations",{"title":242,"items":243},"Découvrir",[244,249,253,258],{"text":245,"config":246},"Histoires de succès client",{"href":247,"dataGaName":248,"dataGaLocation":35},"/fr-fr/customers/","customer success stories",{"text":250,"config":251},"Blog",{"href":252,"dataGaName":5,"dataGaLocation":35},"/fr-fr/blog/",{"text":254,"config":255},"Travail à distance",{"href":256,"dataGaName":257,"dataGaLocation":35},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":259,"config":260},"TeamOps",{"href":261,"dataGaName":262,"dataGaLocation":35},"/fr-fr/teamops/","teamops",{"title":264,"items":265},"Connecter",[266,271,276,281,286],{"text":267,"config":268},"Services GitLab",{"href":269,"dataGaName":270,"dataGaLocation":35},"/fr-fr/services/","services",{"text":272,"config":273},"Communauté",{"href":274,"dataGaName":275,"dataGaLocation":35},"/community/","community",{"text":277,"config":278},"Forum",{"href":279,"dataGaName":280,"dataGaLocation":35},"https://forum.gitlab.com/","forum",{"text":282,"config":283},"Événements",{"href":284,"dataGaName":285,"dataGaLocation":35},"/events/","events",{"text":287,"config":288},"Partenaires",{"href":289,"dataGaName":290,"dataGaLocation":35},"/fr-fr/partners/","partners",{"backgroundColor":292,"textColor":293,"text":294,"image":295,"link":299},"#2f2a6b","#fff","L'avenir du développement logiciel. Tendances et perspectives.",{"altText":296,"config":297},"carte promo The Source",{"src":298},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":300,"config":301},"Lire les articles les plus récents",{"href":302,"dataGaName":303,"dataGaLocation":35},"/fr-fr/the-source/","the source",{"text":305,"config":306,"lists":308},"Société",{"dataNavLevelOne":307},"company",[309],{"items":310},[311,316,322,324,329,334,339,344,349,354,359],{"text":312,"config":313},"À propos",{"href":314,"dataGaName":315,"dataGaLocation":35},"/fr-fr/company/","about",{"text":317,"config":318,"footerGa":321},"Emplois",{"href":319,"dataGaName":320,"dataGaLocation":35},"/jobs/","jobs",{"dataGaName":320},{"text":282,"config":323},{"href":284,"dataGaName":285,"dataGaLocation":35},{"text":325,"config":326},"Leadership",{"href":327,"dataGaName":328,"dataGaLocation":35},"/company/team/e-group/","leadership",{"text":330,"config":331},"Équipe",{"href":332,"dataGaName":333,"dataGaLocation":35},"/company/team/","team",{"text":335,"config":336},"Manuel",{"href":337,"dataGaName":338,"dataGaLocation":35},"https://handbook.gitlab.com/","handbook",{"text":340,"config":341},"Relations avec les investisseurs",{"href":342,"dataGaName":343,"dataGaLocation":35},"https://ir.gitlab.com/","investor relations",{"text":345,"config":346},"Centre de confiance",{"href":347,"dataGaName":348,"dataGaLocation":35},"/fr-fr/security/","trust center",{"text":350,"config":351},"Centre pour la transparence de l'IA",{"href":352,"dataGaName":353,"dataGaLocation":35},"/fr-fr/ai-transparency-center/","ai transparency center",{"text":355,"config":356},"Newsletter",{"href":357,"dataGaName":358,"dataGaLocation":35},"/company/contact/","newsletter",{"text":360,"config":361},"Presse",{"href":362,"dataGaName":363,"dataGaLocation":35},"/press/","press",{"text":365,"config":366,"lists":367},"Nous contacter",{"dataNavLevelOne":307},[368],{"items":369},[370,373,378],{"text":42,"config":371},{"href":44,"dataGaName":372,"dataGaLocation":35},"talk to sales",{"text":374,"config":375},"Aide",{"href":376,"dataGaName":377,"dataGaLocation":35},"/support/","get help",{"text":379,"config":380},"Portail clients GitLab",{"href":381,"dataGaName":382,"dataGaLocation":35},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":384,"login":385,"suggestions":392},"Fermer",{"text":386,"link":387},"Pour rechercher des dépôts et des projets, connectez-vous à",{"text":388,"config":389},"gitlab.com",{"href":49,"dataGaName":390,"dataGaLocation":391},"search login","search",{"text":393,"default":394},"Suggestions",[395,398,403,405,410,415],{"text":64,"config":396},{"href":69,"dataGaName":397,"dataGaLocation":391},"GitLab Duo (AI)",{"text":399,"config":400},"Suggestions de code (IA)",{"href":401,"dataGaName":402,"dataGaLocation":391},"/fr-fr/solutions/code-suggestions/","Code Suggestions (AI)",{"text":116,"config":404},{"href":118,"dataGaName":116,"dataGaLocation":391},{"text":406,"config":407},"GitLab sur AWS",{"href":408,"dataGaName":409,"dataGaLocation":391},"/fr-fr/partners/technology-partners/aws/","GitLab on AWS",{"text":411,"config":412},"GitLab sur Google Cloud ",{"href":413,"dataGaName":414,"dataGaLocation":391},"/fr-fr/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":416,"config":417},"Pourquoi utiliser GitLab ?",{"href":77,"dataGaName":418,"dataGaLocation":391},"Why GitLab?",{"freeTrial":420,"mobileIcon":425,"desktopIcon":430},{"text":421,"config":422},"Commencer votre essai gratuit",{"href":423,"dataGaName":40,"dataGaLocation":424},"https://gitlab.com/-/trials/new/","nav",{"altText":426,"config":427},"Icône GitLab",{"src":428,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":426,"config":431},{"src":432,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"freeTrial":434,"mobileIcon":438,"desktopIcon":440},{"text":435,"config":436},"En savoir plus sur GitLab Duo",{"href":69,"dataGaName":437,"dataGaLocation":424},"gitlab duo",{"altText":426,"config":439},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":441},{"src":432,"dataGaName":429,"dataGaLocation":424},"content:shared:fr-fr:main-navigation.yml","Main Navigation","shared/fr-fr/main-navigation.yml","shared/fr-fr/main-navigation",{"_path":447,"_dir":29,"_draft":6,"_partial":6,"_locale":7,"title":448,"titleMobile":448,"button":449,"config":454,"_id":456,"_type":21,"_source":23,"_file":457,"_stem":458,"_extension":26},"/shared/fr-fr/banner","GitLab Duo Agent Platform est maintenant disponible en version bêta publique !",{"text":450,"config":451},"Essayer la version bêta",{"href":452,"dataGaName":453,"dataGaLocation":35},"/fr-fr/gitlab-duo/agent-platform/","duo banner",{"layout":455},"release","content:shared:fr-fr:banner.yml","shared/fr-fr/banner.yml","shared/fr-fr/banner",{"_path":460,"_dir":29,"_draft":6,"_partial":6,"_locale":7,"data":461,"_id":666,"_type":21,"title":667,"_source":23,"_file":668,"_stem":669,"_extension":26},"/shared/fr-fr/main-footer",{"text":462,"source":463,"edit":469,"contribute":474,"config":479,"items":484,"minimal":657},"Git est une marque déposée de Software Freedom Conservancy et notre utilisation de « GitLab » est sous licence",{"text":464,"config":465},"Afficher le code source de la page",{"href":466,"dataGaName":467,"dataGaLocation":468},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":470,"config":471},"Modifier cette page",{"href":472,"dataGaName":473,"dataGaLocation":468},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":475,"config":476},"Veuillez contribuer",{"href":477,"dataGaName":478,"dataGaLocation":468},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":480,"facebook":481,"youtube":482,"linkedin":483},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[485,508,562,594,628],{"title":53,"links":486,"subMenu":491},[487],{"text":488,"config":489},"Plateforme DevSecOps",{"href":62,"dataGaName":490,"dataGaLocation":468},"devsecops platform",[492],{"title":195,"links":493},[494,498,503],{"text":495,"config":496},"Voir les forfaits",{"href":197,"dataGaName":497,"dataGaLocation":468},"view plans",{"text":499,"config":500},"Pourquoi choisir GitLab Premium ?",{"href":501,"dataGaName":502,"dataGaLocation":468},"/fr-fr/pricing/premium/","why premium",{"text":504,"config":505},"Pourquoi choisir GitLab Ultimate ?",{"href":506,"dataGaName":507,"dataGaLocation":468},"/fr-fr/pricing/ultimate/","why ultimate",{"title":509,"links":510},"Solutions",[511,516,519,521,526,531,535,538,541,546,548,550,552,557],{"text":512,"config":513},"Transformation digitale",{"href":514,"dataGaName":515,"dataGaLocation":468},"/fr-fr/topics/digital-transformation/","digital transformation",{"text":517,"config":518},"Sécurité et conformité",{"href":137,"dataGaName":144,"dataGaLocation":468},{"text":129,"config":520},{"href":112,"dataGaName":113,"dataGaLocation":468},{"text":522,"config":523},"Développement agile",{"href":524,"dataGaName":525,"dataGaLocation":468},"/fr-fr/solutions/agile-delivery/","agile delivery",{"text":527,"config":528},"Transformation cloud",{"href":529,"dataGaName":530,"dataGaLocation":468},"/fr-fr/topics/cloud-native/","cloud transformation",{"text":532,"config":533},"SCM",{"href":126,"dataGaName":534,"dataGaLocation":468},"source code management",{"text":116,"config":536},{"href":118,"dataGaName":537,"dataGaLocation":468},"continuous integration & delivery",{"text":167,"config":539},{"href":169,"dataGaName":540,"dataGaLocation":468},"value stream management",{"text":542,"config":543},"GitOps",{"href":544,"dataGaName":545,"dataGaLocation":468},"/fr-fr/solutions/gitops/","gitops",{"text":180,"config":547},{"href":182,"dataGaName":183,"dataGaLocation":468},{"text":185,"config":549},{"href":187,"dataGaName":188,"dataGaLocation":468},{"text":190,"config":551},{"href":192,"dataGaName":193,"dataGaLocation":468},{"text":553,"config":554},"Formation",{"href":555,"dataGaName":556,"dataGaLocation":468},"/fr-fr/solutions/education/","education",{"text":558,"config":559},"Services financiers",{"href":560,"dataGaName":561,"dataGaLocation":468},"/fr-fr/solutions/finance/","financial services",{"title":200,"links":563},[564,566,568,570,573,575,578,580,582,584,586,588,590,592],{"text":212,"config":565},{"href":214,"dataGaName":215,"dataGaLocation":468},{"text":217,"config":567},{"href":219,"dataGaName":220,"dataGaLocation":468},{"text":222,"config":569},{"href":224,"dataGaName":225,"dataGaLocation":468},{"text":227,"config":571},{"href":229,"dataGaName":572,"dataGaLocation":468},"docs",{"text":250,"config":574},{"href":252,"dataGaName":5},{"text":576,"config":577},"Histoires de réussite client",{"href":247,"dataGaLocation":468},{"text":245,"config":579},{"href":247,"dataGaName":248,"dataGaLocation":468},{"text":254,"config":581},{"href":256,"dataGaName":257,"dataGaLocation":468},{"text":267,"config":583},{"href":269,"dataGaName":270,"dataGaLocation":468},{"text":259,"config":585},{"href":261,"dataGaName":262,"dataGaLocation":468},{"text":272,"config":587},{"href":274,"dataGaName":275,"dataGaLocation":468},{"text":277,"config":589},{"href":279,"dataGaName":280,"dataGaLocation":468},{"text":282,"config":591},{"href":284,"dataGaName":285,"dataGaLocation":468},{"text":287,"config":593},{"href":289,"dataGaName":290,"dataGaLocation":468},{"title":305,"links":595},[596,598,600,602,604,606,608,612,617,619,621,623],{"text":312,"config":597},{"href":314,"dataGaName":307,"dataGaLocation":468},{"text":317,"config":599},{"href":319,"dataGaName":320,"dataGaLocation":468},{"text":325,"config":601},{"href":327,"dataGaName":328,"dataGaLocation":468},{"text":330,"config":603},{"href":332,"dataGaName":333,"dataGaLocation":468},{"text":335,"config":605},{"href":337,"dataGaName":338,"dataGaLocation":468},{"text":340,"config":607},{"href":342,"dataGaName":343,"dataGaLocation":468},{"text":609,"config":610},"Sustainability",{"href":611,"dataGaName":609,"dataGaLocation":468},"/sustainability/",{"text":613,"config":614},"Diversité, inclusion et appartenance (DIB)",{"href":615,"dataGaName":616,"dataGaLocation":468},"/fr-fr/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":345,"config":618},{"href":347,"dataGaName":348,"dataGaLocation":468},{"text":355,"config":620},{"href":357,"dataGaName":358,"dataGaLocation":468},{"text":360,"config":622},{"href":362,"dataGaName":363,"dataGaLocation":468},{"text":624,"config":625},"Déclaration de transparence sur l'esclavage moderne",{"href":626,"dataGaName":627,"dataGaLocation":468},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":365,"links":629},[630,633,635,637,642,647,652],{"text":631,"config":632},"Échanger avec un expert",{"href":44,"dataGaName":45,"dataGaLocation":468},{"text":374,"config":634},{"href":376,"dataGaName":377,"dataGaLocation":468},{"text":379,"config":636},{"href":381,"dataGaName":382,"dataGaLocation":468},{"text":638,"config":639},"Statut",{"href":640,"dataGaName":641,"dataGaLocation":468},"https://status.gitlab.com/","status",{"text":643,"config":644},"Conditions d'utilisation",{"href":645,"dataGaName":646},"/terms/","terms of use",{"text":648,"config":649},"Déclaration de confidentialité",{"href":650,"dataGaName":651,"dataGaLocation":468},"/fr-fr/privacy/","privacy statement",{"text":653,"config":654},"Préférences en matière de cookies",{"dataGaName":655,"dataGaLocation":468,"id":656,"isOneTrustButton":98},"cookie preferences","ot-sdk-btn",{"items":658},[659,661,664],{"text":643,"config":660},{"href":645,"dataGaName":646,"dataGaLocation":468},{"text":662,"config":663},"Politique de confidentialité",{"href":650,"dataGaName":651,"dataGaLocation":468},{"text":653,"config":665},{"dataGaName":655,"dataGaLocation":468,"id":656,"isOneTrustButton":98},"content:shared:fr-fr:main-footer.yml","Main Footer","shared/fr-fr/main-footer.yml","shared/fr-fr/main-footer",[],{"_path":672,"_dir":29,"_draft":6,"_partial":6,"_locale":7,"header":673,"eyebrow":674,"blurb":675,"button":676,"secondaryButton":680,"_id":682,"_type":21,"title":683,"_source":23,"_file":684,"_stem":685,"_extension":26},"/shared/fr-fr/next-steps","Commencez à livrer des logiciels de meilleurs qualité plus rapidement","Plus de 50 % des entreprises du classement Fortune 100 font confiance à GitLab","Découvrez comment la plateforme DevSecOps intelligente\n\n\npeut aider votre équipe.\n",{"text":37,"config":677},{"href":678,"dataGaName":40,"dataGaLocation":679},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":42,"config":681},{"href":44,"dataGaName":45,"dataGaLocation":679},"content:shared:fr-fr:next-steps.yml","Next Steps","shared/fr-fr/next-steps.yml","shared/fr-fr/next-steps",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":687,"content":689,"config":690,"_id":20,"_type":21,"title":22,"_source":23,"_file":24,"_stem":25,"_extension":26},{"config":688,"title":10,"description":11,"ogImage":12},{"noIndex":6},{"title":10,"description":11,"heroImage":12,"date":14,"body":15,"category":16},{"featured":6,"template":18,"slug":19},1761814433392]