Introducción
En este laboratorio, aprenderá las habilidades fundamentales para desplegar y gestionar archivos en un sistema Red Hat Enterprise Linux (RHEL) utilizando Ansible. Obtendrá experiencia práctica con algunos de los módulos de Ansible más comunes y potentes diseñados para operaciones de archivos, pasando del despliegue básico de archivos a la manipulación de contenido y la gestión de estados más avanzadas.
Comenzará utilizando el módulo ansible.builtin.copy para transferir un archivo estático y establecer sus atributos. A continuación, modificará el contenido de los archivos con lineinfile y blockinfile, y generará un MOTD personalizado utilizando el módulo ansible.builtin.template. El laboratorio también cubre la creación de enlaces simbólicos, la verificación de estados de archivos con stat, la recuperación de logs con fetch y la limpieza de archivos gestionados, proporcionando una visión completa de las capacidades de gestión de archivos de Ansible.
Copiar un Archivo Estático y Establecer Atributos con el Módulo ansible.builtin.copy
En este paso, aprenderá a utilizar uno de los módulos de Ansible más fundamentales: ansible.builtin.copy. Este módulo se utiliza para transferir archivos desde su nodo de control (la VM de LabEx) a una ubicación especificada en sus hosts gestionados. En nuestro caso, el host gestionado será localhost en sí mismo. Más allá de la simple copia, el módulo copy le permite controlar con precisión los atributos del archivo, como su propietario, grupo y modo de permisos, lo cual es esencial para una configuración correcta del sistema.
Primero, configuremos nuestro entorno de proyecto. Todo nuestro trabajo se realizará dentro del directorio ~/project.
Navegue al directorio del proyecto y cree un subdirectorio para nuestros archivos de origen. Esta es una práctica común para mantener su proyecto organizado.
Instale el paquete
ansible-core.sudo dnf install -y ansible-coreLuego, navegue al directorio del proyecto y cree un subdirectorio para nuestros archivos de origen.
cd ~/project mkdir filesA continuación, cree un archivo de texto simple que copiaremos. Utilizaremos un comando
catcon un "documento aquí" para crear el archivoinfo.txtdentro del directoriofiles.cat << EOF > ~/project/files/info.txt This file was deployed by Ansible. It contains important system information. EOFAhora, cree un archivo de inventario de Ansible. El inventario le dice a Ansible qué hosts gestionar. Para este laboratorio, gestionaremos la máquina local. Cree un archivo llamado
inventory.ini.cat << EOF > ~/project/inventory.ini localhost ansible_connection=local EOFEn este inventario,
localhostes el host al que nos dirigimos. La variableansible_connection=localinstruye a Ansible a ejecutar las tareas directamente en el nodo de control, sin usar SSH.Cree su primer playbook de Ansible. Este playbook contendrá las instrucciones para copiar el archivo. Use
nanoocatpara crear un archivo llamadocopy_file.yml.nano ~/project/copy_file.ymlAgregue el siguiente contenido al archivo. Este playbook define una tarea: copiar
info.txtal directorio/tmp/y establecer sus atributos.--- - name: Deploy a static file to localhost hosts: localhost tasks: - name: Copy info.txt and set attributes ansible.builtin.copy: src: files/info.txt dest: /tmp/info.txt owner: labex group: labex mode: "0640"Analicemos los parámetros en la tarea
copy:src: files/info.txt: La ruta al archivo de origen en el nodo de control, relativa a la ubicación del playbook.dest: /tmp/info.txt: La ruta absoluta donde se colocará el archivo en el host gestionado.owner: labex: Establece el propietario del archivo en el usuariolabex.group: labex: Establece el grupo del archivo en el grupolabex.mode: '0640': Establece los permisos del archivo.0640significa que el propietario puede leer/escribir, el grupo puede leer y los demás no tienen permisos.
Ejecute el playbook usando el comando
ansible-playbook. La bandera-iespecifica nuestro archivo de inventario.ansible-playbook -i inventory.ini copy_file.ymlDebería ver una salida que indica la ejecución exitosa del playbook, similar a esta:
PLAY [Deploy a static file to localhost] *************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Copy info.txt and set attributes] **************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Finalmente, verifique que el archivo se copió correctamente y tiene los atributos correctos. Use el comando
ls -lpara verificar los permisos, el propietario y el grupo.ls -l /tmp/info.txtLa salida debería mostrar que
labexes el propietario y el grupo, y los permisos son-rw-r-----.-rw-r----- 1 labex labex 72 Jul 10 14:30 /tmp/info.txtTambién puede ver el contenido del archivo para asegurarse de que se copió completamente.
cat /tmp/info.txtThis file was deployed by Ansible. It contains important system information.
Ha utilizado con éxito el módulo ansible.builtin.copy para desplegar un archivo y configurar sus atributos en su sistema local.
Modificar Contenido de Archivos con lineinfile y blockinfile
En este paso, aprenderá a modificar archivos existentes en un host gestionado sin reemplazar el archivo completo. Ansible proporciona módulos potentes para este propósito: ansible.builtin.lineinfile para gestionar líneas individuales y ansible.builtin.blockinfile para gestionar bloques de texto de varias líneas. Estos son extremadamente útiles para tareas como cambiar configuraciones o agregar entradas a archivos de registro.
Continuaremos trabajando con el archivo info.txt que creó en el paso anterior, el cual se encuentra en /tmp/info.txt.
Primero, asegúrese de estar en el directorio del proyecto.
cd ~/projectCree un nuevo playbook llamado
modify_file.yml. Este playbook contendrá dos tareas: una para agregar una línea individual y otra para agregar un bloque de texto a nuestro archivo existente.nano ~/project/modify_file.ymlAgregue el siguiente contenido a su playbook
modify_file.yml. Este playbook se dirige alocalhosty utiliza tantolineinfilecomoblockinfilepara agregar contenido a/tmp/info.txt.--- - name: Modify an existing file hosts: localhost tasks: - name: Add a single line of text to a file ansible.builtin.lineinfile: path: /tmp/info.txt line: This line was added by the lineinfile module. state: present - name: Add a block of text to an existing file ansible.builtin.blockinfile: path: /tmp/info.txt block: | ## BEGIN ANSIBLE MANAGED BLOCK This block of text consists of two lines. They have been added by the blockinfile module. ## END ANSIBLE MANAGED BLOCK state: presentExaminemos los módulos utilizados:
ansible.builtin.lineinfile: Este módulo asegura que una línea específica esté presente en un archivo. Si la línea ya existe, Ansible no hace nada, lo que hace que la tarea sea idempotente.path: El archivo a modificar.line: La línea de texto que se debe asegurar que esté en el archivo.state: present: Esto asegura que la línea exista. Podría usarstate: absentpara eliminarla.
ansible.builtin.blockinfile: Este módulo gestiona un bloque de texto, rodeado por líneas marcadoras (por ejemplo,## BEGIN ANSIBLE MANAGED BLOCK). Esto es ideal para gestionar secciones de configuración.path: El archivo a modificar.block: La cadena de varias líneas a insertar. El|es sintaxis de YAML para un bloque literal, preservando los saltos de línea.state: present: Asegura que el bloque exista.
Ejecute el playbook usando el comando
ansible-playbooky su archivoinventory.ini.ansible-playbook -i inventory.ini modify_file.ymlLa salida mostrará que ambas tareas realizaron cambios en el archivo.
PLAY [Modify an existing file] ************************************************* TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Add a single line of text to a file] ************************************* changed: [localhost] TASK [Add a block of text to an existing file] ********************************* changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Finalmente, verifique los cambios viendo el contenido de
/tmp/info.txt.cat /tmp/info.txtDebería ver el contenido original, seguido de la nueva línea y el nuevo bloque de texto.
This file was deployed by Ansible. It contains important system information. This line was added by the lineinfile module. ## BEGIN ANSIBLE MANAGED BLOCK This block of text consists of two lines. They have been added by the blockinfile module. ## END ANSIBLE MANAGED BLOCKSi ejecuta el playbook nuevamente, Ansible informará
ok=3ychanged=0porque el contenido ya está presente, lo que demuestra la naturaleza idempotente de estos módulos.
Generar un MOTD Personalizado con el Módulo ansible.builtin.template
En este paso, pasará de copiar archivos estáticos a generar archivos dinámicos utilizando el módulo ansible.builtin.template. Este módulo aprovecha el motor de plantillas Jinja2 para crear archivos personalizados con variables e información del sistema, conocidas como "facts" (hechos), que Ansible recopila de sus hosts gestionados. Crearemos un Mensaje del Día (MOTD) dinámico que muestre información específica del sistema.
Primero, asegúrese de estar en el directorio
~/projecty cree un subdirectorio dedicado para sus plantillas. Es una buena práctica estándar de Ansible almacenar las plantillas Jinja2 en un directoriotemplates.cd ~/project mkdir templatesA continuación, cree el archivo de plantilla Jinja2. Este archivo,
motd.j2, contendrá la estructura de nuestro MOTD, con marcadores de posición para datos dinámicos. La extensión.j2es una convención común para las plantillas Jinja2.nano ~/project/templates/motd.j2Agregue el siguiente contenido al archivo. Observe la sintaxis
{{ ... }}, que denota un marcador de posición para una variable o un fact.################################################################# ## Welcome to {{ ansible_facts['fqdn'] }} # ## This is a {{ ansible_facts['distribution'] }} system. ## System managed by Ansible. # ## For support, contact: {{ admin_email }} #################################################################En esta plantilla:
{{ ansible_facts['fqdn'] }}será reemplazado por el Nombre de Dominio Completamente Cualificado (Fully Qualified Domain Name) del host.{{ ansible_facts['distribution'] }}será reemplazado por el nombre de la distribución de Linux (por ejemplo, RedHat).{{ admin_email }}es una variable personalizada que definiremos en nuestro playbook.
Ahora, cree un nuevo playbook llamado
template_motd.yml. Este playbook utilizará la plantilla para generar/etc/motd.nano ~/project/template_motd.ymlAgregue el siguiente contenido. Este playbook requiere privilegios elevados (
become: true) para escribir en el directorio/etc. También define la variable personalizadaadmin_email.--- - name: Deploy a custom MOTD from a template hosts: localhost become: true vars: admin_email: admin@labex.io tasks: - name: Generate /etc/motd from template ansible.builtin.template: src: templates/motd.j2 dest: /etc/motd owner: root group: root mode: "0644"Parámetros clave en este playbook:
become: true: Esto le indica a Ansible que usesudopara ejecutar la tarea, lo cual es necesario para escribir en/etc/motd.vars: Esta sección es donde definimos variables personalizadas, comoadmin_email.ansible.builtin.template: El módulo que procesa la plantilla Jinja2.srcapunta a nuestro archivo.j2, ydestes el archivo de destino en el host gestionado.
Ejecute el playbook.
ansible-playbook -i inventory.ini template_motd.ymlLa salida debería confirmar que la tarea fue exitosa.
PLAY [Deploy a custom MOTD from a template] ************************************ TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Generate /etc/motd from template] **************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Verifique el resultado. Compruebe el contenido del archivo
/etc/motdrecién generado.cat /etc/motdVerá la salida renderizada, con los marcadores de posición de Jinja2 reemplazados por los facts reales del sistema y la variable personalizada que definió. El
fqdncoincidirá con el nombre de host de su entorno de laboratorio.################################################################# ## Welcome to host.labex.io # ## This is a RedHat system. ## System managed by Ansible. # ## For support, contact: admin@labex.io #################################################################
Ahora ha utilizado con éxito una plantilla para crear un archivo personalizado, una habilidad fundamental en la automatización de la infraestructura.
Desplegar Archivos de Soporte y Crear un Enlace Simbólico con copy y file
En este paso, combinará su conocimiento del módulo copy con un nuevo y versátil módulo: ansible.builtin.file. Mientras que copy se utiliza para transferir contenido, file se usa para gestionar el estado de archivos, directorios y enlaces simbólicos en el host gestionado. Lo utilizará para crear directorios, establecer permisos y, lo más importante para este ejercicio, crear enlaces simbólicos.
Nuestro escenario es configurar los mensajes previos al inicio de sesión que muestra el sistema. En muchos sistemas Linux, /etc/issue se muestra a los usuarios de terminal local, y /etc/issue.net se muestra a los usuarios remotos (como a través de SSH). Desplegaremos un único archivo issue y luego crearemos un enlace simbólico para que /etc/issue.net apunte a /etc/issue, asegurando que siempre muestren el mismo mensaje.
Primero, asegúrese de estar en el directorio
~/projecty cree el archivo de origen para nuestro mensaje de issue. Colocaremos este archivo en el subdirectoriofilesque creó anteriormente.cd ~/project cat << EOF > ~/project/files/issue Authorized access only. All connections are logged and monitored. EOFCree un nuevo playbook llamado
deploy_issue.yml. Este playbook contendrá dos tareas: una para copiar el archivoissuey otra para crear el enlace simbólico.nano ~/project/deploy_issue.ymlAgregue el siguiente contenido a su playbook
deploy_issue.yml. Este playbook requiere privilegios elevados (become: true) para gestionar archivos en el directorio/etc/.--- - name: Configure system issue files hosts: localhost become: true tasks: - name: Copy custom /etc/issue file ansible.builtin.copy: src: files/issue dest: /etc/issue owner: root group: root mode: "0644" - name: Ensure /etc/issue.net is a symlink to /etc/issue ansible.builtin.file: src: /etc/issue dest: /etc/issue.net state: link force: yesAnalicemos la nueva tarea
ansible.builtin.file:src: /etc/issue: Cuandostateeslink,srcespecifica el archivo al que debe apuntar el enlace simbólico.dest: /etc/issue.net: Esta es la ruta donde se creará el enlace simbólico en sí.state: link: Este parámetro crucial le indica al módulofileque cree un enlace simbólico, no un archivo o directorio regular.force: yes: Esta es una opción útil que garantiza la idempotencia. Si/etc/issue.netya existe como un archivo regular, Ansible lo eliminará y creará el enlace. Sinforce: yes, el playbook fallaría en esa situación.
Ejecute el playbook.
ansible-playbook -i inventory.ini deploy_issue.ymlLa salida mostrará que ambas tareas realizaron cambios exitosamente.
PLAY [Configure system issue files] ******************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Copy custom /etc/issue file] ********************************************* changed: [localhost] TASK [Ensure /etc/issue.net is a symlink to /etc/issue] ************************ changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Verifique el resultado usando el comando
ls -l. Este comando proporciona una lista detallada que muestra claramente los enlaces simbólicos.ls -l /etc/issue /etc/issue.netLa salida debería mostrar que
/etc/issuees un archivo regular y/etc/issue.netes un enlace simbólico que apunta a él. Lalal principio de los permisos para/etc/issue.netindica que es un enlace.-rw-r--r--. 1 root root 65 Jul 10 15:00 /etc/issue lrwxrwxrwx. 1 root root 10 Jul 10 15:00 /etc/issue.net -> /etc/issue
Ahora ha desplegado con éxito un archivo de configuración y ha utilizado el módulo ansible.builtin.file para crear un enlace simbólico, un patrón común y potente para gestionar configuraciones del sistema.
Verificar Estado de Archivos con stat y Obtener Logs con fetch
En este paso, aprenderá sobre dos módulos importantes de recopilación de datos: ansible.builtin.stat y ansible.builtin.fetch. El módulo stat se utiliza para comprobar el estado de un archivo o directorio en un host gestionado; por ejemplo, para ver si existe, cuáles son sus permisos o cuándo fue modificado por última vez. No cambia nada, lo que lo hace perfecto para comprobaciones y lógica condicional. El módulo fetch hace lo contrario de copy: recupera archivos desde el host gestionado y los guarda en su nodo de control, lo que es ideal para hacer copias de seguridad de configuraciones o recopilar archivos de log para su análisis.
Crearemos un playbook que primero comprueba la existencia del archivo /etc/motd que creó anteriormente, y luego recupera el archivo de log del gestor de paquetes DNF (/var/log/dnf.log) a un directorio local en su VM de LabEx.
Primero, asegúrese de estar en el directorio
~/projecty cree un nuevo subdirectorio para almacenar los archivos que recuperará.cd ~/project mkdir fetched_logsCree un nuevo playbook llamado
check_and_fetch.yml. Este playbook contendrá las tareas para comprobar el archivo y recuperar el log.nano ~/project/check_and_fetch.ymlAgregue el siguiente contenido a su playbook
check_and_fetch.yml. Este playbook utilizastatpara obtener detalles del archivo,registerpara almacenar esos detalles en una variable,debugpara mostrar la variable yfetchpara recuperar el archivo de log.--- - name: Check file status and fetch logs hosts: localhost become: true tasks: - name: Check if /etc/motd exists ansible.builtin.stat: path: /etc/motd register: motd_status - name: Display stat results ansible.builtin.debug: var: motd_status.stat - name: Fetch the dnf log file from managed host ansible.builtin.fetch: src: /var/log/dnf.log dest: fetched_logs/ flat: yesAnalicemos los conceptos clave:
register: motd_status: Esta es una característica crucial de Ansible. Toma toda la salida de una tarea y la guarda en una nueva variable llamadamotd_status.ansible.builtin.debug: Este módulo se utiliza para imprimir valores durante la ejecución de un playbook. Aquí, imprimimos el objetostatdentro de nuestra variable registrada (motd_status.stat) para ver las propiedades del archivo.ansible.builtin.fetch: Este módulo recupera un archivo del host gestionado.src: La ruta del archivo a recuperar del host gestionado.dest: El directorio en el nodo de control (su VM de LabEx) donde se guardará el archivo.flat: yes: Por defecto,fetchcrea una estructura de subdirectorios que coincide con el host y la ruta de origen.flat: yessimplifica esto copiando el archivo directamente en el directoriodestsin subdirectorios adicionales.
Ejecute el playbook. Dado que estamos leyendo un archivo de log del sistema, se utiliza
become: truepara obtener los permisos necesarios.ansible-playbook -i inventory.ini check_and_fetch.ymlLa salida mostrará los resultados de la comprobación
staten la tarea de depuración, seguida de la tareafetch.PLAY [Check file status and fetch logs] **************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Check if /etc/motd exists] *********************************************** ok: [localhost] TASK [Display stat results] **************************************************** ok: [localhost] => { "motd_status.stat": { "exists": true, "gid": 0, "isreg": true, "mode": "0644", "path": "/etc/motd", ... } } TASK [Fetch the dnf log file from managed host] ******************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Verifique que el archivo de log se recuperó correctamente. Liste el contenido del directorio
fetched_logs.ls -l ~/project/fetched_logs/Debería ver el archivo
dnf.log, ahora almacenado localmente en su nodo de control.total 4 -rw-r--r--. 1 labex labex 1234 Jul 10 15:30 dnf.log
Ahora ha aprendido a inspeccionar las propiedades de los archivos sin realizar cambios y a recuperar archivos importantes de sus sistemas gestionados a su nodo de control.
Limpiar Archivos del Host Gestionado con el Módulo file
En este último paso, aprenderá a utilizar el módulo ansible.builtin.file para asegurarse de que los archivos y directorios no estén presentes en un sistema. Una parte fundamental de la gestión de la configuración no es solo crear y modificar recursos, sino también limpiarlos. Al establecer el parámetro state en absent, puede indicar a Ansible que elimine archivos, enlaces simbólicos o incluso directorios completos.
Para concluir este laboratorio, escribiremos un único playbook de "limpieza" que eliminará todos los artefactos que creamos en los pasos anteriores: /tmp/info.txt, /etc/motd, /etc/issue y el enlace simbólico /etc/issue.net.
Primero, asegúrese de estar en el directorio
~/project.cd ~/projectCree un nuevo playbook llamado
cleanup.yml. Este playbook contendrá todas las tareas necesarias para revertir nuestros cambios.nano ~/project/cleanup.ymlAgregue el siguiente contenido a su playbook
cleanup.yml. Este playbook utiliza una lista de tareas, cada una dirigida a uno de los archivos que creamos. Tenga en cuenta quebecome: truese establece en el nivel del play, por lo que todas las tareas se ejecutarán con privilegios elevados.--- - name: Clean up managed files from the system hosts: localhost become: true tasks: - name: Remove the temporary info file ansible.builtin.file: path: /tmp/info.txt state: absent - name: Remove the custom MOTD file ansible.builtin.file: path: /etc/motd state: absent - name: Remove the custom issue file ansible.builtin.file: path: /etc/issue state: absent - name: Remove the issue.net symbolic link ansible.builtin.file: path: /etc/issue.net state: absentLa clave de este playbook es el parámetro
state: absenten cada tarea. Esto le indica al módulofileque se asegure de que el elemento en lapathespecificada no exista. Si encuentra el archivo, lo eliminará. Si el archivo ya no está, no hará nada, manteniendo la idempotencia.Ejecute el playbook de limpieza.
ansible-playbook -i inventory.ini cleanup.ymlLa salida mostrará que cada tarea realizó con éxito un cambio al eliminar un archivo.
PLAY [Clean up managed files from the system] ********************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Remove the temporary info file] ****************************************** changed: [localhost] TASK [Remove the custom MOTD file] ********************************************* changed: [localhost] TASK [Remove the custom issue file] ******************************************** changed: [localhost] TASK [Remove the issue.net symbolic link] ************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Verifique que los archivos han sido eliminados. Puede usar el comando
lspara comprobar su existencia. El comando informará que no puede acceder a ellos porque ya no están.ls /tmp/info.txt /etc/motd /etc/issue /etc/issue.netLa salida esperada es una serie de errores, lo que confirma que la limpieza fue exitosa.
ls: cannot access '/tmp/info.txt': No such file or directory ls: cannot access '/etc/motd': No such file or directory ls: cannot access '/etc/issue': No such file or directory ls: cannot access '/etc/issue.net': No such file or directory
Ahora ha utilizado con éxito Ansible para eliminar archivos y limpiar un sistema, completando el ciclo de vida completo de la gestión de archivos desde la creación hasta la eliminación.
Resumen
En este laboratorio, aprendió los fundamentos de la gestión de archivos en sistemas RHEL utilizando Ansible. Comenzó utilizando el módulo ansible.builtin.copy para transferir un archivo estático a un host gestionado mientras establecía la propiedad y los permisos específicos. Luego exploró cómo modificar archivos existentes asegurando que una línea específica esté presente con lineinfile y gestionando bloques de texto de varias líneas con blockinfile. Una habilidad clave cubierta fue la generación de contenido de archivos dinámico utilizando el módulo ansible.builtin.template y la sintaxis Jinja2 para crear un Mensaje del Día (MOTD) personalizado poblado con hechos del sistema.
Además, practicó el despliegue de archivos de soporte y la creación de enlaces simbólicos utilizando el módulo ansible.builtin.file. Para garantizar el éxito de sus despliegues, utilizó el módulo stat para verificar el estado y los atributos de los archivos y el módulo fetch para recuperar archivos, como logs, del host gestionado al nodo de control. Finalmente, aprendió a realizar operaciones de limpieza utilizando el módulo file con state: absent para eliminar los archivos y directorios creados durante el laboratorio, asegurando un estado limpio en el host gestionado.


