From 86e1c44d8537e52aab4d7e06dee49807fc421ca9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 19 Sep 2026 13:13:47 +0500 Subject: [PATCH] Add monitoring auto-deployment --- .gitignore | 22 +++ ansible.cfg | 2 + group_vars/all/vars.yml | 3 + group_vars/all/vault.yml | 20 ++ playbook.yml | 177 ++++++++++++++++++ templates/docker-compose.yml.j2 | 42 +++++ templates/grafana-datasource.yml.j2 | 12 ++ templates/node-exporter-web.yml.j2 | 2 + templates/node_exporter.service.j2 | 24 +++ templates/prometheus-web.yml.j2 | 2 + templates/prometheus.yml.j2 | 23 +++ terraform-infra/ansible.tf | 26 +++ terraform-infra/inventory.ini.tftpl | 5 + terraform-infra/inventory.ini:Zone.Identifier | Bin 0 -> 25 bytes terraform-infra/main.tf | 48 +++++ terraform-infra/provider.tf | 14 ++ 16 files changed, 422 insertions(+) create mode 100644 .gitignore create mode 100644 ansible.cfg create mode 100644 group_vars/all/vars.yml create mode 100644 group_vars/all/vault.yml create mode 100644 playbook.yml create mode 100644 templates/docker-compose.yml.j2 create mode 100644 templates/grafana-datasource.yml.j2 create mode 100644 templates/node-exporter-web.yml.j2 create mode 100644 templates/node_exporter.service.j2 create mode 100644 templates/prometheus-web.yml.j2 create mode 100644 templates/prometheus.yml.j2 create mode 100644 terraform-infra/ansible.tf create mode 100644 terraform-infra/inventory.ini.tftpl create mode 100644 terraform-infra/inventory.ini:Zone.Identifier create mode 100644 terraform-infra/main.tf create mode 100644 terraform-infra/provider.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87360ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +authorized_key.json +*.pem +*.key +*.pub + +.terraform/ +*.tfstate +*.tfstate.* +crash.log +crash.*.log +*.tfvars +*.tfvars.json +override.tf +override.tf.json +*_override.tf +*_override.tf.json +.terraform.lock.hcl + +*.retry +.vault_pass.txt +inventory.ini +host_vars/ diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..14c8065 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +host_key_checking = False diff --git a/group_vars/all/vars.yml b/group_vars/all/vars.yml new file mode 100644 index 0000000..3ee4142 --- /dev/null +++ b/group_vars/all/vars.yml @@ -0,0 +1,3 @@ +monitoring_dir: /opt/monitoring +node_exporter_version: "1.12.1" +node_exporter_arch: "amd64" \ No newline at end of file diff --git a/group_vars/all/vault.yml b/group_vars/all/vault.yml new file mode 100644 index 0000000..2bcfdc5 --- /dev/null +++ b/group_vars/all/vault.yml @@ -0,0 +1,20 @@ +$ANSIBLE_VAULT;1.1;AES256 +31613364333637343830653564643662323365306334656633626339356261613161323564666234 +3431373364663734626539353264343633303862616133320a363739313230616566316234656262 +62396666633634323339316265393136383232386566653364626436623939323362353063373835 +3132386436313536660a306334653032353038383166303535353262373335343361626564353366 +34316439303334323839396535343237613437356632336131373561323862363864666161656137 +64663231316337343838386338313065336135313535333738616162646430343863393961396432 +34383066666335386330353536333664353566623964616132323964613961663732336565343066 +31643031626261326138633131303638336465376664653366646331333961396139636336643232 +66323339373133346439646237303732383138393762643331336636333965336335643433343265 +61306533373932396366613233356539393339346133616631663738613862373464306434396538 +37626566326532363131356239656339386662363931343930633630393636383261613832313037 +38623766653133626238393165356630623238653765343262613832313230653334393764326466 +37383630343830636630313964303731623363383234626632626236333035636465356365353863 +36636531613762396364643732356635336232336334633561623632633931613339303230383639 +62343963636531343939623965656263306631356435626236623232616636643939393038353135 +63636665633835623034353566323530613762623361363535316634363034626264393738613938 +39633631663631666163623562666163386634336631343439646238323733303333346431376433 +36373036323631316164656131626530646339323939316630626438376632386337643862383330 +613532623061623364333765363739386564 diff --git a/playbook.yml b/playbook.yml new file mode 100644 index 0000000..a2af622 --- /dev/null +++ b/playbook.yml @@ -0,0 +1,177 @@ +--- +- name: Deploy Monitoring on general_server + hosts: general_server + become: yes + vars_files: + - group_vars/all/vars.yml + - group_vars/all/vault.yml + + tasks: + - name: Создание системного юзера + ansible.builtin.user: + name: metrics + state: present + shell: /usr/sbin/nologin + + - name: Создать директории для проекта + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: '0755' + owner: metrics + group: metrics + loop: + - "{{ monitoring_dir }}" + - "{{ monitoring_dir }}/grafana_provisioning" + + - name: Устанавливаем Docker и утилиты + apt: + name: + - docker.io + - docker-compose + - python3-pip + - ufw + - git + - htop + - rsync + state: present + update_cache: yes + + - name: Скопировать конфигурации сервисов + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ monitoring_dir }}/{{ item.dest }}" + mode: '0644' + owner: metrics + group: metrics + loop: + - { src: "prometheus.yml.j2", dest: "prometheus.yml" } + - { src: "prometheus-web.yml.j2", dest: "prometheus-web.yml" } + - { src: "node-exporter-web.yml.j2", dest: "node-exporter-web.yml" } + - { src: "grafana-datasource.yml.j2", dest: "grafana_provisioning/datasource.yml" } + - { src: "docker-compose.yml.j2", dest: "docker-compose.yml" } + + notify: Restart docker-compose + + - name: Запустить Docker Compose + community.docker.docker_compose_v2: + project_src: "{{ monitoring_dir }}" + state: present + + handlers: + - name: Restart docker-compose + community.docker.docker_compose_v2: + project_src: "{{ monitoring_dir }}" + state: restarted + +# ============================================================================================================== + +- name: Deploy Exporter on other servers + hosts: all + become: yes + vars_files: + - group_vars/all/vars.yml + - group_vars/all/vault.yml + + tasks: + - name: Создание системного юзера + ansible.builtin.user: + name: metrics + state: present + shell: /usr/sbin/nologin + + - name: Установить понятное имя хоста с индексом + ansible.builtin.hostname: + name: "node-{{ ansible_play_hosts.index(inventory_hostname) }}" + when: ansible_play_hosts.index(inventory_hostname) > 0 + notify: restart node-exporter + + - name: Создать директории для проекта + ansible.builtin.file: + path: "{{ monitoring_dir }}" + state: directory + mode: '0700' + owner: metrics + group: metrics + + - name: Устанавливаем Docker и утилиты + apt: + name: + - python3-pip + - ufw + - git + - htop + - rsync + state: present + update_cache: yes + + - name: Создать системного пользователя для Node Exporter + ansible.builtin.user: + name: node_exporter + shell: /usr/sbin/nologin + system: true + create_home: false + + - name: Создать директорию под конкретную версию + ansible.builtin.file: + path: "/opt/node_exporter-{{ node_exporter_version }}" + state: directory + owner: node_exporter + group: node_exporter + mode: '0700' + + - name: Скачать и распаковать архив экспортера + ansible.builtin.unarchive: + src: "https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-{{ node_exporter_arch }}.tar.gz" + dest: "/opt/node_exporter-{{ node_exporter_version }}" + remote_src: true + extra_opts: + - "--strip-components=1" + creates: "/opt/node_exporter-{{ node_exporter_version }}/node_exporter" + owner: node_exporter + group: node_exporter + + - name: Создать симлинк на исполняемый файл + ansible.builtin.file: + src: "/opt/node_exporter-{{ node_exporter_version }}/node_exporter" + dest: "/usr/local/bin/node_exporter" + state: link + force: true + + - name: Создать директорию для конфигурации экспортера + ansible.builtin.file: + path: /etc/node_exporter + state: directory + owner: node_exporter + group: node_exporter + mode: '0750' + + - name: Скопировать конфиг веб-авторизации для Node Exporter + ansible.builtin.template: + src: node-exporter-web.yml.j2 + dest: /etc/node_exporter/web.yml + owner: node_exporter + group: node_exporter + mode: '0600' + + - name: Создать systemd unit файл + ansible.builtin.template: + src: node_exporter.service.j2 + dest: /etc/systemd/system/node_exporter.service + owner: root + group: root + mode: '0644' + notify: restart node-exporter + + - name: Включить автозапуск и запустить сервис + ansible.builtin.systemd_service: + name: node_exporter + state: started + enabled: true + + handlers: + - name: restart node-exporter + ansible.builtin.systemd_service: + name: node_exporter + state: restarted + daemon_reload: true \ No newline at end of file diff --git a/templates/docker-compose.yml.j2 b/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..63aa3ea --- /dev/null +++ b/templates/docker-compose.yml.j2 @@ -0,0 +1,42 @@ +services: + prometheus: + image: prom/prometheus:latest + container_name: prometheus + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro + - ./prometheus-web.yml:/etc/prometheus/prometheus-web.yml:ro + - prom_data:/prometheus + + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.config.file=/etc/prometheus/prometheus-web.yml' + - '--storage.tsdb.path=/prometheus' + - '--web.enable-admin-api' + + restart: unless-stopped + + + grafana: + image: grafana/grafana:latest + container_name: grafana + ports: + - "3001:3000" + volumes: + - ./grafana_provisioning/datasource.yml:/etc/grafana/provisioning/datasources/datasource.yml:ro + - grafana_data:/var/lib/grafana + + environment: + - GF_SECURITY_ADMIN_USER="{{ grafana_admin_user }}" + - GF_SECURITY_ADMIN_PASSWORD="{{ grafana_admin_password }}" + - GF_USERS_ALLOW_SIGN_UP=false + + restart: unless-stopped + + depends_on: + - prometheus + +volumes: + prom_data: + grafana_data: diff --git a/templates/grafana-datasource.yml.j2 b/templates/grafana-datasource.yml.j2 new file mode 100644 index 0000000..4cae4b0 --- /dev/null +++ b/templates/grafana-datasource.yml.j2 @@ -0,0 +1,12 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + basicAuth: true + basicAuthUser: {{ prom_admin_user }} + secureJsonData: + basicAuthPassword: {{ prom_admin_password }} + isDefault: true \ No newline at end of file diff --git a/templates/node-exporter-web.yml.j2 b/templates/node-exporter-web.yml.j2 new file mode 100644 index 0000000..8659f87 --- /dev/null +++ b/templates/node-exporter-web.yml.j2 @@ -0,0 +1,2 @@ +basic_auth_users: + {{ exporter_user }}: "{{ exporter_password | password_hash('bcrypt') }}" \ No newline at end of file diff --git a/templates/node_exporter.service.j2 b/templates/node_exporter.service.j2 new file mode 100644 index 0000000..d70a195 --- /dev/null +++ b/templates/node_exporter.service.j2 @@ -0,0 +1,24 @@ +[Unit] +Description=Node Exporter +Wants=network-online.target +After=network-online.target + +[Service] +User=node_exporter +Group=node_exporter +Type=simple +ExecStart=/usr/local/bin/node_exporter \ + --web.config.file=/etc/node_exporter/web.yml + +# Контроль падений и перезапуск +Restart=always +RestartSec=5s + +# Ограничения безопасности процесса +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/templates/prometheus-web.yml.j2 b/templates/prometheus-web.yml.j2 new file mode 100644 index 0000000..b786d1e --- /dev/null +++ b/templates/prometheus-web.yml.j2 @@ -0,0 +1,2 @@ +basic_auth_users: + {{ prom_admin_user }}: "{{ prom_admin_password | password_hash('bcrypt') }}" \ No newline at end of file diff --git a/templates/prometheus.yml.j2 b/templates/prometheus.yml.j2 new file mode 100644 index 0000000..6eb1609 --- /dev/null +++ b/templates/prometheus.yml.j2 @@ -0,0 +1,23 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: "prometheus" + scrape_interval: 15s + basic_auth: + username: "{{ prom_admin_user }}" + password: "{{ prom_admin_password }}" + static_configs: + - targets: ["localhost:9090"] + + - job_name: "node_exporter" + basic_auth: + username: "{{ exporter_user }}" + password: "{{ exporter_password }}" + static_configs: +{% for host in groups['servers'] %} + - targets: ["{{ hostvars[host]['ansible_host'] }}:9100"] + labels: + nodename: "{{ host }}" +{% endfor %} + diff --git a/terraform-infra/ansible.tf b/terraform-infra/ansible.tf new file mode 100644 index 0000000..808f842 --- /dev/null +++ b/terraform-infra/ansible.tf @@ -0,0 +1,26 @@ +locals { + ssh_user = "ubuntu" + ssh_private_key = "~/.ssh/ssh-key-1789658954721" +} + +resource "local_file" "ansible_host_vars" { + count = length(yandex_compute_instance.server) + filename = "${path.module}/../host_vars/${yandex_compute_instance.server[count.index].name}.yml" + directory_permission = "0755" + file_permission = "0644" + content = <<-EOT +ansible_host: "${yandex_compute_instance.server[count.index].network_interface.0.nat_ip_address}" +ansible_user: "${local.ssh_user}" +ansible_ssh_private_key_file: "${local.ssh_private_key}" +EOT +} + +resource "local_file" "ansible_inventory" { + filename = "${path.module}/inventory.ini" + directory_permission = "0755" + file_permission = "0644" + content = templatefile("${path.module}/inventory.ini.tftpl", { + hosts = yandex_compute_instance.server[*].name + }) + depends_on = [local_file.ansible_host_vars] +} diff --git a/terraform-infra/inventory.ini.tftpl b/terraform-infra/inventory.ini.tftpl new file mode 100644 index 0000000..8a4066a --- /dev/null +++ b/terraform-infra/inventory.ini.tftpl @@ -0,0 +1,5 @@ +[servers] +general_server +%{ for host in hosts ~} +${host} +%{ endfor ~} diff --git a/terraform-infra/inventory.ini:Zone.Identifier b/terraform-infra/inventory.ini:Zone.Identifier new file mode 100644 index 0000000000000000000000000000000000000000..d6c1ec682968c796b9f5e9e080cc6f674b57c766 GIT binary patch literal 25 dcma!!%Fjy;DN4*MPD?F{<>dl#JyUFr831@K2x