¿Cómo crear un archivo con contenido en Ansible?

AnsibleBeginner
Practicar Ahora

Introducción

Ansible es una poderosa herramienta de automatización de TI que simplifica la gestión de la infraestructura. En este laboratorio práctico, aprenderá a usar Ansible para crear archivos con contenido específico en sistemas objetivo. Al final de este laboratorio, comprenderá los conceptos básicos de la gestión de archivos con Ansible y podrá implementar la creación automatizada de archivos en su propia infraestructura.

Instalación y Configuración de Ansible

Antes de que podamos comenzar a usar Ansible para crear archivos, necesitamos instalarlo y configurarlo en nuestro sistema. Configuremos nuestro entorno:

Instalación de Ansible

Primero, actualizaremos las listas de paquetes e instalaremos Ansible en nuestro sistema Ubuntu 22.04:

sudo apt update
sudo apt install -y ansible

Después de ejecutar estos comandos, debería ver una salida que indica que Ansible se ha instalado correctamente. Verifiquemos la instalación:

ansible --version

Debería ver una salida similar a esta:

ansible [core 2.12.0]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, ...) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True

Creación de un Inventario Simple de Ansible

Ansible utiliza un archivo de inventario para definir los hosts que gestionará. Para este laboratorio, crearemos un inventario local que incluye nuestra propia máquina:

  1. Cree un nuevo directorio para nuestro proyecto Ansible:
mkdir -p ~/project/ansible-files
cd ~/project/ansible-files
  1. Cree un archivo de inventario usando VSCode:
    • Haga clic en el icono del Explorador en el WebIDE
    • Navegue al directorio ~/project/ansible-files
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo inventory
    • Agregue el siguiente contenido al archivo:
[local]
localhost ansible_connection=local

Este archivo de inventario le dice a Ansible que ejecute comandos en la máquina local sin usar SSH.

  1. Cree un archivo ansible.cfg simple en el mismo directorio:
    • Haga clic en el icono del Explorador en el WebIDE
    • Navegue al directorio ~/project/ansible-files
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo ansible.cfg
    • Agregue el siguiente contenido al archivo:
[defaults]
inventory = ./inventory
host_key_checking = False
  1. Verifiquemos nuestra configuración ejecutando un comando Ansible simple:
cd ~/project/ansible-files
ansible local -m ping

Debería ver una salida similar a:

localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Esto confirma que Ansible está correctamente instalado y configurado para ejecutar comandos en su máquina local.

Creación de Archivos con Contenido Usando Playbooks de Ansible

Ahora que tenemos Ansible configurado, aprendamos a crear archivos con contenido. Ansible proporciona varios módulos para la gestión de archivos, y nos centraremos en el módulo copy en este paso.

Comprensión de los Playbooks de Ansible

Los Playbooks de Ansible son archivos YAML que describen un conjunto de tareas a ejecutar en los hosts objetivo. Cada tarea utiliza un módulo específico de Ansible para realizar una acción.

Creemos nuestro primer playbook para crear un archivo con contenido:

  1. En el WebIDE, cree un nuevo archivo en el directorio ~/project/ansible-files:
    • Haga clic con el botón derecho en el directorio y seleccione "Nuevo archivo"
    • Nombre el archivo create_file.yml
    • Agregue el siguiente contenido:
---
- name: Create a file with content
  hosts: local
  tasks:
    - name: Create a simple text file
      copy:
        dest: "~/project/hello.txt"
        content: |
          Hello from Ansible!
          This file was created using the Ansible copy module.
          Current date: {{ ansible_date_time.date }}

Entendamos qué hace este playbook:

  • La línea hosts: local especifica que este playbook se ejecutará en los hosts del grupo local de nuestro inventario.
  • La sección tasks contiene una lista de tareas a ejecutar.
  • El módulo copy se utiliza para crear un archivo con contenido.
  • El parámetro dest especifica la ruta de destino para el archivo.
  • El parámetro content contiene el contenido de texto que se escribirá en el archivo.
  • {{ ansible_date_time.date }} es una variable que se reemplazará con la fecha actual cuando se ejecute el playbook.
  1. Ahora, ejecutemos el playbook:
cd ~/project/ansible-files
ansible-playbook create_file.yml

Debería ver una salida similar a:

PLAY [Create a file with content] ***********************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create a simple text file] ***********************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. Verifiquemos que el archivo se creó y contiene el contenido esperado:
cat ~/project/hello.txt

Debería ver una salida similar a:

Hello from Ansible!
This file was created using the Ansible copy module.
Current date: 2023-08-15

La fecha reflejará la fecha actual cuando ejecute el playbook.

Idempotencia en Ansible

La idempotencia es una característica clave de Ansible: ejecutar el mismo playbook varias veces debería producir el mismo resultado. Ejecutemos el playbook nuevamente para ver la idempotencia en acción:

ansible-playbook create_file.yml

Esta vez, debería ver que el conteo de "changed" es 0:

PLAY [Create a file with content] ***********************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create a simple text file] ***********************************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Esto muestra que Ansible reconoce que el archivo ya existe con el contenido correcto, por lo que no lo modifica de nuevo.

Uso de Variables y Plantillas en Ansible

En este paso, exploraremos cómo usar variables y plantillas para crear archivos más dinámicos con Ansible.

Trabajo con Variables

Las variables hacen que sus playbooks sean más flexibles y reutilizables. Creemos un playbook que use variables para crear un archivo de configuración:

  1. Cree un nuevo archivo en el WebIDE en el directorio ~/project/ansible-files:
    • Haga clic con el botón derecho en el directorio y seleccione "Nuevo archivo"
    • Nombre el archivo variables_demo.yml
    • Agregue el siguiente contenido:
---
- name: Create files using variables
  hosts: local
  vars:
    app_name: "MyApplication"
    app_version: "1.0.0"
    port_number: 8080
    log_level: "INFO"
  tasks:
    - name: Create config file with variables
      copy:
        dest: "~/project/app_config.ini"
        content: |
          ## Configuration for {{ app_name }}
          ## Generated by Ansible

          [application]
          name = {{ app_name }}
          version = {{ app_version }}

          [server]
          port = {{ port_number }}
          log_level = {{ log_level }}

En este playbook:

  • La sección vars define variables que se pueden usar en todo el playbook.
  • Se hace referencia a las variables usando la sintaxis {{ variable_name }}.
  • El módulo copy se utiliza para crear un archivo con contenido que incluye estas variables.
  1. Ahora, ejecutemos el playbook:
cd ~/project/ansible-files
ansible-playbook variables_demo.yml

Debería ver una salida similar a:

PLAY [Create files using variables] ********************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create config file with variables] ***************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. Examinemos el contenido del archivo generado:
cat ~/project/app_config.ini

Debería ver una salida similar a:

## Configuration for MyApplication
## Generated by Ansible

[application]
name = MyApplication
version = 1.0.0

[server]
port = 8080
log_level = INFO

Uso de Plantillas Jinja2

Para un contenido de archivo más complejo, Ansible admite plantillas Jinja2. Creemos un archivo de plantilla y lo usemos en un playbook:

  1. Cree un directorio de plantillas:
mkdir -p ~/project/ansible-files/templates
  1. Cree un archivo de plantilla en el WebIDE:
    • Navegue al directorio ~/project/ansible-files/templates
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo web_config.j2
    • Agregue el siguiente contenido:
## Web Server Configuration
## Generated by Ansible on {{ ansible_date_time.date }}

server {
    listen {{ web_port }};
    server_name {{ server_name }};

    location / {
        root {{ doc_root }};
        index index.html;
    }

    {% if enable_ssl %}
    ## SSL Configuration
    ssl_certificate {{ ssl_cert }};
    ssl_certificate_key {{ ssl_key }};
    {% endif %}
}
  1. Ahora cree un playbook que use esta plantilla:
    • Navegue al directorio ~/project/ansible-files
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo template_demo.yml
    • Agregue el siguiente contenido:
---
- name: Create files using templates
  hosts: local
  vars:
    web_port: 80
    server_name: "example.com"
    doc_root: "/var/www/html"
    enable_ssl: true
    ssl_cert: "/etc/ssl/certs/example.com.crt"
    ssl_key: "/etc/ssl/private/example.com.key"
  tasks:
    - name: Create web server config from template
      template:
        src: templates/web_config.j2
        dest: ~/project/web_server.conf

En este playbook:

  • El módulo template se utiliza en lugar de copy.
  • El parámetro src apunta a nuestro archivo de plantilla.
  • El parámetro dest especifica dónde crear el archivo de salida.
  • Las variables definidas en la sección vars se usarán en la plantilla.
  1. Ejecute el playbook:
cd ~/project/ansible-files
ansible-playbook template_demo.yml

Debería ver una salida similar a:

PLAY [Create files using templates] ********************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create web server config from template] **********************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. Examinemos el archivo de configuración generado:
cat ~/project/web_server.conf

Debería ver una salida similar a:

## Web Server Configuration
## Generated by Ansible on 2023-08-15

server {
    listen 80;
    server_name example.com;

    location / {
        root /var/www/html;
        index index.html;
    }

    ## SSL Configuration
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
}

Observe cómo la plantilla Jinja2 se representó con nuestras variables, y la sección condicional para SSL se incluyó porque enable_ssl se configuró en true.

Gestión Avanzada de Archivos con Ansible

En este paso final, exploraremos algunas técnicas avanzadas de gestión de archivos con Ansible, incluyendo permisos de archivos, creación condicional de archivos y el uso de múltiples módulos relacionados con archivos.

Establecimiento de Permisos y Propiedad de Archivos

Al crear archivos, a menudo necesita establecer permisos y propiedad específicos. Creemos un playbook que demuestre esto:

  1. Cree un nuevo archivo en el WebIDE:
    • Navegue al directorio ~/project/ansible-files
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo file_permissions.yml
    • Agregue el siguiente contenido:
---
- name: Manage file permissions and ownership
  hosts: local
  tasks:
    - name: Create a script file with execute permissions
      copy:
        dest: ~/project/script.sh
        content: |
          #!/bin/bash
          echo "This script was created by Ansible"
          echo "Current user: $(whoami)"
          echo "Current directory: $(pwd)"
        mode: "0755"

    - name: Create a read-only configuration file
      copy:
        dest: ~/project/readonly.conf
        content: |
          ## This is a read-only configuration file
          setting1 = value1
          setting2 = value2
        mode: "0444"

En este playbook:

  • El parámetro mode se utiliza para establecer los permisos del archivo.
  • 0755 significa lectura, escritura y ejecución para el propietario, y lectura y ejecución para el grupo y otros.
  • 0444 significa solo lectura para todos.
  1. Ejecute el playbook:
cd ~/project/ansible-files
ansible-playbook file_permissions.yml

Debería ver una salida similar a:

PLAY [Manage file permissions and ownership] **********************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create a script file with execute permissions] **************************
changed: [localhost]

TASK [Create a read-only configuration file] **********************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. Comprobemos los permisos de los archivos creados:
ls -l ~/project/script.sh ~/project/readonly.conf

Debería ver una salida similar a:

-rwxr-xr-x 1 labex labex 118 Aug 15 12:34 /home/labex/project/script.sh
-r--r--r-- 1 labex labex  73 Aug 15 12:34 /home/labex/project/readonly.conf
  1. Verifiquemos que el script se puede ejecutar:
~/project/script.sh

Debería ver una salida similar a:

This script was created by Ansible
Current user: labex
Current directory: /home/labex/project/ansible-files

Creación Condicional de Archivos

A veces, necesita crear archivos solo cuando se cumplen ciertas condiciones. Creemos un playbook que demuestre la creación condicional de archivos:

  1. Cree un nuevo archivo en el WebIDE:
    • Navegue al directorio ~/project/ansible-files
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo conditional_file.yml
    • Agregue el siguiente contenido:
---
- name: Conditional file creation
  hosts: local
  vars:
    environment: "development"
    create_debug_file: true
    create_backup: false
  tasks:
    - name: Create environment-specific configuration
      copy:
        dest: "~/project/{{ environment }}_config.yml"
        content: |
          ## Configuration for {{ environment }} environment
          debug: {{ 'enabled' if environment == 'development' else 'disabled' }}
          log_level: {{ 'DEBUG' if environment == 'development' else 'INFO' }}

    - name: Create debug log file
      copy:
        dest: ~/project/debug.log
        content: |
          ## Debug log file
          ## Created: {{ ansible_date_time.iso8601 }}
        mode: "0644"
      when: create_debug_file

    - name: Create backup directory
      file:
        path: ~/project/backup
        state: directory
        mode: "0755"
      when: create_backup

En este playbook:

  • La directiva when se utiliza para la ejecución condicional de tareas.
  • Los condicionales Jinja2 se utilizan en el contenido del archivo para cambiar los valores según las variables.
  • El módulo file se utiliza para crear un directorio.
  1. Ejecute el playbook:
cd ~/project/ansible-files
ansible-playbook conditional_file.yml

Debería ver una salida similar a:

PLAY [Conditional file creation] **********************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create environment-specific configuration] ******************************
changed: [localhost]

TASK [Create debug log file] **************************************************
changed: [localhost]

TASK [Create backup directory] ************************************************
skipped: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Observe que la tarea "Create backup directory" se omitió porque create_backup se configuró en false.

  1. Examinemos los archivos creados:
cat ~/project/development_config.yml
cat ~/project/debug.log
ls -la ~/project/ | grep backup

Debería ver el contenido de los dos archivos que se crearon y confirmar que no se creó ningún directorio de respaldo.

Uso de Múltiples Módulos Relacionados con Archivos

Ansible proporciona varios módulos para la gestión de archivos. Creemos un playbook que demuestre el uso de múltiples módulos relacionados con archivos:

  1. Cree un nuevo archivo en el WebIDE:
    • Navegue al directorio ~/project/ansible-files
    • Haga clic con el botón derecho y seleccione "Nuevo archivo"
    • Nombre el archivo file_modules.yml
    • Agregue el siguiente contenido:
---
- name: Demonstrate file-related modules
  hosts: local
  tasks:
    - name: Create a directory
      file:
        path: ~/project/ansible_demo
        state: directory
        mode: "0755"

    - name: Create a file using the copy module
      copy:
        dest: ~/project/ansible_demo/copied.txt
        content: "This file was created using the copy module.\n"

    - name: Create a symbolic link
      file:
        src: ~/project/ansible_demo/copied.txt
        dest: ~/project/ansible_demo/link_to_copied.txt
        state: link

    - name: Create a file with blockinfile module
      blockinfile:
        path: ~/project/ansible_demo/block.txt
        create: true
        block: |
          This is a block of text
          that will be inserted
          as a single unit.
        marker: "## {mark} ANSIBLE MANAGED BLOCK"

En este playbook:

  • El módulo file se utiliza con state: directory para crear un directorio.
  • El módulo file se utiliza con state: link para crear un enlace simbólico.
  • El módulo blockinfile se utiliza para crear un archivo con un bloque de texto rodeado de comentarios de marcador.
  1. Ejecute el playbook:
cd ~/project/ansible-files
ansible-playbook file_modules.yml

Debería ver una salida similar a:

PLAY [Demonstrate file-related modules] ***************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Create a directory] *****************************************************
changed: [localhost]

TASK [Create a file using the copy module] ************************************
changed: [localhost]

TASK [Create a symbolic link] *************************************************
changed: [localhost]

TASK [Create a file with blockinfile module] **********************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. Verifiquemos los resultados:
ls -la ~/project/ansible_demo/
cat ~/project/ansible_demo/copied.txt
cat ~/project/ansible_demo/link_to_copied.txt
cat ~/project/ansible_demo/block.txt

Debería ver:

  • Un directorio llamado ansible_demo
  • Un archivo llamado copied.txt con el contenido especificado
  • Un enlace simbólico llamado link_to_copied.txt que apunta a copied.txt
  • Un archivo llamado block.txt con un bloque de texto rodeado de comentarios de marcador

La salida del último comando debería ser similar a:

## BEGIN ANSIBLE MANAGED BLOCK
This is a block of text
that will be inserted
as a single unit.
## END ANSIBLE MANAGED BLOCK

Esto demuestra la versatilidad de las capacidades de gestión de archivos de Ansible.

Resumen

Felicitaciones por completar este laboratorio de gestión de archivos de Ansible. Ha aprendido varios conceptos y técnicas importantes:

  1. Cómo instalar y configurar Ansible para tareas de automatización básicas
  2. Creación de archivos con contenido específico utilizando el módulo copy
  3. Uso de variables para hacer que el contenido de sus archivos sea dinámico
  4. Trabajo con plantillas Jinja2 para una generación de archivos más compleja
  5. Establecimiento de permisos y propiedad de archivos
  6. Implementación de la creación condicional de archivos basada en variables
  7. Uso de varios módulos de Ansible para diferentes tareas de gestión de archivos

Estas habilidades forman una base sólida para automatizar las tareas de gestión de archivos en su infraestructura. Con Ansible, puede garantizar un contenido de archivo consistente en múltiples servidores, aplicar cambios de manera controlada y mantener un registro auditable de su configuración.

Para continuar su viaje de aprendizaje de Ansible, considere explorar temas más avanzados como roles, organización de playbooks e integración de Ansible con otras herramientas de DevOps.