Comment dois-je stocker mes variables d'environnement?

11

Il s'agit d'une question très large sur les méthodes et les conseils concernant les variables / structure de l'environnement. Mais en fin de compte, je cherche des réponses à la question très spécifique de "Comment dois-je stocker mes variables d'environnement?"

Tout d'abord quelques clarifications:

  • Un environnement pour moi peut être de 3 à 10 serveurs et est un moyen de contenir l'infrastructure d'un client spécifique.
  • À l'intérieur de chaque environnement, il y a quelques variables qui sont pour la plupart générées automatiquement à partir de quelques entrées clés (nom, taille, etc.).

Dans l'état actuel des choses, nous stockons toutes nos variables d'environnement dans une structure comme celle-ci:

<playbook>.yml                   # Various playbooks for deployment
roles/windows                    # Ansible role for Ubuntu
roles/ubuntu                     # Ansible role for Ubuntu
config/hosts/<name>.yml          # Ansible inventory
config/hosts/vars/<name>.json    # Environment specific variables 

À l'heure actuelle, la configuration est initialisée en tant que sous-module dans le référentiel git ci-dessus. Comme le fichier de variables change assez fréquemment, cela a provoqué des problèmes de modification des données, une, deux ou même trois fois entre les validations, rendant les modifications de plus en plus difficiles à suivre.

Comme je le vois personnellement, nous devrions chercher à stocker toutes nos variables client de manière centralisée / évolutive, puis à s'y connecter avec un inventaire dynamique avec .

Je comprends qu'il existe quelques technologies qui semblent faire une partie de ce qui pourrait être nécessaire, comme Consul, mais elles semblent fonctionner mieux dans un environnement qui sert une grande application plutôt que de nombreuses petites plus légèrement différentes.

Je vois essentiellement que nous devons écrire un script d'inventaire, puis simplement pousser toutes nos données dans une base de données construite à des fins non spécifiques, puis continuer comme si rien n'avait changé. Je vois cela en théorie comme un moyen de réduire potentiellement un grand nombre de données que nous stockons actuellement et peut-être d'examiner différentes façons de stocker les données plutôt que de simplement augmenter ce qui les sert à nouveau.

J'espère que quelqu'un a une certaine expérience dans la mise en œuvre d'une infrastructure en tant que code lorsqu'il doit gérer de nombreux environnements plus petits, par opposition à un, deux ou trois énormes.

Aucune suggestion?

Naphta
la source

Réponses:

13

J'ai eu deux fois à faire des variables d'environnement de manière évolutive et aucune n'a été parfaite car, comme je l'ai découvert, c'est une chose très délicate à faire. Je vais résumer ci-dessous mes deux expériences:

Facteurs communs

  • Les variables d'environnement sont stockées dans un référentiel distinct du code source d'origine (elles sont sous-modulées ensemble mais sont toujours basées sur des référentiels séparés)
  • Il existe un processus de «construction» distinct pour l'artefact et ses variables.
  • Il n'y a pas de processus de publication distinct pour les variables d'environnement. Si vous voulez changer les variables d'environnement, vous devez passer par les mêmes tableaux de révision des changements et

Utilisation des paires Consul KV

Les variables d'environnement sont chargées à partir d'un référentiel d'artefacts (jamais le référentiel git d'origine) et chargées dans une arborescence de paires KV à espace de noms, par exemple

/env/dev1/my/application/v1.1.1

Où dev1 est le nom de l'environnement, my / application est l'espace de noms de l'application et v1.1.1 est la version des variables d'environnement à utiliser.

Pour les développeurs, toutes ces choses sont invisibles. Au moment de l'exécution, la plate-forme vérifie que l'environnement existe dans le cluster de consul actuel (si ce n'est pas le cas, il y a des erreurs), elle vérifie ensuite le sous-arbre pour l'espace de noms des applications (de cette façon, il ne peut y avoir de contamination croisée lorsqu'une application fait référence à une autre application vars), le numéro de version de la configuration est tiré de l'étiquette connectée à l'artefact déployable. La mise à jour de cette étiquette est l'élément clé ici car cela signifie que si nous perdions les deux centres de données de production, nous pourrions à nouveau protéger l'environnement en lisant simplement les métadonnées de nos artefacts déployables et en chargeant toutes les variables d'environnement dans le magasin KV.

Problèmes avec cette approche Les développeurs ont toujours, et je veux dire à chaque fois, trouvé un moyen de glisser les modifications de configuration dans l'environnement qui ont eu des impacts significatifs sur la façon dont l'application s'exécuterait. Parce qu'il a toujours été plus facile de faire approuver les changements de configuration que les changements de code.

Stockage d'un artefact de «déploiement» avec des variables intégrées

Cela couple étroitement la version exacte de l'artefact à la version de configuration. Si vous avez modifié la configuration, vous avez dû reconstruire cet artefact de déploiement.

L'artefact de déploiement lui-même était essentiellement un fichier yaml qui contenait l'URL du binaire libérable et toute la configuration qui lui était attachée.

La plate-forme contient des composants pour lire les variables puis les extraire dans l'arborescence des processus de l'application au démarrage.

Jusqu'à présent, cela a été beaucoup plus réussi, car il existe un artefact dont nous pouvons retracer l'historique et que nous pouvons tenir devant n'importe quel comité d'examen et dire "c'est le seul artefact qui nous intéresse, nous n'avons pas besoin de regarder toute autre modification, uniquement les modifications de cette chose "(par exemple. Version de l'application à déployer, variables d'environnement incluses, etc.

Cela rend un peu plus difficile pour les développeurs d'essayer de créer une logique dans leur application qui changera son comportement en fonction des variables afin qu'ils puissent glisser les changements sans passer par les cycles de test appropriés.

Points bonus

Considérez les secrets d'application. Jusqu'à présent, notre solution a consisté à fournir une clé RSA publique que les équipes de développement utilisent pour chiffrer un magasin de clés Java étendu (presque chaque langue a une bibliothèque quelque part qui peut lire les magasins de clés Java) .Elle est ensuite traitée comme un troisième type d'artefact et est tiré sur le serveur, déchiffré avec notre clé privée de plate-forme et fourni à l'application au moment de l'exécution.

Certes, la gestion des secrets est sa propre boîte de vers. Mais cela vaut probablement la peine d'être considéré.

hvindin
la source
2
Re: secrets d'application, je suggérerais de jeter un œil à Vault ( vaultproject.io ) car il fait également partie de la chaîne d'outils de Hashicorp et s'intègre plutôt bien avec Consul (et d'autres outils de cette boîte)
Michael Bravo
En fait, j'ai été très déçu par le coffre-fort étant donné la qualité des trucs hashicorp. Essentiellement, trois lacunes majeures dans leur produit par rapport au reste du marché - 1. «Secrets for secrets» est essentiellement ce à quoi le modèle se résume. J'obtiens ou utilise un HSM. Mais c'est essentiellement du commerce de secrets. 2. Compatibilité des outils, contrairement à leurs autres outils, il n'y a pas de support pour les plugins 3. Prix. Je ne le croyais pas quand on m'a dit à l'entreprise que je pensais que le coffre-fort était cher. Ils ont rejeté les produits parce qu'ils étaient trop bon marché, c'est foiré. Mais le coffre-fort était tellement important qu'ils n'y ont même pas pensé.
hvindin
Il convient de noter que cela ne coûte que si vous utilisez une version payante . Le produit principal de Vault est open-source. Bien sûr, ils ne répertorient pas les prix des versions pro / entreprise sur leur site, donc je ne sais pas à quel point cela peut être raisonnable pour ces éditions.
Adrian
Hm, je n'ai pas remarqué cette omission de mon commentaire, bien que pour être honnête, mes deux premiers problèmes avec le coffre-fort persistent. Bien que, pour me qualifier, ce soient mes réflexions sur le coffre-fort par rapport aux autres produits hashicorp, qui, je pense, sont tous très bons. Par rapport à d'autres produits sur le marché, la fonction similaire est probablement comparable, juste pour une raison bien plus chère que prévu.
hvindin
Pouvez-vous donner un exemple de "construire une logique dans leur application qui changera son comportement en fonction des variables afin qu'ils puissent glisser dans les changements sans passer par les cycles de test appropriés."? Cela ressemble à quelque chose de vraiment commun, mais je ne peux tout simplement pas imaginer un exemple concret.
kenchew
3

Si vos environnements sont par client, je suggérerais dans votre cas spécifique d'avoir un référentiel par client . (En général, il s'agit d'un référentiel par environnement.) Ce référentiel aurait une structure de répertoire standard pour les variables d'environnement, les variables et inventaires ansibles, les secrets fortement cryptés (jetons d'accès au compte, clés privées, etc.). Vous git sous-modulez le code dans ces référentiels. Je le ferais probablement dans plusieurs référentiels. Un pour les rôles et modules ansibles, un pour les scripts de maintenance et de déploiement, un pour chaque application principale exécutée dans les environnements.

Maintenant, vous pouvez éventuellement fourcher le code ou épingler le sous-module à une balise spécifique pour la publication , en vous assurant que le code gérant l'environnement du client ne changera pas à moins qu'il ne soit testé et publié.

Si vous utilisez un référentiel d'artefacts , assurez-vous que les artefacts sont correctement versionnés et que ces versions sont correctement spécifiées dans les variables d'environnement.

L'automatisation est importante car les variables d'environnement ne doivent pas être mises à jour par les humains dans la mesure du possible, mais générées par des scripts. Assurez-vous qu'il n'y a presque pas de mises à jour manuelles dans l'inventaire par client et que les développeurs ne mettent à jour que les référentiels de code. S'ils souhaitent modifier la configuration, cela doit être fait pour l'un des scripts de génération, qui est ensuite exécuté pour générer les variables et le diff est validé dans le référentiel client. Il est avantageux de configurer une intégration continue pour ce processus. Sans cela à un moment donné, il y aura trop de référentiels à maintenir .

Jiri Klouda
la source
Une seule objection: les secrets ne doivent pas entrer dans un référentiel de contrôle de version à moins qu'il n'ait une prise en charge stricte du contrôle d'accès. Git ne sait pas - quiconque tire sur le référentiel peut voir les secrets, ce qui peut être un problème - ce ne sont plus des secrets.
Dan Cornilescu
Bonne prise. Ce sont des secrets cryptés. Les clés de déchiffrement sont transitoires.
Jiri Klouda