Tutoriales

4 cosas que debe saber sobre la programación con Ansible

Ansible no es un lenguaje de programación.

Tal vez esta información no sea nueva para ti, o tal vez nunca pensaste en ello. Ansible funciona muy bien, entonces, ¿qué importa si es un lenguaje de programación?

Empecé como programador (hace mucho tiempo, en una galaxia muy, muy lejana…) pero mi primera exposición fue Microsoft BASIC, luego COBOLCICS y PerlHe usado otros lenguajes menos antiguos o raros como Java, Python, JavaScript, etc. No digo que sea competente en todos ellos, pero siempre trato de aprender cómo hacer las cosas en los idiomas más recientes y emocionantes.

Recientemente, esto le sucedió a Ansible, aunque Ansible es no un lenguaje de programación.

Ansible no es un lenguaje

Si Ansible no es un lenguaje de programación, ¿qué es?

Ansible es una herramienta escrita en Python que utiliza el lenguaje de marcado declarativo YAML para describir los estados de configuración y dispositivos deseados.

Vinculado al concepto de «estado deseado», Ansible también utiliza idempotenciaAspectos que declara que están configurados en el dispositivo de destino, por ejemplo, el archivo o directorio existe, el paquete está instalado, el servicio se está ejecutando, etc. Cuando hace esto, puede ejecutar su libro de jugadas de Ansible varias veces sin «romper» el objetivo. La mayoría de los módulos de Ansible saben lo que se debe hacer y solo informan que se han realizado cambios en el estado del recurso cuando se requieren cambios.

[ Get started with IT automation with the Ansible Automation Platform beginner’s guide. ]

Esta es mi opinión sobre lo que necesita saber al programar con Ansible.

1. Condiciones

La forma más fácil de definir si una tarea se ejecutará en Ansible es usar when Estado de salud. Puede encontrar muchos ejemplos en la documentación de Ansible, pero aquí hay uno que muestra algunos aspectos interesantes:

---
- name: When
  hosts: localhost
  gather_facts: False
  vars:
    my_number: "1138"
    my_string: "AA-589"
  tasks:
    - name: A - The Force is strong with this one
      ansible.builtin.debug:
        msg: "Use the Force, Luke"
      when:
        - (my_number | int) == 1138
        - my_string == 'AA-589'

    - name: B - Others
      ansible.builtin.debug:
        msg: "Do other things"
      when: (my_number | int) != 1138 or (my_string != 'AA-589')

En la primera tarea usé la siguiente lista de condiciones whenlo que significa una lógica yAdemás, tenga en cuenta que coacciono el tipo de var my_number para ser un número entero (en este caso, necesito hacer esto porque necesito proporcionar la variable a través de algún otro método).

En la segunda tarea, la condición está en una línea porque uso lógica oEn mi ejemplo, esta combinación niega la condición de la primera tarea.

Cuando se ejecuta el libro de jugadas, se ejecuta la primera tarea y se omite la segunda tarea.

Pero la primera tarea se omite y la segunda tarea se ejecuta cuando ejecuta el libro de jugadas pasando un valor diferente para al menos una variable:

$ ansible-playbook 01_when.yml -e my_number=5150 -e my_string="Other rebel"

2. Proceso de ejecución

Hay algunos aspectos especiales cuando observa el orden en que se ejecutan las cosas en Ansible.

En un libro de jugadas simple, las secuencias de tareas se ejecutan en el orden en que aparecen.si llamas roles En el nivel del juego, como se muestra en el siguiente ejemplo, el personaje ejecuta delantero La primera tarea:

---
- name: Simple play
  hosts: webservers
  roles:
    - common
    - webservers
  tasks:
    - name: Task 01
      (...)
...

manipulador es otro caso especial. El ejemplo provisto en la documentación oficial de Ansible se ve así:

---
- name: Verify apache installation
  hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
    - name: Ensure Apache httpd is the latest version
      ansible.builtin.yum:
        name: httpd
        state: latest

    - name: Write httpd config file
      ansible.builtin.template:
        src: /srv/httpd.j2
        dest: /etc/httpd.conf
      notify:
      - Restart apache

    - name: Ensure httpd is running
      ansible.builtin.service:
        name: httpd
        state: started

  handlers:
    - name: Restart httpd
      ansible.builtin.service:
        name: httpd
        state: restarted
...

en la tarea Write httpd config fileEste notify cláusula apunta a una tarea de controlador denominada Restart httpdSe ejecuta la acción del controlador. a no ser que Esta tarea conduce a cambió estado. El servicio se reinicia después de que se completa el cambio.

en el interior handlers sección, nombre de la tarea Restart httpd Se ejecuta cuando cambia la tarea que apunta a ella.

En este escenario simple, el controlador se ejecuta en último lugar, si lo hay.

Más concretamente, según documento, cuando usa la opción de roles en el nivel de juego, Ansible trata los roles como importaciones estáticas y los procesa durante la resolución del libro de jugadas. Ansible ejecuta cada jugada en el siguiente orden:

  1. ningún pre_tasks definido en la obra
  2. cualquier controlador desencadenado por pre_tasks
  3. cada rol enumerado en roles, en el orden indicado; cualquier dependencia de rol definida en roles meta/main.yml Ejecutar primero (sujeto a filtrado de etiquetas y condiciones)
  4. Cualquier misión definida en la obra.
  5. Cualquier controlador desencadenado por roles o tareas
  6. ningún post_tasks definido en la obra
  7. cualquier controlador desencadenado por post_tasks

Así que si una obra tiene pre_tasks O roles con handlers, lo que afecta el orden en que se realizan las operaciones, por lo que es importante prestar atención al orden ya que no es lineal.

Mi opción es usar import_roles o include_roles En lugar de usar este método junto con personajes de nivel de juego (a menos que mi libro de jugadas principal tenga si solo Personajes a nivel de juego, eso es todo).

[ Want to test your sysadmin skills? Take a skills assessment today. ]

La documentación describe diferencia entre import y includeLa idea básica es import* Al analizar un libro de jugadas, las declaraciones son estáticas (preprocesadas), mientras que include* Las declaraciones son dinámicas.Afecta el comportamiento humano. loops, when condiciones y otros aspectos, pero estos están más allá del alcance de este artículo.

3. si/entonces/si no

El ejemplo anterior implicó when es una declaración si/entonces, pero a nivel de tarea.Si desea utilizar un sencillo if Asigne variables o llame a diferentes condiciones lookup (o algo más para decidir)?

Bueno, a veces puedes usar Santuario 2 expresiones para ayudar a resolver este problema.

---
- name: Jinja2 IF
  hosts: localhost
  vars:
    change_provided: True
    job_name: death_star
    change_string: destroy
    current_date_time: 1977-01-01
  tasks:
    - name: Set base schedule name
      ansible.builtin.set_fact:
        base_schedule_name: "{%- if (change_provided | bool) -%}
                            {{ job_name }}_{{ change_string }}
                            {%- else -%}
                            {{ job_name }}_{{ current_date_time }}
                            {%- endif -%}"

    - name: Show value
      ansible.builtin.debug:
        msg: "{{ base_schedule_name }}"
...

En el libro de jugadas anterior, tengo variables estáticamente definidas para demostrar if en código Jinja2. Estas variables pueden provenir de algunos cálculos u otros procesos en la vida real.

[ Download now: Advanced Linux commands cheat sheet. ]

Esto es lo que sucede cuando uso set_fact asignar a base_schedule_name:

  1. Este {% y %} es el delimitador que indica el código Jinja2.En este caso, hay más - El marcado le indica a Jinja2 que quiero eliminar el carácter de espacio antes de la variable (los espacios son solo por estética).
  2. si change_provided Es cierto que combino job_name subrayado y change_string.Solo se asigna este contenido, y se omiten los espacios antes y después de la variable, porque la he usado antes {%- y -%}.
  3. Este else Las declaraciones son similares a lo que podría saber de otros idiomas.En este caso combino job_name subrayado y current_date_time.
  4. Al final, endif cierre if.

Como puede ver, esto es un poco peligroso y puede ensuciarse. Usa el buen sentido común.

puede usar solo uno when Una condición para hacer lo mismo en una tarea. Sin embargo, Jinja2 también se puede usar para manejar una lógica relativamente más compleja, como manejar bucles, calcular y filtrar elementos en listas, etc. Esto corre el riesgo de complicar demasiado las cosas.

Al igual que con cualquier lenguaje de programación real, use algo que facilite la implementación, el mantenimiento, la solución de problemas y la comprensión.

4. Ejecutar un proceso en el sistema operativo

Al comienzo de este artículo mencioné la idea de idempotencia. Siempre que sea posible, trate de usar módulos de Ansible para realizar operaciones, ya que contiene la siguiente lógica necesaria:

  • Hacer lo que debe hacerse solo cuando sea necesario
  • Establezca el estado de cambio de la tarea en función de lo que realmente sucedió (muestra ok cuando el estado deseado ya existe y changed cuando tiene que hacer cambios)

Habiendo dicho eso, si Ud. real ¿Necesitas realizar una acción en el sistema operativo? Después de todo, a veces no tiene un módulo Ansible específico que pueda realizar tareas por usted.

Bueno, hay algunas opciones para hacer esto, dependiendo del sistema operativo que se ejecute en su objetivo.

Para Linux, puede utilizar uno de los siguientes módulos:

  • Ordenar: El comando pasado como parámetro no Procesado por el shell, por lo que las variables de entorno y la redirección de E/S no funcionarán.
  • caparazón: similar a un módulo commandPero usa el shell para ejecutar los comandos que se le pasan y acepta la redirección de E/S.

Para Windows puedes usar el módulo equivalente:

El comando que desea ejecutar en el destino puede ser un binario ejecutable o un script (script de shell en Linux, caja de poder en Windows).Si es un script, es posible que deba usar Copiar o win_copy El módulo envía el script a su máquina de destino, donde luego puede ejecutarlo.

Esencialmente, puede enviar y ejecutar scripts que contengan su lógica.

un estado mental

Ansible no es un lenguaje de programación, pero lo ayuda a tener un marco para un lenguaje de programación cuando lo usa. Después de esta publicación, es posible que (¿quizás debido a algunos mensajes subliminales?) comience a sentirse un poco como Ansible Jedi.

LEER  Cómo instalar PeaZip en Ubuntu 22.04

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba