Automatizar Tareas de Administración de RHEL con Ansible

AnsibleBeginner
Practicar Ahora

Introducción

En este laboratorio integral, dominarás la automatización de tareas críticas de administración de Linux utilizando Ansible. Basándote en tu conocimiento de gestión de archivos, ahora explorarás cómo gestionar el ciclo de vida completo de la administración del sistema, desde la instalación de software hasta la gestión de usuarios, la configuración de servicios, el aprovisionamiento de almacenamiento y la configuración de red.

Comenzarás automatizando la gestión de paquetes de software y la configuración de repositorios utilizando módulos como ansible.builtin.dnf, ansible.builtin.yum_repository y ansible.builtin.rpm_key. A continuación, crearás y gestionarás cuentas de usuario, configurarás el acceso SSH y establecerás privilegios sudo. El laboratorio avanza a la gestión de servicios, tareas programadas con cron y systemd, antes de pasar a la gestión de almacenamiento utilizando LVM y operaciones de sistemas de archivos. Finalmente, configurarás interfaces de red y recopilarás información del sistema.

Este laboratorio enfatiza escenarios del mundo real que se encuentran comúnmente en entornos Linux empresariales, preparándote para implementar prácticas de Infraestructura como Código (Infrastructure as Code) de manera efectiva.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 86%. Ha recibido una tasa de reseñas positivas del 62% por parte de los estudiantes.

Configurar Repositorio y Gestionar Paquetes de Software

En este paso, aprenderás a automatizar la gestión de paquetes de software en sistemas RHEL utilizando Ansible. Configurarás un repositorio Yum, gestionarás claves GPG de RPM y recopilarás información de paquetes en los hosts gestionados. Esto es esencial para mantener instalaciones de software consistentes en tu infraestructura.

Utilizarás varios módulos clave: ansible.builtin.yum_repository para la gestión de repositorios, ansible.builtin.rpm_key para el manejo de claves GPG, ansible.builtin.package_facts para recopilar información de paquetes y ansible.builtin.dnf para la instalación de paquetes.

  1. Primero, configura el entorno del proyecto e instala Ansible.

    Instala el paquete ansible-core y navega al directorio del proyecto.

    sudo dnf install -y ansible-core
    cd ~/project
    mkdir system-software
    cd system-software
  2. Crea un archivo de inventario de Ansible para definir nuestros hosts gestionados. Para este laboratorio, gestionaremos la máquina local.

    cat << EOF > inventory.ini
    [webservers]
    localhost ansible_connection=local
    
    [all:children]
    webservers
    EOF
  3. Crea el playbook principal repo_playbook.yml que gestionará la configuración del repositorio y la instalación de paquetes. Este playbook demuestra un flujo de trabajo completo de gestión de software.

    nano repo_playbook.yml

    Añade el siguiente contenido para crear un playbook completo de gestión de software:

    ---
    - name: Repository Configuration and Software Management
      hosts: all
      become: true
      vars:
        custom_pkg: httpd
      tasks:
        - name: Gather Package Facts
          ansible.builtin.package_facts:
            manager: auto
    
        - name: Show Package Facts for the custom package (initial check)
          ansible.builtin.debug:
            var: ansible_facts['packages'][custom_pkg]
          when: custom_pkg in ansible_facts['packages']
    
        - name: Ensure EPEL repository is configured
          ansible.builtin.yum_repository:
            name: epel
            description: Extra Packages for Enterprise Linux 9
            file: epel
            baseurl: https://download.fedoraproject.org/pub/epel/9/Everything/x86_64/
            gpgcheck: yes
            gpgkey: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
            enabled: yes
            state: present
    
        - name: Import EPEL GPG key
          ansible.builtin.rpm_key:
            state: present
            key: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
    
        - name: Install the custom package
          ansible.builtin.dnf:
            name: "{{ custom_pkg }}"
            state: present
    
        - name: Gather Package Facts (after installation)
          ansible.builtin.package_facts:
            manager: auto
    
        - name: Show Package Facts for the custom package (post-installation)
          ansible.builtin.debug:
            var: ansible_facts['packages'][custom_pkg]
          when: custom_pkg in ansible_facts['packages']
    
        - name: Display installed package version
          ansible.builtin.debug:
            msg: "{{ custom_pkg }} version {{ ansible_facts['packages'][custom_pkg][0]['version'] }} is installed"
          when: custom_pkg in ansible_facts['packages']

    Nota: El archivo de configuración en este laboratorio es bastante extenso, por lo que no proporcionaremos explicaciones detalladas aquí para mantener la documentación concisa. Si necesitas aclaraciones sobre alguna parte, haz clic en el botón "Explain Code" en la esquina inferior izquierda del bloque de código para obtener explicaciones detalladas de Labby.

    Este playbook demuestra varios conceptos importantes:

    • Recopilación de hechos de paquetes: Muestra cómo recopilar información sobre paquetes instalados.
    • Gestión de repositorios: Configura el repositorio EPEL con validación GPG adecuada.
    • Gestión de claves GPG: Importa la clave GPG del repositorio para seguridad.
    • Instalación de paquetes: Instala el paquete especificado utilizando el módulo dnf.
    • Verificación: Confirma la instalación del paquete con hechos actualizados.
  4. Ejecuta el playbook para ver el flujo de trabajo completo de gestión de software en acción.

    ansible-playbook -i inventory.ini repo_playbook.yml

    Deberías ver una salida que muestre:

    • Comprobación inicial del paquete (probablemente omitida ya que httpd no está instalado).
    • Configuración del repositorio.
    • Importación de la clave GPG.
    • Instalación del paquete.
    • Verificación final que muestra el paquete instalado.
  5. Verifica la configuración del repositorio comprobando el archivo de repositorio creado.

    cat /etc/yum.repos.d/epel.repo

    Deberías ver la configuración del repositorio EPEL con los ajustes de baseurl, gpgcheck y gpgkey.

  6. Prueba la idempotencia de la gestión de paquetes ejecutando el playbook nuevamente.

    ansible-playbook -i inventory.ini repo_playbook.yml

    Observa que Ansible informa "ok" para las tareas que no necesitan cambios, lo que demuestra la idempotencia.

Has automatizado con éxito la gestión de paquetes de software, incluida la configuración del repositorio, la gestión de claves GPG y la verificación de la instalación de paquetes utilizando Ansible.

Automatizar la Gestión de Usuarios y la Configuración de SSH

En este paso, aprenderás a automatizar la gestión de cuentas de usuario, la configuración de SSH y los privilegios sudo utilizando Ansible. Esto es crucial para mantener políticas de acceso y seguridad de usuarios consistentes en tu infraestructura.

Utilizarás módulos como ansible.builtin.user para la gestión de usuarios, ansible.builtin.group para la creación de grupos, ansible.posix.authorized_key para la gestión de claves SSH y ansible.builtin.lineinfile para la modificación de archivos de configuración.

  1. Navega a un nuevo directorio de proyecto para las tareas de gestión de usuarios.

    cd ~/project
    mkdir system-users
    cd system-users

    Instala la colección ansible.posix.

    ansible-galaxy collection install ansible.posix
  2. Crea el archivo de inventario para este ejercicio.

    cat << EOF > inventory.ini
    [webservers]
    localhost ansible_connection=local
    EOF
  3. Crea un archivo de variables para definir los usuarios y grupos que queremos gestionar.

    mkdir vars
    nano vars/users_vars.yml

    Añade el siguiente contenido para definir las cuentas de usuario y sus pertenencias a grupos:

    ---
    users:
      - username: webuser1
        groups: webadmin
      - username: webuser2
        groups: webadmin
      - username: devuser1
        groups: webadmin
  4. Genera pares de claves SSH para nuestros usuarios. En un entorno real, los usuarios proporcionarían sus claves públicas.

    mkdir files
    
    ## Genera claves SSH para cada usuario
    ssh-keygen -t rsa -b 2048 -f files/webuser1.key -N "" -C "webuser1@example.com"
    ssh-keygen -t rsa -b 2048 -f files/webuser2.key -N "" -C "webuser2@example.com"
    ssh-keygen -t rsa -b 2048 -f files/devuser1.key -N "" -C "devuser1@example.com"
  5. Crea el playbook principal de gestión de usuarios users.yml. Este playbook creará grupos, usuarios, distribuirá claves SSH y configurará el acceso sudo.

    nano users.yml

    Añade el siguiente playbook completo de gestión de usuarios:

    ---
    - name: Create and manage user accounts
      hosts: webservers
      become: true
      vars_files:
        - vars/users_vars.yml
      tasks:
        - name: Create webadmin group
          ansible.builtin.group:
            name: webadmin
            state: present
    
        - name: Create user accounts
          ansible.builtin.user:
            name: "{{ item['username'] }}"
            groups: "{{ item['groups'] }}"
            shell: /bin/bash
            create_home: yes
            state: present
          loop: "{{ users }}"
    
        - name: Set up SSH authorized keys
          ansible.posix.authorized_key:
            user: "{{ item['username'] }}"
            key: "{{ lookup('file', 'files/' + item['username'] + '.key.pub') }}"
            state: present
          loop: "{{ users }}"
    
        - name: Configure sudo access for webadmin group
          ansible.builtin.lineinfile:
            path: /etc/sudoers.d/webadmin
            state: present
            create: yes
            mode: "0440"
            line: "%webadmin ALL=(ALL) NOPASSWD: ALL"
            validate: /usr/sbin/visudo -cf %s
    
        - name: Configure SSH to disable root login
          ansible.builtin.lineinfile:
            dest: /etc/ssh/sshd_config
            regexp: "^PermitRootLogin"
            line: "PermitRootLogin no"
            backup: yes
          notify: restart sshd
    
        - name: Configure SSH to disable password authentication
          ansible.builtin.lineinfile:
            dest: /etc/ssh/sshd_config
            regexp: "^PasswordAuthentication"
            line: "PasswordAuthentication no"
            backup: yes
          notify: restart sshd
    
      handlers:
        - name: restart sshd
          ansible.builtin.service:
            name: sshd
            state: restarted

    Este playbook demuestra varias mejores prácticas de gestión de usuarios:

    • Gestión de grupos: Crea grupos administrativos.
    • Creación de usuarios: Configura cuentas de usuario con directorios de inicio adecuados.
    • Gestión de claves SSH: Distribuye claves públicas para la autenticación basada en claves.
    • Configuración de Sudo: Otorga privilegios administrativos de forma segura.
    • Fortalecimiento de SSH: Deshabilita el inicio de sesión root y la autenticación por contraseña.
    • Gestión de servicios: Reinicia el servicio SSH cuando cambian las configuraciones.
  6. Ejecuta el playbook de gestión de usuarios.

    ansible-playbook -i inventory.ini users.yml

    El playbook creará usuarios, configurará claves SSH, establecerá acceso sudo y fortalecerá la configuración de SSH.

  7. Verifica la creación de usuarios y la pertenencia a grupos.

    ## Comprueba si se crearon los usuarios
    getent passwd webuser1 webuser2 devuser1
    
    ## Comprueba la pertenencia a grupos
    groups webuser1
    groups webuser2
    groups devuser1
    
    ## Verifica que existe el grupo webadmin
    getent group webadmin
  8. Prueba la autenticación por clave SSH para uno de los usuarios creados.

    ## Prueba la autenticación por clave SSH (esto se conectará a localhost)
    ssh -i files/webuser1.key webuser1@localhost "whoami"
  9. Verifica la configuración de sudo probando el acceso sudo sin contraseña.

    ## Prueba el acceso sudo para webuser1
    ssh -i files/webuser1.key webuser1@localhost "sudo whoami"
  10. Comprueba los cambios en la configuración de SSH.

    ## Verifica la configuración de SSH
    sudo grep "PermitRootLogin\|PasswordAuthentication" /etc/ssh/sshd_config
    
    ## Comprueba la configuración de sudo
    sudo cat /etc/sudoers.d/webadmin

Has automatizado con éxito la creación de cuentas de usuario, la distribución de claves SSH y la configuración de seguridad utilizando Ansible, estableciendo una base para una gestión de usuarios segura en tu infraestructura.

Automatizar la Gestión de Servicios y la Programación de Tareas

En este paso, aprenderás a gestionar servicios systemd, programar trabajos cron y configurar objetivos de arranque del sistema utilizando Ansible. Esto es esencial para mantener la disponibilidad del servicio y automatizar tareas rutinarias en tu infraestructura.

Utilizarás módulos como ansible.builtin.service para la gestión de servicios, ansible.builtin.cron para la programación de tareas, ansible.posix.at para tareas únicas y ansible.builtin.systemd para la gestión de objetivos del sistema.

  1. Navega a un nuevo directorio de proyecto para la gestión de servicios y procesos.

    cd ~/project
    mkdir system-process
    cd system-process
  2. Crea el archivo de inventario para este ejercicio.

    cat << EOF > inventory.ini
    [webservers]
    localhost ansible_connection=local
    EOF
  3. Crea un playbook para gestionar el servicio del servidor web Apache HTTP. Esto demostrará la gestión básica de servicios.

    nano service_management.yml

    Añade el siguiente contenido:

    ---
    - name: Manage Apache HTTP Server Service
      hosts: webservers
      become: true
      tasks:
        - name: Start and enable httpd service
          ansible.builtin.service:
            name: httpd
            state: started
            enabled: yes
    
        - name: Create a simple index.html
          ansible.builtin.copy:
            content: |
              <html>
              <head><title>Ansible Managed Server</title></head>
              <body>
              <h1>Welcome to Ansible Managed Apache Server</h1>
              <p>This server is configured and managed by Ansible.</p>
              <p>Service started at: $(date)</p>
              </body>
              </html>
            dest: /var/www/html/index.html
            owner: apache
            group: apache
            mode: "0644"
    
        - name: Verify httpd service is running
          ansible.builtin.service_facts:
    
        - name: Display httpd service status
          ansible.builtin.debug:
            var: ansible_facts.services['httpd.service']
  4. Crea un playbook para programar trabajos cron. Esto demuestra la programación automatizada de tareas.

    nano create_crontab_file.yml

    Añade el siguiente contenido:

    ---
    - name: Schedule recurring cron jobs
      hosts: webservers
      become: true
      tasks:
        - name: Create labex user for cron jobs
          ansible.builtin.user:
            name: labex
            state: present
            create_home: yes
    
        - name: Schedule system monitoring cron job
          ansible.builtin.cron:
            name: System monitoring log
            job: "date >> /home/labex/system_monitor.log && df -h >> /home/labex/system_monitor.log"
            minute: "*/5"
            hour: "*"
            user: labex
            cron_file: system-monitoring
            state: present
    
        - name: Schedule daily log rotation
          ansible.builtin.cron:
            name: Daily log cleanup
            job: "find /home/labex -name '*.log' -mtime +7 -delete"
            minute: "0"
            hour: "2"
            weekday: "*"
            user: labex
            cron_file: log-cleanup
            state: present
    
        - name: Schedule weekly system update check
          ansible.builtin.cron:
            name: Weekly update check
            job: "dnf check-update > /home/labex/update_check.log 2>&1"
            minute: "0"
            hour: "3"
            weekday: "0"
            user: labex
            cron_file: update-check
            state: present
  5. Crea un playbook para la programación de tareas únicas utilizando at.

    nano schedule_at_task.yml

    Añade el siguiente contenido:

    ---
    - name: Schedule one-time tasks with at
      hosts: webservers
      become: true
      become_user: labex
      tasks:
        - name: Schedule immediate system info collection
          ansible.posix.at:
            command: "uname -a > ~/system_info_$(date +%Y%m%d_%H%M%S).txt"
            count: 2
            units: minutes
            unique: yes
            state: present
    
        - name: Schedule delayed service status check
          ansible.posix.at:
            command: "systemctl status httpd > ~/httpd_status_$(date +%Y%m%d_%H%M%S).txt"
            count: 5
            units: minutes
            unique: yes
            state: present
  6. Crea un playbook para gestionar los objetivos de arranque del sistema.

    nano boot_target_management.yml

    Añade el siguiente contenido:

    ---
    - name: Manage system boot targets
      hosts: webservers
      become: true
      tasks:
        - name: Check current default target
          ansible.builtin.command:
            cmd: systemctl get-default
          register: current_target
          changed_when: false
    
        - name: Display current boot target
          ansible.builtin.debug:
            msg: "Current default boot target: {{ current_target.stdout }}"
    
        - name: Set default boot target to multi-user
          ansible.builtin.systemd:
            name: multi-user.target
            enabled: yes
          when: current_target.stdout != "multi-user.target"
    
        - name: Verify the boot target change
          ansible.builtin.command:
            cmd: systemctl get-default
          register: new_target
          changed_when: false
    
        - name: Display new boot target
          ansible.builtin.debug:
            msg: "New default boot target: {{ new_target.stdout }}"
  7. Ejecuta el playbook de gestión de servicios.

    ansible-playbook -i inventory.ini service_management.yml

    Esto iniciará el servicio httpd y creará una página de bienvenida.

  8. Ejecuta el playbook de programación de trabajos cron.

    ansible-playbook -i inventory.ini create_crontab_file.yml

    Esto creará varias tareas programadas para la monitorización y el mantenimiento del sistema.

  9. Ejecuta el playbook de programación de tareas únicas.

    ansible-playbook -i inventory.ini schedule_at_task.yml

    Esto programará tareas inmediatas utilizando el comando at.

  10. Ejecuta el playbook de gestión de objetivos de arranque.

    ansible-playbook -i inventory.ini boot_target_management.yml

    Esto comprobará y potencialmente modificará el objetivo de arranque predeterminado del sistema.

  11. Verifica las tareas programadas y los servicios.

    ## Comprueba los trabajos cron
    sudo cat /etc/cron.d/system-monitoring
    sudo cat /etc/cron.d/log-cleanup
    sudo cat /etc/cron.d/update-check
    
    ## Comprueba los trabajos at
    sudo atq
    
    ## Comprueba el estado del servicio httpd
    sudo systemctl status httpd
    
    ## Prueba el servidor web
    curl localhost
    
    ## Comprueba el registro de monitorización del sistema (espera unos minutos a que se ejecute cron)
    sudo cat /home/labex/system_monitor.log
  12. Crea un playbook de limpieza para eliminar las tareas programadas cuando sea necesario.

    nano remove_scheduled_tasks.yml

    Añade el siguiente contenido:

    ---
    - name: Remove scheduled tasks
      hosts: webservers
      become: true
      tasks:
        - name: Remove system monitoring cron job
          ansible.builtin.cron:
            name: System monitoring log
            user: labex
            cron_file: system-monitoring
            state: absent
    
        - name: Remove log cleanup cron job
          ansible.builtin.cron:
            name: Daily log cleanup
            user: labex
            cron_file: log-cleanup
            state: absent
    
        - name: Remove update check cron job
          ansible.builtin.cron:
            name: Weekly update check
            user: labex
            cron_file: update-check
            state: absent

Has automatizado con éxito la gestión de servicios, la programación de tareas y la configuración del sistema utilizando Ansible, proporcionando la base para mantener y monitorizar tu infraestructura de forma automática.

Automatizar la Gestión de Almacenamiento con LVM y Sistemas de Archivos

En este paso, aprenderás a automatizar la gestión de almacenamiento utilizando Ansible para crear volúmenes físicos LVM (physical volumes), grupos de volúmenes (volume groups), volúmenes lógicos (logical volumes) y sistemas de archivos (filesystems). Esto es crucial para gestionar los recursos de almacenamiento en tu infraestructura de manera consistente y escalable.

Utilizarás módulos como ansible.builtin.lvg para la gestión de grupos de volúmenes, ansible.builtin.lvol para la creación de volúmenes lógicos, ansible.builtin.filesystem para la creación de sistemas de archivos y ansible.posix.mount para la gestión de puntos de montaje.

  1. Navega a un nuevo directorio de proyecto para la gestión de almacenamiento.

    cd ~/project
    mkdir system-storage
    cd system-storage
  2. Crea el archivo de inventario para este ejercicio.

    cat << EOF > inventory.ini
    [webservers]
    localhost ansible_connection=local
    EOF
  3. Crea un dispositivo de bucle (loop device) para simular almacenamiento adicional, ya que estamos trabajando en un entorno virtual.

    ## Crea un archivo de 1GB para usarlo como disco virtual
    sudo dd if=/dev/zero of=/tmp/virtual_disk bs=1M count=1024
    
    ## Configura el dispositivo de bucle
    sudo losetup /dev/loop0 /tmp/virtual_disk
    
    ## Verifica el dispositivo de bucle
    lsblk | grep loop0
  4. Crea un playbook integral de gestión de almacenamiento. Esto demostrará las operaciones de LVM y la gestión de sistemas de archivos.

    nano storage.yml

    Añade el siguiente contenido:

    ---
    - name: Configure LVM storage and filesystems
      hosts: webservers
      become: true
      vars:
        storage_device: /dev/loop0
        volume_group: apache-vg
        content_lv: content-lv
        logs_lv: logs-lv
        backup_lv: backup-lv
      tasks:
        - name: Install LVM utilities
          ansible.builtin.dnf:
            name: lvm2
            state: present
    
        - name: Create physical volume
          community.general.lvg:
            vg: "{{ volume_group }}"
            pvs: "{{ storage_device }}"
            state: present
    
        - name: Create logical volume for web content
          community.general.lvol:
            vg: "{{ volume_group }}"
            lv: "{{ content_lv }}"
            size: 256m
            state: present
    
        - name: Create logical volume for logs
          community.general.lvol:
            vg: "{{ volume_group }}"
            lv: "{{ logs_lv }}"
            size: 256m
            state: present
    
        - name: Create logical volume for backup
          community.general.lvol:
            vg: "{{ volume_group }}"
            lv: "{{ backup_lv }}"
            size: 256m
            state: present
    
        - name: Create XFS filesystem on content volume
          community.general.filesystem:
            fstype: xfs
            dev: "/dev/{{ volume_group }}/{{ content_lv }}"
            force: no
    
        - name: Create XFS filesystem on logs volume
          community.general.filesystem:
            fstype: xfs
            dev: "/dev/{{ volume_group }}/{{ logs_lv }}"
            force: no
    
        - name: Create ext4 filesystem on backup volume
          community.general.filesystem:
            fstype: ext4
            dev: "/dev/{{ volume_group }}/{{ backup_lv }}"
            force: no
    
        - name: Create mount points
          ansible.builtin.file:
            path: "{{ item }}"
            state: directory
            mode: "0755"
          loop:
            - /var/www
            - /var/log/httpd
            - /backup
    
        - name: Mount web content volume
          ansible.posix.mount:
            path: /var/www
            src: "/dev/{{ volume_group }}/{{ content_lv }}"
            fstype: xfs
            opts: defaults
            state: mounted
    
        - name: Mount logs volume
          ansible.posix.mount:
            path: /var/log/httpd
            src: "/dev/{{ volume_group }}/{{ logs_lv }}"
            fstype: xfs
            opts: defaults
            state: mounted
    
        - name: Mount backup volume
          ansible.posix.mount:
            path: /backup
            src: "/dev/{{ volume_group }}/{{ backup_lv }}"
            fstype: ext4
            opts: defaults
            state: mounted
    
        - name: Set appropriate ownership for web content
          ansible.builtin.file:
            path: /var/www
            owner: apache
            group: apache
            recurse: yes
    
        - name: Set appropriate ownership for httpd logs
          ansible.builtin.file:
            path: /var/log/httpd
            owner: apache
            group: apache
            recurse: yes
    
        - name: Create html directory for web content
          ansible.builtin.file:
            path: /var/www/html
            state: directory
            owner: apache
            group: apache
            mode: "0755"
    
        - name: Create sample web content
          ansible.builtin.copy:
            content: |
              <html>
              <head><title>Storage Management Demo</title></head>
              <body>
              <h1>LVM Storage Configuration</h1>
              <p>This content is served from an LVM logical volume managed by Ansible.</p>
              <p>Volume Group: {{ volume_group }}</p>
              <p>Logical Volume: {{ content_lv }}</p>
              <p>Filesystem: XFS</p>
              </body>
              </html>
            dest: /var/www/html/storage.html
            owner: apache
            group: apache
            mode: "0644"
  5. Instala la colección Ansible requerida para la gestión de LVM.

    ansible-galaxy collection install community.general
  6. Ejecuta el playbook de gestión de almacenamiento.

    ansible-playbook -i inventory.ini storage.yml

    Esto creará la estructura LVM, los sistemas de archivos y los puntos de montaje.

  7. Crea un playbook para recopilar y mostrar información de almacenamiento.

    nano get-storage.yml

    Añade el siguiente contenido:

    ---
    - name: Gather storage information
      hosts: webservers
      become: true
      tasks:
        - name: Gather disk facts
          ansible.builtin.setup:
            gather_subset:
              - hardware
    
        - name: Display volume group information
          ansible.builtin.command:
            cmd: vgdisplay apache-vg
          register: vg_info
          changed_when: false
    
        - name: Display logical volume information
          ansible.builtin.command:
            cmd: lvdisplay apache-vg
          register: lv_info
          changed_when: false
    
        - name: Display filesystem information
          ansible.builtin.command:
            cmd: df -h /var/www /var/log/httpd /backup
          register: fs_info
          changed_when: false
    
        - name: Display mount information
          ansible.builtin.command:
            cmd: cat /proc/mounts
          register: mount_info
          changed_when: false
    
        - name: Show volume group details
          ansible.builtin.debug:
            var: vg_info.stdout_lines
    
        - name: Show logical volume details
          ansible.builtin.debug:
            var: lv_info.stdout_lines
    
        - name: Show filesystem usage
          ansible.builtin.debug:
            var: fs_info.stdout_lines
    
        - name: Show fstab entries
          ansible.builtin.command:
            cmd: grep apache-vg /etc/fstab
          register: fstab_entries
          changed_when: false
          failed_when: false
    
        - name: Display fstab entries
          ansible.builtin.debug:
            var: fstab_entries.stdout_lines
  8. Ejecuta el playbook de recopilación de información de almacenamiento.

    ansible-playbook -i inventory.ini get-storage.yml

    Esto mostrará información detallada sobre la estructura de almacenamiento creada.

  9. Verifica la configuración de almacenamiento manualmente.

    ## Comprueba la estructura LVM
    sudo vgs apache-vg
    sudo lvs apache-vg
    sudo pvs /dev/loop0
    
    ## Comprueba los sistemas de archivos
    df -h /var/www /var/log/httpd /backup
    
    ## Comprueba los puntos de montaje
    mount | grep apache-vg
    
    ## Comprueba las entradas de fstab
    grep apache-vg /etc/fstab
    
    ## Prueba el contenido web
    cat /var/www/html/storage.html
  10. Crea un playbook de expansión de almacenamiento para demostrar las operaciones de escalado.

    nano expand_storage.yml

    Añade el siguiente contenido:

    ---
    - name: Expand storage volumes
      hosts: webservers
      become: true
      vars:
        volume_group: apache-vg
        content_lv: content-lv
      tasks:
        - name: Extend content logical volume
          community.general.lvol:
            vg: "{{ volume_group }}"
            lv: "{{ content_lv }}"
            size: 400m
            state: present
    
        - name: Extend XFS filesystem
          community.general.filesystem:
            fstype: xfs
            dev: "/dev/{{ volume_group }}/{{ content_lv }}"
            resizefs: yes
    
        - name: Display updated filesystem size
          ansible.builtin.command:
            cmd: df -h /var/www
          register: new_size
          changed_when: false
    
        - name: Show new filesystem size
          ansible.builtin.debug:
            var: new_size.stdout_lines
  11. Prueba la expansión del almacenamiento.

    ## Comprueba el tamaño actual antes de la expansión
    df -h /var/www
    
    ## Ejecuta el playbook de expansión
    ansible-playbook -i inventory.ini expand_storage.yml
    
    ## Verifica la expansión
    df -h /var/www
    sudo lvs apache-vg/content-lv

Has automatizado con éxito la gestión de almacenamiento LVM, incluyendo la creación de volúmenes físicos, la gestión de volúmenes lógicos, la creación de sistemas de archivos y la configuración de puntos de montaje utilizando Ansible.

Automatizar la Configuración de Red y la Recopilación de Información

En este último paso, aprenderás a automatizar la configuración de interfaces de red y a recopilar información completa del sistema utilizando Ansible. Esto completa el espectro total de la automatización de la administración del sistema, desde el software hasta el almacenamiento y las redes.

Utilizarás módulos como ansible.builtin.template para archivos de configuración de red, recopilarás datos de red (facts) y crearás informes completos del sistema.

  1. Navega a un nuevo directorio de proyecto para la gestión de red.

    cd ~/project
    mkdir system-network
    cd system-network
  2. Crea el archivo de inventario para este ejercicio.

    cat << EOF > inventory.ini
    [webservers]
    localhost ansible_connection=local
    EOF
  3. Crea un playbook integral de recopilación de información de red y del sistema.

    nano network_info.yml

    Añade el siguiente contenido:

    ---
    - name: Gather comprehensive system information
      hosts: webservers
      become: true
      tasks:
        - name: Gather all system facts
          ansible.builtin.setup:
    
        - name: Create system report directory
          ansible.builtin.file:
            path: /tmp/system_reports
            state: directory
            mode: "0755"
    
        - name: Generate system information report
          ansible.builtin.template:
            src: system_report.j2
            dest: /tmp/system_reports/system_info_{{ ansible_facts['hostname'] }}.html
            mode: "0644"
    
        - name: Generate network configuration report
          ansible.builtin.template:
            src: network_report.j2
            dest: /tmp/system_reports/network_info_{{ ansible_facts['hostname'] }}.html
            mode: "0644"
    
        - name: Collect network interface information
          ansible.builtin.command:
            cmd: ip addr show
          register: ip_info
          changed_when: false
    
        - name: Collect routing information
          ansible.builtin.command:
            cmd: ip route show
          register: route_info
          changed_when: false
    
        - name: Collect DNS configuration
          ansible.builtin.command:
            cmd: cat /etc/resolv.conf
          register: dns_info
          changed_when: false
    
        - name: Display network summary
          ansible.builtin.debug:
            msg: |
              System: {{ ansible_facts['hostname'] }}
              OS: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}
              Kernel: {{ ansible_facts['kernel'] }}
              Default IPv4: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }}
              Default Interface: {{ ansible_facts['default_ipv4']['interface'] | default('N/A') }}
              Total Memory: {{ ansible_facts['memtotal_mb'] }}MB
              CPU Cores: {{ ansible_facts['processor_vcpus'] }}
  4. Crea directorios y archivos de plantilla para los informes.

    mkdir templates
    nano templates/system_report.j2

    Añade el siguiente contenido para la plantilla del informe del sistema:

    <!doctype html>
    <html>
      <head>
        <title>System Report - {{ ansible_facts['hostname'] }}</title>
        <style>
          body {
            font-family: Arial, sans-serif;
            margin: 20px;
          }
          .section {
            margin-bottom: 20px;
            padding: 10px;
            border: 1px solid #ccc;
          }
          .header {
            background-color: #f5f5f5;
            padding: 10px;
          }
          table {
            border-collapse: collapse;
            width: 100%;
          }
          th,
          td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
          }
          th {
            background-color: #f2f2f2;
          }
        </style>
      </head>
      <body>
        <div class="header">
          <h1>System Report for {{ ansible_facts['hostname'] }}</h1>
          <p>
            Generated on: {{ ansible_date_time.date }} {{ ansible_date_time.time
            }}
          </p>
        </div>
    
        <div class="section">
          <h2>System Information</h2>
          <table>
            <tr>
              <th>Property</th>
              <th>Value</th>
            </tr>
            <tr>
              <td>Hostname</td>
              <td>{{ ansible_facts['hostname'] }}</td>
            </tr>
            <tr>
              <td>FQDN</td>
              <td>{{ ansible_facts['fqdn'] }}</td>
            </tr>
            <tr>
              <td>Operating System</td>
              <td>
                {{ ansible_facts['distribution'] }} {{
                ansible_facts['distribution_version'] }}
              </td>
            </tr>
            <tr>
              <td>Kernel</td>
              <td>{{ ansible_facts['kernel'] }}</td>
            </tr>
            <tr>
              <td>Architecture</td>
              <td>{{ ansible_facts['architecture'] }}</td>
            </tr>
            <tr>
              <td>CPU Cores</td>
              <td>{{ ansible_facts['processor_vcpus'] }}</td>
            </tr>
            <tr>
              <td>Total Memory</td>
              <td>{{ ansible_facts['memtotal_mb'] }}MB</td>
            </tr>
            <tr>
              <td>Uptime</td>
              <td>{{ ansible_facts['uptime_seconds'] }} seconds</td>
            </tr>
          </table>
        </div>
    
        <div class="section">
          <h2>Storage Information</h2>
          <table>
            <tr>
              <th>Mount Point</th>
              <th>Filesystem</th>
              <th>Size</th>
              <th>Used</th>
              <th>Available</th>
            </tr>
            {% for mount in ansible_facts['mounts'] %}
            <tr>
              <td>{{ mount.mount }}</td>
              <td>{{ mount.fstype }}</td>
              <td>
                {{ (mount.size_total / 1024 / 1024 / 1024) | round(2) }}GB
              </td>
              <td>
                {{ ((mount.size_total - mount.size_available) / 1024 / 1024 /
                1024) | round(2) }}GB
              </td>
              <td>
                {{ (mount.size_available / 1024 / 1024 / 1024) | round(2) }}GB
              </td>
            </tr>
            {% endfor %}
          </table>
        </div>
    
        <div class="section">
          <h2>Services Status</h2>
          <table>
            <tr>
              <th>Service</th>
              <th>Status</th>
            </tr>
            <tr>
              <td>httpd</td>
              <td>
                {{ ansible_facts.services['httpd.service']['state'] |
                default('not installed') }}
              </td>
            </tr>
            <tr>
              <td>sshd</td>
              <td>
                {{ ansible_facts.services['sshd.service']['state'] |
                default('unknown') }}
              </td>
            </tr>
            <tr>
              <td>NetworkManager</td>
              <td>
                {{ ansible_facts.services['NetworkManager.service']['state'] |
                default('unknown') }}
              </td>
            </tr>
          </table>
        </div>
      </body>
    </html>
  5. Crea la plantilla del informe de red.

    nano templates/network_report.j2

    Añade el siguiente contenido:

    <!doctype html>
    <html>
      <head>
        <title>Network Report - {{ ansible_facts['hostname'] }}</title>
        <style>
          body {
            font-family: Arial, sans-serif;
            margin: 20px;
          }
          .section {
            margin-bottom: 20px;
            padding: 10px;
            border: 1px solid #ccc;
          }
          .header {
            background-color: #f5f5f5;
            padding: 10px;
          }
          table {
            border-collapse: collapse;
            width: 100%;
          }
          th,
          td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
          }
          th {
            background-color: #f2f2f2;
          }
          pre {
            background-color: #f9f9f9;
            padding: 10px;
            overflow-x: auto;
          }
        </style>
      </head>
      <body>
        <div class="header">
          <h1>Network Configuration Report</h1>
          <p>Host: {{ ansible_facts['hostname'] }}</p>
          <p>
            Generated on: {{ ansible_date_time.date }} {{ ansible_date_time.time
            }}
          </p>
        </div>
    
        <div class="section">
          <h2>Network Interfaces</h2>
          <table>
            <tr>
              <th>Interface</th>
              <th>IPv4 Address</th>
              <th>IPv6 Address</th>
              <th>MAC Address</th>
              <th>Status</th>
            </tr>
            {% for interface_name in ansible_facts['interfaces'] %} {% if
            interface_name != 'lo' %} {% set interface_facts =
            ansible_facts[interface_name] %}
            <tr>
              <td>{{ interface_name }}</td>
              <td>
                {{ interface_facts.get('ipv4', {}).get('address', 'N/A') }}
              </td>
              <td>
                {{ interface_facts.get('ipv6', [{}])[0].get('address', 'N/A') if
                interface_facts.get('ipv6') else 'N/A' }}
              </td>
              <td>{{ interface_facts.get('macaddress', 'N/A') }}</td>
              <td>
                {{ interface_facts.get('active', false) | ternary('Active',
                'Inactive') }}
              </td>
            </tr>
            {% endif %} {% endfor %}
          </table>
        </div>
    
        <div class="section">
          <h2>Default Gateway</h2>
          <table>
            <tr>
              <th>Property</th>
              <th>Value</th>
            </tr>
            <tr>
              <td>Default IPv4 Address</td>
              <td>
                {{ ansible_facts['default_ipv4']['address'] | default('N/A') }}
              </td>
            </tr>
            <tr>
              <td>Default Interface</td>
              <td>
                {{ ansible_facts['default_ipv4']['interface'] | default('N/A')
                }}
              </td>
            </tr>
            <tr>
              <td>Default Gateway</td>
              <td>
                {{ ansible_facts['default_ipv4']['gateway'] | default('N/A') }}
              </td>
            </tr>
          </table>
        </div>
    
        <div class="section">
          <h2>DNS Configuration</h2>
          <table>
            <tr>
              <th>DNS Servers</th>
            </tr>
            {% for dns in ansible_facts['dns']['nameservers'] %}
            <tr>
              <td>{{ dns }}</td>
            </tr>
            {% endfor %}
          </table>
        </div>
      </body>
    </html>
  6. Crea un playbook de configuración de interfaz de red.

    nano configure_network.yml

    Añade el siguiente contenido:

    ---
    - name: Configure network settings
      hosts: webservers
      become: true
      tasks:
        - name: Install NetworkManager if not present
          ansible.builtin.dnf:
            name: NetworkManager
            state: present
    
        - name: Ensure NetworkManager is running
          ansible.builtin.service:
            name: NetworkManager
            state: started
            enabled: yes
    
        - name: Configure hosts file with system information
          ansible.builtin.lineinfile:
            path: /etc/hosts
            line: "{{ ansible_facts['default_ipv4']['address'] }} {{ ansible_facts['hostname'] }}.lab.example.com {{ ansible_facts['hostname'] }}"
            regexp: ".*{{ ansible_facts['hostname'] }}.*"
            backup: yes
    
        - name: Create network monitoring script
          ansible.builtin.copy:
            content: |
              #!/bin/bash
              ## Network monitoring script generated by Ansible
              echo "=== Network Status Report ==="
              echo "Generated at: $(date)"
              echo
              echo "=== Interface Status ==="
              ip addr show
              echo
              echo "=== Routing Table ==="
              ip route show
              echo
              echo "=== DNS Configuration ==="
              cat /etc/resolv.conf
              echo
              echo "=== Network Connectivity Test ==="
              ping -c 3 8.8.8.8
            dest: /usr/local/bin/network-status.sh
            mode: "0755"
    
        - name: Create network information gathering cron job
          ansible.builtin.cron:
            name: Network status monitoring
            job: "/usr/local/bin/network-status.sh >> /var/log/network-status.log 2>&1"
            minute: "*/15"
            user: root
            cron_file: network-monitoring
            state: present
  7. Ejecuta el playbook de recopilación de información de red.

    ansible-playbook -i inventory.ini network_info.yml

    Esto generará informes completos del sistema y de la red.

  8. Ejecuta el playbook de configuración de red.

    ansible-playbook -i inventory.ini configure_network.yml

    Esto configurará los ajustes de red y la monitorización.

  9. Visualiza los informes generados.

    ## Lista los informes generados
    ls -la /tmp/system_reports/
    
    ## Visualiza el informe del sistema (también puedes abrirlo en un navegador)
    cat /tmp/system_reports/system_info_*.html
    
    ## Comprueba el script de monitorización de red
    cat /usr/local/bin/network-status.sh
    
    ## Prueba el script de monitorización de red
    sudo /usr/local/bin/network-status.sh
    
    ## Comprueba el trabajo cron de monitorización de red
    sudo cat /etc/cron.d/network-monitoring
  10. Crea un playbook integral final que combine todos los conceptos aprendidos.

    nano complete_system_setup.yml

    Añade el siguiente contenido:

    ---
    - name: Complete system setup and configuration
      hosts: webservers
      become: true
      vars:
        admin_users:
          - webuser1
          - webuser2
      tasks:
        - name: Ensure all required packages are installed
          ansible.builtin.dnf:
            name:
              - httpd
              - lvm2
              - NetworkManager
              - cronie
            state: present
    
        - name: Ensure all services are running
          ansible.builtin.service:
            name: "{{ item }}"
            state: started
            enabled: yes
          loop:
            - httpd
            - NetworkManager
            - crond
    
        - name: Generate final system status report
          ansible.builtin.template:
            src: system_report.j2
            dest: /tmp/final_system_report.html
            mode: "0644"
    
        - name: Display completion message
          ansible.builtin.debug:
            msg: |
              ============================================
              RHEL System Administration Automation Complete!
              ============================================
    
              Summary of configured components:
              - Software: EPEL repository and packages installed
              - Users: {{ admin_users | length }} administrative users created
              - Services: httpd, NetworkManager, and crond configured
              - Storage: LVM volumes and filesystems configured
              - Network: Interface configuration and monitoring set up
              - Scheduling: Cron jobs and at tasks configured
    
              Reports available at:
              - /tmp/system_reports/
              - /tmp/final_system_report.html
    
              Your RHEL system is now fully automated with Ansible!
  11. Ejecuta la configuración integral final.

    ansible-playbook -i inventory.ini complete_system_setup.yml

Has completado con éxito una automatización integral de las tareas de administración del sistema RHEL utilizando Ansible, cubriendo la gestión de software, la administración de usuarios, la gestión de servicios, la configuración de almacenamiento y la configuración de red.

  1. Previsualiza los informes generados en un navegador web.

    Navega al directorio de informes:

    cd /tmp/system_reports

    Inicia un servidor web temporal usando Python:

    python -m http.server 8000

    Para previsualizar los informes en tu navegador:

    1. Haz clic en el botón + en la barra de menú superior
    2. Selecciona Web Service
    3. Introduce el número de puerto 8000
    4. Ahora puedes ver los informes HTML generados en línea
    Preview the generated reports in a web browser

    El servidor web mostrará un listado de directorios donde puedes hacer clic en los archivos HTML para ver los informes completos del sistema y de red generados por tus playbooks de Ansible.

    Nota: Presiona Ctrl+C para detener el servidor web cuando hayas terminado de ver los informes.

Resumen

En este laboratorio integral, has dominado la automatización de tareas esenciales de administración de Red Hat Enterprise Linux (RHEL) utilizando Ansible. Comenzaste con la gestión de paquetes de software, aprendiendo a configurar repositorios, gestionar claves GPG e instalar paquetes mientras recopilabas información del sistema a través de los facts de los paquetes. Esto proporcionó la base para una implementación de software consistente en toda tu infraestructura.

Luego, progresaste a la gestión de usuarios y autenticación, donde automatizaste la creación de cuentas de usuario, configuraste la autenticación basada en claves SSH, estableciste privilegios sudo y reforzaste las configuraciones de SSH. Esto estableció políticas de acceso de usuario seguras y estandarizadas que son cruciales para entornos empresariales.

El laboratorio continuó con la gestión de servicios y la programación de tareas, donde aprendiste a gestionar servicios systemd, crear trabajos cron recurrentes, programar tareas únicas con at y configurar objetivos de arranque del sistema. Estas habilidades son esenciales para mantener la disponibilidad del servicio y automatizar las tareas de mantenimiento rutinarias.

La gestión de almacenamiento se cubrió a través de una automatización integral de LVM, que incluyó la creación de volúmenes físicos, la gestión de grupos de volúmenes, el aprovisionamiento de volúmenes lógicos, la creación de sistemas de archivos y la configuración de puntos de montaje. También aprendiste a expandir volúmenes de almacenamiento dinámicamente, lo cual es crítico para la gestión de infraestructura escalable.

Finalmente, completaste la automatización de la configuración de red y la monitorización integral del sistema. Aprendiste a recopilar datos de red (facts), configurar interfaces, crear informes detallados del sistema utilizando plantillas Jinja2 y configurar scripts de monitorización automatizados. Esto proporcionó la imagen completa de la gestión y generación de informes del estado del sistema.

A lo largo de este laboratorio, has aplicado los principios de Infraestructura como Código (IaC), asegurando que todas las configuraciones del sistema sean reproducibles, controladas por versión y desplegables de manera consistente. Ahora tienes las habilidades para automatizar el ciclo de vida completo de la administración del sistema RHEL, desde la implementación inicial hasta el mantenimiento y la monitorización continuos.