- Add Node Exporter Full dashboard (ID: 1860) from Grafana.com - Configure automatic dashboard installation in playbook.yml - Add prometheus-node-exporter service installation and configuration - Add port 9100 to UFW firewall rules - Add dashboard verification tasks in playbook - Configure Grafana variables for admin credentials
513 lines
17 KiB
YAML
513 lines
17 KiB
YAML
---
|
||
- name: Полная миграция ботов на новый сервер
|
||
hosts: new_server
|
||
become: yes
|
||
|
||
vars:
|
||
# Основная директория проекта
|
||
project_root: "/home/prod"
|
||
# Пользователь и группа
|
||
deploy_user: "deploy"
|
||
uid: "1001"
|
||
gid: "1001"
|
||
# Старый сервер для копирования данных
|
||
old_server: "root@77.223.98.129"
|
||
# Опция: пересоздавать папку /home/prod (по умолчанию — нет)
|
||
recreate_project: false
|
||
# Grafana настройки
|
||
grafana_admin_user: "{{ lookup('env', 'GRAFANA_ADMIN_USER') | default('admin') }}"
|
||
grafana_admin_password: "{{ lookup('env', 'GRAFANA_ADMIN_PASSWORD') | default('admin') }}"
|
||
|
||
tasks:
|
||
- name: Обновить SSH host key для избежания ошибок при переустановке
|
||
known_hosts:
|
||
path: ~/.ssh/known_hosts
|
||
name: "{{ ansible_host }}"
|
||
key: "{{ lookup('pipe', 'ssh-keyscan -t rsa,ecdsa,ed25519 ' + ansible_host) }}"
|
||
state: present
|
||
delegate_to: localhost
|
||
run_once: true
|
||
ignore_errors: yes
|
||
|
||
- name: Переключиться на root для начальной настройки
|
||
set_fact:
|
||
ansible_user: root
|
||
|
||
- name: Обновить кэш пакетов
|
||
apt:
|
||
update_cache: yes
|
||
|
||
- name: Установить необходимые пакеты
|
||
apt:
|
||
name:
|
||
- docker.io
|
||
- docker-compose
|
||
- make
|
||
- git
|
||
- python3-pip
|
||
- curl
|
||
- sshpass
|
||
- rsync
|
||
- vim
|
||
- zsh
|
||
- ufw
|
||
- htop
|
||
- iotop
|
||
- traceroute
|
||
- ncdu
|
||
- prometheus-node-exporter
|
||
state: present
|
||
|
||
- name: Включить и запустить prometheus-node-exporter
|
||
systemd:
|
||
name: prometheus-node-exporter
|
||
enabled: yes
|
||
state: started
|
||
|
||
- name: Проверить статус prometheus-node-exporter
|
||
command: systemctl status prometheus-node-exporter
|
||
register: node_exporter_status
|
||
changed_when: false
|
||
|
||
- name: Показать статус prometheus-node-exporter
|
||
debug:
|
||
var: node_exporter_status.stdout_lines
|
||
|
||
- name: Проверить, что node_exporter слушает на порту 9100
|
||
command: netstat -tulpn | grep 9100
|
||
register: node_exporter_port
|
||
changed_when: false
|
||
|
||
- name: Показать информацию о порте 9100
|
||
debug:
|
||
var: node_exporter_port.stdout_lines
|
||
|
||
- name: Обновить Docker Compose до последней версии
|
||
get_url:
|
||
url: "https://github.com/docker/compose/releases/latest/download/docker-compose-{{ ansible_system }}-{{ ansible_architecture }}"
|
||
dest: /usr/local/bin/docker-compose
|
||
mode: '0755'
|
||
become: yes
|
||
|
||
- name: Включить и запустить Docker
|
||
systemd:
|
||
name: docker
|
||
enabled: yes
|
||
state: started
|
||
|
||
- name: Разрешить SSH (порт 22) перед включением UFW
|
||
ufw:
|
||
rule: allow
|
||
port: "22"
|
||
proto: tcp
|
||
|
||
- name: Настроить политику UFW по умолчанию
|
||
ufw:
|
||
policy: deny
|
||
direction: incoming
|
||
|
||
- name: Включить UFW (файрвол)
|
||
ufw:
|
||
state: enabled
|
||
|
||
- name: Открыть порты для сервисов
|
||
ufw:
|
||
rule: allow
|
||
port: "{{ item }}"
|
||
proto: tcp
|
||
loop:
|
||
- "8080" # Telegram Bot
|
||
- "8081" # AnonBot
|
||
- "9090" # Prometheus
|
||
- "3000" # Grafana
|
||
- "9100" # Node Exporter
|
||
|
||
- name: Проверить существование пользователя deploy
|
||
getent:
|
||
database: passwd
|
||
key: "{{ deploy_user }}"
|
||
register: user_exists
|
||
failed_when: false
|
||
|
||
- name: Переключиться на пользователя deploy
|
||
meta: reset_connection
|
||
|
||
- name: Создать группу deploy с GID 1001
|
||
group:
|
||
name: "{{ deploy_user }}"
|
||
gid: "{{ gid }}"
|
||
when: user_exists.ansible_facts.getent_passwd is not defined
|
||
|
||
- name: Создать пользователя deploy с UID 1001 (если не существует)
|
||
user:
|
||
name: "{{ deploy_user }}"
|
||
uid: "{{ uid }}"
|
||
group: "{{ gid }}"
|
||
shell: /bin/zsh
|
||
create_home: yes
|
||
system: no
|
||
groups: docker
|
||
append: yes
|
||
when: user_exists.ansible_facts.getent_passwd is not defined
|
||
|
||
- name: Установить zsh как оболочку по умолчанию для существующего пользователя deploy
|
||
user:
|
||
name: "{{ deploy_user }}"
|
||
shell: /bin/zsh
|
||
when: user_exists.ansible_facts.getent_passwd is defined
|
||
|
||
- name: Скопировать SSH ключ с локальной машины для пользователя deploy
|
||
authorized_key:
|
||
user: "{{ deploy_user }}"
|
||
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||
state: present
|
||
|
||
- name: Настроить безопасный SSH
|
||
lineinfile:
|
||
path: /etc/ssh/sshd_config
|
||
regexp: "^{{ item.regexp }}"
|
||
line: "{{ item.line }}"
|
||
backup: yes
|
||
loop:
|
||
- { regexp: "PermitRootLogin", line: "PermitRootLogin no" }
|
||
- { regexp: "PasswordAuthentication", line: "PasswordAuthentication no" }
|
||
- { regexp: "PubkeyAuthentication", line: "PubkeyAuthentication yes" }
|
||
notify: reload ssh
|
||
|
||
- name: Удалить /home/prod, если требуется (чистое развертывание)
|
||
file:
|
||
path: "{{ project_root }}"
|
||
state: absent
|
||
when: recreate_project | bool
|
||
|
||
- name: Создать директорию проекта /home/prod
|
||
file:
|
||
path: "{{ project_root }}"
|
||
state: directory
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0755'
|
||
|
||
- name: Настроить SSH ключи для GitHub
|
||
authorized_key:
|
||
user: "{{ deploy_user }}"
|
||
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||
state: present
|
||
|
||
- name: Скопировать приватный SSH ключ для Git
|
||
copy:
|
||
src: "~/.ssh/id_rsa"
|
||
dest: "/home/{{ deploy_user }}/.ssh/id_rsa"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0600'
|
||
remote_src: no
|
||
|
||
- name: Настроить SSH config для GitHub
|
||
lineinfile:
|
||
path: "/home/{{ deploy_user }}/.ssh/config"
|
||
line: "Host github.com\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null"
|
||
create: yes
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0600'
|
||
|
||
- name: Клонировать основной репозиторий prod
|
||
git:
|
||
repo: git@github.com:KerradKerridi/prod.git
|
||
dest: "{{ project_root }}"
|
||
clone: yes
|
||
update: yes
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Клонировать AnonBot
|
||
git:
|
||
repo: git@github.com:KerradKerridi/AnonBot.git
|
||
dest: "{{ project_root }}/bots/AnonBot"
|
||
clone: yes
|
||
update: yes
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Клонировать telegram-helper-bot
|
||
git:
|
||
repo: git@github.com:KerradKerridi/telegram-helper-bot.git
|
||
dest: "{{ project_root }}/bots/telegram-helper-bot"
|
||
clone: yes
|
||
update: yes
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Скопировать SSH ключ на старый сервер для копирования файлов
|
||
authorized_key:
|
||
user: root
|
||
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||
state: present
|
||
delegate_to: "{{ old_server }}"
|
||
|
||
- name: Копировать .env для telegram-helper-bot со старого сервера
|
||
fetch:
|
||
src: "/home/prod/bots/telegram-helper-bot/.env"
|
||
dest: "/tmp/telegram-helper-bot.env"
|
||
flat: yes
|
||
delegate_to: "{{ old_server }}"
|
||
|
||
- name: Переместить .env для telegram-helper-bot на новое место
|
||
copy:
|
||
src: "/tmp/telegram-helper-bot.env"
|
||
dest: "{{ project_root }}/bots/telegram-helper-bot/.env"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Проверить размер БД для telegram-helper-bot
|
||
stat:
|
||
path: "/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
|
||
delegate_to: "{{ old_server }}"
|
||
register: db_size
|
||
|
||
- name: Показать размер БД для telegram-helper-bot
|
||
debug:
|
||
msg: "Размер БД: {{ (db_size.stat.size / 1024 / 1024) | round(2) }} MB"
|
||
|
||
- name: Копировать БД для telegram-helper-bot
|
||
fetch:
|
||
src: "/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
|
||
dest: "/tmp/tg-bot-database.db"
|
||
flat: yes
|
||
delegate_to: "{{ old_server }}"
|
||
|
||
- name: Переместить БД для telegram-helper-bot на новое место
|
||
copy:
|
||
src: "/tmp/tg-bot-database.db"
|
||
dest: "{{ project_root }}/bots/telegram-helper-bot/database/tg-bot-database.db"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Создать папку voice_users на новом сервере
|
||
file:
|
||
path: "{{ project_root }}/bots/telegram-helper-bot/voice_users"
|
||
state: directory
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0755'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Создать временную папку для voice_users на локальной машине
|
||
file:
|
||
path: "/tmp/voice_users_migration"
|
||
state: directory
|
||
mode: '0755'
|
||
delegate_to: localhost
|
||
become: no
|
||
|
||
- name: Копировать voice_users со старого сервера на локальную машину
|
||
command: >
|
||
rsync -avz --progress --stats --partial --verbose
|
||
root@77.223.98.129:/home/prod/bots/telegram-helper-bot/voice_users/
|
||
/tmp/voice_users_migration/
|
||
delegate_to: localhost
|
||
become: no
|
||
|
||
- name: Копировать voice_users с локальной машины на новый сервер
|
||
synchronize:
|
||
src: "/tmp/voice_users_migration/"
|
||
dest: "{{ project_root }}/bots/telegram-helper-bot/voice_users/"
|
||
mode: push
|
||
rsync_opts: "--progress --stats --partial --verbose"
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Очистить временную папку на локальной машине
|
||
file:
|
||
path: "/tmp/voice_users_migration"
|
||
state: absent
|
||
delegate_to: localhost
|
||
become: no
|
||
|
||
- name: Копировать корневой .env файл
|
||
fetch:
|
||
src: "/home/prod/.env"
|
||
dest: "/tmp/root.env"
|
||
flat: yes
|
||
delegate_to: "{{ old_server }}"
|
||
|
||
- name: Переместить корневой .env файл на новое место
|
||
copy:
|
||
src: "/tmp/root.env"
|
||
dest: "{{ project_root }}/.env"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
|
||
- name: Копировать .env для AnonBot
|
||
fetch:
|
||
src: "/home/prod/bots/AnonBot/.env"
|
||
dest: "/tmp/anonbot.env"
|
||
flat: yes
|
||
delegate_to: "{{ old_server }}"
|
||
|
||
- name: Переместить .env для AnonBot на новое место
|
||
copy:
|
||
src: "/tmp/anonbot.env"
|
||
dest: "{{ project_root }}/bots/AnonBot/.env"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Проверить размер БД для AnonBot
|
||
stat:
|
||
path: "/home/prod/bots/AnonBot/database/anon_qna.db"
|
||
delegate_to: "{{ old_server }}"
|
||
register: anon_db_size
|
||
|
||
- name: Показать размер БД для AnonBot
|
||
debug:
|
||
msg: "Размер БД AnonBot: {{ (anon_db_size.stat.size / 1024 / 1024) | round(2) }} MB"
|
||
|
||
- name: Копировать БД для AnonBot
|
||
fetch:
|
||
src: "/home/prod/bots/AnonBot/database/anon_qna.db"
|
||
dest: "/tmp/anon_qna.db"
|
||
flat: yes
|
||
delegate_to: "{{ old_server }}"
|
||
|
||
- name: Переместить БД для AnonBot на новое место
|
||
copy:
|
||
src: "/tmp/anon_qna.db"
|
||
dest: "{{ project_root }}/bots/AnonBot/database/anon_qna.db"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Установить права на скопированные файлы
|
||
file:
|
||
path: "{{ item }}"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
loop:
|
||
- "{{ project_root }}/bots/telegram-helper-bot/.env"
|
||
- "{{ project_root }}/bots/telegram-helper-bot/database/tg-bot-database.db"
|
||
- "{{ project_root }}/bots/AnonBot/.env"
|
||
- "{{ project_root }}/bots/AnonBot/database/anon_qna.db"
|
||
become: yes
|
||
|
||
- name: Исправить права доступа для voice_users (рекурсивно)
|
||
file:
|
||
path: "{{ project_root }}/bots/telegram-helper-bot/voice_users"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0755'
|
||
recurse: yes
|
||
become: yes
|
||
|
||
- name: Убедиться, что дашборд Node Exporter Full скопирован
|
||
copy:
|
||
src: "{{ project_root }}/infra/grafana/provisioning/dashboards/node-exporter-full-dashboard.json"
|
||
dest: "{{ project_root }}/infra/grafana/provisioning/dashboards/node-exporter-full-dashboard.json"
|
||
owner: "{{ deploy_user }}"
|
||
group: "{{ deploy_user }}"
|
||
mode: '0644'
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
- name: Запустить ботов через make up
|
||
command: make up
|
||
args:
|
||
chdir: "{{ project_root }}"
|
||
become: yes
|
||
become_user: "{{ deploy_user }}"
|
||
|
||
# --- НОВОЕ: Проверка портов ---
|
||
- name: Пауза на 30 секунд — дать контейнерам запуститься
|
||
pause:
|
||
seconds: 30
|
||
|
||
- name: Проверить, что порт 8080 (Telegram Bot) открыт
|
||
wait_for:
|
||
port: 8080
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 8081 (AnonBot) открыт
|
||
wait_for:
|
||
port: 8081
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 9090 (Prometheus) открыт
|
||
wait_for:
|
||
port: 9090
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 3000 (Grafana) открыт
|
||
wait_for:
|
||
port: 3000
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 9100 (Node Exporter) открыт
|
||
wait_for:
|
||
port: 9100
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить доступность Grafana API
|
||
uri:
|
||
url: "http://{{ ansible_host }}:3000/api/health"
|
||
method: GET
|
||
status_code: 200
|
||
register: grafana_health
|
||
retries: 5
|
||
delay: 10
|
||
|
||
- name: Проверить, что дашборд Node Exporter загружен в Grafana
|
||
uri:
|
||
url: "http://{{ ansible_host }}:3000/api/search?query=Node%20Exporter%20Full"
|
||
method: GET
|
||
user: "{{ grafana_admin_user | default('admin') }}"
|
||
password: "{{ grafana_admin_password | default('admin') }}"
|
||
status_code: 200
|
||
register: dashboard_check
|
||
retries: 3
|
||
delay: 5
|
||
|
||
- name: Показать информацию о найденных дашбордах
|
||
debug:
|
||
var: dashboard_check.json
|
||
|
||
- name: Проверка запуска ботов завершена — всё работает 🟢
|
||
debug:
|
||
msg: "Все сервисы запущены и слушают нужные порты."
|
||
|
||
# handlers для перезагрузки сервисов
|
||
handlers:
|
||
- name: reload ssh
|
||
systemd:
|
||
name: ssh
|
||
state: reloaded
|
||
|
||
- name: restart ufw
|
||
ufw:
|
||
state: reloaded |