Aller au contenu

Basculement du plan de données

Workload Availability peut basculer de deux façons. Avec le basculement côté serveur (backend failover), Opfield constate qu’un nœud a disparu et crée un remplaçant ; cela nécessite un Opfield en fonctionnement. Avec le basculement du plan de données (mode bail), les nœuds Docker, les nœuds Ingress et les relais de la charge de travail décident entre eux qui la sert ; un nœud mort ou isolé est donc remplacé en 45 secondes environ, même pendant qu’Opfield est arrêté, en cours de mise à jour ou injoignable.

Le mode bail fait partie de Business et Enterprise. Il ne nécessite aucun interrupteur : une politique l’utilise dès que chaque participant le prend en charge et a fonctionné de manière stable pendant 2 minutes. Les participants sont les nœuds Docker qui peuvent exécuter la charge de travail (candidats), les nœuds Ingress de ses Routes et les relais qui transportent son trafic. Ils doivent annoncer la capacité availability_lease_v2, ce que font le démon Docker, le démon nginx et Relay d’Opfield 2.11. Les composants des premières versions candidates de 2.11 qui annoncent availability_lease_v1 sont considérés comme obsolètes.

Le résumé Availability de la charge de travail affiche Lease mode : Lease lorsque les nœuds basculent d’eux-mêmes, Legacy avec le basculement côté serveur, et Bootstrapping ou Closing pendant le changement de mode de la politique. Survolez le badge pour en connaître la raison.

Chaque placement actif est un slot : le mode Failover en a un, le mode Replicated un par réplique. Pour chaque slot, les nœuds et relais de la politique tiennent un bail, et seul le nœud qui le détient (le détenteur) exécute sa copie de la charge de travail.

  • Renouvellement. Le détenteur renouvelle son bail toutes les quelques secondes auprès d’une majorité des votants de la politique. Lorsqu’il n’y parvient pas, il arrête sa propre copie avant que le bail ne puisse passer à quelqu’un d’autre. Le candidat suivant prend alors le slot libre et démarre sa copie, environ 45 secondes après la panne.
  • Secours. Opfield prépare à l’avance jusqu’à deux placements de secours sur d’autres nœuds candidats : l’image est récupérée et le conteneur est créé mais pas démarré ; une reprise se contente donc de le démarrer.
  • Trafic. Les requêtes n’atteignent que le détenteur de chaque slot. Le Secure Link de chaque placement est enregistré sur chaque relais qui prend en charge le mode bail ; les liens des secours restent enregistrés mais fermés jusqu’à ce que leur nœud détienne le slot, de sorte que le nouveau détenteur est joignable via chaque relais dès la reprise. Un détenteur ne reçoit du trafic qu’une fois sa charge de travail prête ; voir Routes et liaisons de bases de données.
  • Libération. Un détenteur qui a arrêté sa copie pour une raison locale (son minuteur de bail, un watchdog perdu, un gel détecté, un bail fermé) libère le slot dès que l’arrêt du conteneur est confirmé ; le candidat suivant démarre donc en quelques secondes au lieu d’attendre l’expiration du bail.
  • Un slot par nœud. En mode Replicated, un nœud ne détient jamais deux slots de la même politique. Un nœud qui revient reprend d’abord son propre slot précédent.
  • Détenteurs injoignables. Lorsque l’hôte d’un détenteur cesse de répondre, les relais abandonnent sa connexion en 3,5 secondes environ, et les nœuds Ingress cessent de lui envoyer des requêtes ; voir Routes et liaisons de bases de données. En mode Replicated, les autres répliques servent dès lors ; le slot lui-même se déplace une fois le bail passé au candidat suivant.

Un Docker Engine (dockerd) bloqué sur le détenteur n’arrête pas le trafic vers la copie en cours d’exécution et n’est pas considéré comme une raison de l’arrêter. Si le bail du détenteur expire entre-temps, le lease watchdog arrête la copie.

Chaque nœud Docker susceptible de détenir un slot exécute le lease watchdog, un petit service nommé opfield-lease-watchdog doté de sa propre ligne de versions (gateway-lease-watchdog sur un nœud installé avant 2.12.1, jusqu’à la mise à jour de son démon Docker). Il arrête un conteneur en mode bail dès que l’échéance de son bail est passée, même lorsque le démon Docker ou dockerd est bloqué. L’installateur du nœud Docker l’installe ; sur les nœuds existants, le démon Docker l’installe lui-même lorsqu’il s’exécute en root, et le watchdog se tient lui-même à jour. Un démon qui ne parvient pas à l’installer fait lister ce nœud par la politique avec watchdog_missing : réexécutez-y l’installateur du nœud.

Un watchdog lent pendant quelques secondes (jusqu’à environ 8) n’arrête jamais une charge de travail. Lorsque son signal de présence manque depuis environ 10 secondes, le détenteur arrête sa copie et libère le slot au profit du candidat suivant. Si un démon Docker est ramené à une version sans prise en charge des baux, le watchdog supprime les échéances laissées au bout de 10 minutes, afin de ne pas arrêter les conteneurs qu’exécute l’ancien démon.

Chaque politique a ses propres votants : ses nœuds candidats, un par hôte physique, dans l’ordre de reprise, plus des témoins pour que leur nombre soit impair et au moins égal à 3, au plus à 7. Seuls les nœuds et relais qui annoncent availability_lease_v2 et ont signalé une identité de bail votent. Une politique à trois candidats n’a pas besoin de témoin.

Un témoin est un relais ou un nœud Docker situé sur un hôte différent de celui de chaque candidat. Choisissez-le sous Witness dans la politique : Auto (farthest by latency) choisit le membre éligible dont le plus court aller-retour vers un candidat est le plus long, donc le moins susceptible de partager un site avec eux ; vous pouvez aussi sélectionner un relais ou un nœud précis. Le témoin automatique n’est jamais le relais local d’Opfield tant qu’un autre relais ou nœud peut servir de témoin, car le relais local s’arrête avec Opfield. Il reste en place jusqu’à ce qu’il ne puisse plus voter ; la gigue des allers-retours ne modifie donc jamais les votants. Le résumé avertit lorsque le témoin se trouve probablement sur le même site qu’un candidat (moins de 2 ms), lorsqu’aucun témoin éligible n’existe, ou lorsque le témoin configuré ne peut pas voter et qu’un témoin automatique est utilisé à la place.

Les votants doivent se joindre mutuellement sans Opfield. Chaque nœud d’une politique en mode bail se connecte à chaque relais pour son trafic de bail, et un seul relais actif suffit tant qu’une majorité des votants peut se joindre par son intermédiaire. Le résumé avertit « Voter reachability margin is insufficient » lorsque la perte d’un votant supplémentaire ne laisserait plus de majorité ; le relais local d’Opfield ne compte pas dans cette marge. Une politique à deux candidats avec un relais sur un autre hôte a une marge d’un votant.

Allow available mode (partitionMode dans l’API) détermine ce qui se passe lorsque le réseau sépare les votants :

  • Désactivé (strict, par défaut). Deux copies d’un slot ne s’exécutent jamais en même temps. Seul le côté qui conserve une majorité de votants sert ; un détenteur de l’autre côté arrête sa copie.
  • Activé (available). Les deux côtés d’une partition continuent de servir, et deux copies peuvent s’exécuter pendant un court instant. Ne l’autorisez jamais pour des singletons comme les indexeurs, les consommateurs de files de messages ou les tâches planifiées.

Les minuteurs de bail utilisent l’horloge monotone de chaque hôte. Un changement de l’horloge murale, comme une correction NTP dans un sens ou dans l’autre et de n’importe quelle ampleur, n’arrête jamais une copie.

Si l’hôte ou la machine virtuelle du détenteur est mis en pause, gelé ou suspendu pendant plus de 2 secondes environ, son bail peut être passé entre-temps à un autre nœud. À la reprise, le nœud déduit le temps perdu des horloges du premier relais ou votant qui lui répond et arrête immédiatement sa copie, sans période de grâce lorsque son temps de bail est écoulé. Le démon Docker le consigne comme une isolation (fence) avec la raison host_frozen. Un bail que le nœud acquiert après le gel n’est jamais arrêté pour cette raison, et les pauses plus courtes restent dans les marges de temps normales. Un détenteur qui ne joint personne après la reprise arrête sa copie selon son propre minuteur de bail.

Une condition propre à un nœud ne change jamais le mode de la politique. Le nœud est alors listé sous Excluded nodes dans le résumé (lease.excludedNodes dans l’API) avec l’une de ces raisons :

Raison Libellé dans le résumé Signification et correction
offline offline Le nœud n’a pas de connexion de contrôle vers Opfield. Rétablissez l’hôte ou son démon.
watchdog_missing lease watchdog not running Le lease watchdog ne s’exécute pas. Démarrez opfield-lease-watchdog ou réexécutez l’installateur du nœud.
daemon_outdated daemon outdated Le démon Docker n’annonce pas availability_lease_v2. Mettez-le à jour.
identity_pending no lease identity yet Le démon n’a pas encore signalé son identité de bail, généralement juste après une mise à jour.

Un nœud exclu ne reçoit aucun nouveau secours, aucun failback ni autre déplacement planifié ne se dirige vers lui, et son démon ne prend pas de slot ; c’est le candidat suivant qui le prend. Opfield n’isole jamais pour cette raison un nœud qui détient un slot : un nœud sans watchdog arrête sa propre copie, et un détenteur obsolète conserve son slot jusqu’à sa mise à jour ou sa passation. Un nœud obsolète ou non identifié ne quitte les votants et la liste des candidats qu’une fois la condition maintenue pendant 2 minutes ; un redémarrage de démon ou une mise à jour progressive ne change donc rien. Un failback vers un nœud qui était exclu attend Return to the primary after à compter de la fin de l’exclusion.

Une politique en basculement côté serveur n’entre en mode bail que lorsque chaque participant dont elle a besoin a exécuté availability_lease_v2 pendant 2 minutes sans interruption ni redémarrage : chaque nœud Docker candidat avec son lease watchdog et son identité, les nœuds Ingress de ses Routes, les relais qui la transportent et ses témoins. D’ici là, sa raison est participants_settling et nomme les nœuds ou relais encore en cours de stabilisation ; une flotte en pleine mise à jour ne bascule donc jamais à mi-chemin. Après un redémarrage d’Opfield, les 2 minutes recommencent.

Le mode bail attend aussi la fin d’une activation ou d’un déploiement en cours de la politique. Le premier détenteur de chaque slot est le nœud où la charge de travail sert à ce moment, quel que soit l’ordre de priorité ; un failback prioritaire le déplace ensuite sous forme de passation planifiée. Si ce nœud n’est pas prêt à prendre son slot, par exemple parce qu’il ne trouve aucune copie de la charge de travail, que son lease watchdog ne s’exécute pas ou que la politique de redémarrage de la copie n’est pas no, son démon Docker en consigne la raison, une fois par raison.

L’entrée en mode bail n’interrompt pas la charge de travail. Les copies actives continuent de s’exécuter et conservent leurs Secure Links : seul un bail formé après le changement compte pour un slot ; un ancien bail d’une période antérieure ne fait donc jamais arrêter sa propre copie à un nœud, et les liens des copies actives changent de rôle sur place au lieu d’être réenregistrés.

Une politique ne quitte le mode bail que lorsque celui-ci est devenu impossible :

Raison Cause
insufficient_voters Moins de membres capables de voter que ne l’exige une majorité ; mettez à jour les candidats ou ajoutez un relais comme témoin
ingress_not_capable Un nœud Ingress des Routes de la charge de travail exécute un démon nginx sans availability_lease_v2
relays_not_capable Un relais qui transporte la charge de travail exécute une version sans availability_lease_v2
candidates_not_capable, watchdog_missing Aucun candidat ne peut détenir de slot, et aucun slot n’est détenu
controller_unsupported Cette édition d’Opfield n’exécute le basculement Availability que côté serveur
signing_key_pending Aucune clé de signature de politique Relay ne peut encore signer les données de bail

controller_unsupported désigne un build Community sans contrôleur de baux. La licence ne ferme jamais le mode bail : aucun changement d’état de licence, y compris l’expiration, n’intervient dans cette décision.

Sauf pour la désactivation d’Availability et les opérations de cycle de vie comme Stop, Start et Restart, qui le quittent immédiatement, la condition doit durer 2 minutes sans interruption. Pendant ce temps, le bail continue de fonctionner, l’API indique depuis quand dans lease.reason.since, et le résumé avertit : « Data-plane failover is impossible right now: … The policy goes back to backend failover at … unless this is fixed before; the serving copy keeps running. »

Quitter le mode bail n’arrête jamais la copie active. La politique passe par Closing : Opfield publie un bail fermé qui désigne, pour chaque slot, le nœud qui le détient. Dès qu’une majorité des votants confirme la fermeture à ce nœud, celui-ci garde sa copie en fonctionnement sans bail, son watchdog ne surveille plus cette copie, et le basculement côté serveur l’adopte telle qu’elle s’exécute, généralement en quelques secondes ; rien ne la redémarre et ses Secure Links continuent de servir. Pendant ce temps, le résumé affiche le nœud sous Kept serving avec « confirming » puis « keeps running » (lease.retainedHolders dans l’API). Un détenteur qui ne peut pas joindre une majorité pendant la fermeture, parce qu’il est isolé, arrête sa copie comme tout détenteur de bail, et le basculement côté serveur redémarre ce slot une fois son bail expiré, environ 47 secondes après qu’une majorité de votants a vu la fermeture.

Une fermeture conserve tous les placements, y compris la charge de travail d’origine : les secours restent préparés, et rien n’est supprimé ni mis en file pour nettoyage. Si une copie doit ensuite être démarrée en basculement côté serveur, un secours préparé est démarré avant la création de tout nouveau placement. Seul Stop arrête la charge de travail, après la fermeture. La désactivation d’Availability garde le placement survivant en fonctionnement et retire elle-même les autres placements. Une fois la cause corrigée, la politique revient d’elle-même en mode bail après les 2 minutes habituelles de stabilisation et reprend les secours conservés tels quels.

Opfield planifie chaque déplacement et tient les enregistrements ; les nœuds décident seulement qui sert lorsque quelque chose tombe en panne.

  • Les opérations s’exécutent en parallèle entre politiques. Chaque politique exécute une opération à la fois. La réparation, la mise à l’échelle, le déploiement et les opérations d’arrière-plan similaires s’exécutent pour au plus 4 politiques à la fois ; le failback, le démarrage, l’arrêt, le redémarrage et la désactivation n’attendent jamais cette limite. Un nœud qui revient peut donc effectuer le failback de plusieurs charges de travail sans faire la queue derrière les réparations d’autres politiques.
  • Les déplacements planifiés sont des passations. Un failback, un vidage, un déplacement manuel, un changement de l’ordre de priorité ou un déploiement déplace un slot sous forme de passation : le nœud actif arrête sa copie et libère le bail, et ce n’est qu’ensuite que le nœud suivant démarre la sienne. Les Secure Links des membres changent de rôle sur place, celui de l’ancien détenteur en secours et celui du nouveau en actif ; aucun lien ni point de terminaison Relay n’est donc créé pendant une passation. Le slot ne sert rien pendant l’arrêt de l’ancienne copie puis le démarrage et la mise en état de la nouvelle, généralement 5 à 15 secondes. En mode Failover avec Allow available mode désactivé, les requêtes échouent pendant ce temps ; en mode Replicated, les autres répliques continuent de servir.
  • Réparation. Une politique qui compte moins de copies actives ou de secours que nécessaire, et qui dispose d’une capacité éligible en ligne, fait l’objet d’une maintenance toutes les 15 secondes et à chaque connexion d’un nœud. Un nœud qui revient récupère son slot libre : son placement est conservé, et un placement manquant est recréé. Un nœud qui se retrouve à détenir deux slots en cède un à un secours situé ailleurs, avec une courte interruption pour cette copie.
  • Les secours restent tels quels. Préparer à nouveau un secours, ce que font régulièrement la réparation, une reconnexion ou la maintenance, ne change rien tant que ses paramètres, son image (comparée par identifiant d’image) et les paramètres de connexion aux bases de données managées qu’il recevrait sont inchangés. Un secours dont les paramètres de connexion à une base de données ont changé, par exemple après la rotation d’un identifiant de liaison, est considéré comme non prêt et préparé à nouveau. Un démon Docker occupé par des commandes de longue durée retarde la réparation (AVAILABILITY_DAEMON_BUSY, retentée) au lieu de déclarer les placements en échec.
  • Après une partition ou une panne. Lorsqu’un nœud revient, Opfield lit l’état de ses placements auprès de son démon : une copie qui était arrêtée devient un secours prêt, et un failback prioritaire s’exécute comme après toute panne.
  • Au retour d’Opfield. Une copie active conserve son chemin Secure Link pendant qu’Opfield reconnecte ses nœuds : si l’actualisation d’un lien de membre échoue parce qu’un nœud ne s’est pas encore reconnecté, le lien conserve son point de terminaison Relay et Opfield réessaie. Un relais qui se reconnecte reçoit immédiatement chaque changement de politique.
  • Enregistrements. Dans les secondes qui suivent son démarrage, Opfield apprend les détenteurs réels auprès de son relais local, avant la reconnexion des nœuds. Une reprise autonome apparaît dans le journal d’audit sous docker.availability.lease_failover, un déplacement planifié sous docker.availability.lease_handoff. Les deux sont datés de l’heure à laquelle le nouveau détenteur a acquis le slot, qui peut être antérieure au moment où Opfield l’a constaté. Un slot arrivé à échéance et repris par le même nœud, parce que sa copie avait été arrêtée ou isolée, y compris pendant qu’Opfield était en panne, apparaît sous docker.availability.lease_reacquired. Un redémarrage de démon dont la copie a conservé son bail n’est pas une nouvelle détention et ne change rien. La meilleure source pour l’heure l’emporte : le propre rapport du nouveau détenteur, puis l’heure la plus ancienne à laquelle un votant l’a vu, et seulement ensuite l’heure du constat par Opfield. Les heures signalées par un démon Docker sont corrigées du décalage mesuré entre son horloge et celle d’Opfield lorsqu’elles diffèrent de plus de 2 secondes, par exemple sur une machine virtuelle qui a repris avec une horloge en retard ; sans horloge mesurable, c’est l’heure des votants ou celle du constat par Opfield qui décide. Lorsque l’heure propre du nouveau détenteur n’est pas encore connue, par exemple parce qu’il a pris le relais pendant qu’Opfield était en panne, l’entrée est écrite une fois l’heure établie : dès que le détenteur la signale, sinon au bout de 60 secondes avec l’heure des votants, ou au bout de 5 minutes lorsqu’aucun membre n’a signalé d’heure. Les détails contiennent takeoverAt, noticedAt, takeoverSource (holder, voters ou noticed) et takeoverId. Une entrée en attente est stockée en base de données ; un redémarrage ou un plantage d’Opfield pendant l’attente ne fait donc rien perdre et ne l’écrit jamais deux fois. L’heure de détention dans le résumé (holderSince dans l’API) est la même heure de reprise et est corrigée à mesure que de meilleurs rapports arrivent.

Mettez d’abord à jour Opfield, puis les démons des nœuds et le Relay Pool ; voir Mises à jour de Relay pour comprendre pourquoi les démons doivent passer en premier en venant de 2.10. Une politique en basculement côté serveur y reste tant qu’un participant exécute encore une version plus ancienne, et entre en mode bail une fois, 2 minutes après la mise à jour du dernier participant. Une politique déjà en mode bail le conserve tant que seuls des nœuds Docker candidats sont obsolètes ; ils sont exclus, et un détenteur obsolète continue de servir jusqu’à sa mise à jour. Un nœud Ingress ou un relais laissé sur une version plus ancienne pendant plus de 2 minutes renvoie la politique en basculement côté serveur via Closing, en gardant les copies actives en fonctionnement ; elle revient d’elle-même une fois ceux-ci mis à jour.

Opfield ordonne lui-même les mises à jour des démons des participants au bail. La mise à jour d’un démon Docker ou d’un relais qui vote pour une politique en mode bail, ou peut en détenir un slot, attend que les autres votants et candidats de cette politique soient de nouveau en ligne, aient signalé leur état de bail et votent à nouveau. Pendant ce temps, le nœud apparaît comme en cours de mise à jour, et l’API indique updatePhase: waiting_for_lease_peers avec les pairs dans updateWaitingFor. Les mises à jour demandées ensemble exécutent d’abord les secours, puis les détenteurs ; les nœuds qui ne partagent aucune politique se mettent à jour en parallèle. Un pair qui ne s’est pas stabilisé 3 minutes après son redémarrage cesse de bloquer, et une mise à jour qui a attendu 30 minutes échoue avec une erreur qui nomme les pairs.

L’attente compte surtout une fois. Le premier redémarrage d’un nœud mis à jour depuis 2.10 s’abstient de voter pendant environ 33 secondes, comme tout démarrage après un redémarrage de l’hôte ou avec un état vierge ; une mise à jour peut alors attendre ses pairs de bail jusqu’à environ une minute par pair. Les redémarrages ultérieurs dans le même cycle de démarrage continuent de voter immédiatement, et un détenteur dont le démon redémarre conserve son slot et continue de servir : son bail reste valide jusqu’à l’échéance de son watchdog, sa copie reprend donc le trafic dès que le nouveau processus du démon s’enregistre, et il continue de renouveler jusqu’à 2 secondes avant cette échéance. Voir Redémarrages du démon Docker.

Après la mise à jour vers 2.11, un secours doté d’une liaison de base de données managée est préparé une fois de plus, car les secours enregistrent désormais les paramètres de connexion à la base de données avec lesquels ils ont été préparés.

Un nœud ramené à n’importe quelle version depuis 2.10.0 démarre toujours : les démons conservent leurs fichiers d’état sous une forme que les versions plus anciennes peuvent lire.

get de manage_docker_availability et l’API Availability renvoient un objet lease :

  • mode : legacy, bootstrapping, lease ou closing ;
  • reason : pourquoi la politique est en basculement côté serveur, ou pourquoi le mode bail est impossible à ce moment, avec code, message, les nodeIds ou relayIds à corriger, et since pendant qu’une politique en mode bail attend la fin des 2 minutes ;
  • excludedNodes : [{ nodeId, reason }] ;
  • retainedHolders pendant closing : [{ slot, holderNodeId, confirmed }], les copies qui continuent de s’exécuter pendant la fermeture ;
  • holders : par slot, holderNodeId, placementId et holderSince ;
  • voters et witness, avec warning valant witness_near_candidate, no_eligible_witness ou configured_witness_unavailable ;
  • voterMargin : voters, reachable, required et margin. Lorsque margin vaut 0 ou moins, la perte d’un votant supplémentaire arrête le basculement autonome.
  • Le basculement du plan de données protège les placements de la charge de travail, et non Opfield, nginx, les moteurs de bases de données, le stockage du registre ou les volumes partagés.
  • Une copie qui ne peut pas renouveler son bail s’arrête. Avec Allow available mode désactivé, une partition réseau arrête donc la charge de travail du côté qui n’a pas la majorité.
  • Les déplacements planifiés entraînent une courte interruption pour un singleton en mode Failover, comme décrit ci-dessus.