--- title: Fiche Aide Ansible author: Rémi Maubanc tags: CGI --- Fiche Aide Ansible === ## Ansible Playbook ### Configuration des hotes #### Ajout des clés SSH sur les clients Génération d'une clé SSH : ```bash ssh-keygen -t rsa -b 4096 -f .ssh/ansible_master ``` Voir le [tutoriel](https://wiki-prog.infoprepa.epita.fr/index.php/Practical_GIT.html) Ajout de la clé sur un client : ```bash ssh-copy-id -i .ssh/ansible_master root@192.168.1.1 ssh-copy-id -i .ssh/ansible_master hyperion@192.168.1.2 ``` Commande de tests ``` ssh root@192.168.1.1 ^D ssh hyperion@192.168.1.2 ^D ``` Si l'injection a fonctionné, on n'a pas besoin de taper de mot de passe pour se connecter Malgré que le compte soit dans le groupe sudo, il nécessite toujours de taper un mot de passe pour Les commandes nécessitant une élévation de privilège. Pour la retirer, il faut : `sudo visudo` ```git - %sudo ALL=(ALL:ALL) ALL + %sudo ALL=(ALL:ALL) NOPASSWD: ALL ``` #### Inventaire des clients Fichier par défaut du système : */etc/ansible/hosts* ```yaml [mes_servers] # Pas d'espace entre le texte et les crochets 192.168.1.1 ansible_user=root # Pour préciser à Ansible l'utilisateur à utiliser 192.168.1.2 ``` Fichier d'inventaire par projet : [ A compléter ] ### Liste des commandes ansible basiques #### Réalisation d'un ping Réaliser un ping sur tous les clients ```bash ansible all -m ping ``` | Option | Arguments | Description | |--------|-----------|---------------------------------------------------| | -m | ping | Charge le module en argument | | None | all | Selectionne toutes les IP du fichier d'inventaire | #### Récupération de la configuration ```bash ansible 192.168.1.1 -m setup -a "filter=*python*" ``` | Option | Arguments | Description | |--------|---------------------|----------------------------------------------| | None | 192.168.1.1 | IP du client à utiliser | | -m | setup | Charge le module `shell` | | -a | "filter=\*python\*" | Filtre les résultats en fonction de leur clé | #### Elevation de privilège ```bash ansible 192.168.1.1 -m shell -a "fdisk -l" -b -K ``` | Option | Arguments | Description | |--------|-------------|-----------------------------------------| | None | 192.168.1.1 | IP du client à utiliser | | -m | shell | Charge le module `shell` | | -b | None | Elevation de privilège sudo | | -K | None | Demande le mot de passe sudo dans stdin | **Note :** Eviter les modules *shell* et *raw* dans les playbooks car ils ne sont pas idempotents #### Envoyer un fichier ```bash # Création d'un fichier pour le test echo "Hello World!" > test.txt ansible all -m copy -a "src=test.txt dest=/home/hyperion/ansible owner=hyperion mode=0644" ``` | Option | Arguments | Description | |--------|--------------------|----------------------------------------------------------| | None | all | Utilise toutes les IP présentes dans l'inventaire | | -m | copy | Charge le module `copy` pour la copie de fichier | | -a | "src=test.txt ..." | Précise les paramètres de commande pour le module | #### Recevoir un fichier ```bash ansible all -m fetch -a "src=/etc/passwd dest=/tmp flat=yes" ls /tmp # Une copie du fichier passwd doit se trouver dans le /tmp du master ``` | Option | Arguments | Description | |--------|--------------------|----------------------------------------------------------| | None | all | Utilise toutes les IP présentes dans l'inventaire | | -m | fetch | Charge le module `fetch` pour télécharger des fichiers | | -a | "src=test.txt ..." | Précise les paramètres de commande pour le module | ### Installation packages Ouvrir le port HTTP pour nginx : [article](https://www.thegeekdiary.com/how-to-open-a-ports-in-centos-rhel-7/) + ajouter nginx dans le fichier */etc/services* aux lignes commencant par http: ```bash - http 80/tcp www www-http # WorldWideWeb HTTP - http 80/udp www www-http # HyperText Transfert Protocol + http 80/tcp www www-http nginx # WorldWideWeb HTTP + http 80/udp www www-http nginx # HyperText Transfert Protocol ``` :::danger => Problème rencontré pour le Lab4 de la formation Ansible ::: Installation de nginx dans deux clients (Debian et Centos 7) Dans un fichier playbook *nginx.yml* ```yaml --- - name: Nginx server installed hosts: demoservers become: yes tasks: - name: Add epel-release repo yum: name: epel-release state: present when: ansible_facts['os_family'] == "RedHat" - name: latest Nginx version installed Centos yum: name: nginx state: present when: ansible_facts['os_family'] == "RedHat" - name: latest Nginx version installed Debian apt: name: nginx state: latest when: ansible_facts['os_family'] == "Debian" - name: Nginx enable and running Centos service: name: nginx enabled: true state: started when: ansible_facts['os_family'] == "RedHat" - name: Add nginx index template copy: src: index.html dest: /var/www/html/ when: ansible_facts['os_family'] == "Debian" - name: Nginx enable and running Debian systemd: name: nginx enabled: true state: started when: ansible_facts['os_family'] == "Debian" ``` OS_Family vs Distribution : [Lien Article](https://techviewleo.com/list-of-ansible-os-family-distributions-facts/) ### Gestion des variables Les variables peuvent être définies de deux manières: - Directement dans le fichier ```yaml vars: user: admin group: wheel ``` - Dans un fichier séparé ```yaml # Fichier dédié --- user: admin group: wheel ``` ```yaml # Dans le fichier principal vars_files: - vars/users.yml ``` Arborescence du projet : ``` |- webserver.yml |- group_vars |- demoservers # Un groupe d'hotes défini dans l'inventaire |- host_vars |- 192.168.1.1 # Un hote existant dans l'inventaire |- html |- dev_index.html |- prod_index.html ``` *webserver.yml* ```yaml --- - name: Copy index.html hosts: demoservers become: yes tasks: - name: copy right index.html copy: src: "html/{{ stage }}_index.html" dest: /var/www/html/index.html ``` *group_vars/demoservers* ```yaml --- stage: dev ``` *host_vars/192.168.1.1* ```yaml --- stage: prod ``` ### Valeur de retour [Documentation](https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html) Dans le playbook : ```yaml --- - name: Installs a package and prints the result hosts: dbservers become: True tasks: - name: Install the package yum: name: git state: present update_cache: yes register: install_result # Récupération du stdout - debug: var=install_result.result ``` :::info `install_result` est un dictionnaire et peut être déréférencé. ::: ### Valeur dans le playbook ```yaml --- - name: Create users hosts: all become: yes vars: user: admin group: wheel homedir: /dev/null shell: /bin/false tasks: - user: name: "{{ user }}" # Avec ou sans espace entre la variable et les accolades group: "{{ group }}" home: "{{ homedir }}" shell: "{{ shell }}" ``` ### Utilisation des facts ```yaml --- - name: Output facts within a playbook hosts: webservers tasks: - name: Prints Ansible facts debug: msg: The default IPv4 address of {{ ansible_fqdn }} is {{ ansible_enp0s3.ipv4.address }} ``` ```bash ok: [192.168.1.1] => { "msg": "The default IPv4 address of debian is 192.168.1.1" } ok: [192.168.1.2] => { "msg": "The default IPv4 address of localhost.localdomain is 192.168.1.Z" } ``` ### Les boucles ```yaml --- - name: Loop demo hosts: 192.168.1.92 vars: check_services: - nginx - sshd tasks: - name: Check if service is started service: name: "{{ item }}" state: started loop: "{{ check_services }}" # Iteration sur chaque élement ``` ### Conditions multiples ```yaml --- - name: MySQL server installation hosts: all become: yes tasks: - name: Install latest MySQL server when host RAM greater than 1 GB with YUM yum: name: mysql-server state: latest when: ansible_facts['os_family'] == "RedHat" and ansible_memtotal_mb > 1024 - name: Install latest MySQL server when host RAM greater than 1 GB with APT apt: name: mysql-server state: latest when: ansible_facts['os_family'] == "Debian" and ansible_memtotal_mb > 1024 ``` ### Handlers/Trigger ```yaml --- - name: Manage Nginx hosts: 192.168.1.57 become: yes tasks: - name: Copy Nginx configuration file copy: src: conf/default.conf dest: /etc/nginx/sites-enabled/ notify: - restart_nginx # Si l'état est "changed", le handler sera appelé handlers: - name: restart_nginx service: name: nginx state: restarted ``` ### Les templates *test_server.yml* ```yaml --- - hosts: demoservers gather_facts: yes become: yes tasks: - name: Install index.html template: src: html/index.html.j2 dest: /var/www/html/index.html mode: 0644 ``` *html/index.html.j2* ```html <html> <h1>Hostname: {{ ansible_fqdn | default('undefined') }}</h1> <center> <ul> <li>System : {{ ansible_os_family | default ('linux') }}</li> <li>Type : {{ stage | upper }}</li> <li>Stage : {{ stage | replace("prod", "Production") | replace("dev", "Development" }}</li> </ul> </center> </html> ``` [Documentation Jinja2](https://jinja.palletsprojects.com/en/2.10.x/templates/) ## Ansible Galaxy ### Création d'un role ```bash ansible-galaxy init nginx ``` Cette commande génère une arborescence de dossier de fichier à la manière de `django startapp nginx` avec les structures essentielles à la déclaration d'un rôle ```bash ├── nginx │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ ├── tests │ │ ├── inventory │ │ └── test.yml │ └── vars | └── main.yml ```