@ -0,0 +1,29 @@
|
||||
variables: |
||||
GIT_SUBMODULE_STRATEGY: recursive |
||||
|
||||
stages: |
||||
- build |
||||
|
||||
make-pdf: |
||||
stage: build |
||||
image: |
||||
name: astefanutti/decktape:2.11.0 |
||||
entrypoint: [""] |
||||
tags: |
||||
- france |
||||
- sii |
||||
script: |
||||
# |
||||
# 1. We change the size with --size due to a strange rendering bug |
||||
# decribed here: https://github.com/astefanutti/decktape/issues/151 |
||||
# |
||||
# 2. We also specify --chrome-arg=--disable-web-security to autorize |
||||
# Cross origin requests in chrome |
||||
# |
||||
- node /decktape/decktape.js --chrome-path chromium-browser --chrome-arg=--no-sandbox --chrome-arg=--disable-web-security --size='1576x1182' index.html ansible-formation.pdf |
||||
artifacts: |
||||
name: ansible.pdf |
||||
expire_in: 3 month |
||||
paths: |
||||
- ansible-formation.pdf |
||||
|
@ -0,0 +1,3 @@
|
||||
[submodule "revealjs"] |
||||
path = revealjs |
||||
url = ../../template-revealjs-sii-theme.git |
@ -0,0 +1,118 @@
|
||||
# Ansible |
||||
__Formation__ |
||||
|
||||
Christian Tritten • Stéfan Lebosq |
||||
|
||||
|
||||
## Pré-requis |
||||
|
||||
* Virtualbox |
||||
4 VMs téléchargées et importées |
||||
|
||||
* Putty |
||||
https://www.putty.org/ |
||||
|
||||
* Café (!) |
||||
|
||||
|
||||
## Formation à distance |
||||
|
||||
* Laisser votre caméra allumée afin de favoriser |
||||
les échanges |
||||
|
||||
* Vous pouvez intervenir quand vous voulez... |
||||
mais gardez votre micro coupé le reste du temps |
||||
|
||||
* Levez la main en cas de problème |
||||
(debug sur les TPs en aparté) |
||||
|
||||
* Double pause pour éviter la surchauffe ! |
||||
|
||||
|
||||
## Horaires jour |
||||
|
||||
||| |
||||
|:-|-:| |
||||
|démarrage|__9h30__| |
||||
|pause|__~ 10h30 ~ 11h30__| |
||||
|repas|__12h30__| |
||||
|reprise|__14h00__| |
||||
|pause|__~ 15h00 ~ 16h00__| |
||||
|fin|__17h30__| |
||||
|
||||
|
||||
## Badge |
||||
|
||||
Le port du badge SII de façon visible |
||||
est obligatoire dans les locaux. |
||||
|
||||
|
||||
## Tour de table |
||||
|
||||
* Qui êtes-vous ? |
||||
|
||||
* Connaissez-vous déjà Ansible ou des outils similaires ? |
||||
|
||||
* Qu'attendez-vous de la formation ? |
||||
|
||||
* Avez-vous des à priori sur le mode distanciel ? |
||||
|
||||
|
||||
## Programme |
||||
|
||||
|
||||
### 1. Introduction |
||||
* DevOps et Infrastructure as Code |
||||
* Présentation d'Ansible |
||||
|
||||
|
||||
### 2. Installation et Mise en œuvre |
||||
* Installation et configuration |
||||
* Configuration SSH |
||||
* Mise en place de l’inventaire |
||||
|
||||
|
||||
### 3. Les commandes Ad-Hoc |
||||
|
||||
* CLI Ansible |
||||
* Principaux modules Ad-Hoc |
||||
|
||||
|
||||
### 4. Les Playbooks |
||||
* Définition de tâches |
||||
* Utilisation de variables |
||||
* Handlers et Notify |
||||
* Notion de rôles |
||||
|
||||
|
||||
### 5. Les structures de contrôle |
||||
* Les facts |
||||
* Les boucles et conditions |
||||
* Les inclusions |
||||
|
||||
|
||||
### 6. Les Templates |
||||
* Jinja2 |
||||
* Filtres |
||||
* Tests |
||||
|
||||
|
||||
### 7. Notions avancées |
||||
* Ansible Vault |
||||
* Tester ses Playbooks Ansible |
||||
* Développer ses propres modules |
||||
|
||||
|
||||
## C'est parti !!! |
||||
|
||||
[La formation](index.html) |
||||
|
||||
|
||||
## Ressources internes |
||||
<!-- .slide: data-state="cheat-sheet" --> |
||||
|
||||
1. Formation Ansible SII |
||||
<small>[https://gitlab.siinergy.net/sii-ouest/trainings/ansible](https://gitlab.siinergy.net/sii-ouest/trainings/ansible)</small> |
||||
|
||||
2. Mattermost DevOps SII ouest |
||||
<small>[https://mattermost.siinergy.net/ouest/channels/topic-devops](https://mattermost.siinergy.net/ouest/channels/topic-devops)</small> |
@ -0,0 +1,206 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
# Ansible |
||||
|
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
|
||||
<small>Antoire Bouhier • Christian Tritten • Alban Berthout</small> |
||||
|
||||
|
||||
## DevOps |
||||
## Infrastructure as Code |
||||
|
||||
|
||||
## DevOps |
||||
|
||||
* Mouvement qui consiste à promouvoir le dialogue et la collaboration entre les équipes _Dev_ et _Ops_. |
||||
|
||||
* Ensemble de bonnes pratiques et de principes |
||||
établis entre : |
||||
|
||||
- les équipes DEV (de développement) |
||||
|
||||
- les équipes OPS (d’exploitations) |
||||
|
||||
* L'objectif de DevOps est de _fluidifier le processus de déploiement_ d'une application. |
||||
|
||||
|
||||
## Les principaux axes du DevOps |
||||
|
||||
1. Améliorer la communication |
||||
<small>Organisation • Collaboration • Partage d'outils communs • Conférences • Réunions</small> |
||||
|
||||
2. Accepter et banaliser les erreurs |
||||
<small>Droit à l'erreur • Responsabilité partagée</small> |
||||
|
||||
3. Mettre en prod le plus souvent possible |
||||
<small>Robustesse • Confiance</small> |
||||
|
||||
4. Automatiser tout ce qui peut l'être |
||||
<small>Tests • Cloud • Déploiements • Configuration • Chaos monkey</small> |
||||
|
||||
5. Récolter des métriques et indicateurs |
||||
dans une optique d'amélioration continue |
||||
|
||||
|
||||
## Le champ d'application du DevOps |
||||
![devops](images/ci-vs-cd-devops-difference.jpg) |
||||
|
||||
|
||||
## Automatisation |
||||
|
||||
Traiter de manière automatique les opérations |
||||
|
||||
* de contrôle, |
||||
|
||||
* de régulation, |
||||
|
||||
* d’administration, |
||||
|
||||
avec peu ou pas d’intervention humaine. |
||||
|
||||
|
||||
## Intérêt de l'automatisation |
||||
|
||||
* Réduire la complexité |
||||
|
||||
* Réduire les possibilités d’erreurs humaine |
||||
|
||||
* Améliorer les performance d’un système |
||||
|
||||
* Augmenter la productivité et l’innovation |
||||
|
||||
* Améliorer la robustesse, l’agilité du déploiement |
||||
|
||||
* Réduire le TTM d’une application |
||||
|
||||
|
||||
## Infrastructure As Code |
||||
|
||||
* L'infrastructure cible peut-être décrite dans des fichiers de description à l'aide d'une syntaxe spécifique. |
||||
|
||||
* Il devient alors possible de gérer et de versionner chaque modification apportée à l'infrastructure. |
||||
|
||||
* Construire, reconstruire, modifier ou dupliquer une infrastructure s'en trouve d'autant simplifié. |
||||
|
||||
* Outils : Terraform, Ansible, Puppet, Docker, Kubernetes... |
||||
|
||||
|
||||
## Les outils de gestion de configuration |
||||
|
||||
* Permettent de contrôler l'ensemble des modifications apportées sur l’infrastructure d’une entreprise. |
||||
|
||||
* Assurent que cette infrastructure est configurée selon les bonnes spécifications. |
||||
|
||||
* Évitent l'apparition de trop grandes variations de configuration entre les serveurs. |
||||
|
||||
|
||||
## Quelques outils |
||||
|
||||
- CFEngine (1993) |
||||
|
||||
- Puppet (2005) |
||||
|
||||
- Chef (2009) |
||||
|
||||
- Ansible (2012) |
||||
|
||||
|
||||
## Ansible |
||||
|
||||
* Logiciel libre (GPL-3.0) |
||||
|
||||
* Initié en 2012 |
||||
|
||||
- Version 1.0 = 2013 |
||||
|
||||
- Version actuelle = 2.10 (2020), 2.9 pour Red Hat subscribers |
||||
|
||||
* Développé en Python |
||||
[https://github.com/ansible/ansible](https://github.com/ansible/ansible) |
||||
|
||||
* Forte communauté d'utilisateurs |
||||
|
||||
|
||||
* Ansible racheté par Red Hat en octobre 2015 |
||||
|
||||
* Red Hat racheté par IBM en octobre 2018 |
||||
|
||||
|
||||
* Ansible est un moteur d'automatisation permettant : |
||||
|
||||
- le provisionnement de logiciel, |
||||
|
||||
- la gestion de la configuration. |
||||
|
||||
|
||||
* Pas d'agent |
||||
|
||||
- utilise _SSH_ sur __Linux/Unix__ |
||||
|
||||
- utilise _WinRM_ sur __Windows__ |
||||
|
||||
* Mode _Push_ |
||||
<small>Peut aussi fonctionner en _Pull_ (sur cibles Linux uniquement)</small> |
||||
|
||||
|
||||
### Cibles Linux |
||||
|
||||
* La plupart des systèmes Linux sont supportés. |
||||
|
||||
* Connexion par SSH. |
||||
|
||||
* Pré-requis sur les machines cibles : |
||||
|
||||
- SSH server |
||||
|
||||
- Python 2.7 ou 3.5 |
||||
|
||||
|
||||
### Cibles Windows |
||||
|
||||
* Desktop : |
||||
Windows 7, 8.1, 10 |
||||
|
||||
* Server : |
||||
Windows Server 2008, 2008 R2, 2012, 2012 R2, 2016, 2019 |
||||
|
||||
* Connexion par WinRM. |
||||
|
||||
* Pré-requis sur les machines cibles : |
||||
- PowerShell 3.0 ou + |
||||
- .NET 4.0 ou + |
||||
- Un WinRM listener doit être créé et activé. |
||||
|
||||
|
||||
### Documentation pour Windows |
||||
|
||||
<small>https://docs.ansible.com/ansible/latest/user_guide/windows.html</small> |
||||
|
||||
### Liste des modules pour Windows |
||||
<small>https://docs.ansible.com/ansible/2.9/modules/list_of_windows_modules.html</small> |
||||
<small>https://docs.ansible.com/ansible/latest/collections/ansible/windows/index.html</small> |
||||
|
||||
|
||||
### Pourquoi utiliser Ansible ? |
||||
|
||||
* Maîtrise des actions exécutées sur les machines cibles. |
||||
|
||||
* Moins d'erreurs qu'avec des actions manuelles. |
||||
|
||||
* Simple à mettre en oeuvre. |
||||
|
||||
* Courbe d'apprentissage rapide. |
||||
|
||||
* Syntaxe déclarative (pas de scripting). |
||||
|
||||
* Libère les Ops des tâches répétitives. |
||||
|
||||
|
||||
### Sans outil de gestion de Configuration |
||||
|
||||
![Schéma connexion sans Ansible](images/manual-deployment-without-ansible.png) |
||||
|
||||
|
||||
### Avec Ansible |
||||
|
||||
![Schéma connexion avec Ansible](images/ansible-ad-hoc-deployment-workflow.png) |
@ -0,0 +1,85 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
# Bonnes pratiques |
||||
|
||||
|
||||
## Rester simple ! |
||||
|
||||
|
||||
## Rester clair ! |
||||
|
||||
- Apporter tout le soin nécessaire à la lisibilité du code Ansible. |
||||
|
||||
- Nommer toujours vos Plays et Tasks de manière précise et significative. |
||||
|
||||
- Privilégiez la syntaxe YAML native. |
||||
<small>(Pas de : `name=httpd state=started enabled=yes`)</small> |
||||
|
||||
- Ainsi fait, le code Ansible peut devenir la documentation de référence de votre workflow. |
||||
|
||||
|
||||
## Penser "déclaratif" |
||||
|
||||
- Ansible permet de décrire un _état désiré_. |
||||
|
||||
- Si vous essayez d'écrire du code dans vos playbooks et rôles, vous augmentez le risque d'échec. |
||||
|
||||
- Utilisez prioritairement les Modules Ansible chaque fois que c'est possible. |
||||
|
||||
|
||||
## Utiliser les Roles |
||||
|
||||
- Utilisez les Roles ! |
||||
|
||||
- Ils permettent un très bon découpage du code Ansible. |
||||
|
||||
- Ils permettent de gérer des variables par défaut pour les composants. |
||||
|
||||
|
||||
## Attention aux variables ! |
||||
|
||||
- Ansible permet de déclarer des variables dans une grande variété d'emplacements. Il devient facile de s'y perdre ! |
||||
|
||||
- Évitez de trop disperser les déclarations de variables dans le code Ansible. |
||||
|
||||
- Limitez les déclarations de variables à deux ou trois emplacements clés : |
||||
|
||||
1. variables de groupes |
||||
2. variables de rôles |
||||
|
||||
- Documenter précisément les variables que vous déclarez dans votre code Ansible. |
||||
|
||||
|
||||
## Eviter autant que possible les Modules "Commands" |
||||
|
||||
- Les modules de commandes génériques tels que `shell` ou `command` peuvent conduire à certains dysfonctionnements. En effet les commandes Shell : |
||||
|
||||
- ne sont pas toujours idempotentes. |
||||
|
||||
- s'exécuteront toujours et retourneront l'état `changed` (à moins de spécifier `changed_when`). |
||||
|
||||
- Les modules plus spécifiques sont souvent prévus pour être agnostique du système d'exploitation, ce qui permet d'augmenter la ré-utilisabilité du code. |
||||
|
||||
|
||||
## Eviter le module "lineinfile" |
||||
|
||||
- Utiliser les modules `copy` ou `template` plutôt que `lineinfile` ou `replace` |
||||
|
||||
- Pas besoin de connaître la syntaxe `regex`. |
||||
|
||||
- Permet de contrôler exactement le contenu du fichier final. |
||||
|
||||
|
||||
## Créer des fichiers d’inventaires séparés |
||||
|
||||
- Si vous devez gérer plusieurs environnements, créez des fichiers d'inventaires séparés afin d'éviter les problèmes ! |
||||
|
||||
|
||||
## Les bonnes pratiques selon Ansible |
||||
|
||||
<small>https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html</small> |
||||
|
||||
|
||||
## Autres bonnes pratiques |
||||
|
||||
<small>https://www.serverraumgeschichten.de/2018/04/ansible-best-practices/</small> |
@ -0,0 +1,384 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
# Commandes Ad-Hoc |
||||
|
||||
Exécuter des actions simples |
||||
sur un ensemble de machines. |
||||
|
||||
|
||||
## Les commandes Ad-Hoc ? |
||||
|
||||
* Commandes permettant l'exécution simple, rapide et ponctuelle de commandes unitaires. |
||||
|
||||
* Elles peuvent cibler |
||||
|
||||
- une seule machine, |
||||
|
||||
- un groupe de machines spécifique, |
||||
|
||||
- l'ensemble des machines présentes dans l'inventaire. |
||||
|
||||
* Elles se reposent sur les Modules Ansible. |
||||
|
||||
|
||||
## Les Modules Ansible |
||||
|
||||
* Unités de traitement réutilisables. |
||||
|
||||
* Permettent la réalisation d’une tâche précise. |
||||
|
||||
* Écrits en Python. |
||||
|
||||
* Code éprouvé. |
||||
|
||||
* Nombreux modules disponibles. |
||||
|
||||
* Possibilité d'écrire ses propres modules. |
||||
|
||||
|
||||
## Des centaines de modules disponibles ! |
||||
|
||||
<small> |
||||
Cloud Modules • Clustering Modules • Commands Modules • Crypto Modules • |
||||
Database Modules • Files Modules • Identity Modules • Inventory Modules • |
||||
Messaging Modules • Monitoring Modules • Network Modules • Notification |
||||
Modules • Packaging Modules • Source Control Modules • Storage Modules • |
||||
System Modules • Utilities Modules • Web Infrastructure Modules • Windows |
||||
Modules • ... |
||||
|
||||
</small> |
||||
|
||||
<small>https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html</small> |
||||
<small>https://docs.ansible.com/ansible/latest/collections/index.html</small> |
||||
|
||||
|
||||
## Utilisation de modules |
||||
|
||||
`$ ansible <pattern> -m <module> [-a <params>]` |
||||
|
||||
* `<pattern>` peut représenter : |
||||
|
||||
- une machine |
||||
|
||||
- toutes les machines (alias `all`) |
||||
|
||||
- un groupe |
||||
|
||||
- une expression |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible formation:\!web -m command -a "uname -r" |
||||
bdd.formation.sii.fr | SUCCESS | rc=0 >> |
||||
3.10.0-327.28.3.el7.x86_64 |
||||
|
||||
lb.formation.sii.fr | SUCCESS | rc=0 >> |
||||
3.10.0-327.28.3.el7.x86_64 |
||||
``` |
||||
|
||||
|
||||
## Module Command |
||||
|
||||
* À utiliser : |
||||
|
||||
* pour des commandes simples |
||||
* Pour recueillir des informations |
||||
|
||||
* Exemples : |
||||
|
||||
* Éteindre/redémarrer des serveurs |
||||
* Copier des fichiers |
||||
* Créer des users/groups |
||||
* Installer des packages |
||||
|
||||
|
||||
### Exemple |
||||
<!-- .slide: data-state="medium-code" --> |
||||
Création rapide d'un utilisateur |
||||
sur un ensemble de machines |
||||
```none |
||||
$ ansible -m command -a "sudo useradd donald" 'formation' |
||||
10.6.214.70 | SUCCESS | rc=0 >> |
||||
10.6.214.73 | SUCCESS | rc=0 >> |
||||
10.6.214.74 | SUCCESS | rc=0 >> |
||||
10.6.214.72 | SUCCESS | rc=0 >> |
||||
|
||||
$ ansible -m command -a "useradd donald" 'formation' --become |
||||
``` |
||||
|
||||
`--become` permet de passer changer d'utilisateur |
||||
pour jouer la commande. |
||||
|
||||
|
||||
### Exemple |
||||
<!-- .slide: data-state="medium-code" --> |
||||
Affichage des utilisateurs créés |
||||
```none |
||||
$ ansible -m command -a "grep donald /etc/passwd" 'formation' |
||||
10.6.214.74 | SUCCESS | rc=0 >> |
||||
donald:x:1009:1010::/home/donald:/bin/bash |
||||
|
||||
10.6.214.70 | SUCCESS | rc=0 >> |
||||
donald:x:1009:1010::/home/donald:/bin/bash |
||||
|
||||
10.6.214.72 | SUCCESS | rc=0 >> |
||||
donald:x:1009:1010::/home/donald:/bin/bash |
||||
|
||||
10.6.214.73 | SUCCESS | rc=0 >> |
||||
donald:x:1009:1010::/home/donald:/bin/bash |
||||
``` |
||||
|
||||
|
||||
## Documentation des modules |
||||
|
||||
* Recherche "ansible module nom-module" (Google) |
||||
|
||||
* `$ ansible-doc <nom-module>` (CLI) |
||||
|
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
## Travaux pratiques |
||||
|
||||
![Travaux pratiques](images/tp.gif) |
||||
|
||||
<small>[TP Ansible : commandes ad-hoc bases](travaux-pratiques/tp-ansible-les-commandes-ad-hoc.html)</small> |
||||
|
||||
|
||||
## Modules de commandes |
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`command` | `ansible.builtin.command` | Executes a command on a remote node |
||||
`expect` | `ansible.builtin.expect` | Executes a command and responds to prompts. |
||||
`psexec` | `community.windows.psexec` | Runs commands on a remote Windows host based on the PsExec model |
||||
`raw` | `ansible.builtin.raw` | Executes a low-down and dirty SSH command |
||||
`script` | `ansible.builtin.script` | Runs a local script on a remote node after transferring it |
||||
`shell` | `ansible.builtin.shell` | Execute commands in nodes. |
||||
`telnet` | `ansible.netcommon.telnet` | Executes a low-down and dirty telnet command |
||||
|
||||
<small>https://docs.ansible.com/ansible/2.9/modules/list_of_commands_modules.html</small> |
||||
|
||||
|
||||
## Modules de gestion de fichiers |
||||
<!-- .slide: data-state="small-table" --> |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`blockinfile` | `ansible.builtin.blockinfile` | Insert/update/remove a text block surrounded by marker lines |
||||
`copy` | `ansible.builtin.copy` | Copies files to remote locations |
||||
`fetch` | `ansible.builtin.fetch` | Fetches a file from remote nodes |
||||
`file` | `ansible.builtin.file` | Sets attributes of files |
||||
`lineinfile` | `ansible.builtin.lineinfile` | Manage lines in text files |
||||
`replace` | `ansible.builtin.replace` | Replace all instances of a particular string in a file using a back-referenced regular expression. |
||||
`stat` | `ansible.builtin.stat` | Retrieve file or file system status |
||||
`template` | `ansible.builtin.template` | Templates a file out to a remote server |
||||
... | ... | ... |
||||
|
||||
<small>https://docs.ansible.com/ansible/2.9/modules/list_of_files_modules.html</small> |
||||
|
||||
|
||||
### Exemple |
||||
|
||||
Modifier les attributs d'un fichier sur les machines |
||||
du groupe formation |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible -m file -a "dest=/etc/foo mode=0660 owner=root group=root" \ |
||||
formation |
||||
|
||||
10.6.214.72 | SUCCESS => { |
||||
"changed": true, |
||||
"gid": 0, |
||||
"group": "root", |
||||
"mode": "0660", |
||||
"owner": "root", |
||||
"path": "/etc/foo", |
||||
"secontext": "system_u:object_r:net_conf_t:s0", |
||||
"size": 158, |
||||
"state": "file", |
||||
"uid": 0 |
||||
... |
||||
} |
||||
``` |
||||
|
||||
|
||||
## Modules de gestion de paquets |
||||
|
||||
<small>https://docs.ansible.com/ansible/2.9/modules/list_of_packaging_modules.html</small> |
||||
|
||||
|
||||
### Paquets Debian / Ubuntu |
||||
<!-- .slide: data-state="small-table" --> |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`apt` | `ansible.builtin.apt` | Manages apt-packages |
||||
`apt_key` | `ansible.builtin.apt_key` | Add or remove an apt key |
||||
`apt_repository` | `ansible.builtin.apt_repository` | Add and remove APT repositories |
||||
`dpkg_selections` | `ansible.builtin.dpkg_selections` | Dpkg package selection selections |
||||
`package` | `ansible.builtin.package` | Generic OS package manager |
||||
`package_facts` | `ansible.builtin.package_facts` | Package information as facts |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Paquets RedHat / CentOS / Fedora |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`dnf` | `ansible.builtin.dnf` | Manages packages with the dnf package manager |
||||
`yum` | `ansible.builtin.yum` | Manages packages with the yum package manager |
||||
`yum_repository` | `ansible.builtin.yum_repository` |Add or remove YUM repositories |
||||
`redhat_subscription` | `community.general.redhat_subscription` | Manage registration and subscriptions to RHSM using subscription-manager |
||||
`rhn_channel` | `community.general.rhn_channel` | Adds or removes Red Hat software channels |
||||
`rhn_register` | `community.general.rhn_register` | Manage RHN registration using rhnreg_ks |
||||
`rhsm_repository` | `community.general.rhsm_repository` | Manage RHSM repositories using subscription-manager |
||||
`rpm_key` | `ansible.builtin.rpm_key` | Adds or removes a gpg key from the rpm db |
||||
`package` | `ansible.builtin.package` | Generic OS package manager |
||||
`package_facts` | `ansible.builtin.package_facts` | Package information as facts |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Paquets Suse / OpenSuse |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`zypper` | `community.general.zypper` | Manage packages on SUSE and openSUSE |
||||
`zypper_repository` |`community.general.zypper_repository` | Add and remove Zypper repositories |
||||
`package` | `ansible.builtin.package` | Generic OS package manager |
||||
`package_facts` | `ansible.builtin.package_facts` | Package information as facts |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Paquets relatifs à des langages de programmation |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`cpanm` | `community.general.cpanm` | Manages Perl library dependencies. |
||||
`gem` | `community.general.gem` | Manage Ruby gems |
||||
`npm` | `community.general.npm` | Manage node.js packages with npm |
||||
`pip` |`ansible.builtin.pip` | Manages Python library dependencies |
||||
... | ... | ... |
||||
|
||||
|
||||
### Exemple |
||||
Vérification de la présence d'un paquet |
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible -m yum -a "name=vim state=present" 'formation' |
||||
10.6.214.70 | SUCCESS => { |
||||
"changed": true, |
||||
"rc": 0, |
||||
"results": [ |
||||
... |
||||
Installing : |
||||
2:vim-filesystem-7.4.160-1.el7_3.1.x86_64 |
||||
2:vim-common-7.4.160-1.el7_3.1.x86_64 |
||||
gpm-libs-1.20.7-5.el7.x86_64 |
||||
2:vim-enhanced-7.4.160-1.el7_3.1.x86_64 |
||||
|
||||
Installed: |
||||
vim-enhanced.x86_64 2:7.4.160-1.el7_3.1 |
||||
Dependency Installed: |
||||
gpm-libs.x86_64 0:1.20.7-5.el7 |
||||
vim-common.x86_64 2:7.4.160-1.el7_3.1 |
||||
vim-filesystem.x86_64 2:7.4.160-1.el7_3.1 |
||||
|
||||
Complete!" |
||||
] |
||||
} |
||||
``` |
||||
|
||||
|
||||
## Modules de gestion de code |
||||
* git |
||||
* subversion |
||||
* hg |
||||
|
||||
Ces modules permettent de cloner des dépôts de code. |
||||
|
||||
<small>https://docs.ansible.com/ansible/2.9/modules/list_of_source_control_modules.html</small> |
||||
|
||||
|
||||
|
||||
## Modules de gestion du système |
||||
|
||||
<small>https://docs.ansible.com/ansible/2.9/modules/list_of_system_modules.html</small> |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Utilisateurs et groupes |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`user` | `ansible.builtin.user` | Manage user accounts |
||||
`group` | `ansible.builtin.group` | Add or remove groups |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Stockage |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`parted` | `community.general.parted` | Configure block device partitions |
||||
`lvg` | `community.general.lvg` | Configure LVM volume groups |
||||
`lvol` | `community.general.lvol` | Configure LVM logical volumes |
||||
`filesystem` | `community.general.filesystem` | Makes a filesystem |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Services |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`service` | `ansible.builtin.service` | Manage services |
||||
`service_facts` | `ansible.builtin.service_facts` | Return service state information as fact data |
||||
`systemd` | `ansible.builtin.systemd` | Manage services |
||||
`sysvinit` | `ansible.builtin.sysvinit` | Manage SysV services |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Réseau |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`ping` | `ansible.builtin.ping` | Try to connect to host, verify a usable python and return pong on success |
||||
`hostname` | `ansible.builtin.hostname` | Manage hostname |
||||
`firewalld` | `ansible.posix.firewalld` | Manage arbitrary ports/services with firewalld |
||||
`iptables` | `ansible.builtin.iptables` | Modify the systems iptables |
||||
|
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
### Configuration SSH |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`authorized_key` | `ansible.posix.authorized_key` | Adds or removes an SSH authorized key |
||||
`known_hosts` | `ansible.builtin.known_hosts` | Add or remove a host from the known_hosts file |
||||
|
||||
|
||||
### Divers |
||||
<!-- .slide: data-state="small-table" --> |
||||
Module (2.9) | Module (2.10) | Description |
||||
- | - | - |
||||
`cron` | `ansible.builtin.cron` | Manage cron.d and crontab entries |
||||
`reboot` | `ansible.builtin.reboot` | Reboot a machine |
||||
`setup` | `ansible.builtin.setup` | Gathers facts about remote hosts |
||||
`timezone` | `community.general.timezone` | Configure timezone setting |
||||
|
||||
|
||||
### Exemple |
||||
<!-- .slide: data-state="small-code" --> |
||||
Récupération des _facts_ de machines distantes |
||||
```none |
||||
$ ansible -m setup 'formation' |
||||
10.6.214.70 | SUCCESS => { |
||||
"ansible_facts": { |
||||
"ansible_all_ipv4_addresses": [ |
||||
"10.6.214.70" |
||||
], |
||||
"ansible_all_ipv6_addresses": [ |
||||
"fe80::250:56ff:fe9d:1ae5" |
||||
], |
||||
"ansible_architecture": "x86_64", |
||||
"ansible_bios_date": "09/17/2015", |
||||
"ansible_bios_version": "6.00", |
||||
"ansible_cmdline": { |
||||
"BOOT_IMAGE": "/vmlinuz-3.10.0-327.28.3.el7.x86_64", |
||||
"LANG": "fr_FR.UTF-8", |
||||
"crashkernel": "auto", |
||||
"quiet": true, |
||||
"rd.lvm.lv": "rootvg/slashlv", |
||||
"rhgb": true, |
||||
``` |
@ -0,0 +1,578 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
# Playbooks Ansible |
||||
|
||||
Jouer et rejouer facilement un jeu de commandes prédéfini sur un ensemble de machines. |
||||
|
||||
|
||||
![Schéma archi globale](images/ansible-archi-playbooks.png) |
||||
|
||||
|
||||
## Format du Playbook |
||||
|
||||
* Il se présente sous la forme d'un simple fichier texte au format `yaml`. |
||||
|
||||
* Il peut donc être facilement versionné dans un outil de gestion de version. |
||||
|
||||
|
||||
### yaml |
||||
|
||||
* Format ouvert de représentation de données. |
||||
|
||||
* Acronyme récursif de _YAML Ain't Markup Language_. |
||||
|
||||
* Permet de représenter des données complexes tout en conservant une excellente lisibilité. |
||||
|
||||
* Utilisation en forte progression ces dernières années. |
||||
<small>Ansible, GitLab, Docker Compose, Kubernetes manifests, etc...</small> |
||||
|
||||
* Site officiel : https://yaml.org/ |
||||
|
||||
|
||||
### YAML basics |
||||
|
||||
https://fr.wikipedia.org/wiki/YAML |
||||
|
||||
* _attention_ ! l'indentation se fait avec un ou plusieurs espaces, jamais avec des tabulations ! |
||||
|
||||
* Les commentaires sont signalés par le signe dièse `#` et se prolongent sur toute la ligne. |
||||
|
||||
* Les éléments de listes sont dénotés par le tiret `-`, suivi d'une espace, à raison d'un élément par ligne. |
||||
|
||||
* Les tableaux sont de la forme `clé: valeur`, à raison d'un couple par ligne. |
||||
|
||||
|
||||
### YAML basics |
||||
|
||||
https://fr.wikipedia.org/wiki/YAML |
||||
|
||||
* Les chaînes de caractères peuvent être entourées de guillemets doubles `"`, ou simples `'`, sachant qu'un guillemet s'échappe avec un antislash `\`, alors qu'une apostrophe s'échappe avec une autre apostrophe. |
||||
|
||||
* Les chaînes de caractères peuvent de plus être représentées par un bloc indenté avec des modificateurs facultatifs pour conserver `|` ou éliminer `>` les retours à la ligne. |
||||
|
||||
* Plusieurs documents rassemblés dans un seul fichier sont séparés par trois traits d'union `---`. |
||||
|
||||
|
||||
### YAML basics |
||||
|
||||
https://fr.wikipedia.org/wiki/YAML |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
``` |
||||
--- |
||||
receipt: Oz-Ware Purchase Invoice |
||||
date: 2012-08-06 |
||||
customer: |
||||
given: Dorothy |
||||
family: Gale |
||||
|
||||
items: |
||||
- part_no: A4786 |
||||
descrip: Water Bucket (Filled) |
||||
price: 1.47 |
||||
quantity: 4 |
||||
|
||||
- part_no: E1628 |
||||
descrip: High Heeled "Ruby" Slippers |
||||
size: 8 |
||||
price: 100.27 |
||||
quantity: 1 |
||||
|
||||
bill-to: &id001 |
||||
street: | |
||||
123 Tornado Alley |
||||
Suite 16 |
||||
city: East Centerville |
||||
state: KS |
||||
|
||||
ship-to: *id001 |
||||
|
||||
specialDelivery: > |
||||
Follow the Yellow Brick |
||||
Road to the Emerald City. |
||||
Pay no attention to the |
||||
man behind the curtain. |
||||
... |
||||
``` |
||||
|
||||
|
||||
### yaml - Définition d’une collection (-) |
||||
<!-- .slide: data-state="medium-code" --> |
||||
|
||||
```yaml |
||||
# Une liste de fruits |
||||
fruits: |
||||
- pomme |
||||
- orange |
||||
- framboise |
||||
- mangue |
||||
``` |
||||
|
||||
Forme abrégée : |
||||
```yaml |
||||
# Une liste de fruits |
||||
fruits: ['pomme', 'orange', 'framboise', 'mangue'] |
||||
``` |
||||
|
||||
|
||||
### Définition d’un dictionnaire (key: value) |
||||
<!-- .slide: data-state="medium-code" --> |
||||
|
||||
```yaml |
||||
# Un utilisateur |
||||
martin: |
||||
name: Martin Dupond |
||||
job: developer |
||||
skill: python |
||||
``` |
||||
|
||||
Forme abrégée : |
||||
```yaml |
||||
# Un utilisateur |
||||
martin: { name: Martin Dupond, job: developer, skill: python } |
||||
``` |
||||
|
||||
|
||||
## Tasks |
||||
|
||||
* Les commandes d'un Playbook sont découpées en instructions unitaires appelées _tâches_ (tasks). |
||||
|
||||
* Chaque tâche exécute un module Ansible avec des paramètres spécifiques. |
||||
|
||||
* Format d'une tâche : |
||||
|
||||
```none |
||||
- name: Description de la tâche |
||||
<nom-du-module>: |
||||
<paramètre-1>: <valeur-1> |
||||
<paramètre-2>: <valeur-2> |
||||
<paramètre-3>: <valeur-3> |
||||
``` |
||||
|
||||
|
||||
### Liste de tâches |
||||
|
||||
* Un playbook peut décrire une liste de plusieurs tâches. |
||||
|
||||
* Les tâches seront exécutées dans l'ordre d'apparition et de façon séquentielle sur chacune des machines cibles. |
||||
|
||||
```none |
||||
tasks: <----------------------------- liste de tâche |
||||
|
||||
- name: Ma tâche 1 <--------------- tâche 1 |
||||
<nom-du-module>: |
||||
<paramètre-1>: <valeur-1> |
||||
<paramètre-2>: <valeur-2> |
||||
<paramètre-3>: <valeur-3> |
||||
|
||||
- name: Ma tâche 2 <--------------- tâche 2 |
||||
<nom-du-module>: |
||||
<paramètre-1>: <valeur-1> |
||||
<paramètre-2>: <valeur-2> |
||||
``` |
||||
|
||||
|
||||
### Exemple réel |
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- hosts: web # exécution d'un 'Play' sur le groupe 'web' |
||||
tasks: |
||||
- name: Installation of Apache Package # tâche 1 |
||||
yum: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure Apache is running (and enabled at boot) # tâche 2 |
||||
service: name=httpd state=started enabled=yes |
||||
``` |
||||
|
||||
* Ici on mixe les deux types de syntaxes (normale et abrégée). |
||||
* __Les bonnes pratiques préconisent l'utilisation de la syntaxe normale.__ |
||||
|
||||
|
||||
### Exemple réel |
||||
avec syntaxe normale |
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- hosts: web |
||||
tasks: |
||||
- name: Installation of Apache Package |
||||
yum: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure Apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
``` |
||||
|
||||
|
||||
### Notion de Play |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
--- |
||||
- hosts: webservers # Play 1 sur le groupe webservers |
||||
tasks: |
||||
- name: My task |
||||
... |
||||
|
||||
- hosts: databases # Play 2 sur le groupe databases |
||||
tasks: |
||||
- name: My task... |
||||
... |
||||
``` |
||||
|
||||
* Chaque Play contient sa propre liste de tâches et cible un ensemble spécifique de machines. |
||||
|
||||
|
||||
## Lancer un playbook |
||||
|
||||
<small>`$ ansible-playbook <fichier-playbook> -i <fichier-inventaire>`</small> |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible-playbook playbook.yaml -i ./hosts |
||||
|
||||
PLAY [web] ******************************************************************* |
||||
|
||||
TASK [setup] ***************************************************************** |
||||
ok: [web1.formation.sii.fr] |
||||
ok: [web2.formation.sii.fr] |
||||
|
||||
TASK [Installation du package Apache] **************************************** |
||||
changed: [web2.formation.sii.fr] |
||||
changed: [web1.formation.sii.fr] |
||||
|
||||
TASK [Ensure Apache is running (and enable it at boot)] ********************** |
||||
changed: [web1.formation.sii.fr] |
||||
changed: [web2.formation.sii.fr] |
||||
|
||||
PLAY RECAP ******************************************************************* |
||||
web1.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
``` |
||||
<small> |
||||
* Notre Playbook comportait 2 tâches seulement, nous en voyons 3 ! |
||||
|
||||
* Ansible a automatiquement ajouté à l'exécution une tâche nommée _setup_ dont l'objectif est de récupérer les _facts_ des machines cibles. |
||||
<small> |
||||
|
||||
|
||||
## Récapitulatif du Playbook |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
PLAY RECAP ******************************************************************* |
||||
web1.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
* Sur les 2 machines cibles : |
||||
|
||||
- `ok` : 3 tâches ont été exécutées avec succès. |
||||
- `changed` : 2 tâches ont modifié l'état du système. |
||||
- `unreachable` : Toutes les machines étaient joignables. |
||||
- `failed` : Aucune tâche n'a échoué. |
||||
|
||||
|
||||
## Relancer un playbook |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible-playbook playbook.yaml -i ./hosts --become |
||||
|
||||
PLAY [web] ******************************************************************* |
||||
|
||||
TASK [setup] ***************************************************************** |
||||
ok: [web1.formation.sii.fr] |
||||
ok: [web2.formation.sii.fr] |
||||
|
||||
TASK [Installation du package Apache] **************************************** |
||||
ok: [web1.formation.sii.fr] |
||||
ok: [web2.formation.sii.fr] |
||||
|
||||
TASK [Ensure Apache is running (and enable it at boot)] ********************** |
||||
ok: [web1.formation.sii.fr] |
||||
ok: [web2.formation.sii.fr] |
||||
|
||||
PLAY RECAP ******************************************************************* |
||||
web1.formation.sii.fr : ok=3 changed=0 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=3 changed=0 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
|
||||
## Première exécution |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
PLAY RECAP ******************************************************************* |
||||
web1.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
## Seconde exécution |
||||
|
||||
```none |
||||
PLAY RECAP ******************************************************************* |
||||
web1.formation.sii.fr : ok=3 changed=0 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=3 changed=0 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
|
||||
## Ordre d'exécution |
||||
|
||||
* Il est possible de contrôler l'ordre dans lequel les machines cibles sont adressées. |
||||
|
||||
* L'ordre par défaut est l'ordre d'apparition dans l'inventaire. |
||||
|
||||
```yaml |
||||
- hosts: all |
||||
order: sorted # l'ordre est défini ici |
||||
gather_facts: False |
||||
tasks: |
||||
- debug: |
||||
var: inventory_hostname |
||||
``` |
||||
|
||||
|
||||
Ordre | Description |
||||
- | - |
||||
`inventory` | Ordre d'apparition dans l'inventaire. C'est le choix par défaut. |
||||
`reverse_inventory` | Ordre inverse d'apparition dans l'inventaire. |
||||
`sorted` | Ordre alphabétique des noms de machines. |
||||
`reverse_sorted` | Ordre alphabétique inverse des noms de machines. |
||||
`shuffle` | Ordre aléatoire. |
||||
|
||||
|
||||
## Démarrer l'exécution à un endroit précis |
||||
|
||||
`$ ansible-playbook playbook.yaml --start-at-task="my task"` |
||||
|
||||
Cette commande démarre l'exécution du playbook à partir de la tâche nommée `my task`. |
||||
|
||||
<small>https://docs.ansible.com/ansible/latest/user_guide/playbooks_startnstep.html</small> |
||||
|
||||
|
||||
## Ignorer le code de retour d'une commande |
||||
|
||||
* Les modules _command_ et _shell_ sont sensibles au code de retour des commandes. |
||||
|
||||
* Pour ignorer les erreurs sur une commande qui renvoie un code > 0 on peut utiliser `ignore_errors`. |
||||
|
||||
* Ou, utiliser `failed_when`. |
||||
|
||||
* De même, `changed_when` peut être utilisé. |
||||
|
||||
```yaml |
||||
tasks: |
||||
- name: run this command and ignore the result |
||||
shell: /usr/bin/somecommand |
||||
ignore_errors: True |
||||
``` |
||||
|
||||
|
||||
## Déclaration de variables |
||||
|
||||
```yaml |
||||
- hosts: web |
||||
vars: |
||||
- app_directory: /var/www/html |
||||
- app_user: apache |
||||
- app_group: apache |
||||
|
||||
tasks: |
||||
- name: Modify permission on {{ app_directory }} |
||||
file: |
||||
dest: '{{ app_directory }}' |
||||
mode: 0755 |
||||
owner: '{{ app_user }}' |
||||
group: '{{ app_group }}' |
||||
recurse: yes |
||||
``` |
||||
|
||||
Les variables sont déclarées dans _vars_ |
||||
et résolues avec `{{ }}`. |
||||
|
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible-playbook playbook.yaml -i ./hosts |
||||
|
||||
PLAY [web] **************************************************************** |
||||
|
||||
TASK [setup] ************************************************************** |
||||
ok: [web1.formation.sii.fr] |
||||
ok: [web2.formation.sii.fr] |
||||
|
||||
TASK [Modify permission of directory /var/www/html] *********************** |
||||
changed: [web1.formation.sii.fr] |
||||
changed: [web2.formation.sii.fr] |
||||
|
||||
PLAY RECAP **************************************************************** |
||||
web1.formation.sii.fr : ok=2 changed=1 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=2 changed=1 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
|
||||
## Les _handlers_ et les _notify_ |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- hosts: web |
||||
vars: |
||||
- apache_listen_port: 8080 |
||||
|
||||
tasks: |
||||
- name: Modify Apache configuration |
||||
lineinfile: |
||||
dest: /etc/httpd/conf/httpd.conf |
||||
regexp: '^Listen ' |
||||
line: 'Listen {{ apache_listen_port }}' |
||||
notify: Reload Apache # Signale que la configuration |
||||
# d'Apache doit être rechargée |
||||
handlers: |
||||
- name: Reload Apache # Recharge la configuration |
||||
service: |
||||
name: httpd |
||||
state: reloaded |
||||
``` |
||||
|
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible-playbook playbook.yaml -i ./hosts |
||||
|
||||
PLAY [web] ******************************************************************* |
||||
|
||||
TASK [setup] ***************************************************************** |
||||
ok: [web1.formation.sii.fr] |
||||
ok: [web2.formation.sii.fr] |
||||
|
||||
TASK [Modify Apache configuration] ******************************************* |
||||
changed: [web1.formation.sii.fr] |
||||
changed: [web2.formation.sii.fr] |
||||
|
||||
RUNNING HANDLER [Reload Apache] ********************************************* |
||||
changed: [web1.formation.sii.fr] |
||||
changed: [web2.formation.sii.fr] |
||||
|
||||
PLAY RECAP ******************************************************************* |
||||
web1.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
web2.formation.sii.fr : ok=3 changed=2 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
|
||||
## Idempotence |
||||
|
||||
* L'idempotence signifie qu'une opération a le même effet qu'on l'applique une ou plusieurs fois. |
||||
|
||||
* Les commandes d'un Playbook doivent être écrites de manière à produire le même résultat quel que soit le nombre de fois où elles sont exécutées sur une même cible. |
||||
|
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
## Travaux pratiques |
||||
|
||||
![Travaux pratiques](images/tp.gif) |
||||
|
||||
<small>[TP Ansible : playbooks](travaux-pratiques/tp-ansible-playbooks.html)</small> |
||||
|
||||
|
||||
## Variables sur la ligne de commande |
||||
|
||||
Il est possible d'initialiser des variables directement sur la ligne de commande avec l'option `--extra-vars` (ou `-e`). |
||||
|
||||
|
||||
* Ces variables peuvent être définies sous la forme : |
||||
|
||||
- chaîne de caractères |
||||
|
||||
`$ ansible-playbook playbook.yaml --extra-vars "my_var_1=foo my_var_2=bar"` |
||||
|
||||
- json |
||||
|
||||
`$ ansible-playbook playbook.yaml --extra-vars '{"my_var_1":"foo","my_var_2":"bar"}'` |
||||
|
||||
`$ ansible-playbook playbook.yaml --extra-vars '{"my_var":"foo","my_list":["foo","bar"]}'` |
||||
|
||||
|
||||
* Utilisez le fomat _json_ si vous voulez passer autre chose que des _strings_ : |
||||
|
||||
- booleans |
||||
- integers |
||||
- floats |
||||
- lists |
||||
- ... |
||||
|
||||
|
||||
## Découper un Playbook |
||||
|
||||
* Un Playbook peut se présenter sous la forme d'un fichier unique. |
||||
|
||||
* Toutefois il est possible de le découper en plusieurs fichiers séparés afin de mieux organiser et favoriser la ré-utilisation de certaines parties. |
||||
|
||||
* Il existe plusieurs manières de découper un Playbook : |
||||
les _includes_, les _imports_, et les _roles_. |
||||
|
||||
<small>https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html</small> |
||||
|
||||
|
||||
### Includes et Imports |
||||
|
||||
* Disponibles à partir de Ansible v2.4. |
||||
|
||||
* Permettent le découpage des tâches d'un gros Playbook en fichiers plus petits. |
||||
|
||||
* Ces fichiers peuvent ensuite être appelés : |
||||
|
||||
- depuis un ou plusieurs Playbooks |
||||
|
||||
- plusieurs fois dans un même Playbook. |
||||
|
||||
|
||||
### Import dynamique vs statique |
||||
|
||||
* Les commandes `import` permettent |
||||
un chargement statique. |
||||
<small>(import_playbook, import_tasks, etc.)</small> |
||||
|
||||
* Les commandes `include` permettent |
||||
un chargement dynamique. |
||||
<small>(include_tasks, include_role, etc.)</small> |
||||
|
||||
|
||||
### Statique vs Dynamique |
||||
|
||||
* _Statique_ |
||||
Ansible traite les imports statique au moment de l'analyse du Playbook (avant l'exécution). |
||||
|
||||
* _Dynamique_ |
||||
Ansible traite les imports dynamiques au fur et à mesure durant l'exécution du Playbook. |
||||
|
||||
* Les imports statiques et dynamiques peuvent être mixés, toutefois cela n'est pas recommandé car cela rend le debug des Playbooks plus complexe. |
||||
|
||||
|
||||
### Import de Playbooks |
||||
|
||||
* Il est possible d'importer un ou plusieurs Playbooks à l'intérieur d'un Playbook maître, avec `import_playbook`. |
||||
|
||||
|
||||
### Roles |
||||
|
||||
* Plus puissants que les _includes_ et les _imports_. |
||||
|
||||
* Permettent d'empaqueter un ensemble de tâches ainsi que les variables, handlers et autres autres éléments associés. |
||||
|
||||
* Les _roles_ peuvent être facilement ré-utilisés et partagés. |
||||
|
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
## Travaux pratiques |
||||
|
||||
![Travaux pratiques](images/tp.gif) |
||||
|
||||
<small>[TP Ansible : imports](travaux-pratiques/tp-ansible-imports.html)</small> |
@ -0,0 +1,516 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
# Templates |
||||
|
||||
|
||||
## Syntaxe jinja2 |
||||
|
||||
* Documentation |
||||
|
||||
- Jinja language : |
||||
http://jinja.pocoo.org/docs/ |
||||
- Template formatting : |
||||
http://jinja.pocoo.org/docs/templates/ |
||||
|
||||
|
||||
## Principe |
||||
|
||||
* On créé les fichiers dans le dossier `templates` du Role. |
||||
|
||||
* On indique l'emplacement des zones variables à l'aide de la syntaxe `{{ ma_variable }}`. |
||||
|
||||
`templates/httpd.conf.j2` |
||||
```none |
||||
... |
||||
Listen {{ apache_port }} |
||||
DocumentRoot {{ apache_document_root }} |
||||
ServerName {{ apache_server_name }} |
||||
ServerAdmin {{ apache_server_admin }} |
||||
... |
||||
``` |
||||
|
||||
|
||||
On utilise le module _template_ |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- hosts: web |
||||
vars: |
||||
apache_port: 80 |
||||
apache_document_root: /var/www/html |
||||
apache_server_name: my-server |
||||
apache_server_admin: admin@localhost |
||||
tasks: |
||||
- name: Deploy Apache configuration |
||||
template: |
||||
src: templates/httpd.conf.j2 |
||||
dest: /etc/http/httpd.conf |
||||
owner: apache |
||||
group: apache |
||||
mode: 0600 |
||||
``` |
||||
|
||||
Les variables sont automatiquement injectées dans le fichier sur la cible. |
||||
|
||||
|
||||
## Exemple pour une configuration du service NTP |
||||
<!-- .slide: data-state="small-code" --> |
||||
`./group_vars/all` |
||||
```none |
||||
ntp_servers: |
||||
- 0.pool.ntp.org |
||||
- 1.pool.ntp.org |
||||
- 2.pool.ntp.org |
||||
- 3.pool.ntp.org |
||||
``` |
||||
|
||||
`./roles/ntp/templates/ntp.conf.j2` |
||||
```none |
||||
... |
||||
{% for server in ntp_servers %} |
||||
server {{ server }} |
||||
{% endfor %} |
||||
... |
||||
``` |
||||
|
||||
|
||||
`./roles/ntp/tasks/main.yaml` |
||||
```yaml |
||||
- name: Install NTP package |
||||
apt: |
||||
name: "ntp" |
||||
|
||||
- name: Configure NTP |
||||
template: |
||||
src: ntp.conf.j2 |
||||
dest: "/etc/ntp.conf" |
||||
owner: "root" |
||||
group: "root" |
||||
mode: 0644 |
||||
notify: Restart ntp service |
||||
``` |
||||
|
||||
|
||||
## Contrôle conditionnel |
||||
|
||||
```none |
||||
{% if condition %} |
||||
do_some_thing |
||||
{% elif condition2 %} |
||||
do_another_thing |
||||
{% else %} |
||||
do_something_else |
||||
{% endif %} |
||||
``` |
||||
|
||||
|
||||
## Filtres |
||||
|
||||
Les variables peuvent être modifiées par des filtres. |
||||
|
||||
<small>https://docs.ansible.com/ansible/playbooks_filters.html</small> |
||||
|
||||
|
||||
### Filtres Jinja2 |
||||
|
||||
* Les filtres Ansible reposent sur Jinja2. |
||||
|
||||
* Ils sont utilisés pour transformer des données. |
||||
|
||||
* Les filtres peuvent être chaînés. |
||||
|
||||
* Il est possible de créer des filtres personnalisés. |
||||
|
||||
|
||||
### Fixer une valeur par défaut aux variables non-définies |
||||
|
||||
```none |
||||
{{ variable | default(5) }} |
||||
``` |
||||
|
||||
|
||||
### Formater des données |
||||
|
||||
```none |
||||
{{ variable | to_json }} |
||||
{{ variable | to_yaml }} |
||||
``` |
||||
```none |
||||
{{ variable | from_json }} |
||||
{{ variable | from_yaml }} |
||||
``` |
||||
|
||||
|
||||
### Filtres de listes |
||||
|
||||
Récupérer les valeurs minimales ou maximales |
||||
```none |
||||
{{ ma_liste | min }} |
||||
{{ [3, 4, 2] | max }} |
||||
``` |
||||
|
||||
Eliminer les doublons |
||||
|
||||
```none |
||||
{{ list1 | unique }} |
||||
``` |
||||
|
||||
Combiner deux listes |
||||
|
||||
```none |
||||
{{ list1 | union(list2) }} |
||||
``` |
||||
|
||||
Obtenir la différence entre deux listes (éléments dans list1 qui n'existent pas dans list2) |
||||
|
||||
```none |
||||
{{ list1 | difference(list2) }} |
||||
``` |
||||
|
||||
|
||||
### Filtres de nombres aléatoires |
||||
|
||||
Obtenir un élément au hasard parmi une liste |
||||
|
||||
```none |
||||
"{{ ['a','b','c'] | random }}" |
||||
# => 'c' |
||||
``` |
||||
|
||||
Obtenir un nombre au hasard entre 0 et une valeur spécifiée |
||||
|
||||
```none |
||||
"{{ 60 | random}} * * * * root /script/from/cron“ |
||||
# => '21 * * * * root /script/from/cron' |
||||
``` |
||||
|
||||
Obtenir un nombre au hasard entre 0 et 100 par pas de 10 |
||||
|
||||
```none |
||||
{{ 101 | random(step=10) }} |
||||
# => 70 |
||||
``` |
||||
|
||||
|
||||
### Tester des adresses IP |
||||
|
||||
Tester si une chaîne est une adresse IP valide |
||||
|
||||
```none |
||||
{{ myvar | ipaddr }} |
||||
``` |
||||
|
||||
Même chose en forçant la version du protocole IP |
||||
|
||||
```none |
||||
{{ myvar | ipv4 }} |
||||
{{ myvar | ipv6 }} |
||||
``` |
||||
|
||||
|
||||
### Filtres sur la notation CIDR |
||||
|
||||
```none |
||||
{{ '192.0.2.1/24' | ipaddr('address') }} |
||||
'192.0.2.1/24' |
||||
``` |
||||
```none |
||||
{{ '192.0.2.1/24' | ipaddr('prefix') }} |
||||
'24' |
||||
``` |
||||
|
||||
<small>https://docs.ansible.com/ansible/playbooks_filters_ipaddr.html</small> |
||||
|
||||
|
||||
### Fonctions de hashage |
||||
|
||||
Obtenir l'empreinte sha1 ou md5 d'une chaîne |
||||
|
||||
```none |
||||
{{ 'test1' | hash('sha1') }} |
||||
'dba7673010f19a94af4345453005933fd511bea9' |
||||
|
||||
{{ 'test1' | hash('md5') }} |
||||
'3e7705498e8be60520841409ebc69bc1' |
||||
``` |
||||
<small>https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#hashing-filters</small> |
||||
|
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
Obtenir un hashage de mot de passe sha512 |
||||
|
||||
```none |
||||
{{ 'passwordsaresecret' | password_hash('sha512') }} |
||||
``` |
||||
|
||||
Obtenir un hashage de mot de passe sha256 avec salage |
||||
|
||||
```none |
||||
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt') }} |
||||
``` |
||||
|
||||
Exemple d'utilisation dans un fichier de variables |
||||
|
||||
```none |
||||
user_password: "{{ 'Mon super password' | password_hash('sha256') }}" |
||||
``` |
||||
|
||||
|
||||
### Filtres de commentaires |
||||
|
||||
Il permettent de "décorer" un texte |
||||
avec un style de commentaire. |
||||
|
||||
Exemple : |
||||
|
||||
```none |
||||
{{ "Hello" | comment }} |
||||
``` |
||||
|
||||
produit : |
||||
|
||||
```none |
||||
# |
||||
# Hello |
||||
# |
||||
``` |
||||
|
||||
|
||||
Il est possible d'appliquer |
||||
différents types de commentaires : |
||||
|
||||
```none |
||||
{{ "C style" | comment('c') }} |
||||
'// C style' |
||||
``` |
||||
|
||||
```none |
||||
{{ "C block style" | comment('cblock') }} |
||||
'/* C block style */' |
||||
``` |
||||
|
||||
```none |
||||
{{ "XML style" | comment('xml') }} |
||||
'<!--XML style-->' |
||||
``` |
||||
|
||||
|
||||
### Filtres d'URL |
||||
|
||||
<!-- .slide: data-state="small-code medium-table" --> |
||||
Obtenir une sous-partie d'une URL. |
||||
```none |
||||
{{ "http://bob:1234@www.test.com:81/dir/index.html?query=term#fragment" |
||||
| urlsplit('scheme') }} |
||||
# => 'http' |
||||
``` |
||||
|
||||
Filtre | Résultat |
||||
- | - |
||||
urlsplit('scheme') | 'http' |
||||
urlsplit('username') | 'bob' |
||||
urlsplit('password') | '1234' |
||||
urlsplit('hostname') | 'www.test.com' |
||||
urlsplit('port') | '81' |
||||
urlsplit('path') | '/dir/index.html' |
||||
urlsplit('query') | 'query=term' |
||||
urlsplit('fragment') | 'fragment' |
||||
|
||||
|
||||
### Autres filtres utiles |
||||
|
||||
|
||||
Ajouter des guillemets pour protéger des variables |
||||
(usage shell) |
||||
|
||||
```none |
||||
- shell: echo {{ string_value | quote }} |
||||
``` |
||||
|
||||
Retourner une valeur si un test est vrai |
||||
et une autre si il est faux |
||||
|
||||
```none |
||||
{{ (name == "John") | ternary('Mr','Mme') }} |
||||
``` |
||||
|
||||
|
||||
Concatener une liste en chaîne |
||||
|
||||
```none |
||||
{{ list | join(" ") }} |
||||
``` |
||||
|
||||
```none |
||||
{{ list | join(",") }} |
||||
``` |
||||
|
||||
|
||||
Obtenir le dernier élément d'un chemin |
||||
|
||||
```none |
||||
{{ '/etc/foo/bar.txt' | basename }} |
||||
'bar.txt' |
||||
``` |
||||
|
||||
Obtenir le début d'un chemin |
||||
|
||||
```none |
||||
{{ '/etc/foo/bar.txt' | dirname }} |
||||
'/etc/foo' |
||||
``` |
||||
|
||||
Obtenir le chemin réel d'un lien |
||||
|
||||
```none |
||||
{{ path | realpath }} |
||||
``` |
||||
|
||||
|
||||
Expanser un chemin contenant un tilde (~) |
||||
|
||||
```none |
||||
{{ path | expanduser }} |
||||
``` |
||||
|
||||
Expanser un chemin contenant des variables d'environnement |
||||
|
||||
```none |
||||
{{ path | expandvars }} |
||||
``` |
||||
|
||||
|
||||
Découper un nom de fichier |
||||
|
||||
```none |
||||
{{ path | splitext }} |
||||
``` |
||||
|
||||
Avec `path` == `nginx.conf` le retour sera `('nginx', '.conf')` |
||||
|
||||
|
||||
## Tests |
||||
|
||||
`variable` is `test expression` |
||||
|
||||
<small>https://docs.ansible.com/ansible/playbooks_tests.html</small> |
||||
|
||||
|
||||
### Tester des chaînes de caractères |
||||
<!-- .slide: data-state="small-code" --> |
||||
```yaml |
||||
vars: |
||||
url: "http://example.com/users/foo/resources/bar" |
||||
|
||||
tasks: |
||||
- debug: |
||||
msg: "matched pattern 1" |
||||
when: url is match("http://example.com/users/.*/resources/.*") |
||||
|
||||
- debug: |
||||
msg: "matched pattern 2" |
||||
when: url is search("/users/.*/resources/.*") |
||||
|
||||
- debug: |
||||
msg: "matched pattern 3" |
||||
when: url is search("/groups/") |
||||
``` |
||||
|
||||
```none |
||||
TASK [debug] ***************************************************************** |
||||
ok: [my-host] => { "msg": "matched pattern 1" } |
||||
|
||||
TASK [debug] ***************************************************************** |
||||
ok: [my-host] => { "msg": "matched pattern 2" } |
||||
|
||||
TASK [debug] ***************************************************************** |
||||
skipping: [my-host] |
||||
``` |
||||
|
||||
|
||||
### Tester des numéros de version |
||||
|
||||
Si `ansible_facts['distribution_version']` est supérieur ou égal à 16.04, le test retourne `True`, sinon il retourne `False`. |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```none |
||||
{{ ansible_facts['distribution_version'] is version('16.04', '>=') }} |
||||
``` |
||||
|
||||
Opérateurs acceptés : |
||||
`<`, `lt`, `<=`, `le`, `>`, `gt`, `>=`, `ge`, `==`, `=`, `eq`, `!=`, `<>`, `ne` |
||||
|
||||
|
||||
### Tester des chemins |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```yaml |
||||
- debug: |
||||
msg: "path is a directory" |
||||
when: mypath is directory |
||||
|
||||
- debug: |
||||
msg: "path is a file" |
||||
when: mypath is file |
||||
|
||||
- debug: |
||||
msg: "path is a symlink" |
||||
when: mypath is link |
||||
|
||||
- debug: |
||||
msg: "path already exists" |
||||
when: mypath is exists |
||||
``` |
||||
|
||||
Chaque tâche est effectuée ou abandonnée |
||||
en fonction du résultat du test. |
||||
|
||||
|
||||
### Tester le résultat final d'une tâche |
||||
|
||||
```yaml |
||||
- shell: /usr/bin/foo |
||||
register: result |
||||
ignore_errors: True |
||||
|
||||
- debug: |
||||
msg: "it failed" |
||||
when: result is failed |
||||
|
||||
- debug: |
||||
msg: "it succeeded" |
||||
when: result is succeeded |
||||
``` |
||||
|
||||
|
||||
## Sortir prématurément en fonction de conditions |
||||
|
||||
* Le module _fail_ permet de stopper l'exécution d'un playbook si un condition n'est pas remplie. |
||||
|
||||
* Dans l'exemple suivant, l'exécution s'arrête car la variable `param2` n'est pas définie. |
||||
|
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
--- |
||||
- hosts: ansible-1 |
||||
|
||||
vars: |
||||
- param1: "test" |
||||
|
||||
tasks: |
||||
- name: 'exit if param1 or param2 are null or invalid' |
||||
fail: msg="Please enter correct Params" |
||||
when: param1 is not defined or param2 is not defined |
||||
|
||||
- debug: |
||||
msg: "other tasks..." |
||||
``` |
||||
|
||||
|
||||
## Travaux pratiques |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
|
||||
![Travaux pratiques](images/tp.gif) |
||||
|
||||
<small>[TP Ansible : templates](travaux-pratiques/tp-ansible-templates.html)</small> |
@ -0,0 +1,306 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
# ansible-vault |
||||
|
||||
Sécuriser les données sensibles. |
||||
|
||||
|
||||
* La commande `ansible-vault` permet la création de conteneurs chiffrés pour les variables sensibles. |
||||
|
||||
```nohighlight |
||||
$ ansible-vault create test.yaml |
||||
Vault password: |
||||
``` |
||||
|
||||
* Le choix d'un un mot de passe est obligatoire lors de la création du fichier. |
||||
|
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
Le contenu en clair : |
||||
|
||||
```nohighlight |
||||
mon_super_mot_de_passe: 12345678 |
||||
``` |
||||
|
||||
devient après chiffrement : |
||||
|
||||
```nohighlight |
||||
$ cat test.yaml |
||||
$ANSIBLE_VAULT;1.1;AES256 |
||||
62366463643661313763313135376434303535646637653237633233306663623635643761643161 |
||||
3834383236386535366533303733613838653836623661340a383263633435336234333335343539 |
||||
30333664666364613731666666636235373633346463353766356364623039656262363238363830 |
||||
3236656664353565620a303034643732636166376535386436616231653363386334663065326337 |
||||
3561 |
||||
``` |
||||
|
||||
|
||||
Le mot de passe sera demandé lors de chacune des exécutions du playbook : |
||||
|
||||
```nohighlight |
||||
$ ansible-playbook mon-playbook.yaml –ask-vault-pass |
||||
Vault password: |
||||
``` |
||||
|
||||
|
||||
### Travaux pratiques |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
|
||||
![Travaux pratiques](images/tp.gif) |
||||
|
||||
<small>[TP Ansible vault](travaux-pratiques/tp-ansible-vault.html)</small> |
||||
|
||||
|
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![Logo Ansible](images/logo-ansible.svg) |
||||
# Notions avancées |
||||
|
||||
|
||||
## Surcharge de variables |
||||
|
||||
* Ansible permet la déclaration de variables en de multiples endroits. |
||||
|
||||
* Ansible supporte la surcharge de variables, cette surcharge dépend de l’endroit où les variables sont déclarées. |
||||
|
||||
|
||||
Ordre de priorité croissant lors de la surcharge : |
||||
|
||||
<small> |
||||
|
||||
* role defaults |
||||
* inventory file or script group vars |
||||
* inventory group_vars/all |
||||
* playbook group_vars/all |
||||
* inventory group_vars/* |
||||
* playbook group_vars/* |
||||
* inventory file or script host vars |
||||
* inventory host_vars/* |
||||
* playbook host_vars/* |
||||
* host facts / cached set_facts |
||||
* play vars |
||||
* play vars_files |
||||
* role vars (defined in role/vars/main.yaml) |
||||
* task vars (only for the task) |
||||
* include_vars |
||||
* set_facts / registered vars |
||||
* role (and include_role) params |
||||
* include params |
||||
* extra vars (always win precedence) |
||||
|
||||
</small> |
||||
|
||||
|
||||
## register + debug + verbosity |
||||
<!-- .slide: data-state="medium-code" --> |
||||
|
||||
```yaml |
||||
- shell: /usr/bin/uptime |
||||
register: result |
||||
|
||||
- name: Display uptime |
||||
debug: |
||||
var: result |
||||
verbosity: 2 # affiché à partir du niveau -vv |
||||
|
||||
- name: Display all variables/facts known for a host |
||||
debug: |
||||
var: hostvars[inventory_hostname] |
||||
verbosity: 4 # affiché à partir du niveau -vvvv |
||||
``` |
||||
|
||||
|
||||
## Niveau de verbosité |
||||
|
||||
```nohighlight |
||||
$ ansible-playbook -i ./hosts playbook.yaml |
||||
``` |
||||
|
||||
```nohighlight |
||||
$ ansible-playbook -vv -i ./hosts playbook.yaml |
||||
``` |
||||
|
||||
```nohighlight |
||||
$ ansible-playbook -vvvv -i ./hosts playbook.yaml |
||||
``` |
||||
|
||||
|
||||
## Check mode (« Dry Run ») |
||||
|
||||
* Simulation de l'exécution d'un Playbook. |
||||
|
||||
* Aucun changement n'est effectué sur les hosts lors du check. |
||||
|
||||
* Utiliser l’option `--check`. |
||||
|
||||
* _Attention_ ! Certains modules sont incompatibles avec le Check mode. |
||||
|
||||
|
||||
Forcer ou non une tâche en check : `check_mode: yes/no` |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```yaml |
||||
tasks: |
||||
- name: this task will make changes to the system even in check mode |
||||
command: /something/to/run --even-in-check-mode |
||||
check_mode: no |
||||
|
||||
- name: this task will always run under checkmode and not change the system |
||||
lineinfile: |
||||
line: "important config" |
||||
dest: /path/to/myconfig.conf |
||||
state: present |
||||
check_mode: yes |
||||
``` |
||||
|
||||
|
||||
## Autres options de ansible-playbook |
||||
<!-- .slide: data-state="medium-table" --> |
||||
Option | Description |
||||
- | - |
||||
`--list-hosts` | Affiche les machines concernées par le Play |
||||
`--list-tags` | Affiche les tags disponibles |
||||
`--list-tasks` | Affiche les tâches qui seront exécutées |
||||
`--step` | Demande confirmation avant l'exécution de chaque tâche |
||||
`--syntax-check` | Analyse syntaxique du Playbook (sans l'exécuter) |
||||
|
||||
|
||||
## Tester du code Ansible |
||||
|
||||
|
||||
![Logo Molecule](images/logo-molecule.png) <!-- .element: width="150px" --> |
||||
|
||||
* Permet de tester des Roles Ansible |
||||
|
||||
<small>https://molecule.readthedocs.io/en/latest/</small> |
||||
|
||||
|
||||
![Logo TestInfra](images/logo-testinfra.svg) <!-- .element: width="150px" --> |
||||
|
||||
Création de tests unitaire en langage Python |
||||
|
||||
<!-- .slide: data-state="small-table" --> |
||||
```python |
||||
def test_passwd_file(host): |
||||
passwd = host.file("/etc/passwd") |
||||
assert passwd.contains("root") |
||||
assert passwd.user == "root" |
||||
assert passwd.group == "root" |
||||
assert passwd.mode == 0o644 |
||||
``` |
||||
|
||||
Combiné avec GitLab-CI/Jenkins et Docker, il permet d'automatiser le test de code Ansible. |
||||
|
||||
<small>https://testinfra.readthedocs.io/en/latest/</small> |
||||
|
||||
|
||||
## Ansible Lint |
||||
|
||||
* Permet de détecter les comportements et les pratiques qui peuvent être améliorés. |
||||
|
||||
<small>https://ansible-lint.readthedocs.io/en/latest/</small> |
||||
|
||||
|
||||
## Ansible en mode Pull |
||||
|
||||
* Ansible fonctionne traditionnellement en mode `Push`. |
||||
|
||||
* Il est possible de passer en mode `Pull` à l'aide de la commande `ansible-pull`. |
||||
|
||||
* Intérêt du mode Pull |
||||
|
||||
- Adresser un grand nombre de machines, |
||||
|
||||
- Remediation des systèmes en continu. |
||||
|
||||
|
||||
* Pré-requis du mode Pull |
||||
|
||||
* Playbooks disponibles sur un dépôt git, |
||||
|
||||
* Ansible installé sur chaque machine cible. |
||||
|
||||
<small>https://docs.ansible.com/ansible/latest/cli/ansible-pull.html</small> |
||||
|
||||
<small>https://github.com/ansible/ansible-examples/blob/master/language_features/ansible_pull.yaml</small> |
||||
|
||||
|
||||
## Développer un module personnalisé |
||||
|
||||
`./library/mymodule.py` |
||||
```python |
||||
#!/usr/bin/python |
||||
|
||||
from ansible.module_utils.basic import * |
||||
|
||||
def main(): |
||||
module = AnsibleModule(argument_spec={}) |
||||
response = {"hello": "world"} |
||||
module.exit_json(changed=False, meta=response) |
||||
if __name__ == '__main__': |
||||
main() |
||||
``` |
||||
|
||||
<small>https://blog.toast38coza.me/custom-ansible-module-hello-world/</small> |
||||
|
||||
<small>https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html</small> |
||||
|
||||
|
||||
## Utiliser un module personnalisé |
||||
<!-- .slide: data-state="small-code" --> |
||||
|
||||
`playbook-demo-mymodule.yaml` |
||||
```yaml |
||||
- hosts: web |
||||
tasks: |
||||
- name: Test that my module works |
||||
mymodule: |
||||
register: result |
||||
- debug: var=result |
||||
``` |
||||
```nohighlight |
||||
$ ansible-playbook -i ./hosts playbook-demo-mymodule.yaml |
||||
... |
||||
TASK [Test that my module works] *********************************************** |
||||
ok: [web2.formation.sii.fr] |
||||
ok: [web1.formation.sii.fr] |
||||
|
||||
TASK [debug] ******************************************************************* |
||||
ok: [web1.formation.sii.fr] => { |
||||
"result": { "changed": false, "meta": { "hello": "world" } } |
||||
} |
||||
ok: [web2.formation.sii.fr] => { |
||||
"result": { "changed": false, "meta": { "hello": "world" } } |
||||
} |
||||
... |
||||
``` |
||||
|
||||
|
||||
## Ansible Tower |
||||
|
||||
* Interface Web propriétaire pour le lancement de playbooks. |
||||
|
||||
* Accès à l’historique des playbooks lancés et aux logs d'exécution. |
||||
|
||||
* Gestion des utilisateurs et de l'inventaire. |
||||
|
||||
* Pilotable via API. |
||||
|
||||
<small>https://www.ansible.com/products/tower</small> |
||||
|
||||
|
||||
### Tableau de bord d'Ansible Tower |
||||
![Tower dashboard](images/tower-dashboard.png) |
||||
|
||||
|
||||
### AWX |
||||
|
||||
* Version opensource de Ansible Tower (sous licence Apache 2.0.) |
||||
|
||||
* AWX est à Ansible Tower ce que Fedora est à Red Hat Enterprise Linux. |
||||
|
||||
* Non recommandé pour les environnements de production. |
||||
|
||||
* Aucun support n'est fourni par Red Hat. |
||||
|
||||
<small>https://www.ansible.com/products/awx-project</small> |
@ -0,0 +1,29 @@
|
||||
# Formation Ansible |
||||
|
||||
|
||||
## Programme |
||||
|
||||
1. Introduction ansible |
||||
2. Installation / Inventaire |
||||
3. Commandes ad-hoc |
||||
4. Playbooks |
||||
5. Roles |
||||
6. Structures de contrôle |
||||
7. Templates |
||||
8. Notions avancées |
||||
|
||||
## Slides |
||||
|
||||
Pour récupérer les slides : |
||||
|
||||
`git clone --recurse-submodules https://gitlab.siinergy.net/sii-ouest/trainings/ansible.git` |
||||
|
||||
Version [pdf](https://gitlab.siinergy.net/sii-ouest/trainings/ansible/-/jobs/artifacts/2019-03-06/raw/ansible.pdf?job=make-pdf) |
||||
|
||||
## Machines vituelles |
||||
|
||||
Voir [ansible-config-virtualbox-vms.md](ansible-config-virtualbox-vms.md). |
||||
|
||||
## Todo |
||||
|
||||
Les améliorations à apporter à la formation : [https://gitlab.siinergy.net/sii-ouest/trainings/ansible/boards](https://gitlab.siinergy.net/sii-ouest/trainings/ansible/boards) |
@ -0,0 +1,54 @@
|
||||
# Machines virtuelles VirtualBox pour la formation Ansible |
||||
|
||||
## Pré-requis de l'hôte |
||||
|
||||
- 8 Go de RAM au minimum |
||||
- Processeur Intel Corei__X__ |
||||
|
||||
|
||||
## Machines virtuelles |
||||
|
||||
Un fichier _.ova_ contenant deux machines virtuelles prêtes à l'emploi est disponible sur le filer. |
||||
|
||||
Mot de passe de l'utilisateur `ansible` : `ansible`. |
||||
|
||||
Mot de passe de l'utilisateur `root` : `ansible`. |
||||
|
||||
VM | description |
||||
- | - |
||||
ansible-0 | Machine ansible maître avec OS Debian 9 et ansible 2.6 installé |
||||
ansible-1 | Machine de test avec OS Centos 7 |
||||
ansible-2 | Machine de test avec OS Centos 7 |
||||
ansible-3 | Machine de test avec OS Debian 9 |
||||
|
||||
### Configuration des ressources |
||||
|
||||
- 1024 Mo RAM par VM |
||||
- 1 CPU par VM |
||||
|
||||
### Configuration réseau |
||||
|
||||
Chaque VM a 2 interfaces réseaux : |
||||
|
||||
- Interface 1 : __NAT__ |
||||
L’accès Internet de la machine hôte est alors partagé, on peut faire des mises à jour etc. La machine virtuelle voit Internet mais n’est pas vue du réseau local (elle est derrière un NAT qui est géré par VirtualBox). |
||||
|
||||
- Interface 2 : __Réseau privé hôte avec DHCP__ |
||||
La machine est visible et voit la machine hôte et réciproquement. Cette interface réseau sert pour se connecter en SSH depuis la machine hôte sur la machine virtuelle. Elle permet également aux différentes machines virtuelles positionnées sur ce réseau de communiquer entre elles. |
||||
|
||||
Le type des cartes est __Intel PRO/1000 MT Desktop (82540EM)__. |
||||
|
||||
|
||||
Qui voit quoi ? |
||||
|
||||
- Via la carte en __NAT__ |
||||
* la VM a accès à Internet pour les mises à jour derrière un NAT. |
||||
* La VM est invisible du réseau local et de la machine hôte (à moins de faire des redirections de port). |
||||
|
||||
- Via la carte __Réseau privé hôte__ |
||||
* la VM a accès à la machine hôte et réciproquement. |
||||
* la VM est visible des autres machines virtuelles situées dans le même réseau privé hôte. |
||||
|
||||
En résumé, les deux machines virtuelles pourront donc communiquer entre elles via l'interface _Réseau privé hôte_ et accéder à internet via l'interface _NAT_. |
||||
|
||||
Si besoin que toutes les VMs des stagiaires se voient entre elles il est possible de remplacer la carte __NAT__ par une carte __Bridge__. |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 135 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 101 KiB |
@ -0,0 +1,150 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - Ansible</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="1.Introduction-ansible.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="2.installation-inventaire.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="3.commandes-ad-hoc.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="4.playbooks.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="5.roles.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="6.structures-de-controle.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="7.templates.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="8.notions-avancees.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="9.Ansible-Galaxy.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
<section data-markdown="10.bonnes-pratiques.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • février 2019</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,72 @@
|
||||
<!doctype html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
||||
|
||||
<title>SII - Formation Ansible</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
<link rel="stylesheet" href="revealjs/css/custom.css"> <!-- your custom styles --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/zenburn.css"> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
</head> |
||||
<body> |
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="0.Introduction-formation.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/lib/js/head.min.js"></script> |
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
history: true, |
||||
|
||||
// Transition style |
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// Transition style for full page slide backgrounds |
||||
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js' }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js' }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } } |
||||
] |
||||
}); |
||||
|
||||
// Slide number formatting can be configured using these variables: |
||||
// "h.v": horizontal . vertical slide number (default) |
||||
// "h/v": horizontal / vertical slide number |
||||
// "c": flattened slide number |
||||
// "c/t": flattened slide number / total slides |
||||
Reveal.configure({ slideNumber: 'c/t' }); |
||||
Reveal.configure({ transition: 'none' }); |
||||
</script> |
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • février 2019</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,5 @@
|
||||
- name: Reload Apache |
||||
service: |
||||
name: httpd |
||||
state: restarted |
||||
|
@ -0,0 +1,38 @@
|
||||
- name: Installation of apache package |
||||
dnf: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php package |
||||
dnf: |
||||
name: php |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php-mysqlnd package |
||||
dnf: |
||||
name: php-mysqlnd |
||||
state: present |
||||
update_cache: yes |
||||
notify: Reload Apache |
||||
|
||||
- name: Installation of wget package |
||||
dnf: |
||||
name: wget |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
|
@ -0,0 +1,19 @@
|
||||
- name: Installation of mariadb-server package |
||||
yum: |
||||
name: mariadb-server |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure mariadb-server is running (and enabled at boot) |
||||
service: |
||||
name: mariadb |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow mariadb traffic on port 3306 |
||||
firewalld: |
||||
service: mysql |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
|
@ -0,0 +1,20 @@
|
||||
- name: Installation of MySQL-python package |
||||
# package required to use ansible mysql modules |
||||
yum: |
||||
name: MySQL-python |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Create a new database with name '{{ DB_NAME }}' |
||||
mysql_db: |
||||
name: '{{ DB_NAME }}' |
||||
state: present |
||||
|
||||
- name: Create a new database user with name '{{ DB_USER }}' |
||||
mysql_user: |
||||
name: '{{ DB_USER }}' |
||||
password: '{{ DB_PASSWORD }}' |
||||
priv: '{{ DB_NAME }}.*:ALL' |
||||
host: '{{ WEB_HOST }}' |
||||
state: present |
||||
|
@ -0,0 +1,31 @@
|
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file with db name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'database_name_here' |
||||
replace: '{{ DB_NAME }}' |
||||
|
||||
|
||||
- name: Update wordpress configuration file with user name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'username_here' |
||||
replace: '{{ DB_USER }}' |
||||
|
||||
- name: Update wordpress configuration file with user password |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'password_here' |
||||
replace: '{{ DB_PASSWORD }}' |
||||
|
||||
- name: Update wordpress configuration file with host |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'localhost' |
||||
replace: '{{ DB_HOST }}' |
||||
|
@ -0,0 +1,18 @@
|
||||
- name: Download wordpress archive |
||||
get_url: |
||||
#url: https://wordpress.org/latest.tar.gz |
||||
url: https://wordpress.org/wordpress-5.0.8.tar.gz |
||||
dest: /var/www/html/wordpress.tar.gz |
||||
mode: 0440 |
||||
|
||||
- name: Untar wordpress archive |
||||
unarchive: |
||||
src: /var/www/html/wordpress.tar.gz |
||||
dest: /var/www/html |
||||
remote_src: true |
||||
|
||||
- name: Remove wordpress archive |
||||
file: |
||||
path: /var/www/html/wordpress.tar.gz |
||||
state: absent |
||||
|
@ -0,0 +1,26 @@
|
||||
- hosts: ansible-2 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_ssh_host'] }}" |
||||
- WEB_HOST: "{{ hostvars['ansible-1']['ansible_ssh_host'] }}" |
||||
tasks: |
||||
- include_tasks: imports/mariadb-install.yaml |
||||
- include_tasks: imports/mariadb-wordpress-configure.yaml |
||||
|
||||
- hosts: ansible-1 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_ssh_host'] }}" |
||||
tasks: |
||||
- include_tasks: imports/apache-install.yaml |
||||
- include_tasks: imports/wordpress-install.yaml |
||||
- include_tasks: imports/wordpress-configure.yaml |
||||
handlers: |
||||
# On utilise import_tasks pour que le fichier contenant |
||||
# les handlers soit chargé dès le départ |
||||
- import_tasks: imports/apache-handlers.yaml |
||||
|
@ -0,0 +1,18 @@
|
||||
--- |
||||
|
||||
- hosts: centos7 |
||||
tasks: |
||||
- name: Generate random password for DB access |
||||
set_fact: |
||||
DB_PASSWORD: "{{ lookup('password', 'passwords.txt') }}" |
||||
|
||||
- hosts: ansible-2 |
||||
roles: |
||||
- role: mariadb-install |
||||
- role: mariadb-configure |
||||
|
||||
- hosts: ansible-1 |
||||
roles: |
||||
- role: apache-install |
||||
- role: wordpress-install |
||||
- role: wordpress-configure |
@ -0,0 +1,5 @@
|
||||
--- |
||||
DB_NAME: wordpress |
||||
DB_USER: wordpressuser |
||||
DB_HOST: 192.168.56.103 |
||||
WEB_HOST: 192.168.56.102 |
@ -0,0 +1,17 @@
|
||||
ansible-1 ansible_ssh_host=192.168.56.102 |
||||
ansible-2 ansible_ssh_host=192.168.56.103 |
||||
ansible-3 ansible_ssh_host=192.168.56.104 tata=tutu |
||||
|
||||
[centos7] |
||||
ansible-1 |
||||
ansible-2 |
||||
|
||||
[debian9] |
||||
ansible-3 |
||||
|
||||
[centos7:vars] |
||||
titi=toto |
||||
|
||||
[all:vars] |
||||
ansible_become=yes |
||||
ansible_become_pass=ansible |
@ -0,0 +1 @@
|
||||
f2OLcLega8W,GC6vDiLn |
@ -0,0 +1,33 @@
|
||||
- name: Installation of apache package |
||||
yum: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php package |
||||
yum: |
||||
name: php |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php-mysql package |
||||
yum: |
||||
name: php-mysql |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of wget package |
||||
yum: |
||||
name: wget |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: name=httpd state=started enabled=yes |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
@ -0,0 +1,19 @@
|
||||
- name: Installation of MySQL-python package |
||||
# package required to use ansible mysql modules |
||||
yum: |
||||
name: MySQL-python |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Create a new database with name '{{ DB_NAME }}' |
||||
mysql_db: |
||||
name: '{{ DB_NAME }}' |
||||
state: present |
||||
|
||||
- name: Create a new database user with name '{{ DB_USER }}' and password '{{ DB_PASSWORD }}' |
||||
mysql_user: |
||||
name: '{{ DB_USER }}' |
||||
password: '{{ DB_PASSWORD }}' |
||||
priv: '{{ DB_NAME }}.*:ALL' |
||||
host: '{{ WEB_HOST }}' |
||||
state: present |
@ -0,0 +1,18 @@
|
||||
- name: Installation of mariadb-server package |
||||
yum: |
||||
name: mariadb-server |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure mariadb-server is running (and enabled at boot) |
||||
service: |
||||
name: mariadb |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow mariadb traffic on port 3306 |
||||
firewalld: |
||||
service: mysql |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
@ -0,0 +1,30 @@
|
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file with db name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'database_name_here' |
||||
replace: '{{ DB_NAME }}' |
||||
|
||||
|
||||
- name: Update wordpress configuration file with user name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'username_here' |
||||
replace: '{{ DB_USER }}' |
||||
|
||||
- name: Update wordpress configuration file with user password '{{ DB_PASSWORD }}' |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'password_here' |
||||
replace: '{{ DB_PASSWORD }}' |
||||
|
||||
- name: Update wordpress configuration file with host |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'localhost' |
||||
replace: '{{ DB_HOST }}' |
@ -0,0 +1,16 @@
|
||||
- name: Download worpress archive |
||||
get_url: |
||||
url: https://wordpress.org/latest.tar.gz |
||||
dest: /var/www/html/wordpress.tar.gz |
||||
mode: 0440 |
||||
|
||||
- name: Untar worpress archive |
||||
unarchive: |
||||
src: /var/www/html/wordpress.tar.gz |
||||
dest: /var/www/html |
||||
remote_src: true |
||||
|
||||
- name: Remove wordpress archive |
||||
file: |
||||
path: /var/www/html/wordpress.tar.gz |
||||
state: absent |
@ -0,0 +1,6 @@
|
||||
--- |
||||
DB_NAME: wordpress |
||||
DB_USER: wordpressuser |
||||
DB_PASSWORD: 12345 |
||||
DB_HOST: "{{ hostvars['ansible-2']['ansible_host'] }}" |
||||
WEB_HOST: "{{ hostvars['ansible-1']['ansible_host'] }}" |
@ -0,0 +1,10 @@
|
||||
ansible-1 ansible_host=192.168.56.101 |
||||
ansible-2 ansible_host=192.168.56.104 |
||||
|
||||
[wordpress] |
||||
ansible-1 |
||||
ansible-2 |
||||
|
||||
[all:vars] |
||||
ansible_become=yes |
||||
ansible_become_pass=ansible |
@ -0,0 +1,9 @@
|
||||
--- |
||||
- hosts: ansible-2 |
||||
roles: |
||||
- role: mariadb |
||||
|
||||
- hosts: ansible-1 |
||||
roles: |
||||
- role: apache |
||||
- role: wordpress |
@ -0,0 +1,36 @@
|
||||
- name: Installation of apache package |
||||
yum: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php package |
||||
yum: |
||||
name: php |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php-mysql package |
||||
yum: |
||||
name: php-mysql |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of wget package |
||||
yum: |
||||
name: wget |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
@ -0,0 +1,4 @@
|
||||
DB_NAME: mydb |
||||
DB_USER: bob |
||||
DB_PASSWORD: 12345678 |
||||
WEB_HOST: localhost |
@ -0,0 +1,19 @@
|
||||
- name: Installation of MySQL-python package |
||||
# package required to use ansible mysql modules |
||||
yum: |
||||
name: MySQL-python |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Create a new database with name '{{ DB_NAME }}' |
||||
mysql_db: |
||||
name: '{{ DB_NAME }}' |
||||
state: present |
||||
|
||||
- name: Create a new user with name '{{ DB_USER }}' with full access to '{{ DB_NAME }} from '{{ WEB_HOST }}' |
||||
mysql_user: |
||||
name: '{{ DB_USER }}' |
||||
password: '{{ DB_PASSWORD }}' |
||||
priv: '{{ DB_NAME }}.*:ALL' |
||||
host: '{{ WEB_HOST }}' |
||||
state: present |
@ -0,0 +1,18 @@
|
||||
- name: Installation of mariadb-server package |
||||
yum: |
||||
name: mariadb-server |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure mariadb-server is running (and enabled at boot) |
||||
service: |
||||
name: mariadb |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow mariadb traffic on port 3306 |
||||
firewalld: |
||||
service: mysql |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
@ -0,0 +1,2 @@
|
||||
- import_tasks: install.yaml |
||||
- import_tasks: add-database.yaml |
@ -0,0 +1,3 @@
|
||||
--- |
||||
dependencies: |
||||
- role: apache |
@ -0,0 +1,30 @@
|
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file with db name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'database_name_here' |
||||
replace: '{{ DB_NAME }}' |
||||
|
||||
|
||||
- name: Update wordpress configuration file with user name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'username_here' |
||||
replace: '{{ DB_USER }}' |
||||
|
||||
- name: Update wordpress configuration file with user password |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'password_here' |
||||
replace: '{{ DB_PASSWORD }}' |
||||
|
||||
- name: Update wordpress configuration file with host |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'localhost' |
||||
replace: '{{ DB_HOST }}' |
@ -0,0 +1,16 @@
|
||||
- name: Download worpress archive |
||||
get_url: |
||||
url: https://wordpress.org/latest.tar.gz |
||||
dest: /var/www/html/wordpress.tar.gz |
||||
mode: 0440 |
||||
|
||||
- name: Untar worpress archive |
||||
unarchive: |
||||
src: /var/www/html/wordpress.tar.gz |
||||
dest: /var/www/html |
||||
remote_src: true |
||||
|
||||
- name: Remove wordpress archive |
||||
file: |
||||
path: /var/www/html/wordpress.tar.gz |
||||
state: absent |
@ -0,0 +1,2 @@
|
||||
- import_tasks: install.yaml |
||||
- import_tasks: configure.yaml |
@ -0,0 +1,6 @@
|
||||
ansible-1 ansible_ssh_host=192.168.56.106 |
||||
ansible-2 ansible_ssh_host=192.168.56.107 |
||||
|
||||
[all:vars] |
||||
ansible_become=yes |
||||
ansible_become_pass=ansible |
@ -0,0 +1,149 @@
|
||||
--- |
||||
- hosts: ansible-2 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_ssh_host'] }}" |
||||
- WEB_HOST: "{{ hostvars['ansible-1']['ansible_ssh_host'] }}" |
||||
tasks: |
||||
- name: Installation of mariadb-server package |
||||
yum: |
||||
name: mariadb-server |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure mariadb-server is running (and enabled at boot) |
||||
service: |
||||
name: mariadb |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Installation of MySQL-python package |
||||
# package required to use ansible mysql modules |
||||
yum: |
||||
name: MySQL-python |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Create a new database with name '{{ DB_NAME }}' |
||||
mysql_db: |
||||
name: '{{ DB_NAME }}' |
||||
state: present |
||||
|
||||
- name: Create a new database user with name '{{ DB_USER }}' |
||||
mysql_user: |
||||
name: '{{ DB_USER }}' |
||||
password: '{{ DB_PASSWORD }}' |
||||
priv: '{{ DB_NAME }}.*:ALL' |
||||
host: '{{ WEB_HOST }}' |
||||
state: present |
||||
|
||||
- name: Allow mariadb traffic on port 3306 |
||||
firewalld: |
||||
service: mysql |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
|
||||
|
||||
|
||||
- hosts: ansible-1 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_ssh_host'] }}" |
||||
tasks: |
||||
- name: Installation of apache package |
||||
dnf: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php package |
||||
dnf: |
||||
name: php |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php-mysqlnd package |
||||
dnf: |
||||
name: php-mysqlnd |
||||
state: present |
||||
update_cache: yes |
||||
notify: Reload Apache |
||||
|
||||
- name: Installation of wget package |
||||
dnf: |
||||
name: wget |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Download wordpress archive |
||||
get_url: |
||||
url: https://wordpress.org/wordpress-5.0.8.tar.gz |
||||
dest: /var/www/html/wordpress.tar.gz |
||||
mode: 0440 |
||||
|
||||
- name: Untar wordpress archive |
||||
unarchive: |
||||
src: /var/www/html/wordpress.tar.gz |
||||
dest: /var/www/html |
||||
remote_src: true |
||||
|
||||
- name: Remove wordpress archive |
||||
file: |
||||
path: /var/www/html/wordpress.tar.gz |
||||
state: absent |
||||
|
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file with db name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'database_name_here' |
||||
replace: '{{ DB_NAME }}' |
||||
|
||||
|
||||
- name: Update wordpress configuration file with user name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'username_here' |
||||
replace: '{{ DB_USER }}' |
||||
|
||||
- name: Update wordpress configuration file with user password |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'password_here' |
||||
replace: '{{ DB_PASSWORD }}' |
||||
|
||||
- name: Update wordpress configuration file with host |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'localhost' |
||||
replace: '{{ DB_HOST }}' |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
|
||||
|
||||
handlers: |
||||
- name: Reload Apache |
||||
service: |
||||
name: httpd |
||||
state: restarted |
@ -0,0 +1,53 @@
|
||||
# -------------------------------------------------------------------------------------------------- |
||||
# 1/ Installation BDD |
||||
|
||||
# Installation packages Mariadb |
||||
yum install mariadb-server |
||||
|
||||
# Mise en place règles firewall |
||||
firewall-cmd --add-service=mysql --permanent |
||||
firewall-cmd --reload |
||||
|
||||
systemctl enable mariadb |
||||
systemctl start mariadb |
||||
|
||||
mysql -u root -p |
||||
CREATE DATABASE wordpress; |
||||
CREATE USER wordpressuser@localhost IDENTIFIED BY 'password'; |
||||
GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost; |
||||
FLUSH PRIVILEGES; |
||||
|
||||
# -------------------------------------------------------------------------------------------------- |
||||
# 2/ Installation WEBSERVER |
||||
|
||||
# Installation de Apache |
||||
yum install httpd php php-mysql wget |
||||
|
||||
# Mise en place règles firewall |
||||
firewall-cmd --add-service=http --permanent |
||||
firewall-cmd --reload |
||||
|
||||
systemctl enable httpd |
||||
systemctl start httpd |
||||
|
||||
# Configuration de Apache |
||||
... |
||||
|
||||
# Déploiement du wordpress : |
||||
cd /var/www/html && wget https://wordpress.org/latest.tar.gz |
||||
|
||||
# Décompression du wordpress |
||||
tar -xzf /var/www/html/latest.tar.gz -C /var/www/html |
||||
rm -f /var/www/html/latest.tar.gz |
||||
|
||||
#create wp config |
||||
cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php |
||||
|
||||
#set database details |
||||
vi /var/www/html/wordpress/wp-config.php |
||||
|
||||
#define('DB_NAME', 'wordpress'); |
||||
#define('DB_USER', 'wordpressuser'); |
||||
#define('DB_PASSWORD', 'password'); |
||||
#define('DB_HOST', 'localhost'); |
||||
|
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 90 KiB |
@ -0,0 +1 @@
|
||||
../revealjs |
@ -0,0 +1,72 @@
|
||||
<!doctype html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
||||
|
||||
<title>SII - TP Ansible : diver</title> |
||||
<link rel="icon" type="image/png" href="../revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<link rel="stylesheet" href="../revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="../revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
<link rel="stylesheet" href="../revealjs/css/custom.css"> <!-- your custom styles --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="../revealjs/lib/css/zenburn.css"> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? '../revealjs/css/print/pdf.css' : '../revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
</head> |
||||
<body> |
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-divers.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="../revealjs/lib/js/head.min.js"></script> |
||||
<script src="../revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
history: true, |
||||
|
||||
// Transition style |
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// Transition style for full page slide backgrounds |
||||
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: '../revealjs/plugin/markdown/marked.js' }, |
||||
{ src: '../revealjs/plugin/markdown/markdown.js' }, |
||||
{ src: '../revealjs/plugin/notes/notes.js', async: true }, |
||||
{ src: '../revealjs/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } } |
||||
] |
||||
}); |
||||
|
||||
// Slide number formatting can be configured using these variables: |
||||
// "h.v": horizontal . vertical slide number (default) |
||||
// "h/v": horizontal / vertical slide number |
||||
// "c": flattened slide number |
||||
// "c/t": flattened slide number / total slides |
||||
Reveal.configure({ slideNumber: 'c/t' }); |
||||
Reveal.configure({ transition: 'none' }); |
||||
</script> |
||||
<img class="logo" src="../revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,15 @@
|
||||
## TP Complémentaires |
||||
|
||||
|
||||
* Variabiliser le port d'écoute d'Apache. |
||||
|
||||
|
||||
* Prévoir de pouvoir dérouler la partie web sur centos _ou_ debian. |
||||
|
||||
|
||||
* Créer des roles pour installer Docker et Docker-Compose sur Debian |
||||
https://docs.docker.com/install/linux/docker-ce/debian/ |
||||
|
||||
Vérification : |
||||
* $ docker version |
||||
* $ docker-compose version |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible Galaxy</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-galaxy.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • janvier 2019</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,111 @@
|
||||
## TP Ansible Galaxy |
||||
|
||||
Créer et partager ses propres roles. |
||||
|
||||
|
||||
## Télécharger des roles |
||||
|
||||
|
||||
* Aller sur Galaxy https://galaxy.ansible.com et rechercher le role Apache de Geerlingguy. |
||||
|
||||
* Récupérer la CLI d'installation. |
||||
|
||||
![](images/ansible-galaxy-search-role.png) |
||||
|
||||
|
||||
* Il est également possible de faire une recherche avec la commande `search` |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible-galaxy search --author geerlingguy apache |
||||
|
||||
Found 14 roles matching your search: |
||||
|
||||
Name Description |
||||
---- ----------- |
||||
geerlingguy.adminer Installs Adminer for Database management. |
||||
geerlingguy.apache Apache 2.x for Linux. |
||||
geerlingguy.apache-php-fpm Apache 2.4+ PHP-FPM support for Linux. |
||||
geerlingguy.certbot Installs and configures Certbot (for Let's Encrypt). |
||||
geerlingguy.drupal Deploy or install Drupal on your servers. |
||||
geerlingguy.htpasswd htpasswd installation and helper role for Linux serv... |
||||
geerlingguy.munin Munin monitoring server for RedHat/CentOS or Debian/... |
||||
geerlingguy.php PHP for RedHat/CentOS/Fedora/Debian/Ubuntu. |
||||
geerlingguy.pimpmylog Pimp my Log installation for Linux |
||||
geerlingguy.solr Apache Solr for Linux. |
||||
geerlingguy.supervisor Supervisor (process state manager) for Linux. |
||||
geerlingguy.svn SVN web server for Linux |
||||
geerlingguy.tomcat6 Tomcat 6 for RHEL/CentOS and Debian/Ubuntu. |
||||
geerlingguy.varnish Varnish for Linux. |
||||
``` |
||||
|
||||
|
||||
* Installer le role apache récupéré. |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ ansible-galaxy install geerlingguy.apache |
||||
|
||||
- downloading role 'apache', owned by geerlingguy |
||||
- downloading role from https://github.com/geerlingguy/ansible-role-apache/archive/3.0.3.tar.gz |
||||
- extracting geerlingguy.apache to /home/formationback/.ansible/roles/geerlingguy.apache |
||||
- geerlingguy.apache (3.0.3) was installed successfully |
||||
``` |
||||
|
||||
|
||||
* Parcourons ensemble la structure des dossiers et notamment le dossier meta. |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```none |
||||
$ cat /home/ansible/.ansible/roles/geerlingguy.apache/meta/main.yml |
||||
``` |
||||
```yaml |
||||
dependencies: [] |
||||
|
||||
galaxy_info: |
||||
author: geerlingguy |
||||
description: Apache 2.x for Linux. |
||||
company: "Midwestern Mac, LLC" |
||||
license: "license (BSD, MIT)" |
||||
min_ansible_version: 2.4 |
||||
platforms: |
||||
- name: EL |
||||
versions: |
||||
- all |
||||
- name: Fedora |
||||
versions: |
||||
- all |
||||
- name: Amazon |
||||
versions: |
||||
- all |
||||
- name: Debian |
||||
versions: |
||||
- all |
||||
- name: Ubuntu |
||||
versions: |
||||
- trusty |
||||
- xenial |
||||
- bionic |
||||
- name: Solaris |
||||
versions: |
||||
- 11.3 |
||||
galaxy_tags: |
||||
- web |
||||
- apache |
||||
- webserver |
||||
- html |
||||
- httpd |
||||
|
||||
allow_duplicates: true |
||||
``` |
||||
|
||||
|
||||
## Gérer les roles comme des dépendances externes |
||||
|
||||
|
||||
* Pour ce TP, nous allons réutiliser les roles que vous venez de créer. Pour plus de facilité, les versions finales sont déjà présentes sur le GitLab `https://gitlab.com/a-berthout`. |
||||
|
||||
* Grâce à Ansible Galaxy, dans votre projet actuel, récupérer les roles suivants : |
||||
* Apache sur la branche master |
||||
* MariaDB sur la branche develop |
||||
* Wordpress sur le tag V1.0.0 |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : les imports</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-imports.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,215 @@
|
||||
## TP Imports |
||||
|
||||
* Reprendre le TP Wordpress et découper le Playbook en plusieurs fichiers de tâches. |
||||
|
||||
* Exemples de découpage pouvant être définis : |
||||
<small> |
||||
|
||||
- mariadb-install.yaml |
||||
- mariadb-configure.yaml |
||||
- apache-install.yaml |
||||
- apache-configure.yaml |
||||
- wordpress-install.yaml |
||||
- wordpress-configure.yaml |
||||
- test-service.yaml |
||||
|
||||
</small> |
||||
|
||||
* Utiliser `include_tasks` pour charger les fichiers de tâches. |
||||
|
||||
|
||||
`install-apache-wordpress-mariadb-imports.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- hosts: ansible-2 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_ssh_host'] }}" |
||||
- WEB_HOST: "{{ hostvars['ansible-1']['ansible_ssh_host'] }}" |
||||
tasks: |
||||
- include_tasks: imports/mariadb-install.yaml |
||||
- include_tasks: imports/mariadb-wordpress-configure.yaml |
||||
|
||||
- hosts: ansible-1 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_ssh_host'] }}" |
||||
tasks: |
||||
- include_tasks: imports/apache-install.yaml |
||||
- include_tasks: imports/wordpress-install.yaml |
||||
- include_tasks: imports/wordpress-configure.yaml |
||||
handlers: |
||||
# On utilise import_tasks pour que le fichier contenant |
||||
# les handlers soit chargé dès le départ |
||||
- import_tasks: imports/apache-handlers.yaml |
||||
``` |
||||
|
||||
|
||||
`imports/mariadb-install.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Installation of mariadb-server package |
||||
yum: |
||||
name: mariadb-server |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure mariadb-server is running (and enabled at boot) |
||||
service: |
||||
name: mariadb |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow mariadb traffic on port 3306 |
||||
firewalld: |
||||
service: mysql |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
``` |
||||
|
||||
|
||||
`imports/mariadb-wordpress-configure.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Installation of MySQL-python package |
||||
# package required to use ansible mysql modules |
||||
yum: |
||||
name: MySQL-python |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Create a new database with name '{{ DB_NAME }}' |
||||
mysql_db: |
||||
name: '{{ DB_NAME }}' |
||||
state: present |
||||
|
||||
- name: Create a new database user with name '{{ DB_USER }}' |
||||
mysql_user: |
||||
name: '{{ DB_USER }}' |
||||
password: '{{ DB_PASSWORD }}' |
||||
priv: '{{ DB_NAME }}.*:ALL' |
||||
host: '{{ WEB_HOST }}' |
||||
state: present |
||||
``` |
||||
|
||||
|
||||
`imports/apache-install.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Installation of apache package |
||||
dnf: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php package |
||||
dnf: |
||||
name: php |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php-mysqlnd package |
||||
dnf: |
||||
name: php-mysqlnd |
||||
state: present |
||||
update_cache: yes |
||||
notify: Reload Apache |
||||
|
||||
- name: Installation of wget package |
||||
dnf: |
||||
name: wget |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
``` |
||||
|
||||
|
||||
`imports/apache-handlers.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Reload Apache |
||||
service: |
||||
name: httpd |
||||
state: restarted |
||||
``` |
||||
|
||||
|
||||
`imports/wordpress-install.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Download wordpress archive |
||||
get_url: |
||||
url: https://wordpress.org/wordpress-5.0.8.tar.gz |
||||
dest: /var/www/html/wordpress.tar.gz |
||||
mode: 0440 |
||||
|
||||
- name: Untar wordpress archive |
||||
unarchive: |
||||
src: /var/www/html/wordpress.tar.gz |
||||
dest: /var/www/html |
||||
remote_src: true |
||||
|
||||
- name: Remove wordpress archive |
||||
file: |
||||
path: /var/www/html/wordpress.tar.gz |
||||
state: absent |
||||
``` |
||||
|
||||
|
||||
`imports/wordpress-configure.yaml` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file with db name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'database_name_here' |
||||
replace: '{{ DB_NAME }}' |
||||
|
||||
- name: Update wordpress configuration file with user name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'username_here' |
||||
replace: '{{ DB_USER }}' |
||||
|
||||
- name: Update wordpress configuration file with user password |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'password_here' |
||||
replace: '{{ DB_PASSWORD }}' |
||||
|
||||
- name: Update wordpress configuration file with host |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'localhost' |
||||
replace: '{{ DB_HOST }}' |
||||
``` |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : Inventaire</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-inventaire.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,268 @@
|
||||
# TP Ansible |
||||
|
||||
## Les bases |
||||
|
||||
* Préparer les machines cibles. |
||||
|
||||
* Créer un fichier d'inventory. |
||||
|
||||
* Vérifier le bon fonctionnement d'Ansible. |
||||
|
||||
|
||||
## Vérifier la version de Ansible |
||||
|
||||
```none |
||||
ansible@ansible-0:~$ ansible --version |
||||
ansible 2.6.4 |
||||
config file = /etc/ansible/ansible.cfg |
||||
configured module search path = [u'/home/ansible/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] |
||||
ansible python module location = /usr/lib/python2.7/dist-packages/ansible |
||||
executable location = /usr/bin/ansible |
||||
python version = 2.7.13 (default, Nov 24 2017, 17:33:09) [GCC 6.3.0 20170516] |
||||
``` |
||||
|
||||
|
||||
## Préparer les machines cibles |
||||
|
||||
Pour que Ansible puisse se connecter à des machines distantes, il faut : |
||||
|
||||
1. Mettre en place une authentification |
||||
via une paire de clés ssh, |
||||
|
||||
2. Générer un fichier d'inventaire qui contiendra |
||||
la liste des machines. |
||||
|
||||
|
||||
## Authentification via clés ssh |
||||
|
||||
|
||||
![Schéma connexion ssh](images/ansible-archi-ssh.png) <!-- .element: height="550px" --> |
||||
|
||||
|
||||
* Créer une paire de clés ssh |
||||
<!-- .slide: data-state="small-code" --> |
||||
|
||||
```none |
||||
$ cd |
||||
$ ssh-keygen |
||||
Generating public/private rsa key pair. |
||||
Enter file in which to save the key (/home/ansible/.ssh/id_rsa): |
||||
Created directory '/home/ansible/.ssh'. |
||||
Enter passphrase (empty for no passphrase): |
||||
Enter same passphrase again: |
||||
Your identification has been saved in /home/ansible/.ssh/id_rsa. |
||||
Your public key has been saved in /home/ansible/.ssh/id_rsa.pub. |
||||
The key fingerprint is: |
||||
SHA256:pipIK6HsauJKf2TuyRRWf/EYgUggRknBmtbIuGVq0/g ansible@ansible-0 |
||||
The key's randomart image is: |
||||
+---[RSA 2048]----+ |
||||
| +*o.o.. .. | |
||||
| .o. . . . | |
||||
|o = . o | |
||||
|.*o. . . = | |
||||
|.=o o S. o . | |
||||
|+= ..o.o . | |
||||
|=++ +.. | |
||||
|*+oEo+. | |
||||
|@o o++ | |
||||
+----[SHA256]-----+ |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
```none |
||||
$ ls -l ~/.ssh/ |
||||
total 12 |
||||
-rw------- 1 ansible ansible 1679 sept. 20 09:43 id_rsa |
||||
-rw-r--r-- 1 ansible ansible 407 sept. 20 09:43 id_rsa.pub |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="2" --> |
||||
|
||||
|
||||
* Copier la clé publique sur les machines cibles |
||||
|
||||
```none |
||||
$ ssh-copy-id -i 192.168.56.102 |
||||
$ ssh 192.168.56.102 |
||||
|
||||
$ ssh-copy-id -i 192.168.56.103 |
||||
$ ssh 192.168.56.103 |
||||
|
||||
$ ssh-copy-id -i 192.168.56.104 |
||||
$ ssh 192.168.56.104 |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
## Fichier d'inventaire minimal |
||||
|
||||
|
||||
* Créer le fichier d'inventaire |
||||
`inventories/formation/hosts`. |
||||
|
||||
```none |
||||
$ mkdir -p inventories/formation |
||||
|
||||
$ cat <<EOF > inventories/formation/hosts |
||||
192.168.56.102 |
||||
192.168.56.103 |
||||
192.168.56.104 |
||||
EOF |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
* Vérifier l'inventaire. |
||||
|
||||
```none |
||||
$ ansible all --list-hosts |
||||
[WARNING]: provided hosts list is empty, |
||||
only localhost is available. |
||||
Note that the implicit localhost does not match 'all' |
||||
hosts (0): |
||||
``` |
||||
```none |
||||
$ ansible all -i inventories/formation/hosts --list-hosts |
||||
hosts (3): |
||||
192.168.56.102 |
||||
192.168.56.103 |
||||
192.168.56.104 |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
Syntaxe des commandes : |
||||
|
||||
`ansible <host-pattern> [options]` |
||||
|
||||
|
||||
* Tester le ping via Ansible. |
||||
|
||||
```none |
||||
$ ansible all -i inventories/formation/hosts -m ping |
||||
192.168.56.104 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
192.168.56.103 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
192.168.56.102 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
* Ajouter le nom des machines dans l'inventaire |
||||
via la syntaxe : |
||||
|
||||
`<host-name> ansible_host=<ip-address>` |
||||
|
||||
```none |
||||
$ cat inventories/formation/hosts |
||||
ansible-1 ansible_host=192.168.56.102 |
||||
ansible-2 ansible_host=192.168.56.103 |
||||
ansible-3 ansible_host=192.168.56.104 |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
```none |
||||
$ ansible all -i inventories/formation/hosts --list-hosts |
||||
hosts (3): |
||||
ansible-1 |
||||
ansible-2 |
||||
ansible-3 |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="2" --> |
||||
|
||||
|
||||
* Tester de nouveau le ping et vérifier que les hostnames apparaissent maintenant dans les résultats. |
||||
|
||||
```none |
||||
$ ansible all -i inventories/formation/hosts -m ping |
||||
|
||||
ansible-3 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
ansible-2 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
ansible-1 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
* Regrouper les machines en 2 groupes : |
||||
`centos` et `debian`. |
||||
|
||||
```none |
||||
$ cat inventories/formation/hosts |
||||
ansible-1 ansible_host=192.168.56.102 |
||||
ansible-2 ansible_host=192.168.56.103 |
||||
ansible-3 ansible_host=192.168.56.104 |
||||
|
||||
[centos] |
||||
ansible-1 |
||||
ansible-2 |
||||
|
||||
[debian] |
||||
ansible-3 |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
* Tester de nouveau le ping mais cette fois-ci uniquement sur les machines CentOS. |
||||
|
||||
```none |
||||
$ ansible centos -i inventories/formation/hosts -m ping |
||||
|
||||
ansible-2 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
ansible-1 | SUCCESS => { |
||||
"changed": false, |
||||
"ping": "pong" |
||||
} |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
* Créer un groupe `tous` qui regroupera |
||||
les groupes `centos` et `debian`. |
||||
|
||||
* Tester de nouveau le ping sur le groupe `tous`. |
||||
|
||||
```none |
||||
ansible-1 ansible_host=192.168.56.102 |
||||
ansible-2 ansible_host=192.168.56.103 |
||||
ansible-3 ansible_host=192.168.56.104 |
||||
|
||||
[centos] |
||||
ansible-1 |
||||
ansible-2 |
||||
|
||||
[debian] |
||||
ansible-3 |
||||
|
||||
[tous:children] |
||||
centos |
||||
debian |
||||
``` |
||||
<!-- .element: class="fragment" data-fragment-index="1" --> |
||||
|
||||
|
||||
* Créer un snapshot Virtualbox pour les machines |
||||
|
||||
- ansible-1 |
||||
|
||||
- ansible-2 |
||||
|
||||
- ansible-3 |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : les commandes ad-hoc</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-les-commandes-ad-hoc.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : les playbooks</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-playbooks.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,434 @@
|
||||
# TP Ansible |
||||
|
||||
## Les Playbooks |
||||
|
||||
Créer un Playbook et l'exécuter sur des cibles. |
||||
|
||||
|
||||
* Créer dans le dossier de travail un fichier playbook nommé `get-user-id.yaml` avec le contenu suivant : |
||||
|
||||
```yaml |
||||
- hosts: all |
||||
tasks: |
||||
- name: Get user id |
||||
command: id |
||||
``` |
||||
|
||||
* Que va faire ce playbook ? |
||||
|
||||
|
||||
* Exécuter le Playbook : |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```nohighlight |
||||
$ ansible-playbook -i inventories/formation/hosts playbooks/get-user-id.yaml |
||||
|
||||
PLAY [all] ******************************************************************** |
||||
|
||||
TASK [Gathering Facts] ******************************************************** |
||||
ok: [ansible-3] |
||||
ok: [ansible-2] |
||||
ok: [ansible-1] |
||||
|
||||
TASK [Get user id] ************************************************************ |
||||
changed: [ansible-3] |
||||
changed: [ansible-2] |
||||
changed: [ansible-1] |
||||
|
||||
PLAY RECAP ******************************************************************** |
||||
ansible-1 : ok=2 changed=1 unreachable=0 failed=0 |
||||
ansible-2 : ok=2 changed=1 unreachable=0 failed=0 |
||||
ansible-3 : ok=2 changed=1 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
L'action est bien effectuée même si on ne voit pas le détail. |
||||
|
||||
|
||||
* Relancer l'éxécution du Playbook en mode verbeux. |
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```nohighlight |
||||
$ ansible-playbook -v -i inventories/formation/hosts playbooks/get-user-id.yaml |
||||
|
||||
PLAY [all] ******************************************************************** |
||||
|
||||
TASK [Gathering Facts] ******************************************************** |
||||
ok: [ansible-3] |
||||
ok: [ansible-2] |
||||
ok: [ansible-1] |
||||
|
||||
TASK [Get user id] ************************************************************ |
||||
changed: [ansible-3] => {"changed": true, "cmd": ["id"], "delta": "0:00:00.008768", "end": "2018-09-21 17:06:07.020080", "rc": 0, "start": "2018-09-21 17:06:07.011312", "stderr": "", "stderr_lines": [], "stdout": "uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible),27(sudo)", "stdout_lines": ["uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible),27(sudo)"]} |
||||
changed: [ansible-2] => {"changed": true, "cmd": ["id"], "delta": "0:00:00.010668", "end": "2018-09-21 17:06:02.736220", "rc": 0, "start": "2018-09-21 17:06:02.725552", "stderr": "", "stderr_lines": [], "stdout": "uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible),10(wheel)", "stdout_lines": ["uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible),10(wheel)"]} |
||||
changed: [ansible-1] => {"changed": true, "cmd": ["id"], "delta": "0:00:00.008940", "end": "2018-09-21 17:06:06.974383", "rc": 0, "start": "2018-09-21 17:06:06.965443", "stderr": "", "stderr_lines": [], "stdout": "uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible),10(wheel)", "stdout_lines": ["uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible),10(wheel)"]} |
||||
|
||||
PLAY RECAP ******************************************************************** |
||||
ansible-1 : ok=2 changed=1 unreachable=0 failed=0 |
||||
ansible-2 : ok=2 changed=1 unreachable=0 failed=0 |
||||
ansible-3 : ok=2 changed=1 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
Pas très pratique... |
||||
|
||||
|
||||
* Utiliser le paramètre `register` pour enregistrer le résultat de la commande. |
||||
|
||||
* Créer une nouvelle tâche basée sur le module `debug` pour afficher le résultat de la commande. |
||||
|
||||
https://docs.ansible.com/ansible/latest/modules/debug_module.html |
||||
|
||||
|
||||
`playbooks/get-user-id.yaml` |
||||
```yaml |
||||
- hosts: all |
||||
tasks: |
||||
|
||||
- name: Get user id |
||||
command: id |
||||
register: user_id |
||||
|
||||
- name: Display user id |
||||
debug: |
||||
var: user_id.stdout |
||||
``` |
||||
|
||||
|
||||
<!-- .slide: data-state="small-code" --> |
||||
```nohighlight |
||||
$ ansible-playbook -i inventories/formation/hosts playbooks/get-user-id.yaml |
||||
... |
||||
|
||||
TASK [Get user id] ************************************************************ |
||||
changed: [ansible-3] |
||||
changed: [ansible-2] |
||||
changed: [ansible-1] |
||||
|
||||
TASK [Display user id] ******************************************************** |
||||
ok: [ansible-1] => { |
||||
"user_id.stdout": "uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible), |
||||
10(wheel)" |
||||
} |
||||
ok: [ansible-2] => { |
||||
"user_id.stdout": "uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible), |
||||
10(wheel)" |
||||
} |
||||
ok: [ansible-3] => { |
||||
"user_id.stdout": "uid=1001(ansible) gid=1001(ansible) groupes=1001(ansible), |
||||
27(sudo)" |
||||
} |
||||
|
||||
PLAY RECAP ******************************************************************** |
||||
ansible-1 : ok=3 changed=1 unreachable=0 failed=0 |
||||
ansible-2 : ok=3 changed=1 unreachable=0 failed=0 |
||||
ansible-3 : ok=3 changed=1 unreachable=0 failed=0 |
||||
``` |
||||
|
||||
|
||||
|
||||
## TP Installer Apache httpd |
||||
|
||||
Installation d'un serveur web Apache httpd. |
||||
|
||||
|
||||
* Créer un playbook qui exécutera les tâches suivantes sur la machine `ansible-1` : |
||||
|
||||
- Installe le paquet `httpd` et lancer le service `httpd`, |
||||
|
||||
- Configure le service `httpd` pour qu'il se relance à chaque redémarrage du système, |
||||
|
||||
- Créé et copie une page web statique à l'emplacement `/var/www/html/index.html`, |
||||
|
||||
- Configure firewalld pour autoriser le traffic `http` entrant, |
||||
|
||||
|
||||
* Exécuter le Playbook sur la cible |
||||
`ansible-1`. |
||||
|
||||
* Se connecter à l'application dans |
||||
le navigateur web. |
||||
|
||||
|
||||
```yaml |
||||
- hosts: ansible-1 |
||||
|
||||
tasks: |
||||
- name: Installation of apache package |
||||
yum: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Copying homepage |
||||
copy: |
||||
src: index.html |
||||
dest: /var/www/html/index.html |
||||
mode: 0444 |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
``` |
||||
|
||||
|
||||
|
||||
## TP Installer un Wordpress |
||||
|
||||
Installation de l'outil de blog Wordpress. |
||||
|
||||
|
||||
* Serveur de base de données : `ansible-2` (centos 7) |
||||
|
||||
* Installer le serveur Mariadb <small>(mariadb-server)</small> |
||||
|
||||
* Créer une base de donnée et un utilisateur <small>(modules mysql_db, mysql_user)</small> |
||||
--- |
||||
* Serveur web : `ansible-1` (centos 8) |
||||
|
||||
* Installer le serveur Apache httpd + php <small>(httpd, php, php-mysqlnd)</small> |
||||
|
||||
* Télécharger Wordpress _5.0.8_ <small>(https://wordpress.org/wordpress-5.0.8.tar.gz)</small> |
||||
|
||||
* Décompresser le dossier dans _/var/www/html/_ avec les bon droits <small>(module unarchive)</small> |
||||
|
||||
* Editer la configuration de Wordpress pour qu'il accède à la bdd |
||||
|
||||
|
||||
### 1. Base de données |
||||
|
||||
* Installer le serveur Mariadb |
||||
|
||||
* Créer une base de donnée et un utilisateur |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```bash |
||||
# Installation packages Mariadb |
||||
yum install mariadb-server |
||||
|
||||
# Mise en place règles firewall |
||||
firewall-cmd --add-service=mysql --permanent |
||||
firewall-cmd --reload |
||||
|
||||
# Options de démarrage de Mariadb |
||||
systemctl enable mariadb |
||||
systemctl start mariadb |
||||
|
||||
# Création base et utilisateur |
||||
mysql -u root -p |
||||
CREATE DATABASE wordpress; |
||||
CREATE USER wordpressuser@localhost IDENTIFIED BY 'password'; |
||||
GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost; |
||||
FLUSH PRIVILEGES; |
||||
``` |
||||
|
||||
|
||||
### 2. Apache |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```bash |
||||
# Installation de Apache |
||||
yum install httpd php php-mysql wget |
||||
|
||||
# Mise en place règles firewall |
||||
firewall-cmd --add-service=http --permanent |
||||
firewall-cmd --reload |
||||
|
||||
# Options de démarrage de Apache |
||||
systemctl enable httpd |
||||
systemctl start httpd |
||||
``` |
||||
|
||||
|
||||
### 3. Wordpress |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```bash |
||||
# Déploiement de wordpress : |
||||
cd /var/www/html && wget https://wordpress.org/latest.tar.gz |
||||
|
||||
# Décompression de wordpress |
||||
tar -xzf /var/www/html/latest.tar.gz -C /var/www/html |
||||
rm -f /var/www/html/latest.tar.gz |
||||
|
||||
# Configuration de Wordpress |
||||
cp /var/www/html/wordpress/wp-config-sample.php \ |
||||
/var/www/html/wordpress/wp-config.php |
||||
vi /var/www/html/wordpress/wp-config.php |
||||
# define('DB_NAME', 'wordpress'); |
||||
# define('DB_USER', 'wordpressuser'); |
||||
# define('DB_PASSWORD', 'password'); |
||||
# define('DB_HOST', 'localhost'); |
||||
``` |
||||
|
||||
|
||||
Quelques modules possibles... |
||||
|
||||
* yum |
||||
* service |
||||
* command |
||||
* mysql_db |
||||
* mysql_user |
||||
* file |
||||
* get_url |
||||
* unarchive |
||||
* copy |
||||
* lineinfile |
||||
* replace |
||||
|
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
`install-apache-wordpress-mariadb.yaml` |
||||
```yaml |
||||
- hosts: ansible-2 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_host'] }}" |
||||
- WEB_HOST: "{{ hostvars['ansible-1']['ansible_host'] }}" |
||||
tasks: |
||||
- name: Installation of mariadb-server package |
||||
yum: |
||||
name: mariadb-server |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure mariadb-server is running (and enabled at boot) |
||||
service: |
||||
name: mariadb |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Installation of MySQL-python package |
||||
# package required to use ansible mysql modules |
||||
yum: |
||||
name: MySQL-python |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Create a new database with name '{{ DB_NAME }}' |
||||
mysql_db: |
||||
name: '{{ DB_NAME }}' |
||||
state: present |
||||
|
||||
- name: Create a new database user with name '{{ DB_USER }}' |
||||
mysql_user: |
||||
name: '{{ DB_USER }}' |
||||
password: '{{ DB_PASSWORD }}' |
||||
priv: '{{ DB_NAME }}.*:ALL' |
||||
host: '{{ WEB_HOST }}' |
||||
state: present |
||||
|
||||
- name: Allow mariadb traffic on port 3306 |
||||
firewalld: |
||||
service: mysql |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
|
||||
- hosts: ansible-1 |
||||
vars: |
||||
- DB_NAME: wordpress |
||||
- DB_USER: wordpressuser |
||||
- DB_PASSWORD: "12345" |
||||
- DB_HOST: "{{ hostvars['ansible-2']['ansible_host'] }}" |
||||
tasks: |
||||
- name: Installation of apache package |
||||
dnf: |
||||
name: httpd |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php package |
||||
dnf: |
||||
name: php |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Installation of php-mysqlnd package |
||||
dnf: |
||||
name: php-mysqlnd |
||||
state: present |
||||
update_cache: yes |
||||
notify: Reload Apache |
||||
|
||||
- name: Installation of wget package |
||||
dnf: |
||||
name: wget |
||||
state: present |
||||
update_cache: yes |
||||
|
||||
- name: Ensure apache is running (and enabled at boot) |
||||
service: |
||||
name: httpd |
||||
state: started |
||||
enabled: yes |
||||
|
||||
- name: Download worpress archive |
||||
get_url: |
||||
url: https://wordpress.org/wordpress-5.0.8.tar.gz |
||||
dest: /var/www/html/wordpress.tar.gz |
||||
mode: 0440 |
||||
|
||||
- name: Untar worpress archive |
||||
unarchive: |
||||
src: /var/www/html/wordpress.tar.gz |
||||
dest: /var/www/html |
||||
remote_src: true |
||||
|
||||
- name: Remove wordpress archive |
||||
file: |
||||
path: /var/www/html/wordpress.tar.gz |
||||
state: absent |
||||
|
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file with db name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'database_name_here' |
||||
replace: '{{ DB_NAME }}' |
||||
|
||||
- name: Update wordpress configuration file with user name |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'username_here' |
||||
replace: '{{ DB_USER }}' |
||||
|
||||
- name: Update wordpress configuration file with user password |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'password_here' |
||||
replace: '{{ DB_PASSWORD }}' |
||||
|
||||
- name: Update wordpress configuration file with host |
||||
replace: |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
regexp: 'localhost' |
||||
replace: '{{ DB_HOST }}' |
||||
|
||||
- name: Allow http traffic on port 80 |
||||
firewalld: |
||||
service: http |
||||
permanent: true |
||||
state: enabled |
||||
immediate: yes |
||||
|
||||
handlers: |
||||
- name: Reload Apache |
||||
service: |
||||
name: httpd |
||||
state: restarted |
||||
``` |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : les roles</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-roles.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : les structures de controle</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-structures-de-controle.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,55 @@
|
||||
## TP Structures de contrôle |
||||
|
||||
Utiliser les boucles pour : |
||||
|
||||
1. gérer l'installation des packages, |
||||
|
||||
2. effectuer les modifications sur le fichier de configuration de Wordpress. |
||||
|
||||
|
||||
Installation des packages avec `loop` |
||||
|
||||
```yaml |
||||
- name: Install packages |
||||
yum: |
||||
name: "{{ item }}" |
||||
state: present |
||||
loop: |
||||
- php |
||||
- php-mysql |
||||
- httpd |
||||
``` |
||||
|
||||
Ou en passant une liste au module `yum` |
||||
```yaml |
||||
- name: Install packages |
||||
yum: |
||||
name: |
||||
- php |
||||
- php-mysql |
||||
- httpd |
||||
state: present |
||||
``` |
||||
|
||||
|
||||
Configuration de Wordpress avec `loop` |
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- name: Create wordpress configuration file |
||||
copy: |
||||
src: /var/www/html/wordpress/wp-config-sample.php |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
remote_src: true |
||||
|
||||
- name: Update wordpress configuration file |
||||
replace: |
||||
path: /var/www/html/wordpress/wp-config.php |
||||
regexp: "{{ item.regexp }}" |
||||
replace: "{{ item.replace }}" |
||||
loop: |
||||
- { regexp: 'database_name_here', replace: '{{ DB_NAME }}'} |
||||
- { regexp: 'username_here', replace: '{{ DB_USER }}'} |
||||
- { regexp: 'password_here', replace: '{{ DB_PASSWORD }}'} |
||||
- { regexp: 'localhost', replace: '{{ DB_HOST }}'} |
||||
``` |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible : les templates</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-templates.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • octobre 2018</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,36 @@
|
||||
## TP Structures de contrôle |
||||
|
||||
Utiliser un fichier template pour effectuer la configuration de Wordpress. |
||||
|
||||
|
||||
`templates/wp-config.php.j2` |
||||
```php |
||||
<?php |
||||
... |
||||
define('DB_NAME', '{{ dbname }}'); |
||||
define('DB_USER', '{{ dbuser }}'); |
||||
define('DB_PASSWORD', '{{ dbpassword }}'); |
||||
define('DB_HOST', '{{ dbhost }}'); |
||||
... |
||||
``` |
||||
|
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
```yaml |
||||
- hosts: web |
||||
vars: |
||||
dbname: wordpress |
||||
dbuser: wordpressuser |
||||
dbpassword: wpassword |
||||
dbhost: localhost |
||||
tasks: |
||||
- name: Deploy wordpress config |
||||
template: |
||||
src: templates/wp-config.php.j2 |
||||
dest: /var/www/html/wordpress/wp-config.php |
||||
owner: apache |
||||
group: apache |
||||
mode: 0600 |
||||
``` |
||||
|
||||
Les variables sont automatiquement injectées dans le fichier sur la cible. |
@ -0,0 +1,96 @@
|
||||
<!doctype html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
|
||||
<title>SII - TP Ansible Vault</title> |
||||
<link rel="icon" type="image/png" href="revealjs/images/favicon-logo-sii.png" /> |
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"> |
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
||||
<link rel="stylesheet" href="revealjs/css/reset.css"> |
||||
<link rel="stylesheet" href="revealjs/css/reveal.css"> |
||||
<link rel="stylesheet" href="revealjs/css/theme/sii.css"> <!-- SII theme --> |
||||
|
||||
<!-- Theme used for syntax highlighting of code --> |
||||
<link rel="stylesheet" href="revealjs/lib/css/monokai.css"> |
||||
|
||||
<!-- Specific CSS override to reduce font size and align text on the left --> |
||||
<style> |
||||
.reveal .slides { |
||||
text-align: left; |
||||
} |
||||
|
||||
.columns { |
||||
display: flex; |
||||
} |
||||
|
||||
.columns pre { |
||||
margin-right: 0.5rem; |
||||
} |
||||
</style> |
||||
|
||||
<!-- Printing and PDF exports --> |
||||
<script> |
||||
var link = document.createElement( 'link' ); |
||||
link.rel = 'stylesheet'; |
||||
link.type = 'text/css'; |
||||
link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; |
||||
document.getElementsByTagName( 'head' )[0].appendChild( link ); |
||||
</script> |
||||
|
||||
<!--[if lt IE 9]> |
||||
<script src="lib/js/html5shiv.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
|
||||
<body> |
||||
|
||||
<div class="reveal"> |
||||
<div class="slides"> |
||||
<section data-markdown="tp-ansible-vault.md" |
||||
data-separator="^\n\n\n" |
||||
data-separator-vertical="^\n\n" |
||||
data-separator-notes="^Note:" |
||||
data-charset="UTF-8"> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
|
||||
<script src="revealjs/js/reveal.js"></script> |
||||
|
||||
<script> |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#configuration |
||||
Reveal.initialize({ |
||||
controls: true, |
||||
progress: true, |
||||
center: true, |
||||
hash: true, |
||||
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom |
||||
|
||||
// More info https://github.com/hakimel/reveal.js#dependencies |
||||
dependencies: [ |
||||
{ src: 'revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, |
||||
{ src: 'revealjs/plugin/highlight/highlight.js', async: true }, |
||||
{ src: 'revealjs/plugin/search/search.js', async: true }, |
||||
{ src: 'revealjs/plugin/zoom-js/zoom.js', async: true }, |
||||
{ src: 'revealjs/plugin/notes/notes.js', async: true } |
||||
] |
||||
}); |
||||
|
||||
Reveal.configure({ |
||||
slideNumber: 'c/t' |
||||
}); |
||||
</script> |
||||
|
||||
<img class="logo" src="revealjs/images/logo-sii.svg" /> |
||||
<p class="footer">SII • www.groupe-sii.com • janvier 2019</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,29 @@
|
||||
variables: |
||||
GIT_SUBMODULE_STRATEGY: recursive |
||||
|
||||
stages: |
||||
- build |
||||
|
||||
build: |
||||
stage: build |
||||
image: |
||||
name: astefanutti/decktape:2.11.0 |
||||
entrypoint: [""] |
||||
tags: |
||||
- france |
||||
- sii |
||||
script: |
||||
# |
||||
# 1. We change the size with --size due to a strange rendering bug |
||||
# as decribed here: https://github.com/astefanutti/decktape/issues/151 |
||||
# |
||||
# 2. We also specify --chrome-arg=--disable-web-security to autorize |
||||
# Cross origin requests in chrome as described here: |
||||
# https://github.com/astefanutti/decktape/issues/157 |
||||
# |
||||
- node /decktape/decktape.js --chrome-path chromium-browser --chrome-arg=--no-sandbox --chrome-arg=--disable-web-security --size='1576x1182' index.html speakup-devops.pdf |
||||
artifacts: |
||||
name: speakup-devops |
||||
expire_in: 8 days |
||||
paths: |
||||
- speakup-devops.pdf |
@ -0,0 +1,3 @@
|
||||
[submodule "revealjs"] |
||||
path = revealjs |
||||
url = ../../template-revealjs-sii-theme.git |
@ -0,0 +1,52 @@
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![DevOps](images/devops_refactor.svg) <!-- .element: width="50%" --> |
||||
|
||||
__Introduction au DevOps__ |
||||
|
||||
Alexan Andrieux | Christian Tritten |
||||
|
||||
<small>Speak Up SII - 25 mars 2021</small> |
||||
|
||||
|
||||
<!-- .slide: data-state="medium-code" --> |
||||
|
||||
<div class="columns"> |
||||
|
||||
<div> |
||||
|
||||
## Alexan Andrieux |
||||
|
||||
SII Rennes |
||||
|
||||
Ingénieur DevOps |
||||
</div> |
||||
|
||||
<div> |
||||
|
||||
## Christian Tritten |
||||
|
||||
SII Rennes |
||||
|
||||
Ingénieur DevOps |
||||
</div> |
||||
|
||||
</div> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
## Introduction au DevOps |
||||
|
||||
De quoi on va parler aujourd'hui ? |
||||
|
||||
1. Constats du travail en Silo |
||||
|
||||
2. Le DevOps |
||||
|
||||
3. Les origines du DevOps |
||||
|
||||
4. La pratique du DevOps |
||||
|
||||
5. Mise en place du DevOps |
||||
|
||||
6. Conclusion |
@ -0,0 +1,163 @@
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
## Constats du travail en Silo |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Deux mondes opposés |
||||
|
||||
Dev vs Ops |
||||
|
||||
![versus](images/versus-retro-style.jpg) <!-- .element: width="50%" --> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le monde du Dev |
||||
|
||||
But des développeurs : |
||||
|
||||
- Créer de nouveaux logiciels/librairies |
||||
|
||||
- Développer des nouvelles fonctionnalités |
||||
|
||||
- Améliorer le code existant (performance, élégance, maintenabilité) |
||||
|
||||
- Versionner du code |
||||
|
||||
- Tester facilement |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le monde du Dev |
||||
|
||||
- Organisé en sprint (Agilité) |
||||
|
||||
- Changement fréquent de l'application |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le monde du Dev |
||||
|
||||
Impacts possibles : |
||||
|
||||
- sécurité |
||||
|
||||
- stabilité |
||||
|
||||
- performances |
||||
|
||||
- l'introduction de bug |
||||
|
||||
- mise à jour et/ou réinstallation d'application |
||||
|
||||
- augmentation des ressources systèmes utilisées |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le monde de l'Ops |
||||
|
||||
Objectifs : |
||||
|
||||
- déployer et maintenir des plateformes |
||||
* stables, |
||||
* sécurisées |
||||
* performantes |
||||
|
||||
- administrer facilement les plateformes |
||||
|
||||
- avoir de la visibilité sur les incidents qui surviennent, voire anticiper l'arrivée des incidents (monitoring) |
||||
|
||||
- pouvoir réparer rapidement (procédures) |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le monde de l'Ops |
||||
|
||||
- Généralement organisé via des outils de ticketing (ITIL) |
||||
|
||||
- Tout changement doit être motivé et tamponné (objectif : stabilité) |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le monde de l'Ops |
||||
|
||||
Impacts possibles : |
||||
|
||||
- Manque de réactivité sur les nouvelles demandes |
||||
|
||||
- Contraintes fortes liées à la sécurité |
||||
|
||||
- Peu (voir pas) de retour d'informations vers les Dev |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### En résumé |
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![dzon](images/people_twin.svg) <!-- .element: width="60%" --> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Petites phrases de Devs... |
||||
|
||||
- "Ça marche sur mon poste, donc ça doit fonctionner sur la VM..." |
||||
|
||||
- "Comment ça quelle version de Java ? La dernière…" |
||||
|
||||
- "C’est quoi ton serveur moisi ?" |
||||
|
||||
- "C'est pas mon code le problème, c'est la VM" |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Petites phrases d'Ops |
||||
|
||||
- "Ton code est vraiment tout pourri, c'est pas optimisé !" |
||||
|
||||
- "Pas touche à mes plateformes !" |
||||
|
||||
- "C'est pas la VM le problème, c'est ton application" |
||||
|
||||
- "On ne peut pas faire confiance aux Devs !" |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
Constat n°1 : Le monde du dev ne comprend pas le monde de l'ops. |
||||
|
||||
![wall](images/wallofconfusion.svg) <!-- .element: width="50%" --> |
||||
|
||||
Constat n°2 : Le monde de l'ops ne comprend pas le monde du dev. |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Mise en lumière des problèmes avec l'Agilité |
||||
|
||||
- 2 semaines d'intégration tous les 6 mois, ce n'est pas choquant |
||||
|
||||
- 2 semaines d'intégration toutes les 2 semaines (sprint) ça commence à devenir problématique |
||||
|
||||
- On veut que lorsque la user story est finie, qu'elle soit vraiment finie ! |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Mise en lumière des problèmes avec l'ITIL |
||||
|
||||
- Il peut se passer (très) longtemps entre le commit et le déploiement en production |
||||
|
||||
- La mise en production est un réel événement |
||||
|
||||
- La mise en production sollicite un grand nombre de personnes |
@ -0,0 +1,156 @@
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
## Le DevOps |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Ce que n'est pas le DevOps |
||||
|
||||
- une nouvelle technologie |
||||
|
||||
- un nouveau métier ou nouvelle fonction dans l’entreprise |
||||
|
||||
- une personne |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Une petite définition DevOps |
||||
|
||||
>Le DevOps est une démarche visant l'adoption d'une _même culture dev et ops_ autour de méthodologies de travail et d'outils dans le but commun d'une _amélioration continue_ : |
||||
* de la productivité |
||||
* de la stabilité des process de développement (ci), |
||||
* de la qualité, |
||||
* et de la mise en production. |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
Il y a souvent une confusion entre __culture__ et __profil__ DevOps |
||||
|
||||
Le DevOps est une __culture__. |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le But |
||||
|
||||
Le DevOps veut réconcilier ces deux mondes pour les faire travailler ensemble dans le but d'améliorer : |
||||
|
||||
- le Time To Market (TTM) |
||||
|
||||
- la qualité des développements |
||||
|
||||
- la fiabilité des déploiements |
||||
|
||||
![collaborate](images/collaborate.svg) <!-- .element: width="30%" --> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Les Concepts |
||||
|
||||
Le DevOps se base sur le modèle **CALMS** : |
||||
- **C** ulture commune |
||||
|
||||
- **A** utomatisation des tâches répétitives |
||||
|
||||
- **L** ean <small>(Amélioration Continue)</small> |
||||
|
||||
- **M** esure |
||||
|
||||
- **S** olidarité et partage |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### CALMS - la Culture |
||||
|
||||
- Favorise la communication |
||||
|
||||
- Réduit les incompréhensions |
||||
|
||||
- Permet de mener un changement d'organisation et/ou de méthodologie |
||||
|
||||
- Entretien l'esprit d'équipe et la motivation |
||||
|
||||
- La productivité |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### CALMS - l'Automatisation |
||||
|
||||
- Automatiser tout ce qui peut l'être |
||||
<small>Builds • Tests • Packaging • Cloud • Déploiements • Configuration • Chaos monkey</small> |
||||
|
||||
- Assure la reproductibilité des actions |
||||
|
||||
- Apporte de la traçabilité |
||||
|
||||
- Évite les erreurs humaines |
||||
|
||||
- Augmente la productivité |
||||
|
||||
- Libère du temps pour les tâches à plus fortes valeurs ajoutées |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### CALMS - le Lean |
||||
|
||||
- C'est une théorie de gestion inventée par Toyota |
||||
|
||||
- Vise une recherche constante de la performance et de la qualité |
||||
|
||||
Le __Lean__ permet de : |
||||
|
||||
- supprimer les éléments inutiles et/ou complexes |
||||
|
||||
- trouver des solutions d'amélioration |
||||
|
||||
- résoudre les problèmes et d'en tirer les enseignements |
||||
|
||||
- produire "juste ce qu'il faut" "juste à temps" |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### CALMS - la Mesure |
||||
|
||||
- Identification des problèmes, des points d'améliorations, |
||||
mais aussi des réussites |
||||
|
||||
- Identification des ressources utilisées, de la stabilité globale d'une plateforme |
||||
|
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### CALMS - la Solidarité |
||||
|
||||
- Favorise la collaboration |
||||
|
||||
- Favorise l'esprit d'équipe |
||||
|
||||
- Amélioration du bien-être des personnes |
||||
|
||||
- Amélioration de la productivité |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### CALMS - le Partage |
||||
|
||||
- De l'information |
||||
|
||||
- Des échecs et succès (rétros) |
||||
|
||||
- Des responsabilités |
||||
|
||||
- Des visions (opérationnelle, stratégique) |
||||
|
||||
- Des techniques (outillage) |
||||
|
||||
- Des expériences |
@ -0,0 +1,83 @@
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
## Les origines du DevOps |
||||
|
||||
Le DevOps s'est essentiellement construit autour de l'_Agilité_ et du _Lean_. |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### L'Agilité |
||||
|
||||
- Méthodes pour répondre au besoin : __comment s'organiser pour développer des produits complexes ?__ |
||||
- Organisation en **Sprint** |
||||
|
||||
![agilecycle](images/cycle_agile.svg) <!-- .element: width="100%" --> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### L'Agilité : 4 valeurs |
||||
|
||||
- La cohésion d'équipe |
||||
|
||||
- La production d'application fonctionnelle |
||||
|
||||
- La collaboration avec le client |
||||
|
||||
- L'acceptation du changement |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### L'Agilité : 12 principes |
||||
|
||||
![principeagile](images/principes_agile.svg) <!-- .element: width="70%" --> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Emprunts du DevOps à l'agilité |
||||
|
||||
- Cohésion et Communication |
||||
<small>(entre développeur et opérationnel)</small> |
||||
|
||||
- Collaboration |
||||
<small>(développeur, opérationnel, business, client, ...)</small> |
||||
|
||||
- Livraisons rapides et régulières |
||||
<small>(jusqu'à la mise en production)</small> |
||||
|
||||
- Confiance et bienveillance |
||||
|
||||
- Réactivité au changement |
||||
|
||||
- Satisfaction client |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le Lean Management du monde industriel |
||||
|
||||
- Repose sur 5 grands principes (5P) |
||||
|
||||
![5Plean](images/lean.svg) <!-- .element: width="30%" --> |
||||
|
||||
- `Produit` <small>- conception au plus juste d’un produit (MVP = Minimum Valuable Product).</small> |
||||
- `Process` <small>- automatiser les tâches répétitives, amélioration continue</small> |
||||
- `Personnel` <small>- autonomie et efficacité dans le travail</small> |
||||
- `Performance` <small>- mesurer le progrès et combattre inefficacité</small> |
||||
- `Pilotage` <small>- logique de flux tiré (juste à temps), niveller la production (juste ce qu'il faut)</small> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Emprunts du DevOps au Lean |
||||
|
||||
- Automatisation des tâches répétitives |
||||
|
||||
- Amélioration continue |
||||
|
||||
- Mesure des difficultés et des progrès |
||||
|
||||
- Efficacité dans le travail |
@ -0,0 +1,66 @@
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
## La pratique du Devops |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### La démarche |
||||
|
||||
La démarche DevOps, c'est l'Agilité et l'amélioration continue |
||||
de bout en bout : |
||||
|
||||
![devops_scope](images/devops-scope.svg) <!-- .element: width="150%" --> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### La démarche |
||||
|
||||
Comparaison avec d'autres méthodologies : |
||||
|
||||
![demarche](images/waterfall_agile_devops.svg) <!-- .element: width="90%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Cycle Agile VS Cycle DevOps |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
|
||||
![cycle_agile](images/cycle_agile.svg) <!-- .element: width="90%" --> |
||||
|
||||
![cycle_devops](images/devops-toolchain-refactor.svg) <!-- .element: width="45%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### L'outillage |
||||
<!-- .slide: data-state="nologo-slide" --> |
||||
- `Plan` (Amélioration Continue) |
||||
![confluence](images/confluence.png)<!-- .element: width="50px" height="50px" --> ![trello](images/trello.png)<!-- .element: width="70px" height="50px" --> ![gitlab](images/gitlab.jpeg)<!-- .element: width="50px" height="50px" --> |
||||
- `Code` |
||||
![vscode](images/vscode.jpeg)<!-- .element: width="50px" height="50px" --> ![github](images/github.png)<!-- .element: width="50px" height="50px" --> ![gitlab](images/gitlab.jpeg)<!-- .element: width="50px" height="50px" --> |
||||
- `Build` (Intégration Continue) |
||||
![jenkins](images/jenkins.png)<!-- .element: width="50px" height="50px" --> ![travis](images/travis.png)<!-- .element: width="50px" height="50px" --> ![gitlab](images/gitlab.jpeg)<!-- .element: width="50px" height="50px" --> |
||||
- `Test` (Intégration Continue) |
||||
![selenium](images/selenium.png)<!-- .element: width="40px" height="40px" --> ![sonar](images/sonar.png)<!-- .element: width="70px" height="50px" --> ![checkmark](images/checkmarx.png)<!-- .element: width="70px" height="50px" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### L'outillage (suite) |
||||
- `Release` (Livraison Continue) |
||||
![jenkins](images/jenkins.png)<!-- .element: width="50px" height="50px" --> ![travis](images/travis.png)<!-- .element: width="50px" height="50px" --> ![gitlab](images/gitlab.jpeg)<!-- .element: width="50px" height="50px" --> |
||||
- `Deployment` (Déploiment continu) |
||||
![puppet](images/puppet.png)<!-- .element: width="70px" height="30px" --> ![ansible](images/ansible.png)<!-- .element: width="50px" height="50px" --> ![k8s](images/kubernetes.png)<!-- .element: width="70px" height="70px" --> |
||||
- `Operate` (Déploiment continu) |
||||
![bash](images/bash.png)<!-- .element: width="50px" height="40px" --> ![terraform](images/terraform.png)<!-- .element: width="60px" height="60px" --> ![k8s](images/kubernetes.png)<!-- .element: width="70px" height="70px" --> |
||||
- `Monitor` (Amélioration Continue) |
||||
![kibana](images/kibana.jpeg)<!-- .element: width="60px" height="50px" --> ![grafana](images/grafana.jpeg)<!-- .element: width="50px" height="50px" --> ![prometheus](images/prometheus.jpeg)<!-- .element: width="60px" height="50px" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### L'outillage |
||||
|
||||
![xebialab](images/periodic_table_devops.png) |
@ -0,0 +1,101 @@
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
## Mise en place du Devops |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
### DevOps et organisation |
||||
|
||||
- Il n'existe pas de système d'organisation universel |
||||
pour mettre en place le DevOps |
||||
|
||||
- Vous seul pouvez définir ce que DevOps signifie pour vous |
||||
|
||||
- Le DevOps ne se résume pas uniquement à l'automatisation via des outils |
||||
|
||||
- La démarche implique un changement de paradigme |
||||
<small>(modèle orienté projet => modèle orienté produit)</small> |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
### La Finalité |
||||
|
||||
- La transmission du savoir-faire |
||||
|
||||
- Meilleur usage des infrastructures |
||||
|
||||
- Simplicité |
||||
|
||||
- Satisfaction client |
||||
|
||||
- Réduction du TTM |
||||
|
||||
- La mise en production doit devenir un non-évènement |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
### Les clefs du succès |
||||
|
||||
- Apporter de l'énergie, proactivité et désir de connaissances |
||||
|
||||
- Favoriser le travail d'équipe, se faire confiance, être bienveillant, se laisser le droit à l'erreur |
||||
|
||||
- Partager les responsabilités, les problématiques, les succès et les échecs |
||||
|
||||
- Optimiser l'environnement de travail pour favoriser le bien être et la productivité |
||||
|
||||
- Encourager un management plus transparent |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Anti patterns |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Equipe Dev sans les Ops |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![team_without_ops](images/devops-topologies-anti-type-c-dev-don-t-need-ops.svg) <!-- .element: width="70%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Equipe Sysadmin avec un autre nom |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![team_rename](images/devops-topologies-anti-type-e-rebranded-sysadmin.svg) <!-- .element: width="70%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Equipe DevOps en silo |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![team_silo](images/devops-topologies-anti-type-b-devops-team-silo.svg) <!-- .element: width="70%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Patterns |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Collaboration Dev et Ops |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![team_collaborate](images/devops-topologies-type-1-dev-and-ops-collaboration.svg) <!-- .element: width="60%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Partage complet des responsabilités |
||||
### entre Dev et Ops |
||||
|
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![team_shared_responsability](images/devops-topologies-type-2-fully-shared-ops-responsabilities.svg) <!-- .element: width="40%" --> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Evangélisation Devops |
||||
<!-- .slide: data-state="nologo-slide" style="text-align: center" --> |
||||
![team_evangelist](images/devops-topologies-type-6-devops-evangelists-team.svg) <!-- .element: width="70%" --> |
@ -0,0 +1,80 @@
|
||||
## Conclusion |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Le DevOps implique |
||||
|
||||
- une nouvelle façon de travailler ensemble |
||||
|
||||
- une nouvelle organisation |
||||
|
||||
- l'utilisation d'outils adaptés aux besoins |
||||
|
||||
- de l'ouverture d'esprit, de la remise en question et éventuellement de la formation des équipes |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Pour le mettre en place, il faut |
||||
|
||||
- une conduite du changement pour faire évoluer les comportements et les mentalités |
||||
|
||||
- redéfinir le rythme via de nouveaux rituels en se basant par exemple sur l'Agilité |
||||
|
||||
- tout le monde doit être acteur de la transformation (dev, ops, manager, métier, ...) |
||||
|
||||
- ne pas avoir peur de l’échec, appendre de ces erreurs et s'améliorer en continue |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### DevOps et au-delà... |
||||
|
||||
- DevSecOps |
||||
|
||||
- SRE (Site Reliability Engineering) |
||||
|
||||
|
||||
<img src="images/alexan.jpg" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Meetups |
||||
|
||||
- Devops Container: |
||||
<small>https://www.meetup.com/fr-FR/devops-containers/</small> |
||||
- Docker Paris: |
||||
<small>https://www.meetup.com/fr-FR/Docker-Paris/</small> |
||||
- Git Paris: |
||||
<small>https://www.meetup.com/fr-FR/git-Paris/</small> |
||||
- Kubernetes Paris: |
||||
<small>https://www.meetup.com/fr-FR/Kubernetes-Paris/</small> |
||||
- CNCF Paris: |
||||
<small>https://community.cncf.io/paris/</small> |
||||
- Rennes Devops: |
||||
<small>https://www.meetup.com/fr-FR/rennes-devops/</small> |
||||
- Nantes Devops: |
||||
<small>https://www.meetup.com/fr-FR/Nantes-DevOps/?_locale=fr-FR</small> |
||||
|
||||
|
||||
<img src="images/chris.png" width="30px" style="position: fixed; right: 0" /> |
||||
|
||||
### Liens utiles: |
||||
|
||||
- Blog tech de la communauté DevOps: |
||||
<small>https://sii-ouest.gitlab.io/devops/blog/articles/demystfication-du-devops/item/</small> |
||||
- Blog tech et formation: |
||||
<small>https://enix.io/</small> |
||||
- Tuto de Xavki: |
||||
<small>https://xavki.blog/</small> |
||||
- Podcast des compagnons du DevOps et de radio DevOps: |
||||
<small>https://lydra.fr/blog/</small> |
||||
- Podcast et interview de Dev’Obs: |
||||
<small>https://devobs.p7t.tech/</small> |
||||
- Interview tech de Electro Monkeys: |
||||
<small>https://podcast.electro-monkeys.fr/</small> |
||||
- Les vidéos DevOps et tech de Krustyhack: |
||||
<small>https://www.youtube.com/channel/UCM0mnsNbecIi_IAPXtHb-TA</small> |
||||
|
||||
|
||||
|
||||
## Des questions ? |
@ -0,0 +1,8 @@
|
||||
FROM nginx:1.12.2 |
||||
LABEL "com.example.vendor" = "SII Ouest" |
||||
LABEL version="1.0" |
||||
LABEL description="Speakup Devops" |
||||
LABEL maintainer="abegou@sii-ouest.com" |
||||
|
||||
#COPY SOURCES FILES |
||||
COPY ./ /usr/share/nginx/html |
@ -0,0 +1,10 @@
|
||||
# DevOps |
||||
|
||||
La vision du DevOps par SII. |
||||
|
||||
## Jouer les slides en local |
||||
|
||||
1. Cloner le dépôt : |
||||
`git clone --recurse-submodules https://gitlab.siinergy.net/sii-ouest/dejtechs/devops` |
||||
|
||||
2. Dans Firefox ouvrir le fichier `index.html` |
After Width: | Height: | Size: 16 KiB |