BLOG | NGINX

Équilibrage de charge d'une infrastructure dynamique avec NGINX, Chef et Consul

NGINX-Partie-de-F5-horiz-black-type-RGB
Vignette de Kevin Reedy
Kevin Reedy
Publié le 22 mai 2017


Cet article est adapté d'une présentation de Kevin Reedy de Belly Card à nginx.conf en octobre 2014. Même si cela s’est passé il y a quelques années, le contenu est toujours très pertinent aujourd’hui. Vous pouvez visionner un enregistrement de la présentation sur YouTube .

Table des matières

0:00 Introduction
  Aperçu
  Clause de non-responsabilité
1:16 Qu'est-ce que Belly ?
  Pile de Belly
1:44 Version 0: L'âge des ténèbres
2:04 Version 1: Un nouvel espoir
2:35 Version 2: Page d'accueil et API séparées
  Mot à la mode du jour : Architecture orientée services !
  Activer SOA
  NGINX remplace ELB
  Configuration du serveur en amont et du serveur virtuel
  Résultats
4:43 Configuration avec Chef
  Recettes
  Fichiers
  Modèles
  Livres de cuisine
6:49 Exemple: Chef pour NGINX
  Installation, configuration et réglage
  Routage du trafic API
9:46 Exemple de chef du monde réel
10:08 Version 2: Déploiement d'applications
10:40 Version 3: SOA Toutes les choses
  Et puis Heartbleed est arrivé
  SSL Toutes les choses
12:25 Version 4: Docker
  Avantages
  Déploiement de conteneurs
15h45 Stratégies de déploiement
17:43 Options de découverte de services
18:33 Architecture Consulaire
19h30 Caractéristiques du Consul
22:07 Modèle de consul
  Commande pour démarrer le modèle Consul
  Configuration NGINX avec le modèle Consul
  Gestion de la configuration avec le modèle Consul
24:35 Utilisation de Chef pour déployer Consul
25:44 Conseils de pro
  Recherche partielle de chef
  DNS
  Éviter les configurations obsolètes
30:35 Questions
36:31 Coordonnées

0:00 Présentation

Bonjour à tous. Je m'appelle Kevin Reedy et je travaille pour une entreprise appelée Belly Card basée à Chicago. Nous avons une centaine de salariés et une vingtaine d'ingénieurs. Aujourd’hui, je vais vous parler de la manière dont nous réalisons notre équilibrage de charge, en particulier dans une infrastructure dynamique en constante évolution.

0:21 Aperçu

Je vais d’abord vous parler de notre infrastructure au fil du temps, en commençant par la version 0, que j’appelle l’âge sombre. Nous verrons ensuite comment nous utilisons Chef pour configurer NGINX. Ensuite, nous parlerons de la façon dont nous avons évolué depuis cette approche vers l’utilisation des données de ce que l’on appelle la plateforme de découverte de services Consul pour configurer NGINX. Si le temps le permet, j’ai quelques conseils de pro sur la configuration de NGINX, notamment en ce qui concerne la gestion de la configuration.

0:49 Avertissement

Donc, même si je vais vous parler de Chef et Consul, je tiens à préciser que rien dans cet exposé ne leur est spécifique. Chef, Puppet, Ansible, Salt, CFEngine et tous les autres sont d'excellents produits et vous devriez en utiliser un. Nous apprécions Chef, et je suis sûr que beaucoup d’autres personnes l’apprécient aussi.

Il en va de même avec la découverte de services. Consul, etcd et ZooKeeper sont tous excellents, alors utilisez ce qui fonctionne pour vous.

1:16 Qu'est-ce que le ventre ?

Qu'est-ce que Belly ? Il s’agit essentiellement d’un remplacement numérique d’une carte perforée dans un café où vous achetez dix boissons et en recevez une gratuite. Nous mettons un iPad dans le magasin, les clients scannent à l'aide de leur téléphone ou d'une carte physique avec un code QR, nous suivons leurs points, donnons des récompenses et nous créons des outils marketing par-dessus cela.

1:36 Pile de Belly

Mais je ne suis pas ici pour vous parler de Belly en tant qu'entreprise. Si cela vous intéresse, vous pouvez simplement vous rendre sur notre site Web . Je vais vous parler de notre infrastructure.

1:44 Version 0: L'âge des ténèbres

Donc la version 0. À l'époque où nous étions trois développeurs et avant que je n'y travaille, Belly était une application Ruby on Rails monolithique, ce qui signifiait que chaque appel d'API et chaque partie de notre site Web étaient dirigés vers une seule application Rails. Elle était soutenue par MySQL, MongoDB et Memcached, et nous l'avons déployée sur Heroku, ce qui est un excellent point de départ.

2:04 Version 1: Un nouvel espoir

Donc la version 1 – Un nouvel espoir. Nous avons décidé qu’Heroku ne répondrait plus à nos besoins, nous avons donc commencé à déployer quelque chose appelé Capistrano, qui est essentiellement « meilleur qu’un script shell » écrit en Ruby. Cela vous aide à déployer des choses.

Nous avions environ six serveurs sur Amazon Web Services EC2. C'était un chiffre statique, mais nous l'augmentions si nous savions qu'il se passait quelque chose d'important et nous le diminuions si nécessaire. Avant cela, nous avions AWS Elastic Load Balancer.

2:35 Version 2: Page d'accueil et API séparées

Nous avons alors eu un projet dans lequel nous souhaitions séparer notre page d'accueil du reste de l'API. Nous voulions le faire pour pouvoir travailler plus rapidement sur notre page d'accueil et faire travailler différents développeurs dessus.

2:47 Mot à la mode du jour : Architecture orientée services !

Le grand mot à la mode à l’époque – et encore aujourd’hui – était l’architecture orientée services.

2:50 Implémenter SOA

La version 2 de notre pile devait donc permettre une architecture orientée services. Notre premier projet était de séparer la page d’accueil de l’API. Cela semble très simple : nous avons juste www.bellycard.com et api.bellycard.com .

Mais cela s’est avéré très complexe et pas du tout simple, car certaines de nos applications mobiles ont été écrites de manière statique pour utiliser www.bellycard.com/api et /api‑assets . Nos fournisseurs de messagerie et tous nos liens cliquables qui avaient déjà été envoyés par courrier électronique aux personnes avaient /eo pour « ouverture de courrier électronique » et /ec pour « clic de courrier électronique ». Notre application Facebook a été configurée sur /facebook/callback .

3:28 NGINX remplace ELB

Cela signifiait donc qu’AWS Elastic Load Balancer ne nous offrait plus la flexibilité dont nous avions besoin pour acheminer ce trafic vers différentes applications. Alors NGINX est venu sauver la situation. Plus précisément, nous pourrions avoir plusieurs flux en amont et réécrire les règles pour acheminer le trafic vers nos différentes applications.

3:44 Configuration du serveur en amont et du serveur virtuel

Dans cet exemple très basique, nous définissons un bloc en amont avec six serveurs pour l'API et un bloc avec deux serveurs pour la page d'accueil.

Il existe également deux blocs de serveurs [définissant des serveurs virtuels]. Sur l'un, nous écoutons api.bellycard.com et acheminons tout ce trafic vers les serveurs API. De l'autre côté, nous écoutons sur www.bellycard.com et acheminons les choses en conséquence.

4:02 Résultats

Cela a très bien fonctionné. Cela a permis à nos développeurs d’avancer rapidement. Nos équipes front-end travaillaient sur un projet et n'étaient pas bloquées par notre API. Nous avons donc déployé un troisième service. Je crois que c’était pour l’intégration avec le Passbook d’Apple. Puis un quatrième – nous avons déplacé toutes nos fonctionnalités Facebook. Notre cinquième mission consistait à gérer les événements utilisateurs sur notre site Web.

Puis quelqu'un a décidé que c'était une excellente idée d'écrire cela en Node.js, nous avions donc maintenant cinq services distincts dans deux langages. Ils sont tous déployés indépendamment sans beaucoup de gestion de configuration, et nous éditions manuellement NGINX, avec lequel je suis sûr que beaucoup de gens commencent.

4:43 Configuration avec le chef

Nous avions besoin d’un meilleur moyen de faire évoluer ce processus, et nous l’avons fait avec Chef.

Chef est une suite de gestion de configuration. Il est écrit en Ruby et vous pouvez écrire votre gestion de configuration réelle en Ruby, donc c'est idéal pour les développeurs. learnchef.com est une ressource incroyable pour en savoir plus sur Chef ; il peut vous en apprendre bien plus sur Chef que moi en 45 minutes.

Je vais passer en revue quelques notions de base, juste pour que nous soyons tous sur la même longueur d’onde.

5:17 Recettes

Le premier type d'élément de base dans Chef est une recette . Le chef utilise beaucoup de noms astucieux comme couteau comme outil et recette et tout est dans un livre de cuisine . Cela rend la tâche amusante et facile à comprendre et fournit une excellente métaphore, mais cela rend également très difficile la recherche sur Google.

Voici donc la recette la plus basique à laquelle j’ai pu penser. Installez le package nginx et démarrez et activez le service nginx .

5:56 Fichiers

Vous pouvez également disposer de ressources de fichiers. Par exemple, je souhaite écrire le contenu Hello World! dans le fichier /usr/share/NGINX/html/index.html .

6:08 Modèles

Vous pouvez également intégrer cela dans un système de modèles. Ici, j'ai quelques variables g et w pour Hello et Kevin et je peux passer ces variables dans un fichier modèle, qui est au format ERB (un script de création de modèles Ruby).

Ainsi, au lieu de simplement écrire le contenu manuellement, nous pouvons rédiger un modèle de lecture et indiquer à qui saluer.

6:19 Livres de cuisine

Le dernier élément majeur est un livre de cuisine, qui est une collection de recettes, de fichiers et de modèles. Également des ressources, des fournisseurs et des bibliothèques, qui sont des ressources plus complexes. Il existe des tonnes de livres de cuisine open source et autres sur https://supermarket.getchef.com , y compris ceux pour NGINX, MySQL, Java, apt et yum , gérant même vos fichiers ssh_known_hosts . La plupart des principaux éléments de base de ce que vous essayez de faire dans la gestion de configuration se trouvent déjà dans un livre de recettes.

6:49 Exemple : Chef pour NGINX

Nous allons passer en revue un exemple NGINX très rapide avec Chef où nous allons installer NGINX et le configurer en modifiant quelques variables. Nous utiliserons Chef pour découvrir où notre application s’exécute, puis configurerons NGINX pour acheminer le trafic vers notre application.

7:14 Installation, configuration et réglage

Dans cet exemple, la première chose qui est faite dans la configuration de Chef est de régler les attributs du nœud NGINX, puis d'installer nginx, de rechercher les nœuds d'application et de générer une configuration de site.

Donc, dans cet exemple, la première chose que nous faisons est de définir certains attributs de nœud. Pour chaque nœud, vous pouvez définir des valeurs d’attribut en ajoutant un document JSON. Nous allons utiliser un livre de recettes NGINX tiers qui recherche les paramètres de ces attributs. Nous définissons worker_connections sur une certaine valeur, la directive worker_rlimit_nofile , le type d'événement que nous allons utiliser dans NGINX et même client_max_body_size .

Après cela, nous incluons deux recettes du livre de cuisine NGINX. Le premier est nginx::repo , qui configure un référentiel apt ou yum selon votre système d'exploitation. Ensuite, [la recette nginx ] installe NGINX. Vous pouvez également installer NGINX à partir de la source, mais l'utilisation de packages est plus rapide.

Ensuite, nous profitons des capacités de recherche de Chef. Lorsque vous exécutez Chef, vous pouvez soit l'exécuter en tant qu'agent sur la machine, soit l'exécuter en mode solo qui l'exécute essentiellement comme un script. Lorsque vous disposez d'un agent sur une machine, vous pouvez interroger le serveur Chef pour connaître les nœuds et d'autres attributs.

Ici, nous demandons à Chef de nous donner une liste de tous les nœuds auxquels la recette belly-api est attachée. Après cela, nous créons un modèle de fichier de site appelé /sites‑enabled/api . Sa source est le modèle [fichier appelé api.erb que] je vais vous montrer ensuite. Les variables que nous transmettons sont les nœuds que nous avons recherchés juste avant.

La dernière nouveauté ici est une instruction de notification pour recharger le service nginx . Cela signifie que chaque fois que ce modèle change, je souhaite que vous rechargez ce service.

8:54 Routage du trafic API

Donc, notre fichier modèle ici est assez simple. Nous avons un amont appelé api et dans ERB nous parcourons tous les serveurs que nous traversons en tant que variable, en spécifiant le serveur par adresse IP et port 8080. Nous ajoutons même un commentaire avec le nom du serveur. Lorsqu'un opérateur cherche à savoir ce qui se passe avec ce service, ce sera un bon commentaire pour lui.

Nous définissons également un bloc serveur pour écouter sur api.bellycard.com . Je transmets simplement tout le trafic à l' API en amont.

9:46 Exemple de chef du monde réel

Je voudrais également donner un exemple concret. C'est peut-être trop petit pour que vous puissiez le lire, mais vous pouvez avoir une idée de la complexité de vos recettes de chef. Il s'agit du modèle et de la recette réels de certains de nos serveurs de production actuels.



10:08 Version 2: Déploiement d'applications

Revenons maintenant à notre pile. Je vous ai dit que nous avions déployé environ cinq applications et que tout se passait très bien. Nous avions désormais un moyen d’acheminer le trafic vers eux, nos développeurs s’en sont donc emparés et aujourd’hui, nous avons environ 40 applications Ruby déployées sur nos serveurs à l’aide de Chef. Le trafic est acheminé de manière entièrement dynamique à l'aide de NGINX.

Nos développeurs n’ont pas vraiment besoin de faire autre chose que de modifier une recette pour inclure le nom de leur nouveau service. Tout le trafic est acheminé par NGINX et configuré dynamiquement avec Chef.

10:40 Version 3: SOA Toutes les choses

Nous avions également une dizaine d'applications JavaScript front-end qui ne sont que des fichiers statiques que nous déployons sur S3 avec un CDN, [Amazon] CloudFront, devant. Nous avons diffusé index.html à partir du bucket S3 et le reste des ressources était sur CloudFront. Nous avions également environ cinq autres applications que les développeurs ont simplement poussées vers Heroku, car il s'agissait d'une chose unique qui est finalement devenue une production et personne n'en a vraiment été informé.

11:10 Puis Heartbleed s'est produit

[Les cinq applications sur Heroku] étaient séparées – complètement en dehors de notre infrastructure – jusqu’à un beau jour d’avril où le bug Heartbleed a été annoncé. Beaucoup de gens se sont précipités. Heartbleed était un bug dans OpenSSL qui permettait aux gens d'extraire potentiellement vos clés privées.

Depuis que nous utilisons Chef, nous avons pu mettre à niveau notre infrastructure OpenSSL sur toutes nos machines dès qu'un correctif était disponible. Je crois qu’il a été déployé en 20 minutes environ partout dans notre infrastructure entière. Cependant, AWS (et donc Heroku) a mis environ 24 heures pour corriger ses équilibreurs de charge élastiques.

Cela nous a incité à déplacer l’ensemble de notre équilibrage de charge et de notre terminaison SSL vers NGINX, quel que soit l’endroit où il était déployé – à la fois S3 et Heroku. Vous encourez une légère pénalité pour avoir agi ainsi, mais au moins ce jour d'avril, cela en valait la peine pour nous.

11:57 SSL Toutes les choses

Ainsi, la version 3 de notre pile est passée de « SOA tout compris » à « SSL tout compris ». Tout notre trafic vers bellycard.com et ses sous-domaines passe par nos équilibreurs de charge. Nos ressources sont toujours effectivement servies depuis CloudFront sur un domaine différent pour des raisons de performances. Nous ne voulons pas des frais généraux liés au SSL, et nous ne sommes qu'un seul centre de données sur la côte Est.

12:25 Version 4: Docker

Version 4 – le mot à la mode dont tout le monde parle cette année est Docker. Étant donné que Docker en était, je crois, à la version 0.5, nos développeurs étaient impatients de commencer à l'utiliser.

12:38 Avantages

Les raisons [d’utiliser Docker] sont simples.

Cela simplifie grandement le déploiement des applications. Il n'y a pas de recettes à écrire. Vous n’avez pas à vous soucier de la manière dont vous allez effectuer la compilation des ressources. Peu importe que vous écriviez votre application en Ruby alors que quelqu’un d’autre écrit la sienne en Python.

Essentiellement, il sépare les responsabilités de développement et d’exploitation. Vos développeurs peuvent se soucier du code, des bibliothèques à utiliser et même des packages Linux à installer. Les opérations peuvent s’inquiéter de davantage de choses comme : où vais-je déployer cela ? Comment vais-je capturer la journalisation à partir de celui-ci ? Comment puis-je le surveiller ? Une fois ces problèmes et opérations résolus, chaque application fonctionnera, quel que soit le format dans lequel elle est écrite.

L’avantage de cela est que cela permet à nos développeurs de lancer facilement des services dépendants sur leurs propres ordinateurs portables. Comme je l’ai mentionné, nous avons environ 55 applications différentes, dont beaucoup sont désormais dans des conteneurs Docker.

Imaginons que vous travaillez sur un nouveau service d’envoi de campagnes par e-mail. Il s'appuie sur le service de messagerie électronique. Ainsi, sur votre machine de développement, vous téléchargez généralement le code, exécutez bundle install , démarrez-le en arrière-plan et « oh, mais en fait, cela repose sur un autre service, le service utilisateur ».

Ce service repose sur autre chose et encore sur autre chose. En fait, le nouveau service de campagne par e-mail s’appuie sur environ cinq autres services, ainsi que sur MySQL, Elasticsearch, Redis, et la liste est longue.

Avec Docker, nous pouvons réellement créer ces conteneurs à partir des mêmes recettes Chef que celles que nous utilisons en production et fournir à nos développeurs des conteneurs qu'ils peuvent télécharger extrêmement rapidement.

Cela accélère ainsi le déploiement et le développement.

14:23 Déploiement de conteneurs

Ainsi, dans la version 4, nous sommes passés du déploiement de nos applications à l’aide de Chef à leur déploiement dans des conteneurs. Il existe des tonnes de solutions pour y parvenir et je suis sûr qu’il y en aura encore plus.

Le premier est CoreOS et Fleet. CoreOS est un système d’exploitation Linux simplifié qui exécute un moteur de découverte de services appelé etcd . Fleet est un moyen pour vous de définir des éléments tels que « Je veux qu'un conteneur s'exécute cinq fois et je ne veux pas qu'il s'exécute sur les mêmes machines que cet autre service ».

Il y en a un autre appelé Deis qui est similaire à Heroku dans le sens où il possède une interface Git Push. Il y a Mesos d’Apache et Kubernetes de Google ; Flynn est un autre qui vient de sortir récemment. En fait, nous avons écrit le nôtre parce que lorsque nous avons commencé ce voyage, la plupart de ces outils n’étaient pas à un endroit où nous pouvions les utiliser.

Le nôtre s’appelle Jockey, et cela a très bien fonctionné car notre processus de déploiement est extrêmement subjectif. L’avantage de Docker est qu’il fournit essentiellement un ensemble d’API communes pour la conteneurisation. Nous n’avons pas à nous soucier de beaucoup de choses comme si nous utilisions simplement les conteneurs LXC de Linux.

Nous prévoyons de le rendre open source, mais comme je l'ai mentionné, les déploiements sont vraiment subjectifs et ce qui fonctionne pour nous pourrait ne pas fonctionner pour vous.

15h45 Stratégies de déploiement

Notre stratégie de déploiement a également quelque peu changé lorsque nous sommes passés à Docker. Auparavant, nous effectuions des déploiements sans interruption de service en déployant une nouvelle version de l’application en place. Cela signifie que si nous avions ce service de fax utilisateur sur quatre machines, nous utiliserions Chef pour extraire la nouvelle version, l'installer par-dessus [l'ancienne version], puis envoyer un signal au serveur Web pour recharger. Unicorn est un excellent moteur Ruby pour faire cela.

Cependant, les conteneurs sont immuables. Une fois que vous avez un conteneur en cours d'exécution, si vous souhaitez créer une nouvelle version, vous devez créer un nouveau conteneur. Vous pouvez en quelque sorte vous y attacher, exécuter des commandes supplémentaires, puis l'enregistrer, un peu comme vous le feriez dans Git. Mais vraiment, si vous voulez tirer le meilleur parti de Docker, votre conteneur doit être complètement immuable.

Cela signifie donc que nous avons dû élaborer une nouvelle stratégie de déploiement, car nous ne sommes plus en mesure de déployer nos services sur place. Il y en a quelques-uns. Le bleu-vert est une couleur intéressante. C'est là que, si vous avez une application exécutée sur quatre machines, vous la lancez sur quatre nouvelles machines et faites en sorte que votre équilibreur de charge pointe vers les nouvelles machines. Une fois que vous êtes sûr que cela fonctionne comme vous l’espérez, vous pouvez démonter votre bleu et votre vert devient le bleu. Amazon dispose d’outils vraiment efficaces pour réaliser cela avec AWS.

Il existe également des déploiements « canari » où je déploie une version de la nouvelle machine, je la surveille et, si elle passe les contrôles de métriques et les contrôles de santé, je peux continuer le déploiement.

La différence avec les conteneurs ici, c’est que vous allez les démonter et en créer de nouveaux. Vous avez donc besoin d’une sorte de système pour suivre l’emplacement de chaque application exécutée dans votre infrastructure.

Le terme « chef » commence en fait à devenir un très bon moyen d’y parvenir. Il existe un livre de recettes en cours de fusion appelé Chef Metal qui vous permet de traiter les conteneurs comme n’importe quelle autre ressource que vous utiliseriez dans votre infrastructure Chef.

17:43 Options de découverte de services

Il existe également la découverte de services. ZooKeeper est un outil très populaire qui est utilisé partout dans Hadoop. [Airbnb] dispose d'un excellent produit appelé SmartStack qui vous permet d'effectuer des déploiements et d'en assurer le suivi dans ZooKeeper.

J’ai mentionné etcd , qui est essentiellement un magasin de clés-valeurs distribué avec une interface REST. C'est formidable par rapport à ZooKeeper, qui est davantage une bibliothèque client Java, car vous pouvez désormais communiquer avec etcd depuis n'importe laquelle de vos applications. Beaucoup de ces plateformes open source en tant que service que j'ai mentionnées plus tôt, comme Deis et Flynn et même Kubernetes de Google, utilisent etcd. Si vous utilisez CoreOS, etcd est déjà là pour vous et intégré.

Un autre est sorti, également basé sur REST, appelé Consul . Il est publié par les gens de HashiCorp qui créent Vagrant et Packer et des tonnes d'autres outils géniaux. C'est en fait Consul que nous avons décidé d'utiliser.

18:33 Consul Architecture

Voici un schéma des bases de Consul. Vous pouvez voir qu’il y a plusieurs centres de données, chacun avec trois serveurs. Dans le centre de données 1, il y a également des clients. Ce qui est intéressant, c’est que parmi vos agents de serveur, vous élirez un agent principal et tous vos clients seront alors réellement informés non seulement de tous les serveurs, mais également de tous les autres clients. Ils utilisent ensuite un protocole de ragots pour communiquer avec tous les autres agents.

Cela me rappelle une vieille publicité d'AT&T où vous dites à deux amis qu'ils disent à deux autres amis, qui disent à deux autres amis, et le message se propage ainsi dans tout votre réseau de nœuds. [ Rédacteur en chef – Enfin, presque : c'était une publicité pour le shampooing Faberge Organics . ] Cela se compare à etcd ou ZooKeeper où vous avez essentiellement juste des agents de serveur et vos clients s'y connectent.

Avec la façon de faire de Consul, vous exécuteriez en fait un client Consul sur pratiquement tous les serveurs, partout où nous déployons Docker et partout où nous exécutons nos équilibreurs de charge. Vous pouvez donc toujours communiquer avec cette API sur le port localhost 8500.

19h30 Consul Caractéristiques

Tout comme etcd, [Consul] est un magasin de clés-valeurs distribué. Vous pouvez définir et obtenir des clés et elles conserveront leur linéarisabilité afin que vous puissiez vous assurer qu'elles sont toujours cohérentes. Il y a quelques pièges ici, mais leur documentation sur l'origine de ces problèmes est phénoménale. Cependant, contrairement à etcd, ils traitent la découverte de services comme un citoyen de première classe.

Au lieu de vous contenter de paires clé-valeur, vous pouvez également enregistrer des services, par exemple une API. Lorsque vous enregistrez un service, vous indiquez à Consul sur quel nœud il s'exécute. Cela signifie que lorsque nous déployons un conteneur, nous demandons également à Consul d’enregistrer également cette API de service sur cet hôte.

De plus, Consul a distribué des contrôles de santé, vous pouvez donc désormais définir des contrôles de santé de style Nagios directement dans votre plateforme de découverte de services. Lorsque vous décidez d'interroger Consul, vous pouvez demander une liste de tous les emplacements où le service API est exécuté. Vous pouvez envoyer un signalement pour « tous », « seulement en état de passage » ou « seulement en mauvais état ».

Il prend également en charge plusieurs centres de données. J'ai mentionné que vous devriez exécuter ce client Consul partout. Lorsque vous le démarrez, vous passez un paramètre spécifiant le centre de données. Si vous disposez d'un centre de données Est et d'un centre de données Ouest, vous pouvez interroger votre client Consul local sans avoir à connaître le centre de données, en demandant une adresse ou autre chose.

En fait, nous utilisons le centre de données comme limite pour nos environnements de préparation et de production. Notre configuration pour une application en phase de test pourrait dire : « demandez-moi où se trouve MySQL.services.consul ». Qu'il s'agisse d'une exécution sur un nœud intermédiaire ou sur un nœud de production, vous obtiendrez la valeur correcte sans jamais avoir à prendre en compte le centre de données ou les environnements multiples.

L’autre avantage de ce logiciel (et d’etcd également) est qu’il dispose d’une fonction d’interrogation longue durée sur son interface HTTP. Cela signifie que vous pouvez interroger et demander une liste de tous les serveurs qui exécutent ce service, mais également garder la connexion ouverte pendant 60 secondes et être immédiatement averti si quelque chose change. Le temps de sondage peut en réalité aller jusqu’à 10 minutes. Cela signifie que vous pouvez recevoir une notification instantanée de tout changement apporté à votre infrastructure.

L’autre chose que j’ai déjà mentionnée est que vous pouvez développer la capacité de faire évoluer vos agents en ayant des clients partout. C'est génial car vous pouvez toujours parler à localhost.

La grande question est cependant la suivante : maintenant que ces données sont stockées sur une plateforme de découverte de services distribuée, comment configurer NGINX à partir de ces données ?

22:07 Modèle de consul

Heureusement, il existe un outil appelé Consul Template . Il est sorti littéralement hier, ce qui m'a fait changer mes diapositives pour aujourd'hui à partir de ce moment. Il s'appelait auparavant « Consul HAProxy », ce qui était un nom terrible car il n'était pas réellement spécifique à HAProxy.

Consul Template vous offre une interface très simple pour créer des modèles permettant de vous abonner aux modifications des services, aux contrôles de santé de ces services et même à un magasin de clés-valeurs. Cela vous permet de stocker des paramètres tels que [le nombre de] travailleurs NGINX dans le magasin clé-valeur et de régénérer votre configuration lorsque cela change.

La grande capacité ici est de générer des fichiers à partir de modèles, ce qui ressemble beaucoup à ce que nous faisions avec Chef auparavant. La plus grande différence ici est qu'il utilise le langage de création de modèles Golang par opposition à ERB, qui est Ruby. Une fois que vous avez modifié un fichier, vous pouvez éventuellement appeler une commande sur la modification, par exemple service nginx reload .

22:59 Commande pour démarrer le modèle Consul

Voici donc un exemple d’exécution de Consul Template sur la ligne de commande. Vous le pointez vers votre hôte Consul réel, qui dans ce cas est consul‑prod.example.com . Dans un environnement de production réel, je suggérerais d'exécuter Consul partout et de se connecter à localhost.

Ensuite, vous transmettez un fichier modèle, qui est un modèle Golang. Dans notre cas, nous transmettons /etc/consul‑templates/api . Ensuite, vous transmettez le fichier à écrire réellement, donc dans notre cas /etc/NGINX/sites‑enabled/api . Ensuite une commande à appeler : service nginx reload .

23:32 Configuration NGINX avec le modèle Consul

Le modèle Consul ressemble beaucoup à une diapositive que j'avais avant, sauf qu'au lieu d'ERB c'est Golang. Nous définissons donc ici deux amonts. L'une s'appelle API et l'autre page d'accueil . Nous disposons d’une instruction de plage pour l’API de service, ainsi que de variables intégrées permettant de récupérer l’adresse IP et le port où ce service s’exécute réellement.

23:54 Gestion de la configuration avec le modèle Consul

L’avantage du modèle Consul et de son utilisation de cette manière est que la convergence des changements de service est rapide. Avant le déploiement avec Docker, Chef s'exécutait environ toutes les 5 ou 10 minutes selon la machine. C'était assez rapide pour nous car nous étions en déploiement sur place.

Maintenant que nous construisons un système de déploiement plus avancé, nous devons être informés de ces changements en quelques secondes plutôt qu’en quelques minutes. En fait, nous l'obtenons en quelques millisecondes, en moyenne probablement environ 200 millisecondes.

Cependant, la gestion de la configuration est toujours nécessaire pour générer des modèles. Nous ne pouvons pas simplement remplacer Chef par Consul. Nous devons encore déterminer comment nous allons déployer Consul, Consul Template et tout le reste.

24:35 Utilisation de Chef pour déployer Consul

Nous utilisons donc en fait des modèles Chef pour déployer nos modèles Consul, ce qui semble un peu compliqué. Ce que nous faisons en premier dans notre recette de Chef est d’interroger notre hôte Consul pour obtenir une liste de tous les services. Ensuite, nous générons un modèle Consul [avec les déclarations de modèle et de source ] et nous transmettons notre certificat SSL et les emplacements de clé et rechargeons consul-template . [ Rédacteur en chef – M. Reedy a d'abord fait référence à consul-haproxy , qui apparaît dans la première déclaration de notification sur la diapositive. Il s'est ensuite corrigé et a précisé que la diapositive est antérieure à la publication du modèle Consul. ]

Nous écrivons également un fichier de configuration pour le modèle Consul et nous transmettons [des variables spécifiant] l'hôte, la source, la destination et la commande de rechargement du Consul. C’est vraiment la manière dont nous utilisons Chef et Consul ensemble pour obtenir des mises à jour instantanées de nos configurations NGINX.

25:44 Conseils de pro

Ensuite, j’ai quelques conseils de pro sur Chef, Consul et la configuration NGINX en général.

25:52 Recherche partielle du chef

Le premier conseil est que si vous utilisez la recherche Chef pour trouver où vos services s’exécutent, vous devriez examiner la recherche partielle Chef. Le problème avec la recherche Chef est qu'elle fait une copie de l'ensemble du nœud, y compris tous les attributs. Si vous enregistrez beaucoup de choses dans les attributs de votre nœud, vous devrez les transférer via le réseau tout en communiquant avec votre serveur Chef, et également les stocker en mémoire.

Si la recherche Chef renvoie des centaines ou des milliers de serveurs, vous pouvez facilement voir comment vous pourriez manquer de mémoire pour votre recette réelle. La recherche partielle vous permet de renvoyer uniquement les clés qui vous intéressent.

Par exemple, nous avons d’abord eu

nœuds = recherche(:node, 'recette:belly-api')

Cette recherche renvoie chaque élément d’information sur chaque objet. Cela inclut des informations sur son espace disque, sa RAM, son processeur et toutes les applications qui ont écrit leurs propres attributs de nœud.

Au lieu de cela, nous pouvons utiliser une recherche partielle où nous créons un nouveau hachage appelé search_keys et lui donnons une liste de clés qui nous intéressent – dans ce cas, uniquement le nom et l'adresse IP. Ensuite, nous accédons à l'API très similaire appelée partial_search et nous transmettons le paramètre supplémentaire [ keys ].

26:53 DNS

La deuxième chose qui nous a mordu lorsque nous sommes passés à l’équilibrage de charge devant S3 et Heroku est que NGINX utilise DNS pour résoudre les noms d’hôtes dans les blocs en amont uniquement lors du rechargement de la configuration. Cela signifie que si vous définissez un serveur en amont sur s3.amazonaws.com ou anything.herokuapp.com et qu'il change, votre équilibreur de charge ne connaît pas la nouvelle adresse IP jusqu'au prochain rechargement.

La façon dont nous avons contourné ce problème est d’effectuer la résolution DNS dans Chef, puis de déclencher le rechargement NGINX lorsque cela change. Cela a conduit à un deuxième problème : [l’ordre des adresses dans une réponse DNS] n’est pas toujours le même, assurez-vous donc de trier également la réponse avant de l’écrire dans votre modèle.

27:36 Éviter les configurations obsolètes

L’autre problème lorsque vous commencez à déployer des tonnes de services est que vous souhaitez éviter une configuration obsolète. [ Rédacteur en chef – M. Reedy interrompt brièvement la présentation pour répondre à une question du public. ] Dans Apache, NGINX et d’autres systèmes UNIX, un modèle de configuration courant consiste à avoir un dossier conf.d , puis à tout charger à partir de celui-ci. Donc si je déploie les services A, B et C, je crée service-a.conf , service-b.conf et service-c.conf .

Ensuite, je décide de remplacer le service B par D, et j'ai maintenant quatre configurations dans le dossier de configuration NGINX mais le service B n'existe plus. Vous pourriez vous retrouver avec des conflits entre B et D car ils ont un nom d'hôte similaire.

Nous avons ciblé deux méthodes pour y parvenir [supprimer la configuration obsolète] dans le passé. Avec les modèles, vous pouvez ajouter une fonction :delete , mais cela devient très vite assez difficile à gérer. Nous avions essentiellement une liste d’anciens services que nous essayions toujours de supprimer s’ils existaient. Cela n’a pas vraiment fonctionné.

Une autre chose que vous pouvez faire est de restituer toutes les configurations de votre site dans un seul fichier. Beaucoup de gens ont appelé cela « déplacer l’idempotence vers le haut ». Essentiellement, au lieu d’avoir une configuration NGINX qui se charge à partir de plusieurs sources, mettez le tout dans votre nginx.conf .

Cela rend la tâche un peu difficile lorsque vous vous connectez réellement à la boîte, mais nous espérons que nous arrivons au point où vous ne résolvez pas de problèmes avec un fichier de configuration en direct en production. Si c'est encore un peu trop difficile à gérer dans vos recettes Chef, ce que nous faisons est d'avoir un nginx.conf qui charge une série de sites différents. Par exemple, l'un de nos fichiers de configuration de site répertorie environ 30 services, puis nous en avons un pour celui d'Heroku, un pour tous les services S3, etc.

Ainsi, si vous restituez toutes les configurations de votre site dans un seul fichier ou dans une petite quantité de fichiers, vous n’avez pas à vous soucier du nettoyage après vous-même. Si du point de vue de Chef, un service disparaît, Chef arrête simplement de le restituer dans le fichier réel.

30:35 Questions

Q: Comment s'est déroulé le programme Consul pour vous jusqu'à présent ?

UN: Nous avons adoré Consul, et ce que j’aime vraiment à son sujet par rapport à quelque chose comme etcd, c’est qu’il existe des services qui continuent d’être construits dessus. Je n’ai pas à m’inquiéter de la découverte de services. En fait, si vous avez des applications héritées et que vous déployez (disons) vos serveurs MySQL à l’aide de Consul, Consul fournit également une interface DNS.

Votre application n'a pas besoin de connaître Consul ; elle peut simplement interroger « quelle adresse puis-je obtenir de mysqldb.services.consul ? ». Dans ce cas, Consul est le serveur DNS. Vous configurez votre infrastructure DNS de sorte que si le TLD [domaine de premier niveau] se termine par .consul , la requête soit acheminée vers Consul.

Cela a bien fonctionné pour nous. Nous manquons d’environ 3 nœuds en production pour les agents serveur et environ 60 clients. Nous n’avons rencontré aucun problème. Ils continuent d'ajouter des fonctionnalités et ne brisent pas la compatibilité descendante, donc la mise à niveau a toujours été formidable.

Q: Utilisez-vous NGINX Plus ?

UN: Nous ne le faisons pas. Nous avons étudié cette question précisément pour cela lorsque nous avons commencé à travailler avec Consul. Si nous n’avions pas besoin d’un système de création de modèles, ce serait formidable car nous pourrions simplement avoir un script qui écoute cette longue interrogation HTTP et qui parle ensuite à l’API NGINX en votre nom. Le seul problème est que vous souhaitez probablement également un système de création de modèles au cas où NGINX redémarrerait. Cela rechargerait vos configurations en amont directement là.

D’autres personnes ont également réalisé des travaux dans NGINX Lua pour interroger Consul directement. Je n’ai pas encore vu de bonne mise en œuvre, car elles ont tendance à tomber dans l’une des deux catégories suivantes. La première est qu’ils interrogent Consul sur chaque requête HTTP, ce qui est lent. La deuxième est qu'ils le chargent au moment de l'exécution de la configuration et vous vous retrouvez avec le même problème qu'avec DNS. Donc, pour l’instant, le modèle est le meilleur, mais je ne serais pas surpris si nous voyions un moyen de le faire avec NGINX Lua à l’avenir.

Q: Vous éloigneriez-vous un jour de Chef ?

UN: Il n’existe pas de moyen efficace intégré à Consul pour maintenir ces modèles, et nous déployons déjà NGINX avec Chef. Nos recettes comportent des centaines, voire des milliers de lignes à ce stade pour toutes les autres choses que nous faisons avec NGINX, y compris la journalisation, le traçage et un peu d'OAuth. Je ne nous vois pas abandonner Chef dans notre infrastructure et le remplacer, mais c’est une excellente amélioration et un bon moyen d’obtenir des notifications rapides.

Q: Combien de frais généraux Chef fournit-il ?

UN: Étant donné que la plupart de nos machines effectuent une seule tâche, nos frais généraux Chef sont assez faibles. L'utilisation de la RAM est faible lorsqu'elle est inactive. En fait, il se trouve dans une minuterie et peut se déconnecter. D'autres personnes l'exécutent également dans un cron s'ils ne se soucient pas de la vitesse à laquelle il converge. Nous constatons une légère augmentation du CPU dans certaines de nos recettes les plus lourdes, mais rien que nous ne puissions pas simplement déployer un autre serveur pour résoudre.

Q: Combien avez-vous réalisé avec CloudFormation ?

UN: Nous n'utilisons pas encore CloudFormation. C’est sur notre radar, mais l’un des changements que nous avons apporté est d’utiliser beaucoup plus de groupes de mise à l’échelle automatique. Le fonctionnement est le suivant : lorsqu’une instance apparaît, elle disposera de données utilisateur contenant sa liste d’exécution Chef.

Une nouvelle machine sera ajoutée à un cluster avec une clé déjà basée sur son image, elle pourra donc communiquer avec notre serveur Chef, s'enregistrer et récupérer les livres de recettes dont elle a besoin. Cela résout la plupart des problèmes liés à CloudFormation pour nous, car nous n’utilisons pas beaucoup d’autres outils AWS qui iraient de pair avec cela.

Q: Comment gérer un serveur détruit ?

UN: Si un serveur disparaît dans un groupe Auto Scaling, vous pouvez utiliser Amazon SNS [Simple Notification Service] pour recevoir une notification à ce sujet. Nous avons un service très simple qui écoute ces notifications et nettoie ensuite le serveur Chef.

Q: Avez-vous utilisé OpsWorks d'AWS ?

UN: Nous ne l’avons pas fait. Nous utilisons le Chef hébergé depuis le début et cela a très bien fonctionné pour nous. Je n’en suis pas sûr, mais je pense qu’OpsWorks ressemble davantage à Chef Solo, où vous l’utilisez uniquement pour le provisionnement. Nous exécutons toujours Chef Agent sur presque toutes nos machines et utilisons ces mêmes recettes Chef pour générer des conteneurs Docker pour le développement.

36:31 Coordonnées


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."