Ansible es una herramienta muy poderosa que le permite automatizar una gran variedad de plataformas en servidores, nubes, redes, contenedores y más.
A menudo, podrá automatizar lo que desee simplemente reutilizando roles y colecciones existentes.
Y hay muchos módulos para elegir que puede usar en sus libros de jugadas.
Pero cuando comience a desarrollar y probar libros de jugadas más complejos, eventualmente necesitará algunos métodos de solución de problemas. Cosas como:
- Comprobación del flujo de las tareas de Ansible.
- Confirmar los tipos de datos de sus variables.
- Incluso haciendo una pausa en algún punto en particular 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 Tower.
1. Su entorno y parámetros de Ansible
Si necesita investigar por qué algo no se comporta como se esperaba en sus libros de jugadas, generalmente es bueno comenzar por verificar su entorno de Ansible.
¿Qué versiones y rutas de los archivos binarios de Ansible y Python está ejecutando?
Si agregó paquetes de SO o módulos de Python que son requeridos por sus playbooks, ¿los está "viendo" el intérprete de Ansible?
Puede obtener esta información básica de muchas maneras diferentes. Desde la línea de comandos, ejecute ansible --version
comando.
❯ 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
o ansible-config
con la --version
opción.
En Ansible Tower, esta información se muestra si la plantilla de trabajo se ejecuta con VERBOSITY 2 (Más detallado) o superior.
Además de las versiones y la ubicación de los archivos binarios de Ansible y Python, siempre es bueno verificar dos veces las rutas utilizadas para los módulos, incluso si la ejecución usa un ansible.cfg
archivo que no es el predeterminado (es decir, no /etc/ansible/ansible.cfg
).
Para investigar opciones provenientes de un ansible.cfg
personalizado 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 su nombre lo indica, esto enumerará los parámetros que son diferentes de los predeterminados.
2. Ejecutando en modo detallado
Ejecutar los libros de jugadas 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
(o -vv
, -vvv
, -vvvv
, -vvvvv
). Los niveles de verbosidad más altos a veces pueden ser demasiada información, por lo que es mejor aumentar gradualmente en 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 problemas de WinRM.
Desde Tower, puede seleccionar la VERBOSIDAD nivel de la definición de plantilla de trabajo.
Nota :Recuerde desactivar el modo de depuración después de resolver la situación porque 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. Usando depuración para mostrar variables
Si tiene una buena idea sobre dónde cuáles pueden ser los problemas, puede usar 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"
}
Esto es por eso que no pude incrementar el contador. El filtro type_debug
muestra que el tipo de datos es texto y no int como supuse.
[ También te puede interesar: Guía de inicio rápido de Ansible para administradores de sistemas de Linux]
4. Asegurarse de que los vars tengan el contenido y el tipo de datos correctos
Puede utilizar la afirmación módulo para confirmar que las variables tienen el contenido/tipo esperado y hacer que la tarea falle si algo está 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 comando, sin 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 comandos, con la variable extra:
❯ 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 que viene como str fue una sorpresa para mí, pero aquí hay una explicación y una solución.
Además, si ejecuta el mismo libro de jugadas desde Tower, pasando el parámetro como variables adicionales o como un campo de una encuesta, el tipo de datos del parámetro será int .
Sí, puede ser complicado... pero si sabe qué buscar, estas "características" no serán un problema para usted.
5. Obtener una lista de los hechos y variables
Ya sea que haya definido variables en su inventario (para hosts y/o grupos) o haya creado y asignado variables adicionales durante la ejecución de 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á las vars y los hechos (si está reuniendo hechos) en archivos individuales para que los analice.
Para la ejecución de la línea de comandos, 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 se ejecuta desde la Torre, también deberá seleccionar uno servidor donde almacenar los archivos (a menos que solo tenga un nodo de destino y no le importe analizar el archivo allí).
6. Uso del depurador de tareas para solucionar problemas desde la línea de comandos
También puede usar el depurador de Ansible para ejecutar libros de jugadas en un modo paso a paso y para 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 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 el cálculo.
❯ 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
Qué pasó aquí:
- Inicialmente, la tarea falló y se quejó de las variables no int.
- Se invocó el depurador.
- Utilicé la impresión (p ) para mostrar los valores de las variables.
- En este caso, sabía que el problema estaba en el tipo de datos, pero uno podría pensar que los valores son correctos (si no se presta atención a las comillas alrededor de los valores).
- Más tarde, actualicé el contenido de las variables, asignándoles números.
- Luego, usé el
redo
comando para volver a ejecutar la tarea con los nuevos valores, y finalizó correctamente.
Este era un escenario simple, ya que sabemos que nadie realmente 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 larga ejecución del libro de jugadas y poder continuar desde ese punto sin reiniciar desde cero.
[ Obtenga este libro electrónico gratuito:Administrar sus clústeres de Kubernetes para principiantes. ]
Resumir
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ápidamente. Dependiendo de dónde se encuentre en la investigación, ciertos métodos son más adecuados.
Por ejemplo, cuando solo intenta tener una idea de qué podría estar mal, y dónde , es posible que desee comenzar aumentando gradualmente el nivel de depuración.
Una vez que tenga una mejor idea de la ubicación del problema, puede ser conveniente disminuir el nivel de depuración (para que tenga menos resultados frente a usted) y usar opciones que sean específicas para la tarea que está analizando.
La solución de problemas de Ansible puede ser complicada, pero al usar un enfoque metódico combinado con las herramientas integradas de resolución de problemas, puede hacerlo mucho más fácil para usted. Confirme el entorno de Ansible y el flujo de tareas, luego busque los tipos de datos adecuados y, por último, considere la posibilidad de pausar y realizar paso a paso cada tarea.