6 habilidades de solución de problemas para los libros de jugadas de Ansible

Ansible es una herramienta muy poderosa que permite automatizar una gran variedad de plataformas en servidores, nubes, redes, contenedores, etc.

Muchas veces podrá automatizar lo que desee simplemente reutilizando el existente. los roles y colecciones.

y hay muchos módulos para elegir entre los que puedes usar en tus playbooks.

Pero cuando comience a desarrollar y probar libros de jugadas más complejos, es posible que necesite algunos métodos de solución de problemas. Cosas como:

  • Compruebe el flujo de trabajo de Ansible.
  • Confirmación de los tipos de datos de sus variables.
  • Incluso deteniéndose en algún punto para inspeccionar sus valores.

Algunos de los consejos discutidos en este artículo solo se aplicarán a la ejecución de Ansible a través de la línea de comandos. Otros también son válidos cuando se ejecutan desde Ansible La Torre.

Índice

1. Su entorno y su configuración de Ansible

Si necesita investigar por qué algo no se comporta como se esperaba en sus libros de jugadas, generalmente es una buena idea verificar primero su entorno de Ansible.

¿Qué versiones y rutas de los archivos binarios de Ansible y Python está ejecutando?

Si agregó paquetes de sistema operativo o módulos de Python requeridos por sus libros de jugadas, ¿los "ve" el intérprete de Ansible?

Puede obtener esta información básica de varias maneras. Desde la línea de comando, ejecute el ansible --version pedido.

❯ ansible --version

ansible 2.9.10

  config file = /etc/ansible/ansible.cfg

  configured module search path = ['/home/admin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']

  ansible python module location = /usr/lib/python3.6/site-packages/ansible

  executable location = /usr/bin/ansible

  python version = 3.6.8 (default, Mar 18 2021, 08:58:41) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)]

Puede obtener la misma información ejecutando otros comandos de Ansible, como ansible-playbook Donde ansible-config con el --version opción.

En Ansible Tower, esta información se muestra si la plantilla de tareas se ejecuta con VERBOSIDAD 2 (más detallada) o superior.

Además de las versiones y la ubicación de los archivos binarios de Ansible y Python, siempre es una buena idea verificar las rutas utilizadas para los módulos, incluido si el tiempo de ejecución utiliza un ansible.cfg archivo que no es el predeterminado (es decir, no /etc/ansible/ansible.cfg).

Para explorar las opciones de un ansible.cfg archivo, puede ejecutar lo siguiente desde la línea de comando:

❯ ansible-config dump --only-changed

DEFAULT_BECOME(/home/admin/ansible/ansible.cfg) = True

DEFAULT_BECOME_USER(/home/admin/ansible/ansible.cfg) = root

DEFAULT_FORKS(/home/admin/ansible/ansible.cfg) = 10

DEFAULT_HOST_LIST(/home/admin/ansible/ansible.cfg) = ['/home/admin/ansible/inventory']

DEFAULT_ROLES_PATH(/home/admin/ansible/ansible.cfg) = ['/home/admin/ansible/roles']

HOST_KEY_CHECKING(/home/admin/ansible/ansible.cfg) = False

Como sugiere el nombre, esto enumerará la configuración predeterminada.

2. Ejecutar en modo detallado

Ejecutar playbooks en modo de depuración puede ser el siguiente paso para obtener más detalles sobre lo que sucede en las tareas y variables.

Desde la línea de comando puede agregar -v (Donde -vv, -vvv, -vvvv, -vvvvv). Los niveles más altos de verbosidad a veces pueden ser demasiada información, por lo que es mejor aumentar gradualmente durante varias ejecuciones hasta que obtenga lo que necesita.

El nivel 4 puede ayudar a solucionar problemas de conectividad y el nivel 5 es útil para los problemas de WinRM.

Desde Torre, puede seleccionar la VERBOSIDAD nivel de la definición del modelo de tareas.

Notar: Recuerde desactivar el modo de depuración después de resolver la situación, ya que la información detallada solo es útil para solucionar problemas.

Además, en el modo de depuración, los valores de ciertas variables (contraseñas, por ejemplo) se mostrarán a menos que use el no_log opción en la tarea, así que borre las salidas cuando haya terminado.

3. Utilice la depuración para mostrar variables

Si tiene una buena idea de los problemas que pueden surgir, puede adoptar un enfoque más quirúrgico: muestre solo las variables que necesita ver.

(...)

  - name: Display the value of the counter
     debug:
      msg: "Counter={{ counter }} / Data type={{ counter | type_debug }}"

(...)

TASK [Display the value of the counter] ****************************************************************************

ok: [node1] => {

    "msg": "Counter=42 / Data type=AnsibleUnicode"

}

por eso no pude incrementar el contador. El filtro type_debug muestra que el tipo de datos es texto y no entero como yo esperaba.

4. Asegúrese de que las variables tengan el contenido correcto y el tipo correcto de datos

Puedes usar el acertar módulo para confirmar que las variables tienen el contenido/tipo esperado y hacer que la tarea falle si algo sale mal.

El siguiente libro de jugadas ilustra esto:

---

- name: Assert examples
  hosts: node1
  gather_facts: no
  vars:
    var01: 13
  tasks:

  - debug:
      msg: "Parameter 01 is {{ (param01 | type_debug) }}"

  - name: Make sure that we have the right type of content before proceeding
    assert:
      that: 

      - "var01 is defined"
      - "(var01 | type_debug) == 'int' "
      - "param01 is defined "
      - "(param01 | type_debug) == 'int' "

Si ejecuto el libro de jugadas desde la línea de comandos, proporcionando las variables adicionales:

❯ ansible-playbook xassert.yml

PLAY [Assert examples] ****************************************************************************

TASK [debug] ****************************************************************************

ok: [node1] => {

    "msg": "Parameter 01 is AnsibleUndefined"

}

TASK [Make sure that we have the right type of content before proceeding] ****************************************************************************

fatal: [node1]: FAILED! => {

    "assertion": "param01 is defined ",

    "changed": false,

    "evaluated_to": false,

    "msg": "Assertion failed"

}

PLAY RECAP ****************************************************************************

node1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0  

Si ejecuto el libro de jugadas desde la línea de comando, la variable adicional:

❯ ansible-playbook xassert.yml -e "param01=99"

PLAY [Assert examples] ****************************************************************************

TASK [debug] ****************************************************************************

ok: [node1] => {

    "msg": "Parameter 01 is str"

}

TASK [Make sure that we have the right type of content before proceeding] ****************************************************************************

fatal: [node1]: FAILED! => {

    "assertion": "(param01 | type_debug) == 'int' ",

    "changed": false,

    "evaluated_to": false,

    "msg": "Assertion failed"

}

PLAY RECAP ****************************************************************************

node1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 

Ver el tipo de datos vienen como calle fue una sorpresa para mí, pero hay una explicacion y una solucion aquí.

Además, si ejecuta el mismo libro de jugadas desde Tower, pasando el parámetro como una variable adicional o como un campo de una encuesta, el tipo de datos del parámetro será entero.

Sí, puede ser complicado... pero si sabe qué buscar, esas "características" no serán un problema para usted.

5. Obtenga una lista de hechos y variaciones

Ya sea que haya definido variables en su inventario (para hosts y/o grupos) o que haya creado y asignado variables adicionales mientras ejecuta su libro de jugadas, puede ser útil en algún momento inspeccionar sus valores.

---
- name: vars
  hosts: node1,node2
  tasks:
 
  - name: Dump vars
    copy:
      content: "{{ hostvars[inventory_hostname] | to_nice_yaml }}"
      dest: "/tmp/{{ inventory_hostname }}_vars.txt"
    delegate_to: control

  - name: Dump facts
    copy: 
      content: "{{ ansible_facts | to_nice_yaml }}"
      dest: "/tmp/{{ inventory_hostname }}_facts.txt"
    delegate_to: control

Esto guardará variables y hechos (si está recopilando hechos) en archivos individuales para que los analice.

Para la ejecución de la línea de comando, delegué la tarea a mi host de control (localhost) para que los archivos se guardaran localmente en lugar de tener los archivos guardados en cada nodo por separado. Si está utilizando Tower, también deberá seleccionar el servidor para almacenar los archivos (a menos que solo tenga un nodo de destino y no le importe escanear el archivo allí).

6. Uso del depurador de tareas para solucionar problemas desde la línea de comandos

También puede utilizar Ansible depurador ejecutar playbooks en modo paso a paso y examinar el contenido de variables y argumentos de forma interactiva.

Además de eso, también puede cambiar los valores de las variables sobre la marcha y continuar la ejecución.

El depurador se puede habilitar a nivel de tarea o a nivel de juego, como en el siguiente ejemplo:

---

- name: Example using debugger
  hosts: localhost
  gather_facts: no
  vars:
    radius: "5.3"
    pi: "3.1415926535"
  debugger: on_failed
  tasks:

  - name: Calculate the area of a circle
    debug:
      msg:
      - "Radius.............: {{ radius }}"
      - "pi................: {{ pi }}"
      - "Area of the circle: {{ (pi * (radius * radius)) }}"

Alerta de spoiler: definí las variables como cadenas, lo que obviamente causará un error cuando intente hacer los cálculos.

❯ ansible-playbook xdebugger.yml 

PLAY [Example using debugger] ****************************************************************************

TASK [Calculate the area of a circle] ****************************************************************************

fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on (Area of the circle: {{ (pi * (radius * radius)) }}): can't multiply sequence by non-int of type 'AnsibleUnicode'"}

[localhost] TASK: Calculate the area of a circle (debug)> p task_vars['pi']

'3.1415926535'

[localhost] TASK: Calculate the area of a circle (debug)> p task_vars['radius']

'5.3'

[localhost] TASK: Calculate the area of a circle (debug)> task_vars['pi']=3.1415926535

[localhost] TASK: Calculate the area of a circle (debug)> task_vars['radius']=5.3

[localhost] TASK: Calculate the area of a circle (debug)> p task_vars['radius']

5.3

[localhost] TASK: Calculate the area of a circle (debug)> task_vars['pi']=3.1415926535

[localhost] TASK: Calculate the area of a circle (debug)> redo

ok: [localhost] => {

    "msg": [

        "Radius............: 5.3",

        "pi................: 3.1415926535",

        "Area of the circle: 88.247337636815"

    ]

}

PLAY RECAP ****************************************************************************

localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0  

Que pasó aquí:

  1. Inicialmente, la tarea falló y se quejó de variables no int.
  2. Se invocó al depurador.
  3. Usé la impresión (pags) para mostrar los valores de las variables.
  4. En este caso, sabía que el problema estaba en el tipo de datos, pero pensarías que los valores son correctos (si no prestas atención a las comillas alrededor de los valores).
  5. Posteriormente, actualicé el contenido de las variables, asignándoles números.
  6. Luego usé el redo comando para volver a ejecutar la tarea con los nuevos valores, y se completó con éxito.

Era un escenario simple, porque sabemos que en realidad usaría Ansible para calcular el área de un círculo. Pero en una situación más compleja, podría ser útil encontrar el contenido de una variable en medio de una ejecución larga del libro de jugadas y poder continuar desde allí sin comenzar de nuevo.

Conclusión

La incorporación de un buen arsenal de opciones de solución de problemas puede ayudarlo a identificar problemas en sus libros de jugadas de Ansible más rápido. Dependiendo de dónde se encuentre en la encuesta, ciertos métodos son más adecuados.

Por ejemplo, cuando solo está tratando de tener una idea de lo que tal vez está mal, y es posible que desee comenzar aumentando gradualmente el nivel de depuración.

Una vez que tenga una mejor idea de dónde está el problema, puede ser útil disminuir el nivel de depuración (para que tenga menos resultados frente a usted) y usar opciones específicas para la tarea que está analizando.

La solución de problemas de Ansible puede ser complicada, pero el uso de un enfoque metódico combinado con las herramientas integradas de solución de problemas puede facilitar su trabajo. Confirme el entorno de Ansible y el flujo de tareas, luego encuentre los tipos de datos apropiados y, finalmente, considere pausar y realizar cada tarea.

Artículos de interés

Subir