Chercher à mettre en place des systèmes robustes implique obligatoirement d’anticiper des pannes. N’avez-vous jamais rêvé d’avoir la possibilité de créer des enregistrements DNS dans un environnement multitenant, sans problèmes et sans créer d’incidents de production ? Le faire d’une manière unique et commune, peu importe le fournisseur souhaité, de pouvoir migrer une zone complète en une commande, d’un fournisseur à un autre. OctoDNS répondra parfaitement à ces besoins et nous verrons dans cet article comment.
1. Présentation de l’outil
OctoDNS est un outil écrit en Python 3, rendu à la communauté open source en 2017 par la société GitHub qui propose une plateforme Git du même nom. Cet outil n’est utilisable qu’en ligne de commandes.
Le paquet OctoDNS embarque plusieurs outils qui sont :
- octodns-compare : permet de comparer les enregistrements de deux zones avant migration ;
- octodns-dump : permet de récupérer les enregistrements d’un fournisseur et de les transformer en fichier YAML au format OctoDNS ;
- octodns-report : permet de vérifier l’état des enregistrements créés et de reporter les informations qui divergent (entre la ou les source(s) et l’état de la zone après modification) ;
- octodns-sync : permet de vérifier les modifications qui vont être à apporter et appliquer les modifications (via l’option --doit) ;
- octodns-validate : permet de valider la configuration et les fichiers de zone, mais également de vérifier que vous n’avez pas écrit de bêtise (oublier un « . » à la fin d’un enregistrement CNAME par exemple) ;
- octodns-versions : permet de connaître la version d’OctoDNS et les modules de type provider/processor/plan_output que vous utilisez.
Tout comme beaucoup d’outils dans l’univers DevOps, OctoDNS utilise le format YAML (Yet Another Markup Language) comme Ansible [ANSIBLE] ou encore Kubernetes [KUBERNETES] pour la configuration ainsi que les enregistrements DNS.
OctoDNS se veut un outil dit avec état, ainsi, dans la même trempe que Terraform [TERRAFORM], celui-ci viendra vérifier par le biais de l’API du fournisseur ou de fichiers (comme pour bind9, /etc/hosts), les modifications à apporter (création, modification ou suppression).
Il est également important de souligner que vous pouvez l’utiliser avec à peu près n’importe quel fournisseur, que ça soit sur du Cloud (Route53 d’Amazon Web Services, NS1, CloudDNS de Google, Cloudflare) ou de l’on-premise (PowerDNS, Bind9, etc.).
Il reste qu’OctoDNS n’est aucunement là pour gérer la configuration même des serveurs DNS (configuration des ports d’écoute, des liens avec les bases de données). OctoDNS permet de manipuler les enregistrements.
2. Installer OctoDNS
Comme vous avez pu le lire plus haut, l’outil est écrit en Python 3, celui-ci s’installe par le biais du gestionnaire de paquets Python nommé pip. Pour ne pas interférer avec les dépendances Python locales de votre machine, nous passerons par un environnement virtuel.
Pour ce faire :
Vous voilà fin prêt à utiliser OctoDNS.
3. Création du projet
3.1 Création de la structure
OctoDNS est complètement ouvert à la structure de fichiers que vous souhaitez. Pour la démonstration, nous partirons sur une structure simple. Cette structure est la suivante :
├── config.yaml
└── zones
└── mazone.org.yaml
3.2 Configuration de la zone
Une fois que la structure est créée, il faut commencer par déclarer dans le fichier config.yaml les sources et destinations. Ces sources et destinations sont appelées providers, vous pouvez utiliser plusieurs types de sources et destinations, vous pouvez également les cumuler.
Ainsi, vous pouvez avoir en source, des fichiers statiques et un provider NetBox par exemple, pour récupérer la liste des enregistrements à créer.
Dans notre structure ci-dessus, nous partions d’un fichier de zone statique au format YAML, ainsi, nous utiliserons la classe Python suivante : octodns.provider.yaml.YamlProvider et la classe octodns.provider.route53.Route53Provider, c’est par le biais du mot class que nous indiquerons à OctoDNS, quelle classe Python utiliser.
En général, toutes les valeurs sensibles ou qui peuvent être fréquemment modifiées doivent provenir de variables d’environnement (exemple : secret_access_key: env/AWS_SECRET_ACCESS_KEY). Ce n’est pas obligatoire, mais cela reste plus que recommandé.
Ainsi, vous trouverez en Figure 1 une configuration simple d’OctoDNS.
3.3 Création des enregistrements
Suivant l’architecture réalisée en 3.1, nous allons pouvoir ajouter les enregistrements. Les enregistrements '' sont ceux de la racine de votre zone. C’est ici que vous pouvez déclarer vos records TXT, SOA par exemple.
Le format d’un enregistrement est le suivant :
Ainsi, pour l’exemple, nous créerons les enregistrements suivants :
Nom |
TTL |
Type |
Valeur(s) |
root (@) |
60 |
A |
10.0.0.1, 10.0.0.2 (round-robin) |
ns1 |
300 |
A |
10.0.0.1 |
Ce qui donne le fichier de zone OctoDNS suivant :
Comme vous le constatez, le format est à la portée de tout le monde. Ce format est lui unique à tous les providers OctoDNS.
4. En action
4.1 Vérifier nos enregistrements
Avant d’appliquer nos modifications, nous préférons vérifier que notre fichier de zone ne comporte pas d’énormités. Via la commande octodns-validate, nous allons donc pouvoir vérifier que nous n’avons pas fait d’erreurs.
N’oubliez pas de mettre un espace devant vos exports pour éviter d’avoir vos secrets dans votre historique bash.
Avant d’appliquer nos modifications, nous préférons vérifier que notre fichier de zone ne comporte pas d’énormités. Via la commande octodns-validate, nous allons donc pouvoir vérifier que nous n’avons pas fait d’erreurs.
En cas d’erreur, la commande vous retournera l’endroit précis où corriger cette erreur. L’étape de validation est aussi appelée étape de lint.
4.2 Vérifier des modifications
Les enregistrements ne possèdent pas d’erreur de syntaxe, nous allons pouvoir, à présent, vérifier les modifications qui vont être effectuées. Comme il était dit dans la présentation d’OctoDNS, OctoDNS est un outil avec état autrement appelé : stateful, qui cherchera donc à vérifier l’état de la configuration distante avant de la modifier pour n’appliquer que les modifications nécessaires (idempotence).
Cette étape peut être comparée au plan de Terraform, seules les modifications seront retournées, mais ne seront pas appliquées. Cette étape est idéale lors de l’intégration dans un dépôt Git où l’on viendrait faire des modifications à la zone par le biais d’une Pull Request ou Merge Request, de visualiser les modifications qui vont être appliquées.
Ainsi cette commande vous permettra d’éviter les suppressions ou modifications non souhaitées.
4.3 Appliquer des modifications
Pour appliquer les modifications que nous avons précédemment contrôlées, nous pouvons utiliser l’option --doit :
Il ne vous restera plus qu’à vérifier avec dig que les enregistrements ont bien été créés.
4.4 Déployer sur 2 destinations différentes
Pour des raisons de sécurité, nous souhaitons parfois, sur des zones à fort trafic, déployer notre zone sur plusieurs providers différents, par exemple Route53 d’un côté et Cloud DNS de l’autre. Ainsi, il conviendra de modifier simplement le fichier de configuration de la zone et d’y spécifier la configuration du nouveau provider et de le rajouter dans la section targets prévue à cet effet.
Ainsi, nous retrouverons dans notre configuration :
Pour installer le provider Cloud DNS, il suffit d’utiliser la commande : pip install octodns-googlecloud. À l’instar du provider Route53, la documentation officielle du provider Cloud DNS préconise l’utilisation du fichier .json contenant les identifiants.
Ainsi si nous vérifions ce qui va être appliqué, nous nous rendons compte qu’il ne cherchera pas à réappliquer la partie Route53, mais qu’il viendra peupler le provider Cloud DNS.
Il est intéressant de préciser que vous pouvez, dans un contexte de plusieurs cibles, spécifier une cible particulière en rajoutant l’option --target route53 par exemple.
4.5 Récupérer vos zones existantes dans OctoDNS
Si vous prenez la décision de vouloir gérer toutes vos zones avec OctoDNS, c’est tout à fait faisable sans trop d’effort, en effet, OctoDNS embarque la commande octodns-dump qui permet de récupérer la totalité des enregistrements d’une zone donnée et de les transposer au format OctoDNS (YAML).
Il suffira de déclarer la configuration du provider comme suit :
Ensuite, vous pourrez lancer la commande suivante pour récupérer le contenu de la zone distante et la copier dans le fichier de zone présent dans tmp/ nommé dump.yaml.
À noter que dès qu’OctoDNS rencontre un problème sur le formatage des enregistrements déjà présents dans la zone distante, il s’arrêtera, vous pouvez passer outre en utiliser l’option --lenient. Cette option permet d’autoriser les configurations et valeurs non conformes lorsque c’est possible. Par exemple, s’il manque un « . » à la fin d’un enregistrement de type CNAME. Il est d’ailleurs possible d’activer ce mode au niveau d’une zone (en spécifiant lenient: true dans la configuration de la zone même) ou encore d’un enregistrement même, vous trouverez plus d’informations sur ce sujet ici [LENIENCE].
4.6 Migrer une zone d’un fournisseur à un autre
Si vous souhaitez par exemple entreprendre une migration d’un fournisseur « on-premise » vers du « cloud », OctoDNS permet de le faire aisément. En effet, il s’agira de modifier la source. Jusque là nous utilisions le provider YAML.
Pour l’exemple, nous allons migrer la zone example.org (Figure 3).
Et modifier la configuration de la zone comme suit :
Pour installer le provider PowerDNS, vous devez utiliser la commande : pip install octodns-powerdns.
Maintenant que la configuration et les sources/targets sont correctement définies, il ne reste plus qu’à valider et appliquer les modifications avec la commande octodns-sync comme cela a été fait plus tôt, il ne faudra pas oublier d’exporter dans notre cas la clé d’API PowerDNS pour la connexion.
4.7 Utiliser une source dynamique
Pour gérer les enregistrements de nos serveurs, le fichier statique montre rapidement ses limites.
Ainsi, si vous avez une CMDB comme NetBox, vous pouvez utiliser le provider associé pour créer les entrées DNS associées aux entrées de type « device » de ce dernier. Par conséquent, pour l’exemple, nous avons une instance NetBox dans laquelle nous avons 2 machines enregistrées, à savoir :
Nom |
Adresse IP (v4) |
web-server-1 |
10.0.10.100 |
web-server-2 |
10.0.10.101 |
Dans les informations de nos machines citées ci-dessus, dans NetBox, nous devons rajouter le custom fields nommé dns_name avec la valeur des enregistrements souhaités (par exemple : web-server-1.example.org).
Côté OctoDNS, il faudra ajouter le provider NetBox pour OctoDNS avec la commande :
Ensuite, dans la configuration, nous devons déclarer ce nouveau provider.
Les enregistrements créés via le provider NetBox sont obligatoirement des records de type A (IPv4) ou AAAA (IPv6).
Il est important de souligner qu’il est possible de créer des enregistrements de type PTR via :
Pour terminer, comme pour les autres actions, il ne restera qu’à valider et appliquer la configuration.
4.8 Découper sa zone dans plusieurs fichiers statiques
OctoDNS embarque par défaut le provider « YAML » qui permet de stocker ses entrées DNS au format YAML. Ce provider possède un gros défaut, celui d’imposer un nom de fichier. Ce nom de fichier est sous le format suivant :
Le gros problème avec ce nom imposé est que l’on ne peut pas découper sa zone en plusieurs sous-fichiers dans le même dossier. En effet, il n’est pas possible d’avoir 2 fichiers avec un même nom dans un répertoire.
Pour pallier à cela, nous allons pouvoir utiliser le provider yamlimproved [YAMLIMPROVED]. Vous devez donc utiliser la commande suivante pour l’installer :
Une fois installé, nous allons pouvoir découper notre zone en plusieurs sous-fichiers.
Pour l’exemple, nous découperons la zone de sorte que nous ayons dans un premier fichier les enregistrements liés aux serveurs DNS, et dans un second les enregistrements courants. Nous devons donc pour commencer déclarer dans notre configuration, les 2 fichiers souhaités :
Il n’est pas nécessaire de spécifier l’extension de fichier « .yaml » pour le nom de fichier dans le paramètre filename.
Ainsi grâce à ce provider, vous pourrez découper votre zone en plusieurs sous-fichiers.
4.9 Augmentez votre qualité de code
Pour aller plus loin, vous pouvez utiliser l’outil yamllint [YAMLLINT] pour vérifier la qualité de votre code YAML.
Ainsi, vous augmenterez naturellement la qualité de code OctoDNS produite. À noter que cet outil vient en complément de la commande octodns-validate.
5. Testez vos enregistrements
La phase souvent oubliée, mais plus que nécessaire reste l’étape de tests. Cette étape est primordiale pour s’assurer que les enregistrements créés le sont bien et qu’ils sont bien fonctionnels.
OctoDNS répond à ce besoin par le biais de la commande octodns-report. Son fonctionnement est simple, une fois que vous avez appliqué vos enregistrements via octodns-sync et l’option --doit, la commande octodns-report va lire les informations déclarées dans la configuration des fournisseurs sources et s’assurer que chaque enregistrement possède bien le contenu déclaré.
Cet outil permet d’éviter de devoir utiliser manuellement la commande nslookup ou dig pour vérifier l’état de l’enregistrement.
Par exemple :
À noter qu’il faut préciser en toute fin le serveur DNS résolveur pour que celui-ci puisse être interrogé et fournir une réponse sur l’état des enregistrements.
Conclusion
Vous l’aurez compris, depuis l’arrivée en 2017 d’OctoDNS, il n’aura jamais été aussi simple de gérer ses enregistrements DNS, peu importe l’environnement ou la solution technique qui se trouve derrière.
Il n’aura jamais été aussi simple de migrer de l’« on-premise » vers une solution cloud et vice-versa.
En bref, OctoDNS est un outil simple, clair, qui n’attend que d’être utilisé.
Pour aller plus loin, et parce que ce n’était pas le but de cet article, vous pouvez intégrer OctoDNS dans un environnement de CI/CD combiné à un dépôt Git, afin d’obtenir une notion de « dynamisme » dans la vérification et l’application, mais également pour effectuer des retours en arrière rapides en cas de dysfonctionnements ou d’erreurs. Cela vous permettra également d’avoir un souci clair, précis et daté des modifications apportées à vos zones DNS.
Références
[ANSIBLE] Lien du site officiel d’Ansible : https://www.ansible.com/
[KUBERNETES] Lien du site officiel de Kubernetes : https://kubernetes.io/fr/
[TERRAFORM] Lien du site officiel de Terraform : https://www.terraform.io/
[RECORDS] Types d’enregistrement supportés : https://github.com/octodns/octodns/blob/main/docs/records.md#record-types
[LENIENCE] Documentation OctoDNS section « Lenience » : https://github.com/octodns/octodns/blob/main/docs/records.md#lenience
[YAMLIMPROVED] Lien du dépôt Git d’octodns-yamlimproved :
https://github.com/junnhy5/octodns-yamlimproved
[YAMLLINT] Lien du dépôt Git de yamllint : https://github.com/adrienverge/yamllint