Aller au contenu principal

Stacks

Une stack regroupe plusieurs services — une application web, un worker, une base de données, un cache — en une seule application multi-services, que vous câblez et déployez d'un bloc. Plutôt que de déployer chaque service à la main et de recopier les identifiants de l'un à l'autre, vous reliez les composants sur un plan de travail visuel et Kuploy injecte les bonnes valeurs, puis déploie le tout dans le bon ordre.

Les stacks sont entièrement natives Kubernetes et réutilisent le moteur de déploiement habituel de Kuploy : chaque composant reste un service ordinaire, si bien que les logs, les domaines, les sauvegardes, la supervision et la facturation continuent de fonctionner exactement comme pour un service isolé.

Les notions​

TermeSignification
StackUn groupe nommé de services, au sein d'un environnement.
ComposantUn service — application ou base de données — qui appartient à une stack. Il reste un service ordinaire.
ConnexionUn lien typé d'un composant fournisseur vers un composant consommateur : une valeur du fournisseur (par exemple une chaîne de connexion à une base) est injectée chez le consommateur sous forme de variable d'environnement — dès que vous la créez, puis réévaluée à chaque déploiement.
Service rattachéUn service qui rend service à une ou plusieurs de vos applications sans appartenir à la stack — aujourd'hui, l'e-mail transactionnel. Il apparaît à côté de la stack, et non dedans. Voir Services rattachés.

Créer une stack​

  1. Ouvrez votre projet, puis un environnement.
  2. Cliquez sur Stacks dans la barre d'outils de l'environnement.
  3. Cliquez sur Create stack, donnez-lui un nom et ouvrez-la.

Ce qui peut être un composant​

Sept types de services peuvent appartenir à une stack :

Application (web, worker ou cron — voir plus bas) · PostgreSQL · MySQL · MariaDB · MongoDB · Redis · Bucket

Tout le reste d'un environnement demeure en dehors de la stack. En particulier, l'e-mail transactionnel et la passerelle de paiement ne sont pas des composants et ne peuvent pas être reliés sur le plan de travail : ils se rattachent à une application et y injectent eux-mêmes leurs réglages, si bien qu'une connexion n'aurait rien à transporter. Ils apparaissent comme services rattachés, et se configurent depuis leurs propres pages : E-mails depuis votre application et Passerelle de paiement.

Notez qu'un bucket est bien un composant, et non un service rattaché. Son point d'accès et ses clés n'existent qu'une fois le bucket provisionné : c'est précisément son statut de composant qui permet à Deploy stack de le provisionner avant l'application qui le lit — voir l'ordre de déploiement.

Ajouter des composants​

Dans le constructeur de stack, cliquez sur Add component et choisissez un service existant de l'environnement. Le service est rattaché à la stack et conserve tous ses réglages. Si vous ne les avez pas encore créés, commencez par les services sous-jacents (voir Déployer votre première application et Bases de données).

Le rôle des composants​

Chaque composant application porte un rôle, qui détermine le type de charge de travail déployé — l'équivalent, pour les stacks, des différents types de processus d'un docker-compose ou d'un Procfile. Sélectionnez un nœud d'application et ouvrez Component role dans le panneau latéral :

RôleDéployé commePublic ?À utiliser pour
Web (par défaut)Deployment + Service + IngressOui — obtient un domaineApplications HTTP, API, tout ce que les utilisateurs appellent
WorkerDeployment + ServiceNonConsommateurs de files, traitements en arrière-plan, tâches longues
CronCronJob, selon une planificationNonTâches planifiées : nettoyages nocturnes, génération de rapports…

La plupart des composants sont en Web, le rôle par défaut : vous n'en changez que pour du travail de fond ou planifié. Le rôle Cron exige une expression cron (par exemple 0 * * * * pour une exécution horaire). Le rôle ne concerne que les applications ; les bases de données l'ignorent.

Une configuration courante : faire pointer deux composants applicatifs vers le même dépôt, mais avec des rôles et des commandes de démarrage différents — par exemple un web (rôle Web) et un worker (rôle Worker) partageant la même base de code, tous deux reliés à la même base de données.

Relier les composants​

Les connexions sont le cœur des stacks. Une connexion dit : « prends ce champ chez le fournisseur et injecte-le chez le consommateur sous forme de variable d'environnement ».

Vous pouvez en créer une de deux façons :

  • en tirant un fil depuis le bord droit d'un nœud fournisseur jusqu'à un nœud consommateur ;
  • ou en cliquant sur Connect et en choisissant le fournisseur, le champ source et le consommateur.

Les champs sources dépendent du fournisseur :

FournisseurChamps disponibles
PostgreSQL / MySQL / MariaDBconnectionString, host, port, user, password, database
MongoDBconnectionString, host, port, user, password
RedisconnectionString, host, port, password
Bucketendpoint, bucket, accessKey, secretKey, region — voir Stockage objet
N'importe quel composanthost (nom interne au cluster), url / wsUrl (adresse publique — exige un domaine attribué), env:<CLE> (recopier une variable d'environnement du fournisseur)

env:<CLE> est le champ à utiliser quand deux composants doivent partager une valeur que vous avez définie vous-même — un secret de signature, un jeton d'API — plutôt qu'une valeur générée par la plateforme. url et wsUrl suivent le domaine personnalisé du composant lorsqu'il en a un, et échouent avec un message explicite tant qu'aucun domaine n'est attribué.

Par exemple, relier le connectionString d'un composant Postgres à votre application web sous le nom DATABASE_URL injecte quelque chose comme :

postgresql://utilisateur:motdepasse@ma-base-monapp:5432/mabase

L'hôte est le nom interne du service de base de données dans le cluster : le trafic reste donc sur le réseau privé de votre projet.

Modifier ou supprimer une connexion​

Sélectionnez un composant sur le plan de travail : ses connexions apparaissent dans le panneau latéral, à droite. Chacune offre deux actions :

  • ✏️ Edit — ouvre la fenêtre de connexion, fournisseur et consommateur verrouillés, pour changer le champ source ou le nom de la variable. L'enregistrement réévalue la valeur et réécrit l'environnement du consommateur. C'est la bonne façon de modifier une valeur injectée comme DATABASE_URL : ne modifiez pas le bloc géré à la main.
  • 🗑️ Remove — supprime la connexion et retire sa variable de l'environnement du consommateur. (Pour changer le fournisseur ou le consommateur eux-mêmes, supprimez la connexion et tirez-en une nouvelle.)
Comment se passe l'injection

Dès que vous créez une connexion, Kuploy en évalue la valeur et l'écrit dans un bloc géré par la plateforme, dans les variables d'environnement du consommateur — vous le verrez dans son onglet Environment, entre les marqueurs # >>> kuploy-stack et # <<< kuploy-stack. Supprimer la connexion l'en retire.

Ce bloc est dérivé de vos connexions : ne le modifiez pas à la main. Kuploy le recalcule à chaque connexion, déconnexion et déploiement, et écrase donc toute modification manuelle — d'où la mention « do not edit ». Pour changer une valeur injectée, changez sa connexion (un autre champ source, un autre nom de variable, depuis la page de la stack) ou les identifiants de la base fournisseur. Vos propres variables d'environnement, en dehors de ce bloc, restent modifiables comme d'habitude dans l'onglet Environment.

Services rattachés​

La page de votre environnement comme le plan de travail de la stack comportent une section Attached services. Un service y figure lorsqu'il sert une ou plusieurs applications de la stack sans faire partie de la stack : l'e-mail transactionnel, la passerelle de paiement le cas échéant, et un bucket qui a été rattaché à l'une des applications de la stack sans en être lui-même membre.

Un bucket rattaché est par définition déjà provisionné : rattacher un bucket non provisionné est refusé, avec la raison. En dehors d'une stack, il n'existe aucun ordre de déploiement capable de le provisionner avant l'application qui a besoin de ses identifiants ; la plateforme refuse donc une promesse qu'elle ne pourrait pas tenir. (Dans une stack, c'est l'inverse : vous pouvez relier un bucket non provisionné, parce que Deploy stack le provisionne d'abord.)

Sur le plan de travail, un service rattaché est dessiné comme un nœud en pointillés, sans pastille d'état, relié par un trait pointillé à chaque application qu'il sert. Ce n'est pas un fil de seconde zone : c'est la représentation fidèle d'une relation différente.

  • Il n'a pas d'état de déploiement propre, et Deploy stack ne le déploie pas.
  • Il n'est pas compté dans le total des services de la stack.
  • Les variables d'environnement qu'il injecte lui appartiennent : vous les modifiez sur sa page, pas au moyen d'une connexion.

Un même service rattaché peut servir plusieurs applications : vous verrez alors un seul nœud, avec un trait vers chacune. Chaque application reçoit malgré tout ses propres identifiants en coulisses, si bien que révoquer l'une n'affecte pas les autres ; le panneau latéral liste chaque application servie, avec son propre lien Configure.

Mon bucket est-il membre ou rattaché ?

Un bucket que vous avez ajouté à la stack est un composant : il figure parmi les membres, avec son propre fil, et Deploy stack le provisionne avant l'application qui a besoin de ses identifiants. Un bucket que vous avez rattaché depuis sa propre page à l'une des applications de la stack apparaît ici, comme service rattaché : il sert l'application sans faire partie de la stack, aucun ordre de déploiement ne s'applique, et c'est pourquoi rattacher un bucket non provisionné est refusé. Voir Stockage objet pour savoir lequel choisir.

Déployer​

Cliquez sur Deploy stack. Kuploy :

  1. ordonne les composants d'après leurs connexions (les fournisseurs avant les consommateurs) ;
  2. évalue chaque connexion et injecte les valeurs ;
  3. déploie chaque composant par le déploiement habituel, service par service.

Les composants sans connexion entre eux se déploient indépendamment ; un cycle (A dépend de B et B de A) est refusé.

Un bucket doit être provisionné pour que ses valeurs existent

Le point d'accès et les clés d'un bucket naissent au moment où il est provisionné, pas au moment où il est créé. Vous pouvez tirer ses connexions avant cela : elles ne résolvent simplement rien tant que le bucket n'est pas provisionné, et Deploy stack le provisionne, dans l'ordre des dépendances, avant ses consommateurs. Si vous l'avez provisionné depuis sa propre page, les applications reliées sont rafraîchies automatiquement et reprendront les valeurs à leur prochain déploiement.

Une connexion qui ne résout rien se voit : le fil est dessiné en ambre et en pointillés, et la connexion affiche dans le panneau latéral « Not set — … » avec la raison, par exemple bucket "media" is not provisioned yet. La variable est alors omise de l'environnement du consommateur plutôt que définie à vide : une application qui en a besoin échoue sur une variable manquante, au lieu de dialoguer en silence avec un point d'accès vide.

Deploy stack échoue immédiatement — avant tout déploiement — si un composant applicatif n'est pas en état d'être construit, et nomme le composant fautif. Chaque composant construit depuis Git a besoin :

  • d'une source configurée (un dépôt sélectionné), avec son fournisseur Git connecté (un fournisseur affichant Action Required compte comme déconnecté) ;
  • et d'un registre de build rattaché dans son onglet Advanced → Build Registry (ajouter un registre dans Settings → Registry ne suffit pas ; voir Registre de conteneurs).

Corrigez les réglages General ou Advanced du composant nommé, puis redéployez.

Arrêter ou annuler une stack​

Le constructeur de stack propose deux commandes à côté de Deploy stack. Elles répondent aux boutons Stop et Cancel build d'une application, expliqués dans Le déploiement et ses commandes :

CommandeCe qu'elle faitMet les composants hors ligne
Cancel deployN'apparaît que pendant le déploiement d'une stack. Interrompt le déploiement des composants restants et abandonne tout build en cours. Les composants déjà déployés continuent de tourner.Non
StopAnnule le déploiement en cours, puis met tous les composants hors ligne : applications et bases de données descendent à zéro réplique. Les données et les réglages sont conservés.Oui

Après un Stop, Deploy stack relance la stack dans l'ordre habituel des dépendances. Les buckets n'ayant pas de charge de travail propre, Stop ne les touche pas.

Un déploiement annulé n'est pas un échec. Les composants qu'il n'a pas atteints restent en l'état, et le Deploy stack suivant repart proprement.

À vous d'essayer​

  1. Ouvrez la stack : sur la page de l'environnement, repérez son groupe et cliquez sur Open. Vous êtes dans le constructeur de stack.
  2. À côté de Deploy stack (ou Redeploy) se trouve Stop, disponible dès lors que la stack a été déployée. Cancel deploy n'apparaît que pendant un déploiement.
  3. Cliquez sur Stop puis confirmez par Stop stack. Un message Stack stopped indique le nombre de composants mis hors ligne, et chacun s'affiche comme arrêté.
  4. Cliquez sur Deploy stack pour relancer. Pendant le déploiement, Cancel deploy puis Cancel stack deploy l'interrompt et signale Deploy cancelled.

Ce que fait réellement « Redeploy stack »​

Un seul clic exécute tout le contrat, dans l'ordre — bon à savoir pour les déploiements courants comme pour comprendre ce qu'un redéploiement change, et ce qu'il ne change pas :

  1. L'ordre — les composants se déploient fournisseurs d'abord, en suivant les connexions (la base de données et le bucket avant l'application qui les consomme).
  2. Le bucket est reprovisionné, de façon idempotente — un bucket membre est reprovisionné contre le stockage partagé à chaque déploiement de la stack. Vos objets ne sont jamais touchés ; les clés d'accès sont renouvelées, et l'environnement de chaque consommateur relié est réécrit avec les nouvelles valeurs avant son propre déploiement. (C'est aussi pourquoi des identifiants recopiés à la main cassent au redéploiement, alors que les identifiants reliés tiennent.)
  3. Le bloc géré est régénéré — le bloc géré par la plateforme chez chaque consommateur (la section # >>> kuploy-stack de son onglet Environment) est recalculé à partir des connexions, à chaque fois. Les modifications faites à la main à l'intérieur du bloc sont écrasées, par construction ; vos propres variables, en dehors, sont conservées.
  4. Les rattachements ne prennent effet qu'au déploiement — les services qui injectent leurs propres réglages (l'e-mail transactionnel) écrivent l'environnement enregistré de l'application au moment où vous les rattachez, les renouvelez ou les reconfigurez, mais un conteneur en cours d'exécution garde son ancien environnement jusqu'à son prochain déploiement. Si vous avez renouvelé un jeton d'e-mail ou rattaché un service et que l'envoi échoue toujours, le remède est presque toujours : déployer l'application.

Après toute modification du câblage d'une stack — une connexion, le quota d'un bucket, un rattachement d'e-mail — Redeploy stack est donc l'action qui remet d'accord la configuration enregistrée et la réalité en production.

Retirer un composant ou supprimer une stack​

Ce sont deux actions bien différentes, à ne pas confondre :

  • Remove from stack (par composant, dans le panneau latéral) dégroupe un service. Il quitte la stack mais continue de tourner comme service autonome, avec tous ses réglages et ses données. C'est l'action pour détacher un service sans le détruire.
  • Delete (le bouton rouge Delete de la stack) est destructif et définitif. Il supprime tous les services composant la stack, avec leurs données — bases de données et volumes compris — et retire les domaines de la stack. C'est irréversible.
Supprimer une stack supprime ses services

Supprimer une stack ne se contente pas de « dégrouper » : cela supprime aussi les services sous-jacents. Si vous voulez conserver un service, faites d'abord Remove from stack dessus, puis supprimez la stack. Tout service encore dans la stack au moment de la suppression disparaît définitivement avec elle, volumes de bases de données inclus.

Import et export (GitOps)​

Ouvrez une stack et descendez jusqu'au panneau Spec pour la voir en YAML, sous deux formats :

  • Native — le format propre à Kuploy, et la source de vérité. Réimportable tel quel.
  • Score (lossy) — un export Score score.dev/v1b1, pour la portabilité. Score est un format neutre, résolu par un fournisseur d'infrastructure — et c'est Kuploy qui joue ce rôle. Cet export est volontairement incomplet : les réglages propres à la plateforme n'y sont pas représentés. Il sert à l'interopérabilité, pas à la sauvegarde.

Le bouton Copy récupère l'un ou l'autre format pour votre dépôt Git.

Pour importer, ouvrez la page Stacks de l'environnement, cliquez sur Import, puis collez une spécification native :

name: mon-app
components:
- name: web
type: web
serviceType: application
env:
- key: DATABASE_URL
fromComponent: db
field: connectionString
- name: db
type: database
serviceType: postgres
L'import s'appuie sur des services existants

L'import met en place le groupement et les connexions au-dessus de services qui existent déjà dans l'environnement, rapprochés par leur nom. Il ne crée aucun service. Créez d'abord les applications et les bases de données, puis importez la spécification pour les grouper et les relier.

Procédure : de rien à une stack déployée​

L'ordre compte plus que tout le reste de cette page. Chaque étape renvoie à sa propre section plutôt que de la répéter.

  1. Créez d'abord les services. Une stack groupe des services qui existent déjà ; elle n'en crée jamais. Les applications viennent de Déployer votre première application, les bases de données de Bases de données, les buckets de Stockage objet.
  2. Donnez à chaque composant applicatif une source et un registre de build — Déployer explique pourquoi : Deploy stack refuse de démarrer sans eux et nomme le composant en défaut.
  3. Provisionnez les buckets que vous comptez relier, pour que leurs clés existent.
  4. Créez la stack et ajoutez-y chaque service.
  5. Définissez le rôle des composants — web, worker ou cron. Seules les applications en ont un.
  6. Tirez les connexions, en choisissant le champ source et le nom de variable que votre code lit déjà. Les valeurs sont injectées dès la connexion créée.
  7. Deploy stack. Les fournisseurs se déploient avant les consommateurs.
  8. Vérifiez l'onglet Environment du consommateur — les valeurs injectées sont dans le bloc géré. S'il en manque une, c'est que son fournisseur n'avait encore rien à donner (bucket non provisionné, url sans domaine) ; corrigez, puis redéployez.

Pour sortir un service plus tard, utilisez Remove from stack — jamais Delete, qui détruit les services eux-mêmes.

Ce qui reste propre à chaque composant​

Puisqu'un composant est un service ordinaire, tout ce que vous savez déjà continue de valoir composant par composant : déploiements et logs, domaines et TLS, volumes, sauvegardes, supervision et facturation. Ouvrez la page de n'importe quel composant (depuis le lien Open service du panneau latéral) pour le gérer.