A casa possiedo alcuni dispositivi IT che funzionano 24 ore su 24, 7 giorni su 7. Per tenerli aggiornati e installare gli aggiornamenti automaticamente, lascio il lavoro ad Ansible. Se sei completamente nuovo di Ansible, troverai una buona introduzione in:
- Iniziare con Ansible
- Demistificazione di Ansible per gli amministratori di sistema Linux
- Guida rapida agli amministratori di sistema di Ansible per Linux
La mia rete domestica include i seguenti dispositivi:
- Due Raspberry Pi con sistema operativo Raspbian
- Il mio host KVM con Debian 10 Buster
- Due host RHEL 8
- Un Synology DS213air
- Quattro host RHEL su una rete isolata
L'host contrassegnato dal quadrato rosso è il mio Ansible Control Node. Il suo compito è aggiornare il mio ambiente Linux. L'ho scelto perché questo host può raggiungere tutti gli altri host nell'ambiente. Altri host, ad esempio gli host Red Hat Enterprise Linux 7 (RHEL)-Ansible, sono in grado di raggiungere solo gli host all'interno della rete isolata.
[ Potrebbe piacerti anche: Come creare un Playbook Ansible ]
Prerequisiti
Su tutti i miei host è presente un account utente che può utilizzare sudo
per eseguire comandi con privilegi di root. Per comodità, ho creato una coppia di chiavi SSH e distribuito la chiave pubblica SSH agli host che vorrei aggiornare utilizzando Ansible. Se hai bisogno di aiuto per generare le chiavi SSH, controlla Utilizzo di ssh-keygen e condivisione per l'autenticazione basata su chiave in Linux di Tyler Carrigan.
Per utilizzare l'host RHEL8-Squid come nodo di controllo Ansible, dovrò abilitare un repository che fornisce Ansible e installarlo:
$ sudo subscription-manager repos --enable=ansible-2.9-for-rhel-8-x86_64-rpms
$ sudo dnf -y install ansible
Per altre distribuzioni, consulta la documentazione ufficiale.
Il file di configurazione predefinito di Ansible si trova in /etc/ansible/ansible.cfg
. Poiché questo file viene spedito e controllato dal pacchetto RPM, mi piace creare un file di configurazione personalizzato in ~/.ansible.cfg
semplicemente copiando quello originale e modificandolo. Ho apportato solo alcune modifiche:
$ egrep -v "^$|^#|^\[" ~/.ansible.cfg
inventory = ~/ansible/hosts
private_key_file = /home/user/.ssh/ansible_id_rsa
Come puoi vedere, ho creato un ansible
directory nella mia HOME
directory per archiviare il file di inventario del mio host. Ho anche specificato il percorso della chiave privata SSH che Ansible dovrebbe utilizzare per connettersi ai nodi della rete.
Con questa configurazione, tutta la magia è controllata dalla mia HOME
directory e non avrò bisogno di alcun privilegio di root sul mio Ansible Control Node per portare a termine il seguente lavoro.
Crea un file di inventario statico
In questo caso d'uso, utilizzo un file di inventario statico inserendo i miei host con il loro FQDN nel ~/ansible/hosts
file.
[special]
localhost
tower-pc.lan
[yum]
rhel7-ansible.private1
rhel7-t1.private1
rhel8-t1.private1
rpm-repo-r8.private1
podhost-r8-1.lan
[apt]
raspi-sht21.lan
pi-hole.lan
[ipkg]
diskstation.lan
Come puoi vedere, ho raggruppato gli host sulla mia rete in base al gestore di pacchetti che usano. Questo è utile durante la creazione del playbook per aggiornarli. Il gruppo [speciale] contiene il mio Ansible Control Node stesso e il mio hypervisor KVM, dove viene eseguito il mio Ansible Control Node.
Per ulteriori informazioni sull'inventario di Ansible, consulta:Come creare il tuo inventario.
Verifica la connettività
Prima di creare il playbook che aggiorna i miei host, controllo se il mio nodo di controllo Ansible RHEL8-Squid posso connettermi a tutti i miei host usando il seguente comando ad hoc:
$ ansible all -m ping -T 30
rhel7-t1.private1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
rhel7-ansible.private1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
rpm-repo-r8.private1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
rhel8-t1.private1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
podhost-r8-1.lan | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[WARNING]: Platform linux on host tower-pc.lan is using the discovered Python
interpreter at /usr/bin/python, but future installation of another Python
interpreter could change this. See https://docs.ansible.com/ansible/2.9/referen
ce_appendices/interpreter_discovery.html for more information.
tower-pc.lan | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[WARNING]: sftp transfer mechanism failed on [diskstation.lan]. Use
ANSIBLE_DEBUG=1 to see detailed information
[WARNING]: Platform linux on host diskstation.lan is using the discovered
Python interpreter at /usr/bin/python, but future installation of another
Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/
reference_appendices/interpreter_discovery.html for more information.
diskstation.lan | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[WARNING]: Platform linux on host pi-hole.lan is using the discovered Python
interpreter at /usr/bin/python, but future installation of another Python
interpreter could change this. See https://docs.ansible.com/ansible/2.9/referen
ce_appendices/interpreter_discovery.html for more information.
pi-hole.lan | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[WARNING]: Platform linux on host raspi-sht21.lan is using the discovered
Python interpreter at /usr/bin/python, but future installation of another
Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/
reference_appendices/interpreter_discovery.html for more information.
raspi-sht21.lan | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Il timeout predefinito per una connessione Ansible è 10 secondi. Perché la mia Synology Diskstation è in modalità standby per la maggior parte del tempo, sto usando l'opzione -T
per specificare un timeout di 30 secondi per dargli il tempo di svegliarsi.
Gli avvisi non mi danno fastidio in questo momento, quindi passo alla creazione del playbook.
Nel caso in cui desideri saperne di più sui comandi ad-hoc, leggi Introduzione ai comandi ad-hoc nei documenti ufficiali.
Il playbook
Il mio playbook contiene tre commedie. Ogni gioco esegue un'attività sugli host che appartengono a un determinato gruppo nel mio inventario tranne [speciale] . In questo semplice esempio, ogni riproduzione si connette a un gruppo di host, li aggiorna e li riavvia in seguito nel caso siano stati installati aggiornamenti.
Per determinare se sono stati installati aggiornamenti, registro le variabili che memorizzano i valori di ritorno delle attività in cui le ho registrate. Li uso per verificare se lo stato di un'attività è cambiato. In tal caso, il sistema verrà riavviato. Ecco il playbook:
---
- hosts: yum
tasks:
- name: Update all installed packages using YUM module
yum:
name: '*'
state: latest
update_cache: yes
update_only: yes
register: yum_update_status
- name: Remove packates not needed anymore
yum:
autoremove: yes
- name: Reboot when packages were updated
reboot:
when: yum_update_status.changed
- hosts: apt
tasks:
- name: Update all installed packages using APT module
apt:
name: '*'
state: latest
update_cache: yes
only_upgrade: yes
register: apt_update_status
- name: Remove packages not needed anymore
apt:
autoremove: yes
- name: Reboot when packages were updated
reboot:
post_reboot_delay: 60
when: apt_update_status.changed
- hosts: ipkg
tasks:
- name: Update the Packages installed on Diskstation
command: /opt/bin/ipkg update && /opt/bin/ipkg upgrade
Come avrai notato, la Diskstation non è stato riavviato. Questo perché solo gli strumenti dello spazio utente verranno aggiornati e non è necessario un riavvio. Se è disponibile una nuova versione del sistema operativo per Diskstation , lo aggiornerò manualmente perché non esiste ancora un modulo Ansible per esso. È una storia simile con gli host tower-pc.lan e rhel8-squid.lan . Li ho lasciati fuori da questo playbook apposta. Il mio nodo di controllo Ansible e il mio hypervisor KVM sono abbastanza importanti per me che li aggiornerò manualmente.
Ecco uno sguardo alla prima esecuzione del playbook:
$ ansible-playbook -T 30 -b --ask-become-pass pkg_update.yml
BECOME password:
PLAY [yum] **************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************
ok: [podhost-r8-1.lan]
ok: [rhel7-t1.private1]
ok: [rhel8-t1.private1]
ok: [rpm-repo-r8.private1]
ok: [rhel7-ansible.private1]
TASK [Update all installed packages using YUM module] *******************************************************************************************
ok: [rhel8-t1.private1]
ok: [podhost-r8-1.lan]
ok: [rpm-repo-r8.private1]
ok: [rhel7-t1.private1]
ok: [rhel7-ansible.private1]
TASK [Remove packates not needed anymore] *******************************************************************************************************
ok: [rhel7-t1.private1]
ok: [rhel7-ansible.private1]
ok: [rhel8-t1.private1]
ok: [podhost-r8-1.lan]
ok: [rpm-repo-r8.private1]
TASK [Reboot when packages were updated] ********************************************************************************************************
skipping: [rhel7-ansible.private1]
skipping: [rhel7-t1.private1]
skipping: [rhel8-t1.private1]
skipping: [rpm-repo-r8.private1]
skipping: [podhost-r8-1.lan]
PLAY [apt] **************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************
ok: [pi-hole.lan]
ok: [raspi-sht21.lan]
TASK [Update all installed packages using APT module] *******************************************************************************************
changed: [pi-hole.lan]
changed: [raspi-sht21.lan]
TASK [Remove packages not needed anymore] *******************************************************************************************************
ok: [pi-hole.lan]
ok: [raspi-sht21.lan]
TASK [Reboot when packages were updated] ********************************************************************************************************
changed: [pi-hole.lan]
changed: [raspi-sht21.lan]
PLAY [ipkg] *************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************
ok: [diskstation.lan]
TASK [Update the Packages installed on Diskstation] *********************************************************************************************
changed: [diskstation.lan]
PLAY RECAP **************************************************************************************************************************************
diskstation.lan : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
pi-hole.lan : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
podhost-r8-1.lan : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
raspi-sht21.lan : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
rhel7-ansible.private1 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
rhel7-t1.private1 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
rhel8-t1.private1 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
rpm-repo-r8.private1 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Come puoi vedere, le mie macchine RHEL erano già aggiornate. Niente da aggiornare o rimuovere e quindi nessun riavvio richiesto. Il mio Raspberry Pis, invece, aveva aggiornamenti disponibili e sono stati installati. Entrambi i dispositivi sono stati riavviati in seguito. La stazione disco il suo stato è cambiato , anche. Ma tieni presente che questo è perché sto usando il command
modulo, che restituisce modificato ogni volta che viene eseguito, indipendentemente dal fatto che qualcosa sul tuo nodo sia cambiato.
[ Una guida gratuita di Red Hat:5 passaggi per automatizzare il tuo business. ]
Concludi
In questo articolo, ti ho mostrato un esempio semplice ma non molto sofisticato di come mantengo aggiornati i miei dispositivi Linux a casa utilizzando l'automazione Ansible. Ti mostra come utilizzare i gruppi dal tuo inventario in diverse riproduzioni del tuo playbook utilizzando alcuni dei moduli Ansible e un semplice comando.