En la administración de sistemas y servicios existen muchas tareas repetitivas y periódicas cuya ejecución programamos haciendo uso del crontab. Muchas de estas, como las copias de seguridad, debemos hacerla en todos y cada uno de los servidores que administramos. Dentro de la gestión automatizada de la infraestructura IT de la EPS hemos automatizado esta tarea (la de programar tareas del cron) con el playbook crontab.yml (no se debe confundir con programar las tareas de Ansible que vimos en esta entrada)
Este playbook permite realizar la configuración de las tareas de cualquier usuario para cualquiera de los servidores (excepto los que aparezcan en el grupo nocrontab) de manera centralizada y, además de poder realizar los cambios una sola vez (en lugar de realizarlo para cada servidor) también es posible modificar solo un servidor o un grupo (utilizando el parámetro –limit nombreServidor o nombreGrupo).
La información de este playbook reside en el fichero crontab.yml y tiene la siguiente estructura:
# All nodes except nocrontab Group - hosts: all:!nocrontab remote_user: ansible become: yes become_user: root become_method: sudo tasks: - include: group_by.yml - include: pathFacts.yml - hosts: all:!nocrontab gather_facts: False remote_user: ansible become: yes become_user: root become_method: sudo roles: - crontab
Como se puede observar usará el rol crontab compuesto por una tarea y dos templates (uno y dos). Si queremos cambiar algo, deberemos cambiar las variables declaradas en el fichero general group_vars/all/crontab y aunque es posible sobreescribir los valores en los ficheros por grupo o por host, no es lo recomendable ya que en el fichero general existen variables para grupos y servidores específicos. A partir de estas variables y los templates referenciados anteriormente, se generarán los ficheros de configuración de crontab de los usuarios para cada servidor tal y como estamos acostumbrados a ver cuando realizamos esta tarea “a mano”.
Estas variables necesarias para el correcto funcionamiento de este playbook son:
- crontabGlobal -> Configuración del crontab para todos los servidores. Se trata de la lista de usuarios que tendrán tareas en el crontab y que debe contener dos atributos: name (el nombre del usuario) y tasks (otra lista con las tareas del crontab para el usuario). Cada item de la lista tasks tendrá los siguientes atributos:
- label -> Este atributo tiene una doble función: por un lado servirá de comentario en el fichero (si no definimos el atributo comment) y por otro lado es la clave del item. Esto quiere decir que si más adelante queremos hacer referencia a una entrada (para eliminarla o sobreescribirla), lo haremos referenciándola con este atributo. Es, además, un atributo obligatorio.
- job -> Se trata de una cadena de texto con el comando o comandos a ejecutar por el cron. También es un atributo obligatorio.
- minute -> Campo minute (0-59) de la entrada del crontab. Atributo optativo cuyo valor por defecto (ni so se define el atributo) es ‘*’
- hour -> Campo hour (0-23) de la entrada del crontab. Atributo optativo cuyo valor por defecto (ni so se define el atributo) es ‘*’
- day -> Campo day of month (1-31) de la entrada del crontab. Atributo optativo cuyo valor por defecto (ni so se define el atributo) es ‘*’
- month -> Campo month (1-12) de la entrada del crontab. Atributo optativo cuyo valor por defecto (ni so se define el atributo) es ‘*’
- weekday -> Campo day of week (0-6) de la entrada del crontab. Atributo optativo cuyo valor por defecto (ni so se define el atributo) es ‘*’
- comment -> Comentario que se escribirá junto con la entrada del crontab. Atributo optativo, si no se define el comentario será el valor del campo label
- disabled -> Atributo optativo que nos permite ‘comentar’ una entrada del crontab en lugar de borrarla (por si queremos ‘activarla’ posteriormente). Si no se define el atributo, la entrada estará activa.
Los atributos label y job deben existir ya que son atributos obligatorios. En caso de que alguno no exista, la entradas no se escribirán en el crontab. Un ejemplo de uso:
crontabGlobal: users: - name: root tasks: - label: Backup diario virtuales job: '/root/scripts/backup.sh all' minute: 30 hour: 2
- crontabGroup -> Configuración del crontab para un grupo específico. Se trata de una lista de variables, cada una de ellas con dos atributos. Un primer atributo llamado group con el nombre del grupo al que se le aplicarán las declaraciones, y otro atributo users que incluye los usuarios que tendrán entradas en el crontab (este atributo también es lista). Como con la variable anterior, esta lista de usuarios users también incluye dos atributos: name y tasks, que son idénticos a los que existían en la variable crontabGlobal y que se comportan de idéntica manera. Al igual que la variable global, el atributo tasks es la lista con las tareas del crontab (con los mismos atributos). Podemos ‘sobreescribir’ o ‘eliminar’ las tareas globales (siempre que pertenezcan al mismo usuario) desde esta variable (en esta lista de tareas por grupo). Para realizar estas operaciones habrá que:
Para sobreescribir tareas globales, declararemos el atributo label de la tarea con el mismo texto que el atributo global, y definimos el resto de atributos con los valores que queramos en este caso concreto.
Para eliminar tareas globales, declararemos el atributo label con el mismo texto que el atributo global, y no declaramos el resto de atributos (en la entrada sólo existirá el atributo label)
El resto de tareas que se escriban (y no coincida el label con ninguna global) se añadiran en el crontab a las globales. Un ejemplo es:
crontabGroup: - group: proxmox users: - name: root tasks: - label: Backup diario virtuales job: '/root/scripts/backup.sh all' minute: 30 hour: 3 comment: Backup diaro virtuales a las 03:30 - label: Backup semanal virtuales job: '/root/scripts/backup.sh all' minute: 30 hour: 3 weekday: 6
- crontabHost -> Configuración del crontab para un servidor específico. Se trata de una lista de variables, cada una de ellas con dos atributos. Un primer atributo llamado host con el nombre del servidor al que se le aplicarán las declaraciones, y otro atributo users que incluye los usuarios que tendrán entradas en el crontab y que es idéntico a la lista de usuarios de las anteriores variables; incluye dos atributos: name y tasks, también idénticos a los que existían en las variables crontabGlobal y crontabGroup y que se comportan de idéntica manera. Al igual que las variables global y de grupo, el atributo tasks es una lista con las tareas del crontab (con los mismos atributos). Podemos ‘sobreescribir’ o ‘eliminar’ las tareas globales o de grupo (siempre que pertenezcan al mismo usuario) desde esta variable (en esta lista de tareas por servidor) de la misma manera que se realiza en la variable crontabGroup (se sobreescribe con el mismo valor de label y cambiando valor de los atributos y se elimina incluyendo solo label) .
El resto de tareas que se escriban (y no coincida el label con ninguna ‘global’ o de ‘grupo’) se añadirán en el fichero a las globales y las de grupo.
Por ejemplo:
crontabHost: - host: Ansible users: - name: root tasks: - label: Backup diario virtuales job: '/root/scripts/backup.sh all' minute: 30 hour: 6 comment: Backup diaro virtuales a las 06:30 - label: Backup mensual virtuales job: '/root/scripts/backup.sh all' minute: 30 hour: 3 day: 1
El primer template (el template del tmp ‘cronUsers’) se encarga de crear una lista de los usuarios que van a tener acciones programadas para lo que necesitará de las variables crontabGlobal, crontabGroup y crontabHost (que definen los crontab generales por grupo o por host para ciertos usuarios). Luego para cada usuario de la lista se genera los crontab a partir del las mismas variables, usando el otro template users. Finalmente hay que borrar los crontab existentes de otros usuarios que no están en la lista. Ambos templates necesitan información que se almacena en la tarea del playbook y cuyo contenido es:
# Crontab configuration - name: Make users list template: src=tmp/cronUsers.j2 dest=/tmp/cronUsers owner=root group=root mode=0600 changed_when: false - name: Get users shell: cat /tmp/cronUsers|uniq|sort executable="/bin/bash" register: cronUsers changed_when: false - name: Configure crontab template: src=var/spool/cron/user.j2 dest={{ crontabDirectory }}/{{ item }} owner=root group={{ crontabGroupFile }} mode=0600 with_items: "{{ cronUsers.stdout_lines }}" - name: Get files in crontab directory shell: ls -1 {{ crontabDirectory }} executable="/bin/bash" register: filesDir changed_when: false - name: Delete files in crontab directory if not belong to users list file: path="{{ crontabDirectory}}/{{ item }}" state="absent" with_items: "{{ filesDir.stdout_lines }}" when: item not in cronUsers.stdout_lines
Con todos estos playbooks y templates podréis disponer de acciones programadas, por usuario, para cualquier servidor (o grupo de servidores).
Un ejemplo de crontab generado, para el servicio de proxmox del ejemplo visto será:
- Por una parte dentro del fichero group_vars/all/crontab tendremos la entrada:
crontabGroup: - group: proxmox users: - name: root tasks: - label: Backup rsyncLocal job: '/root/scripts/rsyncLocal.sh todos' minute: 0 hour: 0
- Lo ejecutaríamos de forma directa mediante (o también podemos seleccionar la opción correspondiente del menú) :
ansible-playbook crontab.yml --limit proxmox
- Generando en el fichero /var/spool/cron/root de los servidores del grupo proxmox (server_14, server_24 y server_34) el siguiente contenido:
# Made by AnsibleEPS # Backup rsyncLocal 0 0 * * * /root/scripts/rsyncLocal.sh todos
¡Esperamos que os sea útil!
One Reply to “Automatización de la programación de tareas del crontab de nuestros servidores con Ansible”