Terraformer - Infrastructure à coder

Terraformer - Infrastructure à coder
Je voudrais vous parler du nouvel outil CLI que j'ai écrit pour résoudre un vieux problème.

problème

Terraform est depuis longtemps un standard dans la communauté Devops/Cloud/IT. La chose est très pratique et utile pour gérer l'infrastructure en tant que code. Il existe de nombreux délices dans Terraform ainsi que de nombreuses fourchettes, couteaux tranchants et râteaux.
Avec Terraform, il est très pratique de créer de nouvelles choses puis de les gérer, les modifier ou les supprimer. Que devraient faire ceux qui disposent d'une énorme infrastructure dans le cloud et non créée via Terraform ? Réécrire et recréer l'intégralité du cloud est en quelque sorte coûteux et dangereux.
J'ai rencontré ce problème lors de 2 tâches, l'exemple le plus simple est lorsque vous voulez que tout soit dans Git sous forme de fichiers Terraform, mais que vous avez plus de 250 buckets et que c'est beaucoup de les écrire manuellement dans Terraform.
Il est aide depuis 2014 à Terrafom qui a été fermé en 2016 dans l'espoir d'y importer.

En général, tout est comme sur la photo uniquement de droite à gauche

Avertissements : L'auteur ne vit pas la moitié de sa vie en Russie et écrit peu en russe. Attention aux fautes d'orthographe.

Решения

1. Il existe une solution toute faite et ancienne pour AWS terraformer. Lorsque j’ai essayé d’y faire passer mes plus de 250 seaux, j’ai réalisé que tout y allait mal. AWS introduit depuis longtemps de nombreuses nouvelles options, mais la terraformation ne les connaît pas et en général c'est Ruby le modèle semble clairsemé. Après 2 heures du soir, j'ai envoyé Demande de tirage pour y ajouter plus de fonctionnalités et j'ai réalisé qu'une telle solution n'était pas du tout adaptée.
Comment fonctionne la terraformation : elle prend les données du SDK AWS et génère tf et tfstate via un modèle.
Il y a 3 problèmes ici :
1. Il y aura toujours un décalage dans les mises à jour
2. Les fichiers tf sortent parfois cassés
3. tfstate est collecté séparément de tf et ne converge pas toujours
En général, il est difficile d'obtenir un résultat dans lequel le « plan de terraformation » indique qu'il n'y a aucun changement.

2. `terraform import` est une commande intégrée à terraform. Comment ça marche?
Vous écrivez un fichier TF vide avec le nom et le type de ressource, puis exécutez `terraform import` et transmettez l'ID de ressource. terraform contacte le fournisseur, reçoit les données et crée un fichier tfstate.
Il y a 3 problèmes ici :
1. Nous obtenons uniquement un fichier tfstate, et le tf est vide, vous devez l'écrire manuellement ou le convertir à partir de tfstate
2. Ne peut fonctionner qu'avec une seule ressource à la fois et ne prend pas en charge toutes les ressources. Et que dois-je faire encore avec plus de 250 buckets ?
3. Vous devez connaître l'ID des ressources, c'est-à-dire que vous devez l'envelopper dans du code qui obtient la liste des ressources.
En général, le résultat est partiel et ne s'adapte pas bien

Ma décision

Exigences:
1. Possibilité de créer des fichiers tf et tfstate pour les ressources. Par exemple, téléchargez tous les compartiments/groupes de sécurité/équilibreur de charge et ce « plan Terraform » a renvoyé qu'il n'y a aucun changement
2. Vous avez besoin de 2 cloud GCP + AWS
3. Solution globale facile à mettre à jour à chaque fois et ne perdant pas de temps sur chaque ressource pour 3 jours de travail
4. Rendez-le Open Source : tout le monde a le même problème

Le langage Go est la raison pour laquelle je l'aime, et il possède une bibliothèque pour créer des fichiers HCL qui est utilisée dans Terraform + beaucoup de code dans Terraform qui peut être utile

Chemin

Première tentative
J'ai commencé avec une version simple. Contacter le cloud via le SDK pour la ressource requise et la convertir en champs pour terraform. La tentative a échoué immédiatement sur le groupe de sécurité car je n'aimais pas le délai d'un jour et demi pour convertir uniquement le groupe de sécurité (et il y a beaucoup de ressources). Pendant longtemps, puis les champs peuvent être modifiés/ajoutés

Deuxième essai
Basé sur l'idée décrite ici. Prenez et convertissez simplement tfstate en tf. Toutes les données sont là et les champs sont les mêmes. Comment obtenir un état complet pour de nombreuses ressources ?? C'est là que la commande « terraform refresh » est venue à la rescousse. terraform prend toutes les ressources dans tfstate et, par ID, extrait les données sur elles et écrit tout dans tfstate. Autrement dit, créez un tfstate vide avec uniquement des noms et des identifiants, exécutez « Terraform Actualiser » et nous obtenons ensuite des tfstates complets. Hourra!
Passons maintenant à la pornographie récursive consistant à écrire un convertisseur de tfstate en tf. Pour ceux qui n'ont jamais lu tfstate, c'est du JSON, mais spécial.
Voici ses attributs de partie importante

 "attributes": {
                            "id": "default/backend-logging-load-deployment",
                            "metadata.#": "1",
                            "metadata.0.annotations.%": "0",
                            "metadata.0.generate_name": "",
                            "metadata.0.generation": "24",
                            "metadata.0.labels.%": "1",
                            "metadata.0.labels.app": "backend-logging",
                            "metadata.0.name": "backend-logging-load-deployment",
                            "metadata.0.namespace": "default",
                            "metadata.0.resource_version": "109317427",
                            "metadata.0.self_link": "/apis/apps/v1/namespaces/default/deployments/backend-logging-load-deployment",
                            "metadata.0.uid": "300ecda1-4138-11e9-9d5d-42010a8400b5",
                            "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",

Il y a:
1. identifiant - chaîne
2. métadonnées - un tableau de taille 1 et un objet avec des champs décrits ci-dessous
3. spec - hachage de taille 1 et clé, valeur qu'il contient
Bref, un format ludique, tout peut être profond sur plusieurs niveaux

                   "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",
                            "spec.0.selector.0.match_expressions.#": "0",
                            "spec.0.selector.0.match_labels.%": "1",
                            "spec.0.selector.0.match_labels.app": "backend-logging-load",
                            "spec.0.strategy.#": "0",
                            "spec.0.template.#": "1",
                            "spec.0.template.0.metadata.#": "1",
                            "spec.0.template.0.metadata.0.annotations.%": "0",
                            "spec.0.template.0.metadata.0.generate_name": "",
                            "spec.0.template.0.metadata.0.generation": "0",
                            "spec.0.template.0.metadata.0.labels.%": "1",
                            "spec.0.template.0.metadata.0.labels.app": "backend-logging-load",
                            "spec.0.template.0.metadata.0.name": "",
                            "spec.0.template.0.metadata.0.namespace": "",
                            "spec.0.template.0.metadata.0.resource_version": "",
                            "spec.0.template.0.metadata.0.self_link": "",
                            "spec.0.template.0.metadata.0.uid": "",
                            "spec.0.template.0.spec.#": "1",
                            "spec.0.template.0.spec.0.active_deadline_seconds": "0",
                            "spec.0.template.0.spec.0.container.#": "1",
                            "spec.0.template.0.spec.0.container.0.args.#": "3",

En général, si quelqu'un souhaite résoudre un problème de programmation pour un entretien, demandez-lui simplement d'écrire un analyseur pour cette tâche :)
Après de nombreuses tentatives pour écrire un analyseur sans bugs, j'en ai trouvé une partie dans le code Terraform, et la partie la plus importante. Et tout semblait bien fonctionner

Tentative trois
Les fournisseurs Terraform sont des binaires qui contiennent du code avec toutes les ressources et la logique nécessaires pour travailler avec l'API cloud. Chaque cloud a son propre fournisseur et terraform lui-même ne les appelle que via son protocole RPC entre deux processus.
J'ai maintenant décidé de contacter les fournisseurs Terraform directement via des appels RPC. Cela s'est avéré magnifique et a permis de remplacer les fournisseurs Terraform par des fournisseurs plus récents et d'obtenir de nouvelles fonctionnalités sans changer le code. Il s'avère également que tous les champs de tfstate ne devraient pas être dans tf, mais comment pouvez-vous le savoir ? Demandez simplement à votre fournisseur à ce sujet. Puis une autre pornographie récursive d'assemblage d'expressions régulières a commencé, recherchant en profondeur des champs à l'intérieur de tfstate à tous les niveaux.

En fin de compte, nous avons obtenu un outil CLI utile qui dispose d'une infrastructure commune pour tous les fournisseurs Terraform et vous pouvez facilement en ajouter un nouveau. De plus, l’ajout de ressources nécessite peu de code. Plus toutes sortes de cadeaux tels que des connexions entre les ressources. Bien sûr, il y avait de nombreux problèmes différents qu’il est impossible de tous décrire.
J'ai nommé l'animal Terrafomer.

Final

En utilisant Terrafomer, nous avons généré 500 à 700 XNUMX lignes de code tf + tfstate à partir de deux nuages. Nous avons pu prendre des éléments hérités et commencer à les toucher uniquement via Terraform, comme dans la meilleure infrastructure en tant qu'idées de code. C'est tout simplement magique lorsque vous prenez un énorme cloud et que vous le recevez via une équipe sous la forme de fichiers de travail Terraform. Et puis grep/replace/git et ainsi de suite.

Je l'ai passé au peigne fin et mis en ordre, j'ai obtenu la permission. Sortie sur GitHub pour tout le monde jeudi (02.05.19/XNUMX/XNUMX). github.com/GoogleCloudPlatform/terraformer
Déjà reçu 600 étoiles, 2 pull request pour l'ajout de la prise en charge d'openstack et de kubernetes. Bon retour. En général, le projet est utile aux personnes
Je conseille à tous ceux qui souhaitent commencer à travailler avec Terraform de ne pas tout réécrire pour cela.
Je serai heureux de répondre aux demandes, aux problèmes et aux étoiles.

Démo
Terraformer - Infrastructure à coder

Source: habr.com

Ajouter un commentaire