Автоматическая проверка бекапов mysql, ldap

Как известно, администраторы делятся на тех кто делает и не делает бекап. В свою очередь те кто делают, еще подразделяются на тех, кто их проверяет или нет. Сам факт наличия бекапов я делаю через простое отображение в Комплексном экране заббикса списка файлов в директории, т.е. просто

ls -oth /DATA/BACKUP/ldap/`date +%m.%Y`/ | grep -v ^total | head -n 6 | cut -d " " -f4-  

 

 

 

 

Следующим шагом захотелось более-менее автоматически проверять бекапы mysql и ldap. Периодически для работы использую ансибл, поэтому решил на нем реализовать.

Предварительно, необходимо где-либо развернуть сервер для проверки бекапов (будем называеть его checkup-server). Сервер будет на дебиане.

- Для установки mysql достаточно просто apt-get install mysql-server

- Для установки ldap-сервера: apt-get install slapd.  Сам рабочий лдап-сервер поднят на freebsd + плюс есть самописные схемы для собственных атрибутов, все конфиги находятся в /usr/local/etc/openldap. Для настройки лдап на checkup-server достаточно просто перенести содержимое этой папки в папку /etc/ldap. В случае необходимости подправить пути в /etc/ldap/slapd.conf.

Потом сделать systemctl start slapd. Если не стартует, то смотрим логи в /var/log/syslog и исправляем возникающие ошибки (например неправильные пути до схем, недостаточно прав на какую-либо директорию).

Считаем что mysql-server и ldap на checlup-server функционируют нормально. Также заранее настраиваем пользователя (прописываем ключи и даем права USER ALL = (root) NOPASSWD: ALL в /ect/sudoers), под которым ансибл будет пушить свои задачи.

 

Сами плэйбуки

1) mysql.yml

---
- hosts: backup
  name: copy dumps from backup.server
  tasks:
   - synchronize: src=/DATA/BACKUP/mysql/{{ ansible_date_time.month  }}.{{ ansible_date_time.year }}/sql/DMZ/{{ item }}.{{ day }}.{{ ansible_date_time.month  }}.{{ ansible_date_time.year }}.sql dest=/tmp mode=pull
     with_items:
     - db1
     - db2
     - db3


- hosts: checkup-server
  name: copy and restore mysql databases to checkup-server
  tasks:
   - copy: src=/tmp/{{ item }}.{{ day }}.{{ ansible_date_time.month  }}.{{ ansible_date_time.year }}.sql dest=/home/ansible
     with_items:
      - db1
      - db2
      - db3
   - mysql_db: name={{ item }}_test state=absent login_user=root login_password=PASS
     with_items:
     - db1
     - db2
     - db3

   - mysql_db: name={{ item }}_test state=present login_user=root login_password=PASS
     with_items:
     - db1
     - db2
     - db3

   - mysql_db:   name={{ item }}_test     state=import     target=~ansible/{{ item }}.{{ day }}.{{ ansible_date_time.month }}.{{ ansible_date_time.year }}.sql login_user=root login_password=PASS
     with_items:
     - db1
     - db2
     - db3

   - file: path=~ansible/{{ item }}.{{ day }}.{{ ansible_date_time.month }}.{{ ansible_date_time.year }}.sql state=absent
     with_items:
     - db1
     - db2
     - db3


   - shell: /usr/bin/mysql -uroot -PASS -e "use db1_test; show tables" | wc -l
     register: s1
   - debug: msg="ALARM - DB  db1; has {{ s1.stdout }} tables"
     when: s1.stdout == "0"

   - shell: /usr/bin/mysql -uroot -PASS -e "use db2_test; show tables" | wc -l
     register: s2
   - debug: msg="ALARM - DB  db2 has {{ s2.stdout }} tables"
     when: s2.stdout == "0"

   - shell: /usr/bin/mysql -uroot -pPASS -e "use db3_test; show tables" | wc -l            
     register: s3
   - debug: msg="ALARM - DB  db3 has {{ s3.stdout }} tables"
     when: s3.stdout == "0"



- hosts: localhost
  name: rm dumps sql from /tmp on ansible
  tasks:
   - file: path=/tmp/{{ item }}.{{ day }}.{{ ansible_date_time.month }}.{{ ansible_date_time.year }}.sql state=absent
     with_items:
     - db1
     - db2
     - db3

 

 Некоторые пометки:

- путь до бекапа выглядит как /DATA/BACKUP/mysql/02.2017/sql/DMZ/db1.01.02.2017.sql

- стандартный модуль fetch для скачивания файлов (более 1Гб) не подошел, т.к. выдавал в процессе скачивания большого файла MemoryError, поэтому в интернете советуют использовать модуль synchronize, который является оберткой над rsync

- проверкой  нормального развернутого дампа является кол-во таблиц в бд, если 0, то выводим debug message (можно вместо этого например отправлять письмо). В словарях s1, s2, s3 сохраняется инфа по сработке команды /usr/bin/mysql -uroot ...   Сам вывод команды сохраняется в переменной s1.stdout

 - команде /usr/bin/mysql -uroot -pPASS передаем открыто пароль, т.к. нет смысла заморачиваться за безопасность - сервер mysql работает локально и ни у кого лишнего не должно быть доступа к checkup-server

 

2) ldap.yml

 

---
- hosts: backup
  name: copy ldif from backup.server
  tasks:
   - synchronize: src=/DATA/BACKUP/ldap/{{ ansible_date_time.month  }}.{{ ansible_date_time.year }}/{{ day }}-{{ ansible_date_time.month  }}-{{ ansible_date_time.year }}.ldif dest=/tmp mode=pull


- hosts: checkup-server
  name: copy and restore ldap to checkup-server
  sudo: yes
  tasks:
   - copy: src=/tmp/{{ day }}-{{ ansible_date_time.month  }}-{{ ansible_date_time.year }}.ldif dest=/home/ansible
   - shell: name=slapd state=stopped
   - shell: rm -rf /var/db/openldap-data/*
   - shell: /usr/sbin/slapadd -l /home/ansible/{{ day }}-{{ ansible_date_time.month  }}-{{ ansible_date_time.year }}.ldif
   - file: path=/var/db/openldap-data recurse=yes owner=openldap group=openldap state=directory
   - service: name=slapd state=restarted
   - file: path=~ansible/{{ day }}-{{ ansible_date_time.month }}-{{ ansible_date_time.year }}.ldif state=absent
   - shell: /usr/bin/ldapsearch -h localhost -x -b "dc=test.com" '(uid=testuser)' | grep "^result" | awk '{ print $2 }'
     register: s
   - debug: msg="ALARM - LDAP db is empty"
     when: s.stdout != "0"


- hosts: localhost
  name: rm ldif from /tmp on ansible
  tasks:
   - file: path=/tmp/{{ day }}-{{ ansible_date_time.month }}-{{ ansible_date_time.year }}.ldif state=absent

 

 

 

 Некоторые пометки:

- путь до бекапа имеет вид /DATA/BACKUP/ldap/03.2017/01-03-2017.ldif

- проверкой бекапа является ldapsearch в определенной ветке. В случае, если например дамп будет пустой, соответственно ветка не будет существовать и ldapsearch вернет ответ "result: 32 No such object"

 

Сами плэйбуки запускаем так:

ansible-playbook mysql.yml -e "day=12"
ansible-playbook ldap.yml -e "day=06"

 

Please publish modules in offcanvas position.