Formatux Devops
Formatux Devops
Formatux Devops
DevOPS
Antoine Le Morvan, Xavier Sauvignon
Crédits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
L’histoire de Formatux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Licence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Antora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1. Généralités DevOPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.3. Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.6. Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4. Ansible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.5. Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5. Ansible Niveau 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6. Ansible Ansistrano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
7.1. Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.2. Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.1. Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
10.8. TD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Glossaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Préface
GNU/Linux est un système d’exploitation libre fonctionnant sur la base d’un noyau Linux,
également appelé kernel Linux.
Linux est une implémentation libre du système UNIX et respecte les spécifications POSIX.
GNU/Linux est généralement distribué dans un ensemble cohérent de logiciels, assemblés autour
du noyau Linux et prêt à être installé. Cet ensemble porte le nom de “Distribution”.
• Les plus connues et utilisées sont les distributions Debian, RedHat et Arch, et servent de base
pour d’autres distributions comme Ubuntu, CentOS, Fedora, Mageia ou Manjaro.
Chaque distribution présente des particularités et peut être développée pour répondre à des
besoins très précis :
• services d’infrastructure ;
• pare-feu ;
• serveur multimédia ;
• serveur de stockage ;
• etc.
La distribution présentée dans ces pages est principalement la CentOS, qui est le pendant gratuit de
la distribution RedHat, mais la plupart des supports s’appliquent généralement aussi à Ubuntu et
Debian. La distribution CentOS est particulièrement adaptée pour un usage sur des serveurs
d’entreprises.
Crédits
Ce support de cours a été rédigé sur plusieurs années par de nombreux formateurs.
• Antoine Le Morvan ;
• Xavier Sauvignon ;
• Patrick Finet ;
• Carl Chenet
Préface | 1
Ils ont contribués à la rédaction :
• …
Enfin, les illustrations de qualité sont dessinées pour formatux par François Muller (aka Founet).
L’histoire de Formatux
Nous étions (Xavier, Antoine et Patrick) tous les trois formateurs dans la même école de formation
pour adulte.
L’idée de fournir aux stagiaires un support en PDF reprenant la totalité des cours dispensés pour
leur permettre de réviser et approfondir les points vus en classe pendant la journée nous a
rapidement paru être une priorité.
En décembre 2015, nous testions les solutions qui existaient pour rédiger un support d’une telle
taille, et nous avons retenu dès le début du projet le format Asciidoc pour sa simplicité et le
générateur Asciidoctor pour la qualité du support généré, la possibilité de personnaliser le rendu
mais surtout pour l’étendue de ses fonctionnalités. Nous avons également testé le markdown, mais
avons été plus rapidement limité.
5 ans après le début du projet et après avoir basculé notre site web sous Antora,
nous ne regrettons absolument pas le choix technique d’Asciidoc.
La gestion des sources a été confiée dès l’année suivante à la forge Gitlab de Framagit, ce qui nous
permettait de travailler à plusieurs en même temps sur le support, et de faciliter la relecture du
support par Patrick. En découvrant la CI de gitlab-ci, nous avions enfin la stack qui nous
permettrait d’automatiser totalement la génération du support. Il ne nous manquait plus que la
génération d’un site web depuis ces mêmes sources.
Le travail de rédaction étant fortement personnel, sachant que nous risquions d’être muté
rapidement dans les années à suivre, nous avons voulu ce support sous Licence Libre, afin qu’un
maximum de personnes puissent à la fois contribuer et en profiter, et que notre beau support ne se
perde pas.
Même après avoir tous quitté notre organisme de formation, nous avons continué à faire vivre le
projet formatux, en faisant évoluer certaines parties, en nous appuyant sur d’autres pour nos
formations et en intégrant de nouvelles parties, comme la partie Git de Carl Chenet.
En juillet 2019, nous (Xavier et Antoine, Patrick ayant pris sa retraite informatique) avons décidé de
reprendre le développement de Formatux plus activement et d’en faire un peu plus sa promotion.
L’organisation complète du support a été revue, en le scindant en 8 dépôts disctincts, correspondant
à chacune des parties, au support global ainsi qu’au site web. Nous avons voulu notre organisation
full devops, afin que la génération de chacune des parties soient totalement automatisées et inter-
dépendantes les unes des autres.
2 | Préface
Il est difficile aujourd’hui d’évaluer la popularité de notre support. Ce dernier a longtemps été
disponible en téléchargement par torrent sur freetorrent (malheureusement aujourd’hui disparu)
et en direct depuis le site web. Nous n’avons pas de métriques et nous n’en voulons pas
particulièrement. Nous retirons notre satisfaction dans les contacts que nous avons avec nos
lecteurs.
Licence
Formatux propose des supports de cours Linux libres de droits à destination des formateurs ou des
personnes désireuses d’apprendre à administrer un système Linux en autodidacte.
Les supports de Formatux sont publiés sous licence Creative Commons-BY-SA et sous licence Art
Libre. Vous êtes ainsi libre de copier, de diffuser et de transformer librement les œuvres dans le
respect des droits de l’auteur.
Les documents de Formatux et leurs sources sont librement téléchargeables sur formatux.fr :
• https://www.formatux.fr/
Les sources de nos supports sont hébergés chez Framasoft sur leur forge Framagit. Vous y
trouverez les dépôts des codes sources à l’origine de la version de ce document :
• https://framagit.org/formatux/
A partir des sources, vous pouvez générer votre support de formation personnalisé. Nous vous
recommandons le logiciel AsciidocFX téléchargeable ici : http://asciidocfx.com/ ou l’éditeur Atom
avec les plugins Asciidoc.
Vous pourrez ensuite apporter vos modifications, compiler votre support personnalisé et nous
proposer vos modifications.
Préface | 3
• Promouvoir le projet
De votre côté
2. Créer un fork du projet que vous voulez modifier parmi la liste des projets du groupe : Créer le
fork,
Si vous n’êtes pas un grand utilisateur de git, ce n’est pas grave. Vous pouvez
toujours lire la partie Git de notre support puis nous contacter. Nous vous
guiderons ensuite pour vos premiers pas.
Essayer de conserver le même ton qui est déjà employé dans le reste du support (pas de 'je' ni de
smileys par exemple).
2. S’il y a des remarques sur le travail, le relecteur fera des commentaires sur la merge request,
3. Si la merge request lui semble correcte il peut merger votre travail avec la branche develop.
La relecture de la merge request peut vous amener à faire des corrections. Vous pouvez faire ces
corrections dans votre branche, ce qui aura pour effet de les ajouter à la merge request.
Après avoir forké notre projet ou l’avoir cloné (git clone https://framagit.org/group/formatux-
PARTIEXX.git), déplacez-vous dans le dossier formatux-PARTIEXX nouvellement créé.
• Vous utilisez le logiciel AsciiDocFX ou Atom avec ses plugins Asciidoc (recommandé sous
Windows) : lancez le logiciel, ouvrez le fichier .adoc désiré, et cliquez sur le bouton PDF
4 | Préface
(AsciidoctorFX) ou regardez la prévisualisation (Atom).
• Vous êtes sous Linux et vous avez déjà installé le paquet asciidoctor : exécutez la commande
asciidoctor-pdf -t -D public -o support.pdf support.adoc.
Vous pouvez faire un don par paypal pour soutenir nos efforts. Ces dons serviront à payer notre
nom de domaine et notre hébergement. Nous pourrons également reverser une partie de ces dons à
Framasoft, qui héberge gracieusement nos repos et met à disposition un runner qui compile nos
supports et notre site web. Enfin, une petite bière entre nous peut également être au programme.
Nous contacter
Nous sommes disponibles sur gitter pour échanger autour de formatux, de Linux et de la formation
: https://gitter.im/formatux-fr/formatux.
Antora
Pour la génération de notre site web, nous utilisons Antora. Antora nous permet, depuis les mêmes
sources, de pouvoir générer le support en PDF et le site web statique en HTML. Le développement
d’Antora est sponsorisé par OpenDevise Inc.
1.3 Février 2019 Ajout des cours Ansible Niveau 2, Ansistrano, Asciidoc,
Terraform
Préface | 5
Chapitre 1. Généralités DevOPS
Découvrir la philosophie devops.
Objectifs pédagogiques
Connaissances :
Niveau technique :
Le mouvement devops cherche à optimiser le travail de toutes les équipes intervenant sur un
système d’information.
• Les développeurs (les dev) cherchent à ce que leurs applications soient déployées le plus
souvent et le plus rapidement possible.
• Les administrateurs systèmes, réseaux ou de bases de données (les ops) cherchent à garantir la
stabilité, la sécurité de leurs systèmes et leur disponibilité.
Les objectifs des dev et des ops sont donc bien souvent opposés, la communication entre les
équipes parfois difficile : les dev et les ops n’utilisent pas toujours les mêmes éléments de langage.
• Il n’y a rien de plus frustrant pour un développeur que de devoir attendre la disponibilité d’un
administrateur système pour voir la nouvelle fonctionnalité de son application être mise en
ligne ;
• Quoi de plus frustrant pour un administrateur système de devoir déployer une nouvelle mise à
jour applicative manuellement alors qu’il vient de finir la précédente ?
La philosophie devops regroupe l’ensemble des outils des deux mondes, offre un langage commun,
afin de faciliter le travail des équipes avec comme objectif la performance économique pour
l’entreprise.
Le travail des développeurs et des administrateurs doit être simplifié afin d’être automatisé avec
des outils spécifiques.
• idempotence : une opération est idempotente si elle a le même effet quelle soit appliquée une
ou plusieurs fois. Les outils de gestion de configuration sont généralement idempotent.
Même si la connaissance du Bash est une exigence de base pour un administrateur système,
celui-ci est un langage de programmation interprété "impératif". Il exécute les instructions
les unes à la suite des autres.
Les langages dédiés au domaine (DSL Domain Specific Language) comme ceux utilisés par
Ansible, Terraform, ou Puppet, quant à eux, ne spécifient pas les étapes à réaliser mais l’état à
obtenir.
Parce qu’Ansible, Terraform ou Puppet utilisent un langage déclaratif, ils sont très simples. Il
suffit de leur dire "Fais cette action" ou "Met le serveur dans cet état". Ils considéreront l’état
désiré indépendamment de l’état initial ou du contexte. Peu importe dans quel état le serveur
se situe au départ, les étapes à franchir pour arriver au résultat, le serveur est mis dans l’état
désiré avec un rapport de succès (avec ou sans changement d’état) ou d’échec.
La même tâche d’automatisation en bash nécessiterait de vérifier tous les états possibles, les
autorisations, etc. afin de déterminer la tâche à accomplir avant de lancer l’exécution de la
commande, souvent en imbriquant de nombreux "si", ce qui complique la tâche, l’écriture et
la maintenance du script.
◦ Puppet
◦ Ansible
◦ Saltstack
◦ Chef
• Intégration continue
◦ Jenkins
◦ Gitlab-ci
◦ Rundeck
◦ Ansible Tower
• Infrastructure As Code
◦ Terraform
• Docs as Code
◦ Markdown
◦ ReSTructured Text
Git reste un programme incompris et craint par beaucoup alors qu’il est aujourd’hui
indistinctement utilisé par les développeurs et les sysadmins. Afin de démystifier ce formidable
outil, je vous propose une série d’articles à l’approche très concrète pour débuter avec Git et
l’utiliser efficacement ensuite.
Le dépôt de sources est très concrètement un répertoire sur votre système, contenant lu-même un
répertoire caché nommé .git à sa racine. Vous y stockerez votre code source et il enregistrera les
modifications apportées au code dont il a la charge.
Pour prendre directement de bonnes habitudes, nous allons créer un nouveau projet à partir de
notre compte Gitlab.com. Un projet Gitlab offre un dépôt distant et une suite d’outils autour. Dans
un premier temps nous ne nous intéresserons qu’au dépôt. Le but est, dans un premier temps, de
montrer le lien entre le dépôt distant et le dépôt local.
Tout simplement dans un premier temps pour sauver votre code sur un autre ordinateur que le
vôtre, et dans un second temps de permettre le travail collaboratif.
Nous lui donnons également un nom. Ce projet n’ayant pas (encore) comme but de devenir public,
nous restons en dépôt privé, ce qui signifie que l’accès au dépôt sera restreint par un identifiant et
un mot de passe.
Sur notre poste, nous allons commencer par cloner le dépôt distant depuis Gitlab.com vers notre
poste local :
Comment se souvenir d’où vient ce code ? La commmande git remote va nous permettre de voir le
lien entre notre dépôt local et le dépôt distant de Gitlab.com :
Nous détaillerons plus tard, l’important est de voir qu’il y a bien un lien entre le dépôt local et le
dépôt distant.
S’identifier
Le dépôt Git dans lequel vous travaillez va bientôt chercher à identifier la personne qui procède à
des modifications. Pour cela nous allons définir notre identité au niveau local – c’est-à-dire de ce
dépôt – avec les commandes suivantes :
Git créé en fait ici un fichier .git/config contenant les informations fournies.
Vous pouvez également définir votre identité au niveau global, pour ré-utiliser cette configuration
pour tous les dépôts que vous créerez avec cet utilisateur du système :
Git crée en fait ici un fichier ~/.gitconfig contenant les informations fournies.
Lorsque nous avons cloné notre dépôt plus haut dans l’article, vous avez dû saisir un mot de passe.
J’imagine que vous avez choisi un mot de passe à 24 caractères pour protéger votre compte
Gitlab.com, qui est donc également le mot de passe de votre dépôt distant. Dans les prochains
articles, nous allons beaucoup interagir avec le dépôt distant et il serait assez pénible d’avoir à le
saisir régulièrement. Pour remédier à cela nous allons immédiatement passer la commande
suivante :
Le dernier argument indique le type de stockage du mot de passe. Ici il s’agit uniquement d’un
cache d’une durée de vie égale à 15 minutes. Si vous souhaitez stocker définitivement votre mot de
passe, vous pouvez utiliser la commande suivante :
Vos mots de passe seront stockés par défaut dans ~/.git-credentials. Attention, les mots de passe sont
sauvés en clair dans ce fichier.
Conclusion
Pour une première approche de Git, nous avons appris à créer un projet sur Gitlab.com, à rapatrier
localement le dépôt créé puis à le configurer pour l’utiliser le plus simplement possible. Nous
verrons les premières utilisations de ce dépôt dans une prochaine partie.
Dans un premier temps, nous allons nous positionner dans le dépôt que nous avons créé durant la
première partie sur notre poste de travail local et vérifier l’état courant de notre dépôt :
$ cd ~/toto
$ git status
On branch master
No commits yet
• Le message On branch master vous signale la branche dans laquelle vous êtes positionné.
• Mais qu’est-ce qu’une branche ? Retenons ici essentiellement que nous travaillons dans un état
particulier du dépôt appelé branche et qu’il s’agit de celle par défaut, nommée master. Nous
serons beaucoup plus précis sur cette notion dans une prochaine partie.
• Le message No commits yet est assez explicite et indique qu’aucun commit n’a encore été
enregistré dans le dépôt, ce qui est cohérent.
• Mais qu’est-ce qu’un commit ? Un commit est l’état du code enregistré dans votre dépôt à un
moment T, un instantané de tous les éléments dans votre dépôt au moment où vous effectuez le
commit.
Allons donc maintenant ajouter un fichier dans la branche master de notre dépôt :
Créons maintenant un fichier vide nommé README.md. Nous utilisons ensuite la commande git add
README.md afin d’ajouter le fichier sur la branche. Après cela, le nouvel état du dépôt est le suivant :
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
Nous observons que nous sommes toujours sur la branche master et qu’aucun commit n’a toujours
été effectué sur cette branche. La section suivante indique par contre qu’un changement est
désormais pris en compte par Git et qu’il s’agit d’un nouveau fichier nommé README.md.
Notion importante ici à retenir : la commande git add nous a permis de faire passer une
modification – ici l’ajout d’un fichier – de l’état où ce fichier n’était pas pris en compte par Git vers
un espace de travail, appelé ici stage, ce qui signifie donc que ce fichier est désormais surveillé par
Git.
Premier commit
Premier grand événement de la vie de notre dépôt, nous allons maintenant effectuer notre premier
commit avec la commande suivante :
La command git commit nous permet de spécifier un fichier à prendre en compte pour le commit
en question. Ici c’était facile, nous n’en avons qu’un. L’option -m accompagnée d’un texte permet de
spécifier un message explicatif à associer à ce commit. Git nous retourne différentes informations
sur le commit effectué puis nous vérifions de nouveau l’état du dépôt :
$ git status
On branch master
nothing to commit, working tree clean
$ git log
commit 5c1b4e9826a147aa1e16625bf698b4d7af5eca9b
Author: Carl Chenet <[email protected]>
Date: Mon Apr 29 22:12:08 2019 +0200
add README.md
La commande git log nous apprend l’identifiant, l’auteur et la date du commit, suivi par le
message explicatif dudit commit.
Dans la première partie de cette série, nous avions créé un dépôt distant à partir duquel avait été
cloné le dépôt local dans lequel nous venons de travailler. Il s’agit maintenant de synchroniser le
dépôt distant avec le dépôt local. Pour cela, nous utilisons la commande suivante :
La commande git push nous permet de pousser nos modifications d’un dépôt local vers un dépôt
distant. L’option --set-upstream permet d’indiquer que notre branche courante dans le dépôt local
(désigné par le terme origin et qui est donc ici nommée master) sera poussée vers la branche du
dépôt distant nommée elle aussi master. Cette option n’est obligatoire qu’à votre premier push.
Git nous indique ici [new branch] car, pour rappel, nous avions cloné un dépôt vide. Il créé donc la
branche du dépôt distant nommé master. Refaisons appel à la commande git remote que nous
avions déjà utilisée dans la première partie. En effet elle va nous permettre de mieux appréhender
le rapport entre la branche locale et la branche distante :
$ git remote -v
origin https://gitlab.com/chaica/toto (fetch)
origin https://gitlab.com/chaica/toto (push)
Nous voyons sur la seconde ligne qu’en effet l’origine pour la branche en cours, ici l’url
https://gitlab.com/chaica/toto, pour l’action push est bien notre dépôt distant.
$ git push
Everything up-to-date
Le message de Git est clair, notre dépôt local est à jour par rapport au dépôt distant. Nos récentes
modifications, représentées au niveau de Git par le commit que nous venons de créer, ont été
poussées vers le dépôt distant, assurant la redondance des données et permettant – nous le verrons
plus tard dans quelques parties – le travail collaboratif.
Conclusion
Cette deuxième partie sur comment débuter avec Git nous a permis de réaliser les toutes premières
opérations d’ajouts de code sur notre dépôt local et de s’assurer de sa synchronisation avec le dépôt
distant. Les notions de branche et de commit ont également été abordées pour la première fois.
Dans une prochaine partie nous présenterons comment gérer un commit plus complexe.
Objectif
Pour bien débuter avec Git, nous avons vu dans la partie précédente comment réaliser un commit
très simple, consistant à enregistrer un seul fichier. Nous allons aller plus loin pour coller
davantage à la complexité du monde réel en constituant un nouveau commit avec plusieurs
modifications différentes issues de plusieurs fichiers.
Nous allons commencer avec un dépôt Git contenant un seul fichier texte nommé README qui est
assez long.
$ cd commit-complexe
$ ls
README
$ wc -l README
19 README
Premiers changements
Nous allons ajouter sur la première ligne la phrase “do not forget to read the file foo!” et sur la
$ cd commit-complexe
$ git diff
diff --git a/README b/README
index d012f47..737bc05 100644
--- a/README
+++ b/README
@@ -1,5 +1,7 @@
this is a README
Let's work
@@ -17,3 +19,5 @@ These criteria eliminated every then-extant version-control system,
so immediate
The development of Git began on 3 April 2005.[16] Torvalds announced the project on 6
April;[17] it became self-hosting as of 7 April.[16] The first merge of multiple
branches took place on 18 April.[18] Torvalds achieved his performance goals; on 29
April, the nascent Git was benchmarked recording patches to the Linux kernel tree at
the rate of 6.7 patches per second.[19] On 16 June Git managed the kernel 2.6.12
release.[20]
Torvalds turned over maintenance on 26 July 2005 to Junio Hamano, a major contributor
to the project.[21] Hamano was responsible for the 1.0 release on 21 December 2005 and
remains the project's maintainer.[22]
+
+To finish, do not forget to read file bar!
Git nous indique les changements intervenus avec des + devant les ajouts. Nous avons donc rajouté
deux lignes et deux sauts de lignes.
Bien, il nous reste maintenant à écrire les nouveaux fichiers foo et bar. Mais il est 19h, je suis
fatigué et je ne vais avoir le temps que d’écrire le premier fichier foo. Nous procédons comme suit
pour écrire et ajouter le fichier foo :
Une furieuse envie d’enregistrer le travail en cours en faisant un git commit -a est notre premier
réflexe, mais le fichier README va donc évoquer un fichier bar qui n’existe pas encore dans le dépôt.
Ce n’est pas propre, surtout si un collègue relit immédiatement mon travail.
Dans notre situation, la solution est de choisir ce que l’on veut ajouter au commit, c’est à dire le
fichier foo (ce que nous venons de faire) et seulement une partie des modifications du fichier
README. C’est possible avec l’option --patch ou -p de git add qui va nous permettre d’indexer
seulement les modifications qui nous intéressent pour préparer le prochain commit.
@@ -1,5 +1,7 @@
this is a README
Let's work
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y
Cette commande nous présente notre première modification dans le fichier README. Un hunk est ici
donc une modification unitaire identifiée par Git. Le contenu ajouté apparaît avec un symbole + en
tout début de ligne. Nous acceptons d’indexer la première modification en appuyant sur y (yes).
+
+To finish, do not forget to read file bar!
Stage this hunk [y,n,q,a,d,K,g,/,e,?]? n
Git nous affiche ensuite la seconde modification identifiée dans le fichier. Nous refusons la seconde
en appuyant sur n (no), que nous ajouterons demain quand nous aurons écrit le fameux fichier bar
dans un futur commit, parce qu’il est 19h et qu’à chaque jour suffit sa peine.
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README
new file: foo
modified: README
La commande est très claire si on la lit rigoureusement : sur la branche master, les modifications
suivantes sont prêtes à être committées : le fichier README a été modifié et un nouveau fichier foo a
été créé.
Git nous indique également qu’un changement est survenu mais qu’il n’a pas été indexé (sous la
phrase Changes not staged for commit) : c’est le fameux changement que nous souhaitons faire
demain.
Le commit lui-même
Il est grand temps de valider nos modifications et de créer un commit. Il ne faut ici surtout pas
utiliser l’option -a de git commit sous peine de valider indistinctement toutes les modifications
présentes dans le dépôt, ce que nous ne voulons absolument pas faire.
$ git commit -v
Let's work
diff --git a/foo b/foo
new file mode 100644
index 0000000..7c50c6a
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+very interesting stuff
Nous retrouvons ici le résultat du précédent git status et le détail des modifications qui vont être
validées. Nous remarquons que seule la mention du fichier foo dans le README et la création de ce
fichier foo y figurent. Nous avons donc réussi notre commit.
Si ça n’était pas le cas, vous pouvez quitter votre éditeur de texte sans enregistrer, cela annulera le
commit. Si tout est bon, entrez simplement un message de commit pertinent comme “mention foo
in README and add the foo file” et sauvegardez.
Nous voyons notre message de validation et également que deux fichiers ont été modifiés.
Dans quel état est notre dépôt après ce commit ? Encore une fois l’analyse de la commande git
status va nous aider.
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README
no changes added to commit (use "git add" and/or "git commit -a")
En effet nous avons la seconde modification du fichier README que nous avions faite qui n’a pas
encore été enregistrée dans aucun commit. Nous n’avons pas indexé cette modification. Elle
demeure donc dans notre dépôt en attente d’un prochain traitement.
$ git diff
diff --git a/README b/README
index 6c50e6b..737bc05 100644
+
+To finish, do not forget to read file bar!
Sauvegarde du travail
Nous avons un beau commit, mais il n’existe pour l’instant que sur notre ordinateur personnel. Un
malheureux accident ou un vol est si vite arrivé, il est indispensable de sauver notre travail sur
notre dépôt Git distant (voir la création du dépôt distant dans la partie 1). Nous procédons avec un
simple git push vers notre dépôt distant:
Conclusion
Bien débuter avec Git nécessite de comprendre ce que l’on fait et pour cela nous abordons les
notions fondamentales une par une.
La notion essentielle abordée aujourd’hui est l’ajout de modifications à l’index. L’index constitue
l’ensemble des modifications à prendre en compte dans le prochain commit. Nos modifications ont
donc pour l’instant 3 statuts possible dans Git : non-indexées, indexées ou enregistrées dans un
commit. À chaque statut correspond une palette d’opérations possibles et Git vous tient en
permanence au courant du statut de vos différentes modifications en cours, en vous proposant
souvent des actions possibles.
Nous aborderons bientôt dans une prochaine partie une autre notion fondamentale de Git : les
branches.
Objectif
Comme nous l’avons vu à la partie 2 et à la partie 3, Git enregistre les modifications qui surviennent
au code dans le dépôt sous forme de commits.
Au fil des commits, nous construisons donc un historique des nos modifications. Git nous permet de
naviguer entre ces modifications et donc de retrouver les états antérieurs des sources dans notre
dépôt. Nous allons aujourd’hui détailler les possibilités offertes par cette organisation des commits.
Nous nous positionnons dans un dépôt Git contenant actuellement deux fichiers.
$ cd historique-commit
$ ls
file1 file2
Le dépôt Git a connu 4 commits, comme nous l’indique la commande git log.
commit 7b6882a5148bb6a2cd240dac4d339f45c1c51738
Author: Carl Chenet <[email protected]>
Date: Tue May 28 20:46:14 2019 +0200
commit ce9804dee8a2eac55490f3aee189a3c67865481c
Author: Carl Chenet <[email protected]>
Date: Tue May 28 20:45:21 2019 +0200
commit 667b2590fedd4673cfa4e219823c51768eeaf47b
Author: Carl Chenet <[email protected]>
Date: Tue May 28 20:44:30 2019 +0200
first commit
La commande git status nous précise quant à elle qu’aucun travail n’est en cours.
$ git status
On branch master
nothing to commit, working tree clean
$ cat file2
this is the number 2 file
Nous allons maintenant tenter de retrouver un état antérieur de notre dépôt, à savoir l’état de
notre dépôt au précédent commit.
La commande git checkout va nous permettre de revenir à l’état de notre dépôt à un certain
commit. Nous pouvons utiliser pour ça un nombre de commits antérieurs, par exemple juste 1
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
La sortie de Git est un peu difficile à comprendre tout de suite, mais le fait est que nous sommes
revenus à l’état du dépôt à l’avant-dernier commit.
$ cat file2
this is the number 2 file
Son contenu a bien changé, nous sommes donc bien revenus en arrière dans l’histoire des
modifications de notre dépôt.
Le pointeur HEAD
Un composant important de la commande git précédente reste assez obscure : que signifie HEAD ? Et
pourquoi ~1 ?
Il s’agit tout simplement d’un pointeur de position parmi les commits de notre dépôt. Un pointeur
est ici un repère logique, un petit drapeau au sein de Git, qui indique un commit et que l’on peut
déplacer pour indiquer un autre commit.
Un schéma va nous aider à comprendre. Nous identifions les commits par les 4 derniers caractères
de leurs identifiants.
Nous entrons dans un mode spécial de Git (detached head ou tête détachée), qui nous permet de
retrouver les données du dépôt telles qu’elles étaient au moment de ce commit. À partir de cet état
du dépôt, nous pourrons évoluer vers un autre état sans modifier les commits déjà existants.
Nous allons maintenant observer les différences entre le commit sur lequel nous sommes
positionnés et le commit le plus avancé que nous avons écrit, à l’aide de la commande git diff.
Nous voyons bien la ligne ajoutée au fichier file2 lors du dernier commit.
Remarquons que nous avons utilisé dans notre commande master, avec HEAD. Ici HEAD point sur
l’avant-dernier commit de notre liste. Nous voyons les différences entre l’avant-dernier et le
dernier commit. Or le dernier argument de notre ligne de commande était master. Il s’agit donc
aussi, comme HEAD, d’un pointeur, mais sur le dernier commit réalisé. Nous y reviendrons.
Cette commande git diff marche bien sûr avec n’importe quel identifiant de commit, par exemple
voici la différence entre le premier et le second commit, en utilisant ici leur identifiant unique.
Nous sommes donc positionnés sur l’avant-dernier commit. Nous nous apercevons que nous
aimerions continuer avec un contenu différent que celui enregistré dans le dernier commit, sans
toutefois effacer ce dernier commit. Pour résumer nous voulons créer un embranchement dans
l’histoire de nos commits pour créer une suite différente. Nous allons donc créer notre première
branche.
Pour cela il suffit de relire le dernier message affichée lors de notre commande git checkout HEAD~1
:
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
Nous allons donc passer la commande suivante afin de créer une nouvelle branche dans laquelle
nous écrirons la nouvelle suite des modifications que nous souhaitons.
Remarquons la première ligne On branch new-file alors que jusqu’ici nous avions On branch master.
Nous avons donc bien créé une nouvelle branche nommée new-file.
Nous créons maintenant un nouveau commit contenant un nouveau fichier et l’ajoutons au dépôt.
• notre première série de commits finit par un commit f2ee sur lequel un pointeur nommé master
est positionné. Il s’agit de la branche master
Une branche est donc définie par une série de commits et un pointeur du nom de cette branche sur
le dernier commit de cette branche.
Conclusion
Arrêtons-nous là pour l’instant. Nous avons vu une notion fondamentale, à savoir ce qu’est
rééllement une branche Git et les principes sous-jacents à une branche, le lien entre les commits et
les pointeurs. Il était malheureusement difficile de parler des branches précisément (ce que nous
avions fait dans notre première partie) sans toutes ces notions.
Dans un dépôt Git, l’unité est le commit, qui est un ensemble de modifications survenus sur le code
dans ce dépôt. Un commit et ses prédecesseurs représentent une branche. On positionne sur certains
commits des pointeurs, ayant chacun un rôle distinct :
• Un pointeur spécial nommé HEAD indique en permanence l’état du dépôt au dernier commit
pointé par le pointeur HEAD.
Mise en place
Pour cette partie nous créons un dépôt distant sur notre Gitlab (comme expliqué dans la partie 1),
puis nous le clonons sur notre machine locale.
Notre dépôt initial contient simplement un fichier README.md, créé par Gitlab, contenant un titre en
langage Markdown
$ cat README.md
# merge-branch
À ce niveau, nous avons donc deux commits qui constituent notre branche master, comme nous
l’indique la commande git log.
Initial commit
Mise en place un peu longue, mais qui nous a permis de réviser quelques commandes
fondamentales. Nous entrons dans le vif du sujet.
Un client nous demande une évolution du code. Afin de ne pas toucher à la branche master qui
contient le code de référence courant, nous allons compliquer maintenant un peu les choses en
créant une nouvelle branche nommée branch-with-foo. Cette étape a déjà été expliquée dans la
partie 4 plus en détail.
Nous créons immédiatement un fichier nommé foo dans cette branche que nous ajoutons et
enregistrons dans la foulée.
Nous revenons maintenant sur master et nous créons un fichier bar que nous enregistrons aussi
dans la foulée.
Faisons une pause, nous venons de créer notre première divergence entre nos branches, nous
avons créé un embranchement dans l’historique de nos commits, les deux derniers commits
n’appartenant plus aux mêmes branches.
Fuuuuuuuuuusion
Le besoin que nous avions de créer une nouvelle branche a disparu, le client a annulé le projet.
Bon, nous allons réintégrer les modifications de cette branche dans la branche master. Nous nous
positionnons dans la branche master, ou d’une manière générale la branche à laquelle nous
souhaitons réintégrer les modifications d’une autre, et nous passons la commande suivante :
La sortie de la commande nous précise ce qui s’est passé : un fichier foo (celui de la branche branch-
with-foo) a été créé dans la branche courante master.
Cette représentation est très parlante. Au niveau de l’histoire elle va de haut en bas, le haut étant le
commit le plus récent et le plus bas le plus vieux. Une étoile (*) est un commit, avec son message à
droite , et le nom de la branche s’il y ambiguité.
Nous avons bien fusionné la branche branch-with-foo dans master. Fusion réussie.
Avant de s’arrêter aujourd’hui, n’oublions pas de pousser tout ce que nous avons fait vers notre
$ git push
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (11/11), 975 bytes | 975.00 KiB/s, done.
Total 11 (delta 2), reused 0 (delta 0)
To https://gitlab.com/chaica/merge-branches.git
11cb68a..69fa060 master -> master
La dernière ligne indique bien que nous avons poussé depuis notre branche master locale vers
notre branche master distante présent sur notre Gitlab.
Passons à la branche branch-with-foo, qui, même si elle a été fusionnée dans master, existe toujours.
Pourquoi ? Car le nom de la branche branch-with-foo est un pointeur, un indicateur qui désigne le
dernier commit connu de cette branche. Rien de plus.
Pour changer un peu nous varions la syntaxe de notre commande git push en utilisant l’option
--all afin de pousser toutes les branches locales vers le dépot distant. Nous n’en avons qu’une ici,
branch-with-foo.
Point très intéressant, nous voyons que les lignes commençant par remote: proviennent du Gitlab,
qui nous indiquent comment créer une demande de fusion (Merge Request). Inutile, nous avons déjà
fusionné. Mais ce sera intéressant dans le cadre du travail collaboratif. Ce sera pour un prochain
article.
Conclusion
Nous avons vu aujourd’hui la fusion de branches Git. Cette opération permet de récupérer le travail
réalisé dans une autre branche, en divergence du code “principal” que nous conservons – comme
bonne pratique dans l’industrie en général – dans la branche master. C’est le cas le plus courant.
Vous devriez quasi systématiquement commencer par créer une nouvelle branche quand vous
envisagez d’introduire du nouveau code dans un dépôt Git, afin de ne pas travailler directement
vous-même dans master. Pourquoi pas ? C’est ce que nous verrons dans le prochain article de cette
série.
Nous allons démystifier une situation qui provoque un stress important auprès des nouveaux
utilisateurs de Git : lorsqu’une fusion de branches échoue.
En effet Git est un outil très bien conçu, mais il ne prendra jamais une décision à la place de ses
utilisateurs. Or, si la même partie du code est modifiée par deux utilisateurs différents, qui a raison
? Qui a tort ? Qui Git doit-il croire ?
Nous allons tout d’abord créer un fichier README.md dans un nouveau dépôt Git avec un titre et deux
sections.
$ mkdir fusion-echoue
$ cd fusion-echoue/
$ git init .
Initialized empty Git repository in /tmp/fusion-echoue/.git/
$ vi README.md
$ cat README.md
# README
## installation
## use
Nous créons maintenant une branche dédiée à l’ajout d’une nouvelle section pour indiquer la
licence du projet dans le README.md.
## installation
## use
# license
BSD
Pendant ce temps, dans la branche master, un développeur semble avoir fait un choix différent au
niveau de la licence.
# README
## installation
## use
# license
GPLv3
Oups, le CONFLICT en majuscule nous annonce que Git a rencontré un conflit en tentant de fusionner
la branche new-license dans la branche master.
La dernière phrase est très claire : résoudre les conflits est un préalable indispensable à continuer
la fusion.
Si vous avez déjà rencontré ce problème en utilisant Git, vous avez sûrement éprouvé ce sentiment
: la grosse panique. Vous vous voyez déjà accuser des pires manipulations par vos collègues et de
casser l’outil de travail commun. DU CALME, PAS DU TOUT.
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add …" to mark resolution)
both modified: README.md
La sortie de la commande est très claire : un simple git merge --abort vous fera revenir à la
situation précédant le git merge. Voyons cela.
Voilà, vous pouvez vous détendre et ranger votre lette de démission. Tout va bien se passer.
Résoudre le conflit
Nous allons maintenant tenter de réellement résoudre notre conflit. Avant cela, nous devons
prendre conscience de la tâche qui nous attend.
La sortie de la commande git status nous indique qu’un seul fichier pose problème par la mention
sur la dernière ligne both modified: README.md.
Ce n’est pas nos quelques lignes dans le README.md qui vont nous décourager. Jetons donc un oeil au
fichier en question.
$ cat README.md
# README
## installation
## use
## license
<<<<<<< HEAD
GPLv3
=======
BSD
>>>>>>> new-license
Dans la section license du fichier, nous voyons que la partie entre <<<<<<< HEAD et ======= provient
de HEAD, qui pointe actuellement sur master, donc le code provenant de master. Vous avez oublié ce
qu’est HEAD ? On en parle dans la partie 4.
À l’opposé, la partie entre ======= et >>>>>>> new-license provient donc de la branche new-license.
C’est maintenant à vous de jouer et de faire un choix, Git ne le fera pas à votre place, une décision
humaine est attendue.
Après consultation avec vos collègues, vous choisissez la licence GPLv3. Vous allez donc éditer le
code de la section license pour ne laisser que la partie suivante :
La commande git status précédente nous indiquait la marche à suivre une fois le fichier édité.
Unmerged paths:
(use "git add …" to mark resolution)
both modified: README.md
Le conflit est résolu. Nous allons maintenant utiliser git commit pour terminer la fusion.
Si vous n’utilisez que la commande git commit sans argument, votre éditeur de texte s’ouvre et
propose d’enregistrer le message de commit suivant :
Conclusion
Nous avons brilliamment résolu notre premier conflit de fusion entre deux branches. Il était
franchement facile à régler, mais il nous a permis de détailler toutes les étapes nécessaires. Bien
évidemment nous pouvons avoir des conflits bien plus sévères à régler, mais nous avons vu
comment interrompre une fusion, ce qui nous aidera quoiqu’il arrive à revenir à un état stable du
dépôt.
S’engager dans une fusion complexe réclame un très bonne connaissance du code manipulé et de
ce qu’on fait vos collègues, pour ne pas écraser du code utile par inadvertance.
Lorsque les environnements grossissent ou que les équipes accueillent de plus en plus de
techniciens, ces méthodes sont difficiles à maintenir et à optimiser. Elles peuvent causer des
risques pour la sécurité du système, incluant des erreurs de configuration, ce qui au final, peut
faire réduire la productivité.
Parmi les systèmes de gestion de configurations, plusieurs systèmes ont fait leur apparition :
• puppet ;
• chef ;
• ansible ;
• etc.
Des outils ont également fait leur apparition pour encore faciliter l’administration de ces systèmes :
Concrètement, lors de l’ajout d’un nouveau serveur au sein d’une infrastructure informatique
complexe, les administrateurs système ne doivent pas perdre de temps pour la configuration des
briques de base du système : la configuration des services NTP, DNS, SMTP, SSH, la création des
comptes utilisateurs, etc… doit être totalement automatisée et transparente aux équipes.
3.2. Puppet
Puppet a été conçu pour fonctionner en mode client-serveur. Son utilisation en mode de
fonctionnement « autonome » est également possible et facile. La migration vers un système de
clients « Puppet / Master Puppet » n’est pas d’une réalisation complexe.
Puppet est un logiciel d’automatisation qui rend simple pour l’administrateur système le
provisionnement (la description matérielle d’une machine virtuelle), la configuration et la gestion
de l’infrastructure tout au long de son cycle de vie. Il permet de décrire l’état de configuration d’un
ensemble hétérogène de stations de travail ou de serveurs et de s’assurer que l’état réel des
machines correspond bien à l’état demandé.
Par sa structure de langage, il fait le lien entre les bonnes pratiques, le cahier de procédures et l’état
effectif des machines.
Vocabulaire Puppet
• Module : unité de code Puppet qui est réutilisable et pouvant être partagé ;
• Facter : librairie multi-plateforme qui fournit à Puppet sous forme de variables les
informations propres au système (nom, adresse ip, système d’exploitation, etc.) ;
• Ressource (Resource): objet que Puppet peut manipuler (fichier, utilisateur, service, package,
etc.) ;
Architecture
Puppet conseille de coupler son fonctionnement avec un gestionnaire de version type « git ».
La communication est assurée via des canaux chiffrés, en utilisant le protocole https et donc TLS
(une mini-pki est fournie).
Toute la configuration (le référentiel) de Puppet est centralisée dans l’arborescence /etc/puppet du
serveur de référence :
• /etc/puppet/manifests/site.pp : est le premier fichier analysé par Puppet pour définir son
référentiel. Il permet de définir les variables globales et d’importer des modules ;
3.3. Installation
Les dépôts Puppets doivent être activés :
[puppetlabs-deps]
name=Puppet Labs Dependencies EL 6 - $basearch
baseurl=http://yum.puppetlabs.com/el/6/dependencies/$basearch
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
enabled=1
gpgcheck=1
puis :
L’installation d’un module complémentaire pourra se faire, soit directement depuis internet, soit
par le téléchargement manuel de l’archive .tar.gz.
Depuis internet :
export http_proxy=http://10.10.10.7:8080
export https_proxy=http://10.10.10.7:8080
Sans connexion internet, un module peut être installé en fournissant dans la commande puppet le
chemin vers le fichier tar.gz :
Grâce aux modules du dépôt Puppet, les possibilités de l’outil sont quasiment infinies. Le
téléchargement et l’utilisation des modules du dépôt permettent un gain de temps confortable car
l’outil nécessite peu de compétences en développement.
3.6. Documentation
La liste des types et leurs attributs est consultable en ligne :
• https://docs.puppetlabs.com/references/latest/type.html
• https://doc.puppetlabs.com/learning/introduction.html
puppet describe -l
Le code du manifeste doit être découpé en classe pour des raisons de maintenance et d’évolutivité.
Un objet de type node recevra les classes à exécuter. Le node « default » est automatiquement
exécuté.
node default {
include init_services
}
La classe init_services contient les services qui doivent être lancés sur le nœud et ceux qui doivent
être stoppés :
class init_services {
service { [“sshd”,”NetworkManager”,”iptables”,”postfix”,”puppet”,”rsyslog”,”sssd”,
”vmware-tools”]:
ensure => ‘running’,
enable => ‘true’,
}
service { [“atd”,”cups”,”bluetooth”,”ip6tables”,”ntpd”,”ntpdate”,”snmpd”,”snmptradp”]:
ensure => ‘stopped’,
enable => ‘false’,
}
}
La ligne ensure ⇒ a pour effet de démarrer ou non un service, tandis que la ligne enable ⇒ activera
ou non le démarrage du service au démarrage du serveur.
La classe create_users contiendra les utilisateurs de notre système. Pensez à ajouter l’appel de cette
classe dans le node default !
node default {
include init_services
include create_users
}
Au départ du personnel pour mutation, il sera aisé de supprimer son compte en remplaçant la ligne
ensure ⇒ present par ensure ⇒ absent et en supprimant le reste des options.
La directive managehome permet de créer les répertoires personnels à la création des comptes.
group { "DSI":
ensure => present,
gid => 1001
}
file { '/etc/skel/boulot':
ensure => directory,
mode => 0644,
}
Modification de valeurs
La commande augeas, développée par la société RedHat, permet de modifier les valeurs des
variables dans les fichiers de configuration. Son utilisation peut s’avérer autant puissante que
complexe.
Le contexte est suffixé de « /files/ » pour préciser qu’il s’agit d’un système de fichiers local.
exec { "Redirection":
command => "/usr/sbin/useradd -D > /STAGE/utilisateurs/defaut",
}
De manière générale, les commandes et les fichiers doivent être décrits en absolu
dans les manifestes.
Rappel : la commande whereis fournit le chemin absolu d’une commande.
• sans agent (il ne nécessite pas de déploiements spécifiques sur les clients),
L’ouverture des flux SSH vers l’ensemble des clients depuis le serveur Ansible font
de lui un elément critique de l’architecture qu’il faudra attentivement surveiller.
48 | Chapitre 4. Ansible
4.1. Le vocabulaire ansible
• Le poste de gestion : la machine sur laquelle Ansible est installée. Ansible étant agentless,
aucun logiciel n’est déployé sur les serveurs gérés.
• Les tâches (tasks) : une tâche est un bloc définissant une procédure à exectuer (par exemple
créer un utilisateur ou un groupe, installer un paquet logiciel, etc.).
• Un module : un module rend abstrait une tâche. Il existe de nombreux modules fournis par
Ansible.
• Les playbooks : un fichier simple au format yaml définissant les serveurs cibles et les tâches
devant être effectuées.
• Un rôle : un rôle permet d’organiser les playbooks et tous les autres fichiers nécessaires
(modèles, scripts, etc.) pour faciliter le partage et la réutilisation du code.
• Les facts : ce sont des variables globales contenant des informations à propos du système (nom
de la machine, version du système, interface et configuration réseau, etc.).
• les handlers: il sont utilisés pour provoquer un arrêt ou un redémarrage d’un service en cas de
changement.
• Installation d’EPEL :
• Le fichier inventaire de gestion des machines clientes hosts : déclaration des clients, des
groupes.
Chapitre 4. Ansible | 49
Le fichier /etc/ansible/hosts
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110
...
Par exemple, un groupe centos7 est créé en insérant le bloc suivant dans ce fichier :
[centos7]
172.16.1.217
172.16.1.192
Exemples :
50 | Chapitre 4. Ansible
• Lister les hôtes appartenant à un groupe :
• Exécuter une commande sur un groupe d’hôtes en invoquant le module command avec des
arguments :
Option Information
-a 'arguments' Les arguments à passer au module.
-b -K Demande un mot de passe et lance la commande avec des privilèges
supérieurs.
--user=utilisateur Utilise cet utilisateur pour se connecter à l’hôte cible au lieu d’utiliser
l’utilisateur courant.
--become Exécute l’opération en tant que cet utilisateur (défaut : root).
-user=utilisateur
-C Simulation. Ne fait pas de changement sur la cible mais la teste pour voir ce
qui devrait être changé.
-m module Exécute le module appelé
Chapitre 4. Ansible | 51
Tester avec le module ping
Par défaut la connexion par mot de passe n’est pas autorisée par Ansible.
ask_pass = True
Le mot de passe root des serveurs distants vous est demandé, ce qui pose un
problème de sécurité…
52 | Chapitre 4. Ansible
# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:RpYuJzkkaeZzve8La8Xd/8kTTE8t43DeS+L7WB26WF8 root@ansible-srv
The key's randomart image is:
+---[RSA 2048]----+
| |
| . . |
| = . + .|
| + o * . +.o|
| o * S. . *o*.|
| o * .o ..=+=|
| o. .oooE|
| .+ o.*o+|
| ...+o +o=+|
+----[SHA256]-----+
# ssh-copy-id [email protected]
# ssh-copy-id [email protected]
#ask_pass = True
Pour le prochain test, le module shell, permettant l’exécution de commandes à distance, est utilisé :
Chapitre 4. Ansible | 53
Aucun mot de passe n’est demandé, l’authentification par clé privée/publique fonctionne !
Lors de la création d’une instance Amazon, une clef privée est créée et téléchargée sur le poste
local.
ssh-add path/to/fichier.pem
4.5. Utilisation
Ansible peut être utilisé depuis l’interpréteur de commandes ou via des playbooks.
Les modules
Il existe un module pour chaque besoin ou presque ! Il est donc conseillé, au lui d’utiliser le module
shell, de chercher un module adapté au besoin.
Chaque catégorie de besoin dispose de son module. En voici une liste non exhaustive :
Type Exemples
54 | Chapitre 4. Ansible
Type Exemples
Gestion du monitoring
Le module yum permet d’installer des logiciels sur les clients cibles :
Le logiciel installé étant un service, il faut maintenant le démarrer avec le module service (CentOS
6) ou systemd (CentOS 7) :
Chapitre 4. Ansible | 55
# ansible centos7 -m systemd -a "name=httpd state=started"
172.16.1.192 | SUCCESS => {
"changed": true,
"name": "httpd",
"state": "started"
}
172.16.1.217 | SUCCESS => {
"changed": true,
"name": "httpd",
"state": "started"
}
Code Erreur
0 OK ou aucun hôte correspondant
1 Erreur
2 Un ou plusieurs hôtes sont en échecs
3 Un ou plusieurs hôtes ne sont pas joignables
4 Erreur d’analyse
5 Mauvaises options ou options incomplètes
99 Execution interrompue par l’utilisateur
250 Erreur inattendue
56 | Chapitre 4. Ansible
Exemple de playbook Apache et MySQL
Le playbook suivant permet d’installer Apache et MySQL sur nos serveurs cibles :
---
- hosts: centos7
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd,php,php-mysqli state=latest
- name: ensure httpd is started
systemd: name=httpd state=started
- name: ensure mysql is at the latest version
yum: name=mysql-server state=latest
- name: ensure mysqld is started
systemd: name=mysqld state=started
Chapitre 4. Ansible | 57
$ ansible-playbook test
Dans ce playbook, un serveur va être installé et configuré pour héberger une base de données
MySQL.
Le playbook utilise :
• Des variables ;
• Créer une base de données, un utilisateur et lui donne tous les droits sur les bases de données.
58 | Chapitre 4. Ansible
---
- hosts: centos7
become: yes
vars:
mysqlpackage: "mariadb-server,MySQL-python"
mysqlservice: "mariadb"
mysql_port: "3306"
dbuser: "synchro"
dbname: "mabase"
upassword: "M!rro!r"
tasks:
- name: configurer le noeud 1 dans /etc/hosts
lineinfile:
dest: /etc/hosts
line: "13.59.197.48 mirroir1.local.lan mirroir1"
state: present
- name: configurer le noeud 2 dans /etc/hosts
lineinfile:
dest: /etc/hosts
line: "52.14.125.109 mirroir2.local.lan mirroir2"
state: present
- name: mariadb installe et a jour
yum: name="{{ mysqlpackage }}" state=latest
- name: mariadb est demarre
service: name="{{ mysqlservice }}" state=started
- name: creer la base de donnee
mysql_db: name="{{ dbname }}" state=present
- name: creer un utilisateur
mysql_user: name="{{ dbuser }}" password="{{ upassword }}" priv=*.*:ALL host='%'
state=present
- name: restart mariadb
service: name="{{ mysqlservice }}" state=restarted
...
• with_items
• with_file
• with_fileglob
• …
Chapitre 4. Ansible | 59
Exemple d’utilisation, création de 3 utilisateurs :
Un squelette de rôle, servant comme point de départ du développement d’un rôle personnalisé,
peut être généré par la commande ansible-galaxy :
La commande aura pour effet de générer l’arborescence suivante pour contenir le rôle formatux :
$ tree formatux
formatux/
├── defaults
│ └── main.yml
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
La commande ansible-galaxy
60 | Chapitre 4. Ansible
Syntaxe de la commande ansible-galaxy
ansible-galaxy [import|init|install|login|remove|...]
Sous-commandes Observations
install installe un rôle
remove retire un ou plusieurs rôles
init génère un squelette de nouveau rôle
import importe un rôle depuis le site web galaxy. Nécessite un login au préalable.
Chapitre 4. Ansible | 61
Chapitre 5. Ansible Niveau 2
Objectifs
• la valeur simple
• le dictionnaire
Une variable peut être définie dans un playbook, dans un rôle ou depuis la ligne de commande.
---
- hosts: apache1
remote_user: root
vars:
port_http: 80
service:
debian: apache2
centos: httpd
Une fois définie, une variable peut être utilisée en l’appellant entre doubles accolades :
tasks:
- name: make sure apache is started
service: name={{ service['centos'] }} state=started
Evidemment, il est également possible d’accéder aux variables globales d’Ansible (type d’OS,
adresses IP, nom de la VM, etc.).
Les variables peuvent être déportées dans un fichier externe au playbook, auquel cas il faudra
définir ce fichier dans le playbook avec la directive vars_files :
---
- hosts: apache1
remote_user: root
vars_files:
- mesvariables.yml
Le fichier mesvariables.yml
---
port_http: 80
service:
debian: apache2
centos: httpd
Pour afficher une variable, il faut activer le mode debug de la façon suivante :
- debug:
msg: "Afficher la variable : {{ service['debian'] }}"
Pour enregistrer le retour d’une tâche et pouvoir y accéder plus tard, il faut utiliser le mot clef
register à l’intérieur même de la tâche.
tasks:
- name: contenu de /home
shell: ls /home
register: homes
Les chaînes de caractères composant la variable enregistrée sont accessibles via la valeur stdout (ce
qui permet de faire des choses comme homes.stdout.find("core") != -1), de les exploiter en
utilisant une boucle (voir with_items), ou tout simplement par leurs indices comme vu dans
l’exemple précédent.
Il existe plusieurs types de boucles sous Ansible, en fonction de l’objet que vous voulez manipuler :
• with_items
• with_file
• with_dict
• with_fileglob
• …
tasks:
- name: contenu de /home
shell: ls /home
register: homes
Une fois un dictionnaire créé, celui-ci peut être parcouru en utilisant la variable item comme index :
---
- hosts: ansiblecli
remote_user: ansible
become: true
vars:
users:
antoine:
group: users
state: present
erwan:
group: users
state: absent
tasks:
L’instruction when est très pratique dans de nombreux cas : ne pas effectuer certaines actions sur
certains type de serveur, si un fichier ou un n’utilisateur n’existe pas, etc.
tasks:
- name: "ne redemarre que les OS Debian"
command: /sbin/shutdown -r now
when: ansible_os_family == "Debian"
tasks:
- name: "ne redémarre que les CentOS version 6 et Debian version 7"
command: /sbin/shutdown -r now
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version ==
"6") or
(ansible_distribution == "Debian" and ansible_distribution_major_version ==
"7")
Les conditions correspondant à un ET logique peuvent être fournies sous forme de liste :
tasks:
- name: "ne redémarre que les CentOS 6"
command: /sbin/shutdown -r now
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "6"
Le résultat de la variable peut aussi être utilisé conjointement aux conditions when et son absence
de contenu évalué :
tasks:
En fonction de votre besoin, vous allez être amenés à utiliser différents modules Ansible pour
modifier les fichiers de configuration du système.
Le module ini_file
Lorsqu’il s’agit de modifier un fichier de type INI (section entre [] puis paires de clef=valeur), le plus
simple est d’utiliser le module ini_file.
Le module nécessite :
• La valeur de la section
• Le nom de l’option
• La nouvelle valeur
Exemple d’utilisation :
Le module lineinfile
Pour s’assurer qu’une ligne est présente dans un fichier, ou lorsqu’une seule ligne d’un fichier doit
être ajoutée ou modifiée.
Voir http://docs.ansible.com/ansible/latest/lineinfile_module.html.
Dans ce cas, la ligne à modifier d’un fichier sera retrouvée à l’aide d’une regexp.
Par exemple, pour s’assurer que la ligne commençant par 'SELINUX=' dans le fichier
/etc/selinux/config contiennent la valeur enforcing :
- lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: 'SELINUX=enforcing'
Lorsqu’un fichier doit être copié depuis le serveur Ansible vers un ou plusieurs hosts, dans ce cas il
est préférable d’utiliser le module copy :
- copy:
src: /data/ansible/sources/monfichier.conf
dest: /etc/monfichier.conf
owner: root
group: root
mode: 0644
Le module fetch
Lorsqu’un fichier doit être copié depuis un serveur distant vers le serveur local.
- fetch:
src: /etc/monfichier.conf
dest: /data/ansible/backup/monfichier-{{ inventory_hostname }}.conf
flat: yes
Le module template
- template:
src: /data/ansible/templates/monfichier.j2
dest: /etc/monfichier.conf
owner: root
group: root
mode: 0644
Il est possible d’ajouter une étape de validation si le service ciblé le permet (par exemple apache
avec la commande apachectl -t) :
Le module get_url
Pour télécharger vers un ou plusieurs hôtes des fichiers depuis un site web ou ftp.
- get_url:
url: http://site.com/archive.zip
dest: /tmp/archive.zip
mode: 0640
checksum: sha256:f772bd36185515581aa9a2e4b38fb97940ff28764900ba708e68286121770e9a
En fournissant un checksum du fichier, ce dernier ne sera pas re-téléchargé s’il est déjà présent à
l’emplacement de destination et que son checksum correspond à la valeur fournie.
Les handlers permettent de lancer des opérations, comme relancer un service, lors de
changements.
Un module, étant idempotent, un playbook peut détecter qu’il y a eu un changement significatif sur
un système distant, et donc déclencer une opération en réaction à ce changement. Une notification
est envoyée à la fin d’un bloc de tâche du playbook, et l’opération en réaction ne sera déclenchée
qu’une seule fois même si plusieurs tâches différentes envoient cette notification.
Par exemple, plusieurs tâches peuvent indiquer que le service httpd nécessite une relance à cause
d’un changement dans ses fichiers de configuration. Mais le service ne sera redémarré qu’une seule
fois pour éviter les multiples démarrages non nécessaires.
• Il ne se lance pas immédiatement, mais attend que toutes les tâches soient complètes pour
s’exécuter.
Exemple de handlers
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart httpd
service: name=httpd state=restarted
Depuis la version 2.2 d’Ansible, les handlers peuvent se mettre directement à l’écoute des tâches :
handlers:
- name: restart memcached
service: name=memcached state=restarted
listen: "restart web services"
- name: restart apache
service: name=apache state=restarted
listen: "restart web services"
tasks:
- name: restart everything
command: echo "this task will restart the web services"
notify: "restart web services"
Un squelette de rôle, servant comme point de départ du développement d’un rôle personnalisé,
peut être généré par la commande ansible-galaxy :
La commande aura pour effet de générer l’arborescence suivante pour contenir le rôle claranet :
Les rôles permettent de s’affranchir totalement de l’inclusion des fichiers. Plus besoin de spécifier
les chemins d’accès aux fichiers, les directives include dans les playbook. Il suffit de spécifier une
tâche, ansible s’occupe des inclusions.
La commande ansible-galaxy
ansible-galaxy [import|init|install|login|remove|...]
Sous-commandes Observations
install installe un rôle
remove retire un ou plusieurs rôles
init génère un squelette de nouveau rôle
import importe un rôle depuis le site web galaxy. Nécessite un login au préalable.
Par défaut, les connexions SSH vers les hosts restent ouvertes durant l’exécution des différentes
tâches d’un playbook sur l’ensemble des noeuds.
Dans ce cas, il faudra basculer en mode asynchrone et spécifier un temps maximum d’exécution
ainsi que la fréquence (par défaut à 10s) avec laquelle vous allez vérifier le status de l’hôte.
En spécifiant une valeur de poll à 0, Ansible va exécuter la tâche et continuer sans se soucier du
résultat.
Voici un exemple mettant en oeuvre les tâches asynchrones, qui permet de relancer un serveur et
d’attendre que le port 22 soit de nouveau joignable :
ssh-add path/to/fichier.pem
6.1. Introduction
Ansistrano est un rôle Ansible pour déployer facilement des applications PHP, Python, etc. Il se base
sur le fonctionnement de Capistrano
Il peut télécharger le code source depuis rsync, git, scp, http, S3, …
• Symlink Shared et Symlink : après avoir déployé la nouvelle release, le lien symbolique current
est modifié pour pointer vers cette nouvelle release
/var/www/site/
├── current -> ./releases/20180821070043Z
├── releases
│ └── 20180821070043Z
│ ├── css -> ../../shared/css/
│ ├── img -> ../../shared/img/
│ └── REVISION
├── repo
└── shared
├── css/
└── img/
• La VM cliente :
Pour gérer notre serveur web, nous allons utiliser le rôle geerlingguy.apache qu’il faut installer sur
le serveur :
Une fois le rôle installé, nous allons pouvoir créer la première partie de notre playbook, qui va :
• Installer Apache,
Considérations techniques :
• Comme nous le verrons plus loin, ansistrano va créer un lien symbolique current vers le dossier
de la release en cours.
• Le code source à déployer contient un dossier html sur lequel le vhost devra pointer. Sa
DirectoryIndex est index.htm.
---
- hosts: ansiblecli
become: yes
vars:
dest: "/var/www/site/"
apache_global_vhost_settings: |
DirectoryIndex index.php index.htm
apache_vhosts:
- servername: "website"
documentroot: "{{ dest }}current/html"
tasks:
roles:
- { role: geerlingguy.apache }
Pour cela, nous allons utiliser le rôle ansistrano.deploy dans un second playbook dédié au
déploiement applicatif (pour plus de lisibilité).
---
- hosts: ansiblecli
become: yes
vars:
dest: "/var/www/site/"
ansistrano_deploy_via: "git"
ansistrano_git_repo: https://framagit.org/alemorvan/demo-ansible.git
ansistrano_deploy_to: "{{ dest }}"
roles:
- { role: ansistrano.deploy }
Une redirection du port http a été mis en place pour accéder depuis l’extérieur à votre serveur.
Notez :
Notez :
roles:
- { role: ansistrano.deploy }
---
[ansiblesrv] $ ansible-playbook -i hosts playbook-deploy.yml
Sur le client :
roles:
- { role: ansistrano.deploy }
TASK [ansistrano.deploy : ANSISTRANO | Create softlinks for shared paths and files]
**************************************************
changed: [192.168.10.11] => (item=img)
changed: [192.168.10.11] => (item=css)
changed: [192.168.10.11] => (item=logs)
Sur le client :
Dès lors, les fichiers contenus dans ces 2 dossiers et le fichier logs sont toujours accessibles via les
chemins suivants :
• /var/www/site/current/css/,
• /var/www/site/current/img/,
• /var/www/site/current/logs,
Dans notre cas, le dépôt contient un dossier html, qui contient les fichiers du site.
---
- hosts: ansiblecli
become: yes
vars:
dest: "/var/www/site/"
apache_global_vhost_settings: |
DirectoryIndex index.php index.htm
apache_vhosts:
- servername: "website"
documentroot: "{{ dest }}current/" ①
tasks:
roles:
- { role: geerlingguy.apache }
---
- hosts: ansiblecli
become: yes
vars:
dest: "/var/www/site/"
ansistrano_deploy_via: "git"
ansistrano_git_repo: https://framagit.org/alemorvan/demo-ansible.git
ansistrano_deploy_to: "{{ dest }}"
ansistrano_keep_releases: 3
ansistrano_shared_paths:
- "img"
- "css"
ansistrano_shared_files:
- "log"
ansistrano_git_repo_tree: 'html' ①
roles:
- { role: ansistrano.deploy }
roles:
- { role: ansistrano.deploy }
Vous pouvez vous amuser, durant le déploiement, à rafraichir votre navigateur, pour voir en 'live'
le changement s’effectuer.
roles:
- { role: ansistrano.deploy }
Vous pouvez vous amuser, durant le déploiement, à rafraichir votre navigateur, pour voir en 'live'
le changement s’effectuer.
• Setup
• Update Code
• Symlink
• Clean Up
Un playbook peut être inclu par les variables prévues à cet effet :
• ansistrano_before_<task>_tasks_file
• ou ansistrano_after_<task>_tasks_file
roles:
- { role: ansistrano.deploy }
Le fichier deploy/before-setup-tasks.yml
---
- name: Envoyer un mail
mail:
subject: Debut de MEP sur {{ ansible_hostname }}.
delegate_to: localhost
[root] # mailx
Heirloom Mail version 12.5 7/5/10. Type ? for help.
"/var/spool/mail/root": 1 message 1 new
>N 1 [email protected] Tue Aug 21 14:41 28/946 "Debut de MEP sur localhost."
---
- hosts: ansiblecli
become: yes
vars:
dest: "/var/www/site/"
ansistrano_deploy_via: "git"
ansistrano_git_repo: https://framagit.org/alemorvan/demo-ansible.git
ansistrano_deploy_to: "{{ dest }}"
ansistrano_keep_releases: 3
ansistrano_shared_paths:
- "img"
- "css"
ansistrano_shared_files:
- "logs"
ansistrano_git_repo_tree: 'html'
ansistrano_git_branch: 'v2.0.0'
ansistrano_before_setup_tasks_file: "{{ playbook_dir }}/deploy/before-setup-
tasks.yml"
ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/deploy/after-symlink-
tasks.yml"
roles:
- { role: ansistrano.deploy }
Le fichier deploy/after-symlink-tasks.yml
---
- name: restart apache
service:
name: httpd
state: restarted
Rundeck est un ordonnanceur centralisé open source (licence Apache) écrit en Java.
Depuis l’interface de Rundeck, il est possible de gérer les différents travaux (commandes ou scripts)
à exécuter sur les serveurs distants.
Fonctionnalités :
• Notifications ;
Rundeck peut être intégré aux autres outils de gestion de configuration comme Puppet, Ansible et
d’intégration continue comme Jenkins, etc.
7.1. Installation
Rundeck utilisant le protocle SSH pour se connecter aux systèmes distants, un
compte avec les droits sudo est nécessaire sur chacun des stations clientes.
# wget http://dl.bintray.com/rundeck/rundeck-deb/rundeck-2.6.7-1-GA.deb
# dpkg -i ./rundeck-2.6.7-1-GA.deb
7.2. Configuration
Par défaut, Rundeck n’est configuré en écoute que sur l’adresse de boucle interne (localhost).
Si vous ne souhaitez pas mettre en place un proxy inverse (Apache, Nginx ou HAProxy), éditez les
fichiers /etc/rundeck/framework.properties et /etc/rundeck/rundeck-config.properties et remplacer
localhost par l’adresse IP du serveur, pour mettre en écoute Rundeck sur son interface réseau :
framework.server.url = http://xxx.xxx.xxx.xxx:4440
grails.serverURL=http://xxx.xxx.xxx.xxx:4440
Créer un projet
Un nouveau projet peut être ajouté en cliquant sur le lien Nouveau projet.
Dans la section Resource Model Source, cliquer sur le bouton Edit et choisir Require File Exists `,
puis cliquer sur `Save.
Le serveur est prêt à recevoir une première tâche. Cette tâche consiste en une connection SSH pour
lancer une commande distante.
Dans le champ Input Type, choisir Secure Remote Authentication et mettre Required à Yes.
Dans la section Add a Step, choisir Command. Fournir la commande dans le champ Command. Par
exemple :
Pour appliquer cette tâche à un système distant (appelé noeud), éditer le fichier de configuration du
noeud :
vi /var/rundeck/projects/your_project_name/etc/resources.xml
Interfacé avec des systèmes de gestion de version tel que Git, Subversion etc., il peut être utilisé
pour compiler, tester et déployer des scripts shell ou des projets Ant, Maven, etc, selon des
planifications ou des requêtes à des URLs.
• testé automatiquement ;
Ainsi, les problèmes d’intégrations peuvent être corrigés au plus tôt et la dernière version stable de
l’application est connue.
8.1. Installation
Jenkins peut fonctionner :
En mode standalone
Installation de Jenkins :
• Sous debian :
Installation :
# apt-get update
# apt-get install jenkins
• Sous RedHat :
Installation du paquet :
# yum update
# yum install java-1.8.0-openjdk jenkins
• http://IPSERVEUR:8080/jenkins
Installation de tomcat :
• Sous debian :
• Sous redhat :
Téléchargement de l’application :
cd /var/lib/tomcat6/webapps
wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war
• http://IPSERVEUR:8080/jenkins
server{
listen 80;
server_name jenkins.formatux.fr;
access_log /var/log/nginx/jenkins.access.log;
error_log /var/log/nginx/jenkins.error.log;
proxy_buffers 16 64k;
proxy_buffer_size 128k;
location / {
proxy_pass http://jenkins;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503
http_504;
proxy_redirect off;
Vous pouvez alternativement installer un proxy inversé Apache. Dans ce cas, le VHOST suivant
pourra être utilisé :
<Proxy http://localhost:8080/*>
Order deny,allow
Allow from all
</Proxy>
# setsebool httpd_can_network_connect 1 -P
cat /var/lib/jenkins/secrets/initialAdminPassword
L’assistant va ensuite demander quels plugins doivent être installés et proposer l’installation des
plugins suggérés.
L’étape suivante consiste à créer un utilisateur avec les droits d’administration pour l’accès à la
Saisir un nom pour la tâche, par exemple test. Choisir Freestyle Project et cliquer sur OK.
top -b -n 1 | head -n 5
Dans la page dédiée à la tâche test, cliquer sur Build Now pour executer la tâche test.
Une fois que la tâche a été executée, vous verrez l’historique du Build. Cliquer sur la première tâche
8.6. Sources
Source principale : howtoforge.
Pour favoriser la rédaction de documentations de qualité, les mêmes outils que ceux utilisés pour
coder sont utilisés :
• gestionnaire de bugs,
• revue de code,
• tests automatiques.
• le Markdown,
• le reStructuredText,
• l’Asciidoc.
• Le rédacteur se concentre uniquement sur le contenu et non sur la mise en forme comme c’est
malheureusement trop souvent le cas avec les éditeurs de texte WYSIWYG (openoffice, word,
etc.),
• Le même code source permet de générer des formats différents : pdf, html, word, confluence,
epub, manpage, etc.
• Le travail collaboratif est grandement simplifié : code review, merge request, etc.
• Gestion des versions par branches ou tags git (pas une copie de fichier .doc).
Le processeur initial était développé en python mais à depuis été réécrit en ruby
(https://asciidoctor.org/).
= Hello, AsciiDoc!
Doc Writer <[email protected]>
An introduction to http://asciidoc.org[AsciiDoc].
== First Section
* item 1
* item 2
Comme vous pouvez le constater, le texte (malgré le balisage) reste lisible, la syntaxe est facilement
assimilable et n’est pas trop lourde comparée à ce qui se faisait en latex.
— Linus Torvalds
• https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/
Compiler sa documentation
Après avoir installé l’environnement asciidoc, la commande suivante permet de compiler son
document .adoc en html5 (format par défaut) :
asciidoctor index.adoc
Une image docker existant, il est facile d’utiliser la CI d’un environnement tel que GitLab pour
générer automatiquement la documentation à chaque commit, tag, etc.
• asciidoc-image-helper
• asciidoc-assistant
• asciidoc-preview
• autocomplete-asciidoc
• language-asciidoc
9.3. Références
• http://www.writethedocs.org/guide/docs-as-code/
• https://www.technologies-ebusiness.com/enjeux-et-tendances/moi-code-madoc
• planifier le déploiement,
• créer l’infrastructure.
Les changements apportés par une modification de code à l’infrastructure sont prédictifs.
Le même outil permet de créer des ressources chez les plus grands fournisseurs d’infrastructure :
• AWS,
• GCP,
• Azure,
• OpenStack,
• VMware,
• etc.
/* Un enregistrement DNS
en IPV4 type "A"
*/
resource "dnsimple_record" "hello" {
domain = "example.com"
name = "test"
value = "${digitalocean_droplet.web.ipv4_address}"
type = "A"
}
10.2. La HCL
Le langage HashiCorp Configuration Language est spécifique. Voici quelques points d’attention :
• Les variables sont assignées avec la syntaxe key = value (aucune importance concernant les
espaces). Les valeurs peuvent être des primitives string, number ou boolean ou encore une list
ou une map.
En voici quelques-uns :
• Azure,
• VMware vSphere
• Gitlab,
• Datadog, PagerDuty,
• MySQL,
• Active Directory
• …
Chaque provider venant avec ses propres ressources, il faut lire la doc !
La première commande à lancer pour une nouvelle configuration qui va initialiser la configuration
locale (import de modules par exemple).
• terraform plan
La commande terraform plan permet d’afficher le plan d’exécution, qui décrit quelles actions
Terraform va prendre pour effectuer les changements réels de l’infrastructure.
Si une valeur est affichée comme <computed>, cela veut dire que cette valeur ne sera connue qu’au
moment de l’exécution du plan.
• terraform apply
La commande terraform apply va réellement appliquer les changements tels qu’ils ont été décrits
par la commande terraform plan.
• terraform show
Une fois que l’infrastructure est gérée via Terraform, il est préférable d’éviter de la
modifier manuellement.
• terraform destroy
Avec l’avènement du cloud, le cycle de vie d’un serveur et notre façon de consommer les ressources
ont considérablement changé. Une VM ou une infrastructure doit tout aussi facilement pouvoir être
créée que supprimée.
Avec Terraform, une infrastructure complète peut être déployée juste à l’occasion des tests de non
régréssion lors de la création d’une nouvelle version logicielle par exemple et être totalement
détruite à la fin de ceux-ci pour réduire les coûts d’infrastructure au plus juste.
# Le VPC de la plateforme
resource "cloudstack_vpc" "default" {
name = "our-vpc"
cidr = "10.1.0.0/16"
vpc_offering = "Default VPC offering"
zone = "EU-FR-IKDC2-Z4-ADV"
}
Dans l’exemple ci-dessus, un VPC (Virtual Private Cloud) est créé ainsi qu’un réseau privé. Ce réseau
privé est rattaché à son VPC en lui fournissant son id connu dans terraform en tant que
${cloudstack_vpc.default.id} où :
Les informations de dépendances déterminent l’ordre dans lequel Terraform va créer les
ressources.
provisioner "local-exec" {
command = "echo ${aws_instance.example.public_ip} > ip_address.txt"
}
}
Lors de la création de la nouvelle VM, son adresse IP publique est stockée dans un fichier
ip_address.txt, mais elle aurait très bien pu être envoyée à la CMDB par exemple.
Le provisioner local-exec exécute une commande localement, mais il existe de nombreux autres
provisionners : https://www.terraform.io/docs/provisioners/index.html.
# definition explicite
variable "cidrs" { type = "list" }
provider "aws" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "${var.region}"
}
Vous pouvez stocker vos variables dans un fichier externe (par exemple
variables.tf) sachant que tous fichiers ayant pour extension .tf du répertoire
courant seront chargés.
L’exemple du chapitre précédent peut être repris pour variabiliser la zone de déploiement de nos
ressources :
# Le VPC de la plateforme
resource "cloudstack_vpc" "default" {
name = "our-vpc"
cidr = "10.1.0.0/16"
vpc_offering = "Default VPC offering"
zone = "${var.zone}"
}
Les variables peuvent être également définies depuis la ligne de commande ou un fichier externe
terraform.tfvars qui sera chargé automatiquement à l’exécution.
Il est d’usage de stocker les variables critiques (api key, mots de passe, etc.) dans un
fichier terraform.tfvars et d’exclure ce fichier de votre configuration git.
Voir la documentation pour plus d’informations sur les variables (Maps, etc.) :
https://learn.hashicorp.com/terraform/getting-started/variables
• Installer grafana ou un autre logiciel disposant d’un provider sur une de vos VM et utiliser les
ressources de ce provider.
120 | Glossaire
Index
@ H
--set-upstream, 16 HCL, 113
~1, 25 HEAD, 25
hunk, 19
A
augeas, 47 I
automation, 7 idempotence, 7
intégration continue, 7
B
branch, 14 J
build, 6 Jenkins, 99
C M
CI, 7 Merge Request, 33
Continuous Integration, 7
change, 6 O
commit, 14 orchestration, 7
D P
DSL, 8 provisionning, 7
detached head, 26 puppet, 40
devops, 6
dépôt, 10 R
Rundeck, 93
G run, 6
git, 10
git add, 14 S
git add --patch, 19 stage, 15
git branch, 27
git checkout, 25
git checkout -b, 27
git clone, 12
git commit, 15
git config, 13
git log, 16
git log --graph --oneline, 32
git merge, 31
git merge --abort, 37
git push, 16
git push --all, 33
git remote, 16
git status, 14
Index | 121