diff --git a/docs/books/admin_guide/00-toc.pt.md b/docs/books/admin_guide/00-toc.pt.md new file mode 100644 index 0000000000..f2fdb5b5cf --- /dev/null +++ b/docs/books/admin_guide/00-toc.pt.md @@ -0,0 +1,27 @@ +--- +title: Aprendendo Linux com Rocky +--- + +# Aprendendo Linux com Rocky + +O Guia da Administração é uma coleção de Documentos de Ensino para Administradores do Sistema. Esses documentos podem ser usados por futuros administradores do sistema que tentam aprimorar seu aprendizado rapidamente, pelos atuais administradores do sistema que gostariam de se atualizar, ou por qualquer usuário do Linux que gostaria de aprender mais sobre o ambiente do Linux, comandos, processos e muito mais. Como todos os documentos desse tipo, ele será incrementado e atualizado ao longo do tempo. + +Inicialmente, discutiremos Linux, distribuições e todo o ecossistema em torno do nosso sistema operacional. + +Em seguida, vamos ver os comandos do usuário que são essenciais para acelerar o aprendizado com Linux. Os usuários mais experientes devem também consultar o capítulo dedicado aos "comandos avançados". + +O Capítulo seguinte trata sobre o editor de texto VI. Embora o Linux venha com muitos editores, VI é um dos mais poderosos. Outros comandos às vezes usam sintaxes idênticas(`sed` ou similares) aos comandos do VI . Portanto, saber algo sobre o VI, ou ao menos desmistificar suas funções essenciais (como abrir um arquivo, salvar, sair e salvar ou sair sem salvar) é muito importante. O usuário ficará mais confortável com as funções do VI a medida que usa o editor. Uma alternativa seria usar o editor de texto nano que vem instalado por padrão no Rocky Linux. Embora não seja versátil, é simples de usar, direto e supre as necessidade do trabalho a ser feito. + +Em seguida, podemos entrar no funcionamento mais profundo do Linux para compreender como o sistema funciona: + +* Usuários; +* Sistemas de Arquivos; +* Processos. + +Em seguida, abordaremos um assunto essencial para o Administrador do Sistema: O Processo de Backup. Muitas soluções de software vêm com Linux para melhorar o backup (rsnapshot, lsyncd, etc). É bom conhecer os componentes essenciais do processo de backup que estão dentro do sistema operacional. Neste capítulo vamos estudar duas ferramentas: `tar` e o menos conhecido `cpio`. + +A gestão do sistema durante o processo de inicialização evoluiu significativamente nos últimos anos, desde a chegada do systemd. + + +Concluiremos analisando a gestão de tarefas, a implementação da rede e a instalação de software. + diff --git a/docs/books/admin_guide/00-toc.zh.md b/docs/books/admin_guide/00-toc.zh.md index ffec45f059..69939064be 100644 --- a/docs/books/admin_guide/00-toc.zh.md +++ b/docs/books/admin_guide/00-toc.zh.md @@ -10,7 +10,7 @@ title: 使用 Rocky 学习 Linux 然后,我们将了解掌握Linux所必需的用户命令。 经验更丰富的用户还应查阅专门介绍更"高级"的"命令"章节 -接下来是关于 VI 编辑器的章节。. 虽然Linux附带了许多编辑器,但VI是最强大的编辑器之一。 其他命令有时使用与VI相同的语法(想起了`sed`)。 因此,了解一些关于VI的知识,或者至少了解其基本功能(如何打开文件、保存、退出或不保存而退出),是非常重要的。 用户在使用编辑器的过程中,会对VI的其他功能更加熟悉。 另一种选择是使用默认安装在Rocky Linux中的nano, 虽然功能不多,但它使用简单、直观,并且能完成工作。 +接下来是关于 VI 编辑器的章节。 虽然Linux附带了许多编辑器,但VI是最强大的编辑器之一。 其他命令有时使用与VI相同的语法(想起了`sed`)。 因此,了解一些关于VI的知识,或者至少了解其基本功能(如何打开文件、保存、退出或不保存而退出),是非常重要的。 用户在使用编辑器的过程中,会对VI的其他功能更加熟悉。 另一种选择是使用默认安装在Rocky Linux中的nano, 虽然功能不多,但它使用简单、直观,并且能完成工作。 接着,我们可以深入了解Linux的深层功能,以了解系统是如何管理的: diff --git a/docs/books/admin_guide/04-advanced-commands.fr.md b/docs/books/admin_guide/04-advanced-commands.fr.md index 6221e700a4..2e2174d32d 100644 --- a/docs/books/admin_guide/04-advanced-commands.fr.md +++ b/docs/books/admin_guide/04-advanced-commands.fr.md @@ -1,32 +1,32 @@ --- -title: Advanced Linux Commands +title: Commandes avancées Linux --- -# Advanced Commands for Linux users +# Commandes avancées pour utilisateurs Linux -In this chapter you will learn some advanced commands for Linux. +Dans ce chapitre, vous apprendrez quelques commandes avancées pour Linux. **** -**Objectives** : In this chapter, future Linux administrators will learn: +**Objectifs** : Dans ce chapitre, les futurs administrateurs Linux vont apprendre : -:heavy_check_mark: some useful commands not covered in the previous chapter; -:heavy_check_mark: some advanced commands. +:heavy_check_mark: quelques commandes utiles non couvertes dans le chapitre précédent ; +:heavy_check_mark: quelques commandes avancées. -:checkered_flag: **user commands**, **Linux** +:checkered_flag: **commandes utilisateurs**, **Linux** -**Knowledge**: :star: -**Complexity**: :star: :star: :star: +**Connaissances : ** :star: +**Complexité : ** :star: :star: :star: **Temps de lecture : **20 minutes **** -## `uniq` command +## La commande `uniqu` -The `uniq` command is a very powerful command, used with the `sort` command, especially for log file analysis. It allows you to sort and display entries by removing duplicates. +La commande `uniq` est une commande, utilisée avec la commande `sort`, très puissante, notamment pour l’analyse de fichiers de logs. Elle permet de trier et d’afficher des entrées en supprimant les doublons. -To illustrate how the `uniq` command works, let's use a `firstnames.txt` file containing a list of first names: +Pour illustre le fonctionnement de la commande `uniq`, utilisons un fichier `firstnames.txt` contenant une liste de prénoms : ``` antoine @@ -39,9 +39,9 @@ antoine steven ``` -!!! abstract Note `uniq` requires the input file to be sorted because it only compares consecutive lines. +!!! Note `uniq` réclame que le fichier d’entrée soit trié car il ne compare que les lignes consécutives. -Without an argument, the `uniq` command will not display identical lines that follow each other in the `firstnames.txt` file: +Sans argument, la commande `uniq` ne va pas afficher les lignes identiques qui se suivent du fichier `firstnames.txt` : ``` $ sort firstnames.txt | uniq @@ -51,14 +51,14 @@ steven xavier ``` -To display only the rows that appear only once, use the `-u` option: +Pour n’afficher que les lignes n’apparaissant qu’une seule fois, il faut utiliser l’option `-u` : ``` $ sort firstnames.txt | uniq -u patrick ``` -Conversely, to display only the lines that appear at least twice in the file, you must use the `-d` option: +À l’inverse, pour n’afficher que les lignes apparaissant au moins deux fois dans le fichier, il faut utiliser l’option `-d` : ``` $ sort firstnames.txt | uniq -d @@ -67,7 +67,7 @@ steven xavier ``` -To simply delete lines that appear only once, use the `-D` option: +Pour simplement supprimer les lignes qui n’apparaissent qu’une seule fois, il faut utiliser l’option `-D` : ``` $ sort firstnames.txt | uniq -D @@ -80,7 +80,7 @@ xavier xavier ``` -Finally, to count the number of occurrences of each line, use the `-c` option: +Enfin, pour compter le nombre d’occurrences de chaque ligne, il faut utiliser l’option `-c` : ``` $ sort firstnames.txt | uniq -c @@ -97,13 +97,13 @@ $ sort firstnames.txt | uniq -cd 2 xavier ``` -## `xargs` commands +## La commande `xargs` -The `xargs` command allows the construction and execution of command lines from standard input. +La commande `xargs` permet la construction et l’exécution de lignes de commandes à partir de l’entrée standard. -The `xargs` command reads whitespace or linefeed delimited arguments from standard input, and executes the command (`/bin/echo` by default) one or more times using the initial arguments followed by the arguments read from standard input. +La commande `xargs` lit des arguments délimités par des blancs ou par des sauts de ligne depuis l’entrée standard, et exécute une ou plusieurs fois la commande (`/bin/echo` par défaut) en utilisant les arguments initiaux suivis des arguments lus depuis l’entrée standard. -A first and simplest example would be the following: +Un premier exemple le plus simple possible serait le suivant : ``` $ xargs @@ -114,16 +114,16 @@ xargs use of xargs ``` -The `xargs` command waits for an input from the standard **stdin** input. Three lines are entered. The end of the user input is specified to `xargs` by the keystroke sequence CTRL+D. `xargs` then executes the default command `echo` followed by the three arguments corresponding to the user input, namely : +La commande `xargs` attend une saisie depuis l’entrée standard **stdin**. Trois lignes sont saisies. La fin de la saisie utilisateur est spécifiée à `xargs` par la séquence de touches CTRL + D. `xargs` exécute alors la commande par défaut `echo` suivi des trois arguments correspondants à la saisie utilisateur, soit : ``` $ echo "use" "of" "xargs" use of xargs ``` -It is possible to specify a command to be run by `xargs`. +Il est possible de spécifier une commande à lancer par `xargs`. -In the following example, `xargs` will run the command `ls -ld` on the set of folders specified in the standard input: +Dans l’exemple qui suit, `xargs` va exécuter la commande `ls -ld` sur l’ensemble des dossiers qui seront spécifiés depuis l’entrée standard : ``` $ xargs ls -ld @@ -136,9 +136,9 @@ dr-xr-x---. 2 root root 4096 5 avril 15:52 /root drwxrwxrwt. 3 root root 4096 6 avril 10:25 /tmp ``` -In practice, the `xargs` command executed the `ls -ld /home /tmp /root` command. +En pratique, la commande `xargs` a exécuté la commande `ls -ld /home /tmp /root`. -What happens if the command to be executed does not accept multiple arguments as is the case with the `find` command? +Que se passe-t-il si la commande à exécuter n’accepte pas plusieurs arguments comme c’est le cas pour la commande `find` ? ``` $ xargs find /var/log -name @@ -147,14 +147,14 @@ $ xargs find /var/log -name find: paths must precede expression: *.log ``` -The `xargs` command attempted to execute the `find` command with multiple arguments behind the `-name` option, which caused `find` to generate an error: +La commande `xargs` a tenté d’exécuter la commande `find` avec plusieurs arguments derrière l’option `-name`, ce qui fait généré par `find` une erreur : ``` $ find /var/log -name "*.old" "*.log" find: paths must precede expression: *.log ``` -In this case, the `xargs` command must be forced to execute the `find` command several times (once per line entered as standard input). The `-L` option followed by an **integer** allows you to specify the maximum number of entries to be processed with the command at one time: +Dans ce cas, il faut forcer la commande `xargs` à exécuter plusieurs fois (une fois par ligne saisie en entrée standard) la commande `find`. L’option `-L `suivie d’un nombre **entier** permet de spécifier le nombre maximal d’entrées à traiter avec la commande en une seule fois : ``` $ xargs -L 1 find /var/log -name @@ -173,7 +173,7 @@ $ xargs -L 1 find /var/log -name ``` -If we wanted to be able to specify both arguments on the same line, we would have to use the `-n 1` option: +Si nous avions voulu pouvoir spécifier sur la même ligne les deux arguments, il aurait fallut utiliser l’option `-n 1` : ``` $ xargs -n 1 find /var/log -name @@ -191,7 +191,7 @@ $ xargs -n 1 find /var/log -name ``` -Case study of a backup with a `tar` based on a search: +Cas concret d’une sauvegarde avec un `tar` en fonction d’une recherche : ``` $ find /var/log/ -name "*.log" -mtime -1 | xargs tar cvfP /root/log.tar @@ -200,37 +200,37 @@ $ tar tvfP /root/log.tar -rw-r--r-- root/root 499270 2017-04-06 11:01 /var/log/audit/audit.log ``` -The special feature of the `xargs` command is that it places the input argument at the end of the called command. This works very well with the above example since the files passed in will form the list of files to be added to the archive. +La particularité de la commande `xargs` est quelle place l’argument en entrée à la fin de la commande appelée. Ceci fonctionne très bien avec l’exemple ci-dessus puisque les fichiers passés en entrée vont constituer la liste des fichiers à ajouter à l’archive. -Now, if we take the example of the `cp` command and want to copy a list of files in a directory, this list of files will be added at the end of the command... but what the `cp` command expects at the end of the command is the destination. To do this, we use the `-I` option to put the input arguments somewhere else than at the end of the line. +Maintenant, si nous prenons l’exemple de la commande `cp` en voulant copier une liste de fichiers dans un répertoire, cette liste de fichiers sera ajoutée en fin de commande… or ce qui est attendu par la commande `cp` en fin de commande est plutôt la destination. Pour ce faire, nous utilisons l’option `-I` afin de placer les arguments en entrée ailleurs qu’en fin de ligne. ``` $ find /var/log -type f -name "*.log" | xargs -I % cp % /root/backup ``` -The `-I` option allows you to specify a character (in our example the `%` character) where the input files to `xargs` will be placed. +L’option `-I` permet de spécifier un caractère (dans notre exemple le caractère `%`) où seront placés les fichiers en entrée de `xargs`. -## `yum-utils` package +## Le paquet `yum-utils` -The `yum-utils` package is a collection of utilities from different authors for `yum`, which make it easier and more powerful to use. +Le paquet `yum-utils` est une collection d’utilitaires de différents auteurs pour `yum`, qui le rendent plus simple et plus puissant à utiliser. -!!! abstract Note While `yum` has been replaced by `dnf` in Rocky Linux 8, the package name has remained `yum-utils` although it can be installed as `dnf-utils` as well. These are classic YUM utilities implemented as CLI shims on top of DNF to maintain backwards compatibility with `yum-3`. +!!! Note Bien que `yum` ait été remplacé par `dnf` dans Rocky Linux 8, le nom du paquet est resté `yum-utils` mais il peut tout aussi bien être installé avec le paquet `dnf-utils`. Ce sont des utilitaires YUM classiques implémentés comme des CLI au-dessus de DNF pour maintenir une compatibilité ascendante avec `yum-3`. -Here are some examples of usage: +Voici quelques exemples d’utilisation : -* `repoquery` command: +* la commande `repoquery` : -The `repoquery` command queries the repositories. +La commande `repoquery` interroge les dépôts. -Examples of use: +Exemples d’utilisation : - * Knowing the dependencies of an uninstalled package: + * Connaître les dépendances d’un paquet non-installé : ``` repoquery --requires ``` - * Know the files provided by a non-installed package: + * Connaître les fichiers fournis par un paquet non-installé : ``` $ repoquery -l yum-utils @@ -260,32 +260,32 @@ $ repoquery -l yum-utils … ``` -* `yumdownloader` command: +* La commande `yumdownloader` : -The `yumdownloader` command downloads RPM packages from the repositories. +La commande `yumdownloader` télécharge les paquets RPM depuis les dépôts. -!!! abstract Note This command is very useful to quickly build a local repository of a few rpm! +!!! Note Cette commande est très pratique pour construire un dépôt local de quelques rpm ! -Example: `yumdownloader` will download the _repoquery_ rpm package and all its dependencies: +Exemple : `yumdownloader` va télécharger le paquet rpm de _repoquery_ ainsi que toutes ses dépendances : ``` $ yumdownloader --destdir /var/tmp -- resolve repoquery ``` -| Options | Comments | -| ----------- | --------------------------------------------------------------- | -| -`-destdir` | The downloaded packages will be stored in the specified folder. | -| `--resolve` | Also downloads the package dependencies. | +| Options | Commentaires | +| ----------- | ------------------------------------------------------------------ | +| -`-destdir` | Les paquets téléchargés seront conservés dans le dossier spécifié. | +| `--resolve` | Télécharge également les dépendances du paquet. | -## `psmisc` packages +## Le paquet `psmisc` -The `psmisc` package contains utilities for managing system processes: +Le paquet `psmisc` contient des utilitaires pour gérer les processus du système : -* `pstree`: the `pstree` command displays the current processes on the system in a tree-like structure. -* `killall`: the `killall` command sends a kill signal to all processes identified by name. -* `fuser`: the `fuser` command identifies the `PID` of processes that use the specified files or file systems. +* `pstree` : la commande `pstree` affiche les processus en cours sur le système sous forme de structure en forme d’arbre. +* `killall` : la commande `killall` envoie un signal d’extinction à tous les processus identifiés par un nom. +* `fuser` : la commande `fuser` identifie les `PID` des processus qui utilisent les fichiers ou les systèmes de fichiers spécifiés. -Examples: +Exemples : ``` $ pstree @@ -311,29 +311,29 @@ systemd─┬─NetworkManager───2*[{NetworkManager}] # killall httpd ``` -Kill processes (option `-k`) that access the `/etc/httpd/conf/httpd.conf` file: +Tue les processus (option `-k`) qui accèdent au fichier `/etc/httpd/conf/httpd.conf` : ``` # fuser -k /etc/httpd/conf/httpd.conf ``` -## `watch` command +## La commande `watch` -The `watch` command regularly executes a command and displays the result in the terminal in full screen. +La commande `watch` exécute régulièrement une commande et affiche le résultat dans le terminal en plein écran. -The `-n` option allows you to specify the number of seconds between each execution of the command. +L’option `-n` permet de spécifier le nombre de secondes entre chaque exécution de la commande. -!!! abstract Note To exit the `watch` command, you must type the keys: CTRL+C to kill the process. +!!! Note Pour quitter la commande `watch`, il faut saisir les touches : CTRL+C pour tuer le processus. -Examples: +Exemples : -* Display the end of the `/etc/passwd` file every 5 seconds: +* Afficher la fin du fichier `/etc/passwd` toutes les 5 secondes : ``` $ watch -n 5 tail -n 3 /etc/passwd ``` -Result: +Résultat : ``` Every 5,0s: tail -n 3 /etc/passwd rockstar.rockylinux.lan: Thu Jul 1 15:43:59 2021 @@ -343,13 +343,13 @@ chrony:x:995:992::/var/lib/chrony:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin ``` -* Monitoring the number of files in a folder: +* Surveillance du nombre de fichier dans un dossier : ``` $ watch -n 1 'ls -l | wc -l' ``` -* Display a clock: +* Afficher une horloge : ``` $ watch -t -n 1 date diff --git a/docs/books/learning_ansible/02-advanced.it.md b/docs/books/learning_ansible/02-advanced.it.md index 0cf4ff72b0..7cf1eaa8b4 100644 --- a/docs/books/learning_ansible/02-advanced.it.md +++ b/docs/books/learning_ansible/02-advanced.it.md @@ -144,7 +144,7 @@ Uso di una variabile memorizzata: var: homes.stdout_lines[1] ``` -!!! Note Nota La variabile `homes. tdout_lines` è un elenco di variabili di tipo stringa, un modo per organizzare variabili che non avevamo ancora incontrato. +!!! Note Nota La variabile `homes.stdout_lines` è un elenco di variabili di tipo stringa, un modo per organizzare variabili che non avevamo ancora incontrato. Le stringhe che compongono la variabile memorizzata possono essere consultate tramite il valore `stdout` (che ti permette di fare cose come `homes.stdout.find("core") != -1`), per sfruttarli usando un ciclo (vedi `loop`), o semplicemente dai loro indici come visto nell'esempio precedente. diff --git a/docs/books/learning_ansible/03-working-with-files.it.md b/docs/books/learning_ansible/03-working-with-files.it.md new file mode 100644 index 0000000000..edd8698de0 --- /dev/null +++ b/docs/books/learning_ansible/03-working-with-files.it.md @@ -0,0 +1,141 @@ +--- +title: Gestione File +--- + +# Ansible - Gestione dei file + +In questo capitolo imparerai come gestire i file con Ansable. + +**** + +**Obiettivi**: In questo capitolo imparerai come: + +:heavy_check_mark: modificare il contenuto del file; +:heavy_check_mark: caricare i file ai server di destinazione; +:heavy_check_mark: recuperare i file dai server di destinazione. + +:checkered_flag: **ansible**, **moduli**, **files** + +**Conoscenza**: :star: :star: +**Complessità**: :star: + +**Tempo di lettura**: 20 minuti + +**** + +A seconda delle vostre esigenze, dovrete utilizzare diversi moduli Ansible per modificare i file di configurazione del sistema. + +## modulo `ini_file` + +Quando si desidera modificare un file INI (sezione tra doppie `[]` e `key=value`), il modo più semplice è usare il modulo `ini_file`. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/collections/community/general/ini_file_module.html). + +Il modulo richiede: + +* Il valore della sezione +* Il nome dell'opzione +* Il nuovo valore + +Esempio di utilizzo: + +``` +- name: change value on inifile + community.general.ini_file: + dest: /path/to/file.ini + section: SECTIONNAME + option: OPTIONNAME + value: NEWVALUE +``` + +## modulo `lineinfile` + +Per garantire che una riga sia presente in un file, o quando una singola riga in un file debba essere aggiunta o modificata, usa il modulo `linefile`. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html). + +In questo caso, la riga da modificare in un file verrà trovata usando un regexp. + +Ad esempio, per garantire che la linea che inizia con `SELINUX=` nel file `/etc/selinux/config` contenga il valore `enforcing`: + +``` +- ansible.builtin.lineinfile: + path: /etc/selinux/config + regexp: '^SELINUX=' + line: 'SELINUX=enforcing' +``` + +## modulo `copy` + +Quando un file deve essere copiato dal server Ansible in uno o più host, è meglio utilizzare il modulo `copy`. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html). + +Qui stiamo copiando `myflile.conf` da una posizione all'altra: + +``` +- ansible.builtin.copy: + src: /data/ansible/sources/myfile.conf + dest: /etc/myfile.conf + owner: root + group: root + mode: 0644 +``` + +## modulo `fetch` + +Quando un file deve essere copiato da un server remoto al server locale, è meglio utilizzare il modulo `fetch`. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fetch_module.html). + +Questo modulo fa il contrario del modulo `copy`: + +``` +- ansible.builtin.fetch: + src: /etc/myfile.conf + dest: /data/ansible/backup/myfile-{{ inventory_hostname }}.conf + flat: yes +``` + +## modulo `template` + +Ansible e il suo modulo `template` utilizzano il sistema di template **Jinja2** (http://jinja.pocoo.org/docs/) per generare file sugli host di destinazione. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html). + +Per esempio: + +``` +- ansible.builtin.template: + src: /data/ansible/templates/monfichier.j2 + dest: /etc/myfile.conf + owner: root + group: root + mode: 0644 +``` + +È possibile aggiungere una fase di convalida se il servizio di destinazione lo permette (ad esempio apache con il comando `apachectl -t`): + +``` +- template: + src: /data/ansible/templates/vhost.j2 + dest: /etc/httpd/sites-available/vhost.conf + owner: root + group: root + mode: 0644 + validate: '/usr/sbin/apachectl -t' +``` + +## modulo `get_url` + +Per caricare file da un sito web o ftp a uno o più host, utilizzare il modulo `get_url`: + +``` +- get_url: + url: http://site.com/archive.zip + dest: /tmp/archive.zip + mode: 0640 + checksum: sha256:f772bd36185515581aa9a2e4b38fb97940ff28764900ba708e68286121770e9a +``` + +Fornendo un checksum del file, il file non verrà nuovamente scaricato se è già presente nella posizione di destinazione e il suo checksum corrisponde al valore fornito. diff --git a/docs/books/learning_ansible/04-ansible-galaxy.it.md b/docs/books/learning_ansible/04-ansible-galaxy.it.md new file mode 100644 index 0000000000..3bb9f528bb --- /dev/null +++ b/docs/books/learning_ansible/04-ansible-galaxy.it.md @@ -0,0 +1,532 @@ +--- +title: Galassia Ansible +--- + +# Galassia Ansibile: Collezioni e Ruoli + +In questo capitolo imparerai come usare, installare e gestire ruoli e collezioni Ansible. + +**** + +**Obiettivi**: In questo capitolo imparerai come: + +:heavy_check_mark: installare e gestire collezioni; +:heavy_check_mark: installare e gestire i ruoli;. + +:checkered_flag: **ansible**, **ansible-galaxy**, **ruoli**, **collezioni** + +**Conoscenza**: :star: :star: +**Complessità**: :star: :star: :star: + +**Tempo di lettura**: 40 minuti + +**** + +La [Galassia Ansible](https://galaxy.ansible.com) fornisce Ruoli Ansible e Collezioni della Comunità Ansible. + +Gli elementi forniti possono essere referenziati nei playbook e pronti da usare + +## comando `ansible-galaxy` + +Il comando `ansible-galaxy` gestisce ruoli e collezioni utilizzando [galaxy.ansible.com](http://galaxy.ansible.com). + +* Per gestire i ruoli: + +``` +ansible-galaxy role [import|init|install|login|remove|...] +``` + +| Sotto comandi | Osservazioni | +| ------------- | ------------------------------------------------------------------ | +| `install` | installare un ruolo. | +| `remove` | rimuovere uno o più ruoli. | +| `list` | mostrare il nome e la versione dei ruoli installati. | +| `info` | visualizzare informazioni su un ruolo. | +| `init` | generare uno scheletro di un nuovo ruolo. | +| `import` | importare un ruolo dal sito web della galassia. Richiede un login. | + +* Per gestire le collezioni: + +``` +ansible-galaxy collection [import|init|install|login|remove|...] +``` + +| Sotto comandi | Osservazioni | +| ------------- | --------------------------------------------------------------- | +| `init` | generare uno scheletro di una nuova collezione. | +| `install` | installare una collezione. | +| `list` | visualizzare il nome e la versione delle collezioni installate. | + +## Ruoli Ansible + +Un ruolo Ansible è un'unità che promuove la riutilizzabilità dei playbook. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html) + +### Installazione di ruoli utili + +Al fine di evidenziare l'interesse ad utilizzare i ruoli, vi suggerisco di utilizzare il ruolo `alemorvan/patchmanagement`, che vi permetterà di eseguire un sacco di attività (pre-aggiornamento o post-aggiornamento, per esempio) durante il processo di aggiornamento, in poche righe di codice. + +Puoi controllare il codice nel repo github del ruolo [qui](https://github.com/alemorvan/patchmanagement). + +* Installare il ruolo. Questo richiede un solo comando: + +``` +ansible-galaxy role install alemorvan.patchmanagement +``` + +* Creare un playbook per includere il ruolo: + +``` +- name: Start a Patch Management + hosts: ansible_clients + vars: + pm_before_update_tasks_file: custom_tasks/pm_before_update_tasks_file.yml + pm_after_update_tasks_file: custom_tasks/pm_after_update_tasks_file.yml + + tasks: + - name: "Include patchmanagement" + include_role: + name: "alemorvan.patchmanagement" +``` + +Con questo ruolo, puoi aggiungere i tuoi compiti per tutto il tuo inventario o solo per il nodo selezionato. + +Creiamo delle attività che saranno eseguite prima e dopo il processo di aggiornamento: + +* Crea la cartella `custom_tasks`: + +``` +mkdir custom_tasks +``` + +* Crea `custom_tasks/pm_before_update_tasks_file.yml` (puoi liberamente cambiare il nome e il contenuto di questo file) + +``` +--- +- name: sample task before the update process + debug: + msg: "This is a sample tasks, feel free to add your own test task" +``` + +* Crea `custom_tasks/pm_after_update_tasks_file.yml` (puoi liberamente cambiare il nome e il contenuto di questo file) + +``` +--- +- name: sample task after the update process + debug: + msg: "This is a sample tasks, feel free to add your own test task" +``` + +E lancia il tuo primo Gestione Patch: + +``` +ansible-playbook patchmanagement.yml + +PLAY [Start a Patch Management] ************************************************************************* + +TASK [Gathering Facts] ********************************************************************************** +ok: [192.168.1.11] + +TASK [Include patchmanagement] ************************************************************************** + +TASK [alemorvan.patchmanagement : MAIN | Linux Patch Management Job] ************************************ +ok: [192.168.1.11] => { + "msg": "Start 192 patch management" +} + +... + +TASK [alemorvan.patchmanagement : sample task before the update process] ******************************** +ok: [192.168.1.11] => { + "msg": "This is a sample tasks, feel free to add your own test task" +} + +... + +TASK [alemorvan.patchmanagement : MAIN | We can now patch] ********************************************** +included: /home/ansible/.ansible/roles/alemorvan.patchmanagement/tasks/patch.yml for 192.168.1.11 + +TASK [alemorvan.patchmanagement : PATCH | Tasks depends on distribution] ******************************** +ok: [192.168.1.11] => { + "ansible_distribution": "Rocky" +} + +TASK [alemorvan.patchmanagement : PATCH | Include tasks for CentOS & RedHat tasks] ********************** +included: /home/ansible/.ansible/roles/alemorvan.patchmanagement/tasks/linux_tasks/redhat_centos.yml for 192.168.1.11 + +TASK [alemorvan.patchmanagement : RHEL CENTOS | yum clean all] ****************************************** +changed: [192.168.1.11] + +TASK [alemorvan.patchmanagement : RHEL CENTOS | Ensure yum-utils is installed] ************************** +ok: [192.168.1.11] + +TASK [alemorvan.patchmanagement : RHEL CENTOS | Remove old kernels] ************************************* +skipping: [192.168.1.11] + +TASK [alemorvan.patchmanagement : RHEL CENTOS | Update rpm package with yum] **************************** +ok: [192.168.1.11] + +TASK [alemorvan.patchmanagement : PATCH | Inlude tasks for Debian & Ubuntu tasks] *********************** +skipping: [192.168.1.11] + +TASK [alemorvan.patchmanagement : MAIN | We can now reboot] ********************************************* +included: /home/ansible/.ansible/roles/alemorvan.patchmanagement/tasks/reboot.yml for 192.168.1.11 + +TASK [alemorvan.patchmanagement : REBOOT | Reboot triggered] ******************************************** +ok: [192.168.1.11] + +TASK [alemorvan.patchmanagement : REBOOT | Ensure we are not in rescue mode] **************************** +ok: [192.168.1.11] + +... + +TASK [alemorvan.patchmanagement : FACTS | Insert fact file] ********************************************* +ok: [192.168.1.11] + +TASK [alemorvan.patchmanagement : FACTS | Save date of last PM] ***************************************** +ok: [192.168.1.11] + +... + +TASK [alemorvan.patchmanagement : sample task after the update process] ********************************* +ok: [192.168.1.11] => { + "msg": "This is a sample tasks, feel free to add your own test task" +} + +PLAY RECAP ********************************************************************************************** +192.168.1.11 : ok=31 changed=1 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0 +``` + +Piuttosto facile per un processo così complesso, vero? + +Questo è solo un esempio di ciò che può essere fatto utilizzando i ruoli resi disponibili dalla comunità. Dai un'occhiata a [galaxy.ansible.com](https://galaxy.ansible.com/) per scoprire i ruoli che potrebbero essere utili per te! + +Puoi anche creare i tuoi ruoli per le tue esigenze e pubblicarli su Internet se te la senti. Questo è quanto affronteremo brevemente nel prossimo capitolo. + +### Introduzione allo sviluppo del ruolo + +Uno scheletro di ruolo, che serve come punto di partenza per lo sviluppo di ruolo personalizzato, può essere generato dal comando `ansible-galaxy`: + +``` +$ ansible-galaxy role init rocky8 +- Role rocky8 was created successfully +``` + +Il comando genererà la seguente struttura ad albero per contenere il ruolo `rocky8`: + +``` +tree rocky8/ +rocky8/ +├── defaults +│   └── main.yml +├── files +├── handlers +│   └── main.yml +├── meta +│   └── main.yml +├── README.md +├── tasks +│   └── main.yml +├── templates +├── tests +│   ├── inventory +│   └── test.yml +└── vars + └── main.yml + +8 directories, 8 files +``` + +I ruoli consentono di eliminare la necessità di includere i file. Non c'è bisogno di specificare i percorsi dei file o `includere` direttive nei playbook. Devi solo specificare un compito, e Ansible si occupa delle inclusioni. + +La struttura di un ruolo è abbastanza evidente da capire. + +Le variabili sono semplicemente memorizzate in `vars/main.yml` se le variabili non devono essere sovrascritte, oppure in `default/main. ml` se vuoi lasciare la possibilità di sovrascrivere il contenuto variabile dall'esterno del tuo ruolo. + +I gestori, i file e i modelli necessari per il tuo codice sono memorizzati rispettivamente in `handlers/main.yml`, `files` e `templates`. + +Tutto ciò che rimane è definire il codice per le attività del tuo ruolo in `tasks/main.yml`. + +Una volta che tutto questo funziona bene, è possibile utilizzare questo ruolo nei tuoi playbook. Sarete in grado di utilizzare il vostro ruolo senza preoccuparvi dell'aspetto tecnico dei suoi compiti, durante la personalizzazione del suo funzionamento con variabili. + +### Lavoro pratico: creare un primo ruolo semplice + +Implementiamo questo con un ruolo "go anywhere" che creerà un utente predefinito e installerà pacchetti software. Questo ruolo può essere applicato sistematicamente a tutti i tuoi server. + +#### Variabili + +Creeremo un utente `rockstar` su tutti i nostri server. Poiché non vogliamo che questo utente sia sovrascritto, definiamolo nel `vars/main.yml`: + +``` +--- +rocky8_default_group: + name: rockstar + gid: 1100 +rocky8_default_user: + name: rockstar + uid: 1100 + group: rockstar +``` + +Ora possiamo usare queste variabili all'interno dei nostri `tasks/main.yml` senza alcuna inclusione. + +``` +--- +- name: Create default group + group: + name: "{{ rocky8_default_group.name }}" + gid: "{{ rocky8_default_group.gid }}" + +- name: Create default user + user: + name: "{{ rocky8_default_user.name }}" + uid: "{{ rocky8_default_user.uid }}" + group: "{{ rocky8_default_user.group }}" +``` + +Per testare il tuo nuovo ruolo, creiamo un playbook `test-role.yml` nella stessa directory del tuo ruolo: + +``` +--- +- name: Test my role + hosts: localhost + + roles: + + - role: rocky8 + become: true + become_user: root +``` + +e lancialo: + +``` +ansible-playbook test-role.yml + +PLAY [Test my role] ************************************************************************************ + +TASK [Gathering Facts] ********************************************************************************* +ok: [localhost] + +TASK [rocky8 : Create default group] ******************************************************************* +changed: [localhost] + +TASK [rocky8 : Create default user] ******************************************************************** +changed: [localhost] + +PLAY RECAP ********************************************************************************************* +localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +Congratulazioni! Ora siete in grado di creare grandi cose con un playbook di solo poche righe. + +Vediamo l'uso delle variabili predefinite. + +Crea un elenco di pacchetti da installare per impostazione predefinita sui server e un elenco vuoto di pacchetti da disinstallare. Modifica i file `defaults/main.yml` e aggiungi questi due elenchi: + +``` +rocky8_default_packages: + - tree + - vim +rocky8_remove_packages: [] +``` + +e usali nei tuoi `tasks/main.yml`: + +``` +- name: Install default packages (can be overridden) + package: + name: "{{ rocky8_default_packages }}" + state: present + +- name: "Uninstall default packages (can be overridden) {{ rocky8_remove_packages }}" + package: + name: "{{ rocky8_remove_packages }}" + state: absent +``` + +Verifica il tuo ruolo con l'aiuto del playbook precedentemente creato: + +``` +ansible-playbook test-role.yml + +PLAY [Test my role] ************************************************************************************ + +TASK [Gathering Facts] ********************************************************************************* +ok: [localhost] + +TASK [rocky8 : Create default group] ******************************************************************* +ok: [localhost] + +TASK [rocky8 : Create default user] ******************************************************************** +ok: [localhost] + +TASK [rocky8 : Install default packages (can be overridden)] ******************************************** +ok: [localhost] + +TASK [rocky8 : Uninstall default packages (can be overridden) []] *************************************** +ok: [localhost] + +PLAY RECAP ********************************************************************************************* +localhost : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +Ora puoi sovrascrivere i `rocky8_remove_packages` nel tuo playbook e disinstallare ad esempio `cockpit`: + +``` +--- +- name: Test my role + hosts: localhost + vars: + rocky8_remove_packages: + - cockpit + + roles: + + - role: rocky8 + become: true + become_user: root +``` + +``` +ansible-playbook test-role.yml + +PLAY [Test my role] ************************************************************************************ + +TASK [Gathering Facts] ********************************************************************************* +ok: [localhost] + +TASK [rocky8 : Create default group] ******************************************************************* +ok: [localhost] + +TASK [rocky8 : Create default user] ******************************************************************** +ok: [localhost] + +TASK [rocky8 : Install default packages (can be overridden)] ******************************************** +ok: [localhost] + +TASK [rocky8 : Uninstall default packages (can be overridden) ['cockpit']] ****************************** +changed: [localhost] + +PLAY RECAP ********************************************************************************************* +localhost : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +Ovviamente, non c'è limite a quanto si può migliorare il proprio ruolo. Immaginate che per uno dei vostri server, avete bisogno di un pacchetto che è nell'elenco di quelli da disinstallare. Si potrebbe quindi, ad esempio, creare una nuova lista che può essere sovrascritta e quindi rimuovere dall'elenco dei pacchetti da disinstallare quelli nell'elenco dei pacchetti specifici da installare utilizzando il filtro jinja `difference()`. + +``` +- name: "Uninstall default packages (can be overridden) {{ rocky8_remove_packages }}" + package: + name: "{{ rocky8_remove_packages | difference(rocky8_specifics_packages) }}" + state: absent +``` + +## Collezioni Ansible + +Le collezioni sono un formato di distribuzione per i contenuti Ansible che possono includere libri di gioco, ruoli, moduli e plugin. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) + +Per installare o aggiornare una collezione: + +``` +ansible-galaxy collection install namespace.collection [--upgrade] +``` + +È quindi possibile utilizzare la collezione appena installata usando lo spazio dei nomi e il nome del modulo prima del nome o del ruolo: + +``` +- import_role: + name: namespace.collection.rolename + +- namespace.collection.modulename: + option1: value +``` + +Puoi trovare un indice di raccolta [qui](https://docs.ansible.com/ansible/latest/collections/index.html). + +Installiamo la collezione `community.general`: + +``` +ansible-galaxy collection install community.general +Starting galaxy collection install process +Process install dependency map +Starting collection install process +Downloading https://galaxy.ansible.com/download/community-general-3.3.2.tar.gz to /home/ansible/.ansible/tmp/ansible-local-51384hsuhf3t5/tmpr_c9qrt1/community-general-3.3.2-f4q9u4dg +Installing 'community.general:3.3.2' to '/home/ansible/.ansible/collections/ansible_collections/community/general' +community.general:3.3.2 was installed successfully +``` + +Ora possiamo utilizzare il nuovo modulo disponibile `yum_versionlock`: + +``` +- name: Start a Patch Management + hosts: ansible_clients + become: true + become_user: root + tasks: + + - name: Ensure yum-versionlock is installed + package: + name: python3-dnf-plugin-versionlock + state: present + + - name: Prevent kernel from being updated + community.general.yum_versionlock: + state: present + name: kernel + register: locks + + - name: Display locks + debug: + var: locks.meta.packages +``` + +``` +ansible-playbook versionlock.yml + +PLAY [Start a Patch Management] ************************************************************************* + +TASK [Gathering Facts] ********************************************************************************** +ok: [192.168.1.11] + +TASK [Ensure yum-versionlock is installed] ************************************************************** +changed: [192.168.1.11] + +TASK [Prevent kernel from being updated] **************************************************************** +changed: [192.168.1.11] + +TASK [Display locks] ************************************************************************************ +ok: [192.168.1.11] => { + "locks.meta.packages": [ + "kernel" + ] +} + +PLAY RECAP ********************************************************************************************** +192.168.1.11 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 + +``` + +### Creare la propria collezione + +Come per i ruoli, puoi creare la tua collezione con l'aiuto del comando `ansible-galaxy`: + +``` +ansible-galaxy collection init rocky8.rockstarcollection +- Collection rocky8.rockstarcollection was created successfully +``` + +``` +tree rocky8/rockstarcollection/ +rocky8/rockstarcollection/ +├── docs +├── galaxy.yml +├── plugins +│   └── README.md +├── README.md +└── roles +``` + +È quindi possibile memorizzare i propri plugin o ruoli all'interno di questa nuova collezione. diff --git a/docs/books/learning_ansible/05-deployments.it.md b/docs/books/learning_ansible/05-deployments.it.md new file mode 100644 index 0000000000..7b3156d41c --- /dev/null +++ b/docs/books/learning_ansible/05-deployments.it.md @@ -0,0 +1,777 @@ +--- +title: Distribuzione con Ansistrano +--- + +# Distribuzione Ansible con Ansistrano + +In questo capitolo imparerai come distribuire applicazioni con il ruolo Ansible [Ansistrano](https://ansistrano.com). + +**** + +**Obiettivi**: In questo capitolo imparerai come: + +:heavy_check_mark: Implementare Ansistrano; +:heavy_check_mark: Configurare Ansistrano; +:heavy_check_mark: Usare cartelle e file condivisi tra le versioni distribuite; +:heavy_check_mark: Distribuire diverse versioni di un sito da git; +:heavy_check_mark: Reagire tra i passaggi di implementazione. + +:checkered_flag: **ansible**, **ansistrano**, **ruoli**, **distribuzioni** + +**Conoscenza**: :star: :star: +**Complessità**: :star: :star: :star: + +**Tempo di lettura**: 40 minuti + +**** + +Ansistrano è un ruolo Ansible per distribuire facilmente applicazioni PHP, Python, ecc. Si basa sulla funzionalità di [Capistrano](http://capistranorb.com/). + +## Introduzione + +Ansistrano richiede quanto segue: + +* Ansible sulla macchina di distribuzione, +* `rsync` o `git` sulla macchina client. + +Può scaricare il codice sorgente da `rsync`, `git`, `scp`, `http`, `S3`, ... + +!!! Note Nota Per il nostro esempio di distribuzione, useremo il protocollo `git`. + +Ansistrano distribuisce applicazioni seguendo questi 5 passaggi: + +* **Setup**: crea la struttura delle directory per ospitare le release; +* **Update Code**: scaricando la nuova release per gli obiettivi; +* **Symlink Shared** e **Symlink**: dopo aver distribuito la nuova release, il `link simbolico corrente` è modificato per puntare a questa nuova versione; +* **Clean Up**: per fare un po' di pulizia (rimuovi le vecchie versioni). + +![Fasi di una distribuzione](images/ansistrano-001.png) + +Lo scheletro di una distribuzione con Ansistrano assomiglia a questo: + +``` +/var/www/site/ +├── current -> ./releases/20210718100000Z +├── releases +│   └── 20210718100000Z +│   ├── css -> ../../shared/css/ +│   ├── img -> ../../shared/img/ +│   └── REVISION +├── repo +└── shared + ├── css/ + └── img/ +``` + +Puoi trovare tutta la documentazione di Ansistrano sul suo [repository Github](https://github.com/ansistrano/deploy). + +## Labs + +Continuerai a lavorare sui tuoi 2 server: + +Il server di gestione: + +* Ansible è già installato. Dovrai installare il ruolo `ansistrano.deploy`. + +Il server gestito: + +* Sarà necessario installare Apache e distribuire il sito client. + +### Distribuzione del server Web + +Per una maggiore efficienza, useremo il ruolo `geerlingguy.apache` per configurare il server: + +``` +$ ansible-galaxy role install geerlingguy.apache +Starting galaxy role install process +- downloading role 'apache', owned by geerlingguy +- downloading role from https://github.com/geerlingguy/ansible-role-apache/archive/3.1.4.tar.gz +- extracting geerlingguy.apache to /home/ansible/.ansible/roles/geerlingguy.apache +- geerlingguy.apache (3.1.4) was installed successfully +``` + +Probabilmente avremo bisogno di aprire alcune regole del firewall, quindi installeremo anche la collezione `ansibile. osix` per lavorare con il suo modulo `firewalld`: + +``` +$ ansible-galaxy collection install ansible.posix +Starting galaxy collection install process +Process install dependency map +Starting collection install process +Downloading https://galaxy.ansible.com/download/ansible-posix-1.2.0.tar.gz to /home/ansible/.ansible/tmp/ansible-local-519039bp65pwn/tmpsvuj1fw5/ansible-posix-1.2.0-bhjbfdpw +Installing 'ansible.posix:1.2.0' to '/home/ansible/.ansible/collections/ansible_collections/ansible/posix' +ansible.posix:1.2.0 was installed successfully +``` + +Una volta installato il ruolo e la collezione, possiamo creare la prima parte del nostro playbook, che sarà: + +* Installare Apache, +* Creare una cartella di destinazione per il nostro `vhost`, +* Creare un `vhost` di default, +* Apri il firewall, +* Avviare o riavviare Apache. + +Considerazioni tecniche: + +* Distribuiremo il nostro sito nella cartella `/var/www/site/`. +* Come vedremo più tardi, `ansistrano` creerà un collegamento simbolico `corrente` alla cartella di rilascio corrente. +* Il codice sorgente da distribuire contiene una cartella `html` alla quale il vhost dovrebbe puntare. Il suo `DirectoryIndex` è `index.htm`. +* La distribuzione è fatta da `git`, il pacchetto sarà installato. + +!!! Note Nota Il bersaglio del nostro vhost sarà: `/var/www/site/current/html`. + +Il nostro playbook per configurare il server: `playbook-config-server.yml` + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + apache_global_vhost_settings: | + DirectoryIndex index.php index.htm + apache_vhosts: + - servername: "website" + documentroot: "{{ dest }}current/html" + + tasks: + + - name: create directory for website + file: + path: /var/www/site/ + state: directory + mode: 0755 + + - name: install git + package: + name: git + state: latest + + - name: permit traffic in default zone for http service + ansible.posix.firewalld: + service: http + permanent: yes + state: enabled + immediate: yes + + roles: + - { role: geerlingguy.apache } +``` + +Il playbook può essere applicato al server: + +``` +$ ansible-playbook playbook-config-server.yml +``` + +Nota l'esecuzione dei seguenti compiti: + +``` +TASK [geerlingguy.apache : Ensure Apache is installed on RHEL.] **************** +TASK [geerlingguy.apache : Configure Apache.] ********************************** +TASK [geerlingguy.apache : Add apache vhosts configuration.] ******************* +TASK [geerlingguy.apache : Ensure Apache has selected state and enabled on boot.] *** +TASK [permit traffic in default zone for http service] ************************* +RUNNING HANDLER [geerlingguy.apache : restart apache] ************************** +``` + +Il ruolo `geerlingguy.apache` rende il nostro lavoro molto più facile prendendosi cura dell'installazione e della configurazione di Apache. + +Puoi controllare che tutto funzioni usando `curl`: + +``` +$ curl -I http://192.168.1.11 +HTTP/1.1 404 Not Found +Date: Mon, 05 Jul 2021 23:30:02 GMT +Server: Apache/2.4.37 (rocky) OpenSSL/1.1.1g +Content-Type: text/html; charset=iso-8859-1 +``` + +!!! Note Nota Non abbiamo ancora distribuito alcun codice, quindi è normale che `curl` restituisca un codice HTTP `404`. Ma possiamo già confermare che il servizio `httpd` funziona e che il firewall è aperto. + +### Distribuzione del software + +Ora che il nostro server è configurato, possiamo distribuire l'applicazione. + +Per questo, useremo il ruolo `ansistrano.deploy` in un secondo playbook dedicato alla distribuzione delle applicazioni (per una maggiore leggibilità). + +``` +$ ansible-galaxy role install ansistrano.deploy +Starting galaxy role install process +- downloading role 'deploy', owned by ansistrano +- downloading role from https://github.com/ansistrano/deploy/archive/3.10.0.tar.gz +- extracting ansistrano.deploy to /home/ansible/.ansible/roles/ansistrano.deploy +- ansistrano.deploy (3.10.0) was installed successfully + +``` + +Le fonti del software possono essere trovate nel [repository github](https://github.com/alemorvan/demo-ansible.git). + +Creeremo un playbook `playbook-deploy.yml` per gestire la nostra distribuzione: + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + + roles: + - { role: ansistrano.deploy } +``` + +``` +$ ansible-playbook playbook-deploy.yml + +PLAY [ansible_clients] ********************************************************* + +TASK [ansistrano.deploy : ANSISTRANO | Ensure deployment base path exists] ***** +TASK [ansistrano.deploy : ANSISTRANO | Ensure releases folder exists] +TASK [ansistrano.deploy : ANSISTRANO | Ensure shared elements folder exists] +TASK [ansistrano.deploy : ANSISTRANO | Ensure shared paths exists] +TASK [ansistrano.deploy : ANSISTRANO | Ensure basedir shared files exists] +TASK [ansistrano.deploy : ANSISTRANO | Get release version] ******************** +TASK [ansistrano.deploy : ANSISTRANO | Get release path] +TASK [ansistrano.deploy : ANSISTRANO | GIT | Register ansistrano_git_result variable] +TASK [ansistrano.deploy : ANSISTRANO | GIT | Set git_real_repo_tree] +TASK [ansistrano.deploy : ANSISTRANO | GIT | Create release folder] +TASK [ansistrano.deploy : ANSISTRANO | GIT | Sync repo subtree[""] to release path] +TASK [ansistrano.deploy : ANSISTRANO | Copy git released version into REVISION file] +TASK [ansistrano.deploy : ANSISTRANO | Ensure shared paths targets are absent] +TASK [ansistrano.deploy : ANSISTRANO | Create softlinks for shared paths and files] +TASK [ansistrano.deploy : ANSISTRANO | Ensure .rsync-filter is absent] +TASK [ansistrano.deploy : ANSISTRANO | Setup .rsync-filter with shared-folders] +TASK [ansistrano.deploy : ANSISTRANO | Get current folder] +TASK [ansistrano.deploy : ANSISTRANO | Remove current folder if it's a directory] +TASK [ansistrano.deploy : ANSISTRANO | Change softlink to new release] +TASK [ansistrano.deploy : ANSISTRANO | Clean up releases] + +PLAY RECAP ******************************************************************************************************************************************************************************************************** +192.168.1.11 : ok=25 changed=8 unreachable=0 failed=0 skipped=14 rescued=0 ignored=0 + +``` + +Tante cose fatte con sole 11 righe di codice! + +``` +$ curl http://192.168.1.11 + + +Demo Ansible + + +

Version Master

+ + +``` + +### Controllo sul server + +Ora puoi connetterti da ssh alla tua macchina client. + +* Crea un `albero` nella directory `/var/www/site/`: + +``` +$ tree /var/www/site/ +/var/www/site +├── current -> ./releases/20210722155312Z +├── releases +│   └── 20210722155312Z +│   ├── REVISION +│   └── html +│   └── index.htm +├── repo +│   └── html +│   └── index.htm +└── shared +``` + +Nota che: + +* il `current` symlink alla release `./releases/20210722155312Z` +* la presenza di una directory `shared` +* la presenza dei git repos in `./repo/` + +* Dal server Ansible riavviare la distribuzione **3** volte, quindi controllare il client. + +``` +$ tree /var/www/site/ +var/www/site +├── current -> ./releases/20210722160048Z +├── releases +│   ├── 20210722155312Z +│   │   ├── REVISION +│   │   └── html +│   │   └── index.htm +│   ├── 20210722160032Z +│   │   ├── REVISION +│   │   └── html +│   │   └── index.htm +│   ├── 20210722160040Z +│   │   ├── REVISION +│   │   └── html +│   │   └── index.htm +│   └── 20210722160048Z +│   ├── REVISION +│   └── html +│   └── index.htm +├── repo +│   └── html +│   └── index.htm +└── shared +``` + +Nota che: + +* `ansistrano` ha mantenuto le ultime 4 release, +* il link `current` è collegato ora all'ultima release + +### Limita il numero di release + +La variabile `ansistrano_keep_releases` è usata per specificare il numero di rilasci da mantenere. + +* Utilizzando la variabile `ansistrano_keep_releases`, mantieni solo 3 rilasci del progetto. Verifica. + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + + roles: + - { role: ansistrano.deploy } +``` + +``` +--- +$ ansible-playbook -i hosts playbook-deploy.yml +``` + +Sulla macchina client: + +``` +$ tree /var/www/site/ +/var/www/site +├── current -> ./releases/20210722160318Z +├── releases +│   ├── 20210722160040Z +│   │   ├── REVISION +│   │   └── html +│   │   └── index.htm +│   ├── 20210722160048Z +│   │   ├── REVISION +│   │   └── html +│   │   └── index.htm +│   └── 20210722160318Z +│   ├── REVISION +│   └── html +│   └── index.htm +├── repo +│   └── html +│   └── index.htm +└── shared +``` + +### Utilizzo di shared_path e shared_files + + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + ansistrano_shared_paths: + - "img" + - "css" + ansistrano_shared_files: + - "logs" + + roles: + - { role: ansistrano.deploy } +``` + +Sulla macchina client, crea il file `log` nella directory `shared`: + +``` +sudo touch /var/www/site/shared/logs +``` + +Quindi esegui il playbook: + +``` +TASK [ansistrano.deploy : ANSISTRANO | Ensure shared paths targets are absent] ******************************************************* +ok: [192.168.10.11] => (item=img) +ok: [192.168.10.11] => (item=css) +ok: [192.168.10.11] => (item=logs/log) + +TASK [ansistrano.deploy : ANSISTRANO | Create softlinks for shared paths and files] ************************************************** +changed: [192.168.10.11] => (item=img) +changed: [192.168.10.11] => (item=css) +changed: [192.168.10.11] => (item=logs) +``` + +Sulla macchina client: + +``` +$ tree -F /var/www/site/ +/var/www/site/ +├── current -> ./releases/20210722160631Z/ +├── releases/ +│   ├── 20210722160048Z/ +│   │   ├── REVISION +│   │   └── html/ +│   │   └── index.htm +│   ├── 20210722160318Z/ +│   │   ├── REVISION +│   │   └── html/ +│   │   └── index.htm +│   └── 20210722160631Z/ +│   ├── REVISION +│   ├── css -> ../../shared/css/ +│   ├── html/ +│   │   └── index.htm +│   ├── img -> ../../shared/img/ +│   └── logs -> ../../shared/logs +├── repo/ +│   └── html/ +│   └── index.htm +└── shared/ + ├── css/ + ├── img/ + └── logs +``` + +Si prega di notare che l'ultima versione contiene 3 link: `css`, `img`e `log` + +* da `/var/www/site/releases/css` alla directory `../../shared/css/`. +* da `/var/www/site/releases/img` alla directory `../../shared/img/`. +* da `/var/www/site/releases/logs` al file `../../shared/logs`. + +Pertanto, i file contenuti in queste 2 cartelle e il file `log` sono sempre accessibili attraverso i seguenti percorsi: + +* `/var/www/site/current/css/`, +* `/var/www/site/current/img/`, +* `/var/www/site/current/logs`, + +ma soprattutto saranno mantenuti da una release all'altra. + +### Usa una sottodirectory del repository per la distribuzione + +Nel nostro caso, il repository contiene una cartella `html`, che contiene i file del sito. + +* Per evitare questo livello extra di directory, usa la variabile `ansistrano_git_repo_tree` specificando il percorso della sotto-directory da usare. + +Non dimenticare di modificare la configurazione di Apache per tenere conto di questo cambiamento! + +Modifica il playbook per la configurazione del server `playbook-config-server.yml` + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + apache_global_vhost_settings: | + DirectoryIndex index.php index.htm + apache_vhosts: + - servername: "website" + documentroot: "{{ dest }}current/" # <1> + + tasks: + + - name: create directory for website + file: + path: /var/www/site/ + state: directory + mode: 0755 + + - name: install git + package: + name: git + state: latest + + roles: + - { role: geerlingguy.apache } +``` + +<1> Modifica questa riga + +Cambia il playbook per la distribuzione `playbook-deploy.yml` + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + ansistrano_shared_paths: + - "img" + - "css" + ansistrano_shared_files: + - "log" + ansistrano_git_repo_tree: 'html' # <1> + + roles: + - { role: ansistrano.deploy } +``` + +<1> Modifica questa riga + +* Non dimenticare di eseguire entrambi i playbook + +* Controlla la macchina cliente: + +``` +$ tree -F /var/www/site/ +/var/www/site/ +├── current -> ./releases/20210722161542Z/ +├── releases/ +│   ├── 20210722160318Z/ +│   │   ├── REVISION +│   │   └── html/ +│   │   └── index.htm +│   ├── 20210722160631Z/ +│   │   ├── REVISION +│   │   ├── css -> ../../shared/css/ +│   │   ├── html/ +│   │   │   └── index.htm +│   │   ├── img -> ../../shared/img/ +│   │   └── logs -> ../../shared/logs +│   └── 20210722161542Z/ +│   ├── REVISION +│   ├── css -> ../../shared/css/ +│   ├── img -> ../../shared/img/ +│   ├── index.htm +│   └── logs -> ../../shared/logs +├── repo/ +│   └── html/ +│   └── index.htm +└── shared/ + ├── css/ + ├── img/ + └── logs +``` + +<1> Notare l'assenza di `html` + +### Gestione del ramo o dei tag git + +La variabile `ansistrano_git_branch` è usata per specificare un `branch` o un `tag` da distribuire. + +* Distribuisci il branch `releases/v1.1.0`: + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + ansistrano_shared_paths: + - "img" + - "css" + ansistrano_shared_files: + - "log" + ansistrano_git_repo_tree: 'html' + ansistrano_git_branch: 'releases/v1.1.0' + + roles: + - { role: ansistrano.deploy } +``` + +!!! Note Nota Puoi divertirti, durante la distribuzione, aggiornando il tuo browser, per vedere in 'live' il cambiamento. + +``` +$ curl http://192.168.1.11 + + +Demo Ansible + + +

Version 1.0.1

+ + +``` + +* Distribuisci il tag `v2.0.0`: + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + ansistrano_shared_paths: + - "img" + - "css" + ansistrano_shared_files: + - "log" + ansistrano_git_repo_tree: 'html' + ansistrano_git_branch: 'v2.0.0' + + roles: + - { role: ansistrano.deploy } +``` + +``` +$ curl http://192.168.1.11 + + +Demo Ansible + + +

Version 2.0.0

+ + +``` + +### Azioni tra le fasi di implementazione + +Una distribuzione con Ansistrano rispetta le seguenti fasi: + +* `Setup` +* `Update Code` +* `Symlink Shared` +* `Symlink` +* `Clean Up` + +È possibile intervenire prima e dopo ciascuno di questi passi. + +![Fasi di una distribuzione](images/ansistrano-001.png) + +Un playbook può essere incluso attraverso le variabili fornite per questo scopo: + +* `ansistrano_before__tasks_file` +* o `ansistrano_after__tasks_file` + +* Esempio semplice: invia un'email (o qualsiasi cosa desideri come la notifica di Slack) all'inizio della distribuzione: + + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + ansistrano_shared_paths: + - "img" + - "css" + ansistrano_shared_files: + - "logs" + ansistrano_git_repo_tree: 'html' + ansistrano_git_branch: 'v2.0.0' + ansistrano_before_setup_tasks_file: "{{ playbook_dir }}/deploy/before-setup-tasks.yml" + + roles: + - { role: ansistrano.deploy } +``` + +Crea il file `deploy/before-setup-tasks.yml`: + +``` +--- +- name: Send a mail + mail: + subject: Starting deployment on {{ ansible_hostname }}. + delegate_to: localhost +``` + +``` +TASK [ansistrano.deploy : include] ************************************************************************************* +included: /home/ansible/deploy/before-setup-tasks.yml for 192.168.10.11 + +TASK [ansistrano.deploy : Send a mail] ************************************************************************************* +ok: [192.168.10.11 -> localhost] +``` + +``` +[root] # mailx +Heirloom Mail version 12.5 7/5/10. Type ? for help. +"/var/spool/mail/root": 1 message 1 new +>N 1 root@localhost.local Tue Aug 21 14:41 28/946 "Starting deployment on localhost." +``` + +* Probabilmente dovrai riavviare alcuni servizi alla fine della distribuzione, per esempio per pulire la cache. Riavviamo Apache alla fine della distribuzione: + +``` +--- +- hosts: ansible_clients + become: yes + become_user: root + vars: + dest: "/var/www/site/" + ansistrano_deploy_via: "git" + ansistrano_git_repo: https://github.com/alemorvan/demo-ansible.git + ansistrano_deploy_to: "{{ dest }}" + ansistrano_keep_releases: 3 + ansistrano_shared_paths: + - "img" + - "css" + ansistrano_shared_files: + - "logs" + ansistrano_git_repo_tree: 'html' + ansistrano_git_branch: 'v2.0.0' + ansistrano_before_setup_tasks_file: "{{ playbook_dir }}/deploy/before-setup-tasks.yml" + ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/deploy/after-symlink-tasks.yml" + + roles: + - { role: ansistrano.deploy } +``` + +Crea il file `deploy/after-symlink-tasks.yml`: + +``` +--- +- name: restart apache + systemd: + name: httpd + state: restarted +``` + +``` +TASK [ansistrano.deploy : include] ************************************************************************************* +included: /home/ansible/deploy/after-symlink-tasks.yml for 192.168.10.11 + +TASK [ansistrano.deploy : restart apache] ************************************************************************************** +changed: [192.168.10.11] +``` + +Come avete visto durante questo capitolo, Ansible può migliorare notevolmente la vita dell'amministratore di sistema. Ruoli molto intelligenti come Ansistrano sono dei "must haves" che diventano rapidamente indispensabili. + +L'utilizzo di Ansistrano garantisce il rispetto delle buone pratiche di diffusione, riduce i tempi necessari per mettere in produzione un sistema ed evita il rischio di potenziali errori umani. La macchina funziona velocemente, bene, e raramente commette errori! diff --git a/docs/books/learning_ansible/06-large-scale-infrastructure.it.md b/docs/books/learning_ansible/06-large-scale-infrastructure.it.md new file mode 100644 index 0000000000..4a7f1915c1 --- /dev/null +++ b/docs/books/learning_ansible/06-large-scale-infrastructure.it.md @@ -0,0 +1,324 @@ +--- +title: Infrastrutture su larga scala +--- + +# Ansible - Infrastrutture su larga scala + +In questo capitolo imparerai come ridimensionare il tuo sistema di gestione delle configurazioni. + +**** + +**Obiettivi**: In questo capitolo imparerai come: + +:heavy_check_mark: Organizzare il tuo codice per un'infrastruttura di grandi dimensioni; +:heavy_check_mark: Applicare tutto o parte della tua gestione di configurazione a un gruppo di nodi; + +:checkered_flag: **ansible**, **config management**, **scale** + +**Conoscenza**: :star: :star: :star: +**Complessità**: :star: :star: :star: :star: + +**Tempo di lettura**: 30 minuti + +**** + +Abbiamo visto nei capitoli precedenti come organizzare il nostro codice sotto forma di ruoli ma anche come utilizzare alcuni ruoli per la gestione degli aggiornamenti (patch management) o la distribuzione del codice. + +Che dire della gestione della configurazione? Come gestire la configurazione di dieci, centinaia, o anche migliaia di macchine virtuali con Ansible? + +L'avvento del cloud ha cambiato un po' i metodi tradizionali. La VM è configurata al momento della distribuzione. Se la sua configurazione non è più conforme, viene distrutta e sostituita da una nuova. + +L'organizzazione del sistema di gestione della configurazione presentato in questo capitolo risponderà a questi due modi di consumare IT: "uso one-shot" o regolare "riconfigurazione" di una flotta. + +Tuttavia, attenzione: utilizzare Ansible per garantire la conformità al parco richiede cambiamenti nelle abitudini lavorative. Non è più possibile modificare manualmente la configurazione di un service manager senza vedere queste modifiche sovrascritte alla prossima esecuzione di Ansible. + +!!! Note Nota Quello che stiamo per impostare qui sotto non è il terreno preferito di Ansible. Tecnologie come Puppet o Salt faranno molto meglio. Ricordiamo che Ansible è un coltello svizzero dell'automazione ed è senza agenti, il che spiega le differenze nelle prestazioni. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/user_guide/sample_setup.html) + +## Archiviazione variabili + +La prima cosa che dobbiamo discutere è la separazione tra i dati e il codice Ansible. + +Poiché il codice diventa più grande e più complesso, sarà sempre più complicato modificare le variabili che contiene. + +Per garantire la manutenzione del vostro sito, la cosa più importante è separare correttamente le variabili dal codice Ansible. + +Non ne abbiamo ancora discusso qui, ma dovresti sapere che Ansible può caricare automaticamente le variabili che trova in cartelle specifiche a seconda del nome dell'inventario del nodo gestito, o i suoi gruppi membri. + +La documentazione Ansible suggerisce di organizzare il nostro codice come sotto: + +``` +inventories/ + production/ + hosts # inventory file for production servers + group_vars/ + group1.yml # here we assign variables to particular groups + group2.yml + host_vars/ + hostname1.yml # here we assign variables to particular systems + hostname2.yml +``` + +Se il nodo selezionato è `hostname1` di `group1`, le variabili contenute nei file `hostname1.yml` e `group1.yml` verranno caricate automaticamente. È un bel modo per memorizzare tutti i dati per tutti i tuoi ruoli nello stesso posto. + +In questo modo, il file dell'inventario del tuo server diventa la sua carta d'identità. Contiene tutte le variabili che differiscono dalle variabili predefinite per il tuo server. + +Dal punto di vista della centralizzazione delle variabili, diventa essenziale organizzare il nome delle sue variabili nei ruoli prefissandole, ad esempio, con il nome del ruolo. Si consiglia anche di utilizzare nomi di variabili flat piuttosto che dizionari. + +Ad esempio, se si desidera rendere il valore `PermitRootLogin` nel file `sshd_config` una variabile, un buon nome della variabile potrebbe essere `sshd_config_permitrootlogin` (invece di `sshd.config.permitrootlogin` che potrebbe anche essere un buon nome di variabile). + +## Informazioni sui tag ansible + +L'uso di tag Ansible ti permette di eseguire o saltare una parte delle attività nel tuo codice. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html) + +Ad esempio, modifichiamo l'attività di creazione degli utenti: + +``` +- name: add users + user: + name: "{{ item }}" + state: present + groups: "users" + loop: + - antoine + - patrick + - steven + - xavier + tags: users +``` + +Ora puoi riprodurre solo le attività con il tag `users` con l'opzione `ansible-playbook` `--tags`: + +``` +ansible-playbook -i inventories/production/hosts --tags users site.yml +``` + +Puoi anche usare l'opzione `--skip-tags`. + +## Informazioni sul layout delle directory + +Concentriamoci su una proposta per l'organizzazione di file e directory necessari per il corretto funzionamento di un CMS (Content Management System). + +Il nostro punto di partenza sarà il file `site.yml`. Questo file è un po 'come il direttore d'orchestra del CMS in quanto includerà solo i ruoli necessari per i nodi di destinazione se necessario: + +``` +--- +- name: "Config Management for {{ target }}" + hosts: "{{ target }}" + + roles: + + - role: roles/functionality1 + + - role: roles/functionality2 +``` + +Naturalmente, questi ruoli devono essere creati sotto la directory `roles` allo stesso livello del file `site.yml`. + +Mi piace gestire i miei vars globali all'interno di un `vars/global_vars.yml`, anche se potrei memorizzarli all'interno di un file situato in `inventories/production/group_vars/all.yml` + +``` +--- +- name: "Config Management for {{ target }}" + hosts: "{{ target }}" + vars_files: + - vars/global_vars.yml + roles: + + - role: roles/functionality1 + + - role: roles/functionality2 +``` + +Mi piace inoltre mantenere la possibilità di disabilitare una funzionalità. Quindi includo i miei ruoli con una condizione e un valore predefinito come questo: + +``` +--- +- name: "Config Management for {{ target }}" + hosts: "{{ target }}" + vars_files: + - vars/global_vars.yml + roles: + + - role: roles/functionality1 + when: + - enable_functionality1|default(true) + + - role: roles/functionality2 + when: + - enable_functionality2|default(false) +``` + +Non dimenticare di usare i tag: + + +``` +- name: "Config Management for {{ target }}" + hosts: "{{ target }}" + vars_files: + - vars/global_vars.yml + roles: + + - role: roles/functionality1 + when: + - enable_functionality1|default(true) + tags: + - functionality1 + + - role: roles/functionality2 + when: + - enable_functionality2|default(false) + tags: + - functionality2 +``` + +Dovresti ottenere qualcosa di simile: + +``` +$ tree cms +cms +├── inventories +│   └── production +│   ├── group_vars +│   │   └── plateform.yml +│   ├── hosts +│   └── host_vars +│   ├── client1.yml +│   └── client2.yml +├── roles +│   ├── functionality1 +│   │   ├── defaults +│   │   │   └── main.yml +│   │   └── tasks +│   │   └── main.yml +│   └── functionality2 +│   ├── defaults +│   │   └── main.yml +│   └── tasks +│   └── main.yml +├── site.yml +└── vars + └── global_vars.yml +``` + +!!! Note Nota Sei libero di sviluppare i tuoi ruoli all'interno di una collezione + +## Test + +Avviamo il playbook ed eseguiamo alcuni test: + +``` +$ ansible-playbook -i inventories/production/hosts -e "target=client1" site.yml + +PLAY [Config Management for client1] **************************************************************************** + +TASK [Gathering Facts] ****************************************************************************************** +ok: [client1] + +TASK [roles/functionality1 : Task in functionality 1] ********************************************************* +ok: [client1] => { + "msg": "You are in functionality 1" +} + +TASK [roles/functionality2 : Task in functionality 2] ********************************************************* +skipping: [client1] + +PLAY RECAP ****************************************************************************************************** +client1 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 +``` + +Come puoi vedere, per impostazione predefinita, vengono giocate solo le attività del ruolo `functionality1`. + +Attiviamo nell'inventario la `functionality2` per il nostro nodo mirato e riavviamo il playbook: + +``` +$ vim inventories/production/host_vars/client1.yml +--- +enable_functionality2: true +``` + + +``` +$ ansible-playbook -i inventories/production/hosts -e "target=client1" site.yml + +PLAY [Config Management for client1] **************************************************************************** + +TASK [Gathering Facts] ****************************************************************************************** +ok: [client1] + +TASK [roles/functionality1 : Task in functionality 1] ********************************************************* +ok: [client1] => { + "msg": "You are in functionality 1" +} + +TASK [roles/functionality2 : Task in functionality 2] ********************************************************* +ok: [client1] => { + "msg": "You are in functionality 2" +} + +PLAY RECAP ****************************************************************************************************** +client1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +Prova ad applicare solo `funzionalità2`: + +``` +$ ansible-playbook -i inventories/production/hosts -e "target=client1" --tags functionality2 site.yml + +PLAY [Config Management for client1] **************************************************************************** + +TASK [Gathering Facts] ****************************************************************************************** +ok: [client1] + +TASK [roles/functionality2 : Task in functionality 2] ********************************************************* +ok: [client1] => { + "msg": "You are in functionality 2" +} + +PLAY RECAP ****************************************************************************************************** +client1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +Eseguiamo l'intero l'inventario: + +``` +$ ansible-playbook -i inventories/production/hosts -e "target=plateform" site.yml + +PLAY [Config Management for plateform] ************************************************************************** + +TASK [Gathering Facts] ****************************************************************************************** +ok: [client1] +ok: [client2] + +TASK [roles/functionality1 : Task in functionality 1] ********************************************************* +ok: [client1] => { + "msg": "You are in functionality 1" +} +ok: [client2] => { + "msg": "You are in functionality 1" +} + +TASK [roles/functionality2 : Task in functionality 2] ********************************************************* +ok: [client1] => { + "msg": "You are in functionality 2" +} +skipping: [client2] + +PLAY RECAP ****************************************************************************************************** +client1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +client2 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 +``` + +Come puoi vedere, `functionality2` è riprodotto solo sul `client1`. + +## Vantaggi + +Seguendo i consigli forniti nella documentazione Ansible otterrete rapidamente un: + +* codice sorgente facilmente mantenibile anche se contiene un gran numero di ruoli +* un sistema di conformità relativamente veloce, ripetibile che è possibile applicare parzialmente o completamente +* può essere adattato caso per caso e dai server +* le specifiche del vostro sistema informativo sono separate dal codice, facilmente controllabili, e centralizzate nei file di inventario della vostra gestione della configurazione. diff --git a/docs/books/learning_ansible/07-working-with-filters.it.md b/docs/books/learning_ansible/07-working-with-filters.it.md new file mode 100644 index 0000000000..1d55459671 --- /dev/null +++ b/docs/books/learning_ansible/07-working-with-filters.it.md @@ -0,0 +1,479 @@ +--- +title: Lavorare Con I Filtri +author: Antoine Le Morvan +contributors: Steven Spencer, Franco Colussi +update: 12-22-2021 +--- + +# Ansible - Lavorare con filtri + +In questo capitolo imparerai come trasformare i dati con i filtri jinja. + +**** + +**Obiettivi**: In questo capitolo imparerai come: + +:heavy_check_mark: Trasformare le strutture dati come dizionari o liste; +:heavy_check_mark: Trasformare variabili; + +:checkered_flag: **ansible**, **jinja**, **filtri** + +**Conoscenza**: :star: :star: :star: +**Complessità**: :star: :star: :star: :star: + +**Tempo di lettura**: 20 minuti + +**** + +Abbiamo già avuto la possibilità, durante i capitoli precedenti, di utilizzare i filtri jinja. + +Questi filtri, scritti in python, ci permettono di manipolare e trasformare le nostre variabili ansible. + +!!! Note Nota Ulteriori informazioni possono essere [trovate qui](https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html). + +In tutto questo capitolo, useremo il seguente playbook per testare i diversi filtri presentati: + +``` +- name: Manipulating the data + hosts: localhost + gather_facts: false + vars: + zero: 0 + zero_string: "0" + non_zero: 4 + true_booleen: True + true_non_booleen: "True" + false_boolean: False + false_non_boolean: "False" + whatever: "It's false!" + user_name: antoine + my_dictionary: + key1: value1 + key2: value2 + my_simple_list: + - value_list_1 + - value_list_2 + - value_list_3 + my_simple_list_2: + - value_list_3 + - value_list_4 + - value_list_5 + my_list: + - element: element1 + value: value1 + - element: element2 + value: value2 + + tasks: + - name: Print an integer + debug: + var: zero +``` + +!!! Note Nota Di seguito è riportato un elenco non esaustivo di filtri che è più probabile incontrare o necessari. Fortunatamente, ce ne sono molti altri. Potresti anche scrivere il tuo! + +Il playbook sarà riprodotto come segue: + +``` +ansible-playbook play-filter.yml +``` + +## Conversione dei dati + +I dati possono essere convertiti da un tipo all'altro. + +Per conoscere il tipo di dati (il tipo nel linguaggio python), è necessario utilizzare il filtro `type_debug`. + +Esempio: + +``` +- name: Display the type of a variable + debug: + var: true_boolean|type_debug +``` + +che ci fornisce: + +``` +TASK [Display the type of a variable] ****************************************************************** +ok: [localhost] => { + "true_boolean|type_debug": "bool" +} +``` + +È possibile trasformare un intero in una stringa: + +``` +- name: Transforming a variable type + debug: + var: zero|string +``` + +``` +TASK [Transforming a variable type] *************************************************************** +ok: [localhost] => { + "zero|string": "0" +} +``` + +Trasforma una stringa in un intero: + +``` +- name: Transforming a variable type + debug: + var: zero_string|int +``` + +oppure una variabile in un booleano: + +``` +- name: Display an integer as a boolean + debug: + var: non_zero | bool + +- name: Display a string as a boolean + debug: + var: true_non_boolean | bool + +- name: Display a string as a boolean + debug: + var: false_non_boolean | bool + +- name: Display a string as a boolean + debug: + var: whatever | bool + +``` + +Una stringa di caratteri può essere trasformata in maiuscolo o minuscolo: + +``` +- name: Lowercase a string of characters + debug: + var: whatever | lower + +- name: Upercase a string of characters + debug: + var: whatever | upper +``` + +che ci fornisce: + +``` +TASK [Lowercase a string of characters] ***************************************************** +ok: [localhost] => { + "whatever | lower": "it's false!" +} + +TASK [Upercase a string of characters] ***************************************************** +ok: [localhost] => { + "whatever | upper": "IT'S FALSE!" +} +``` + +Il filtro `replace` consente di sostituire i caratteri con altri. + +Qui rimuoviamo gli spazi o addirittura sostituiamo una parola: + +``` +- name: Replace a character in a string + debug: + var: whatever | replace(" ", "") + +- name: Replace a word in a string + debug: + var: whatever | replace("false", "true") +``` + +che ci fornisce: + +``` +TASK [Replace a character in a string] ***************************************************** +ok: [localhost] => { + "whatever | replace(\" \", \"\")": "It'sfalse!" +} + +TASK [Replace a word in a string] ***************************************************** +ok: [localhost] => { + "whatever | replace(\"false\", \"true\")": "It's true !" +} +``` + +Il filtro `split` divide una stringa in una lista in base a un carattere: + +``` +- name: Cutting a string of characters + debug: + var: whatever | split(" ", "") +``` + + +``` +TASK [Cutting a string of characters] ***************************************************** +ok: [localhost] => { + "whatever | split(\" \")": [ + "It's", + "false!" + ] +} +``` + +## Unire gli elementi di una lista + +È frequente dover unire i diversi elementi in una singola stringa. Possiamo quindi specificare un carattere o una stringa da inserire tra ogni elemento. + +``` +- name: Joining elements of a list + debug: + var: my_simple_list|join(",") + +- name: Joining elements of a list + debug: + var: my_simple_list|join(" | ") +``` + +che ci fornisce: + +``` +TASK [Joining elements of a list] ***************************************************************** +ok: [localhost] => { + "my_simple_list|join(\",\")": "value_list_1,value_list_2,value_list_3" +} + +TASK [Joining elements of a list] ***************************************************************** +ok: [localhost] => { + "my_simple_list|join(\" | \")": "value_list_1 | value_list_2 | value_list_3" +} + +``` + +## Trasformare dizionari in liste (e viceversa) + +I filtri `dict2items` and `itemstodict`, un po 'più complessi da implementare, sono frequentemente utilizzati, soprattutto nei cicli. + +Si noti che è possibile specificare il nome della chiave e del valore da usare nella trasformazione. + +``` +- name: Display a dictionary + debug: + var: my_dictionary + +- name: Transforming a dictionary into a list + debug: + var: my_dictionary | dict2items + +- name: Transforming a dictionary into a list + debug: + var: my_dictionary | dict2items(key_name='key', value_name='value') + +- name: Transforming a list into a dictionary + debug: + var: my_list | items2dict(key_name='element', value_name='value') +``` + +``` +TASK [Display a dictionary] ************************************************************************* +ok: [localhost] => { + "my_dictionary": { + "key1": "value1", + "key2": "value2" + } +} + +TASK [Transforming a dictionary into a list] ************************************************************* +ok: [localhost] => { + "my_dictionary | dict2items": [ + { + "key": "key1", + "value": "value1" + }, + { + "key": "key2", + "value": "value2" + } + ] +} + +TASK [Transforming a dictionary into a list] ************************************************************* +ok: [localhost] => { + "my_dictionary | dict2items (key_name = 'key', value_name = 'value')": [ + { + "key": "key1", + "value": "value1" + }, + { + "key": "key2", + "value": "value2" + } + ] +} + +TASK [Transforming a list into a dictionary] ************************************************************ +ok: [localhost] => { + "my_list | items2dict(key_name='element', value_name='value')": { + "element1": "value1", + "element2": "value2" + } +} +``` + +## Lavorare con liste + +È possibile unire o filtrare i dati da una o più liste: + +``` +- name: Merger of two lists + debug: + var: my_simple_list | union(my_simple_list_2) +``` + +``` +ok: [localhost] => { + "my_simple_list | union(my_simple_list_2)": [ + "value_list_1", + "value_list_2", + "value_list_3", + "value_list_4", + "value_list_5" + ] +} +``` + +Per mantenere solo l'intersezione dei 2 elenchi (i valori presenti nelle 2 liste): + +``` +- name: Merger of two lists + debug: + var: my_simple_list | intersect(my_simple_list_2) +``` + +``` +TASK [Merger of two lists] ******************************************************************************* +ok: [localhost] => { + "my_simple_list | intersect(my_simple_list_2)": [ + "value_list_3" + ] +} +``` + +O al contrario mantenere solo la differenza (i valori che non esistono nella seconda lista): + +``` +- name: Merger of two lists + debug: + var: my_simple_list | difference(my_simple_list_2) +``` + +``` +TASK [Merger of two lists] ******************************************************************************* +ok: [localhost] => { + "my_simple_list | difference(my_simple_list_2)": [ + "value_list_1", + "value_list_2", + ] +} +``` + +Se la tua lista contiene valori non univoci, è anche possibile filtrarli con il filtro `unique`. + +``` +- name: Unique value in a list + debug: + var: my_simple_list | unique +``` + +## Trasformazione json/yaml + +Potrebbe essere necessario importare i dati json (da un'API per esempio) o esportare i dati in yaml o json. + +``` +- name: Display a variable in yaml + debug: + var: my_list | to_nice_yaml(indent=4) + +- name: Display a variable in json + debug: + var: my_list | to_nice_json(indent=4) +``` + +``` +TASK [Display a variable in yaml] ******************************************************************** +ok: [localhost] => { + "my_list | to_nice_yaml(indent=4)": "- element: element1\n value: value1\n- element: element2\n value: value2\n" +} + +TASK [Display a variable in json] ******************************************************************** +ok: [localhost] => { + "my_list | to_nice_json(indent=4)": "[\n {\n \"element\": \"element1\",\n \"value\": \"value1\"\n },\n {\n \"element\": \"element2\",\n \"value\": \"value2\"\n }\n]" +} +``` + +## Valori predefiniti, variabili opzionali, proteggere le variabili + +Se non fornisci valori predefiniti per le tue variabili, ti troverai rapidamente di fronte a errori nell'esecuzione dei tuoi playbook, o se non li proteggi. + +Il valore di una variabile può essere sostituito con un'altra se non esiste con il filtro `default`: + +``` +- name: Default value + debug: + var: variablethatdoesnotexists | default(whatever) +``` + +``` +TASK [Default value] ******************************************************************************** +ok: [localhost] => { + "variablethatdoesnotexists | default(whatever)": "It's false!" +} +``` + +Nota la presenza dell'apostrofo `'` che dovrebbe essere protetto, per esempio, se usi il modulo `shell`: + +``` +- name: Default value + debug: + var: variablethatdoesnotexists | default(whatever| quote) +``` + +``` +TASK [Default value] ******************************************************************************** +ok: [localhost] => { + "variablethatdoesnotexists | default(whatever|quote)": "'It'\"'\"'s false!'" +} +``` + +Infine una variabile facoltativa in un modulo può essere ignorata se non esiste con la parola chiave `omit` nel filtro `default`, che ti salverà da un errore al runtime. + +``` +- name: Add a new user + ansible.builtin.user: + name: "{{ user_name }}" + comment: "{{ user_comment | default(omit) }}" +``` + +## Associa un valore in base ad un altro (`ternary`) + +A volte è necessario utilizzare una condizione per assegnare un valore a una variabile, in questo caso è comune passare attraverso un passaggio `set_fact`. + +Questo può essere evitato utilizzando il filtro `ternary`: + +``` +- name: Default value + debug: + var: (user_name == 'antoine') | ternary('admin', 'normal_user') +``` + +``` +TASK [Default value] ******************************************************************************** +ok: [localhost] => { + "(user_name == 'antoine') | ternary('admin', 'normal_user')": "admin" +} +``` + +## Altri filtri + + * `{{ 10000 | random }}`: come indica il suo nome, dà un valore casuale. + * `{{ my_simple_list | first }}`: estrae il primo elemento della lista. + * `{{ my_simple_list | length }}`: dà la lunghezza (di una lista o di una stringa). + * `{{ ip_list | ansible.netcommon.ipv4 }}`: visualizza solo gli IP v4. Senza soffermarsi su questo, se necessario, ci sono molti filtri dedicati alla rete. + * `{{ user_password | password_hash('sha512') }}`: genera una password hash in sha512.