commit 86e1c44d8537e52aab4d7e06dee49807fc421ca9 Author: Your Name Date: Sat Sep 19 13:13:47 2026 +0500 Add monitoring auto-deployment 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 0000000..d6c1ec6 Binary files /dev/null and b/terraform-infra/inventory.ini:Zone.Identifier differ diff --git a/terraform-infra/main.tf b/terraform-infra/main.tf new file mode 100644 index 0000000..59158bb --- /dev/null +++ b/terraform-infra/main.tf @@ -0,0 +1,48 @@ +data "yandex_compute_image" "ubuntu" { + family = "ubuntu-2204-lts" +} + +resource "yandex_vpc_network" "main_network" { + name = "main-network" +} + +resource "yandex_vpc_subnet" "main_subnet" { + name = "main-subnet" + zone = "ru-central1-a" + network_id = yandex_vpc_network.main_network.id + v4_cidr_blocks = ["192.168.10.0/24"] +} + +resource "yandex_compute_instance" "server" { + count = 5 + + name = "server_${count.index + 1}" + platform_id = "standard-v3" + zone = "ru-central1-a" + + resources { + cores = 2 + memory = 2 + } + + boot_disk { + initialize_params { + image_id = data.yandex_compute_image.ubuntu.id + size = 15 + } + } + + network_interface { + subnet_id = yandex_vpc_subnet.main_subnet.id + nat = true + } + + metadata = { + ssh-keys = "ubuntu:${file("~/.ssh/ssh-key-1789658954721.pub")}" + } +} + +output "public_ips" { + description = "Публичные IP адреса созданных серверов" + value = yandex_compute_instance.server[*].network_interface.0.nat_ip_address +} diff --git a/terraform-infra/provider.tf b/terraform-infra/provider.tf new file mode 100644 index 0000000..5603bc6 --- /dev/null +++ b/terraform-infra/provider.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + yandex = { + source = "yandex-cloud/yandex" + } + } + required_version = ">= 0.13" +} +provider "yandex" { + service_account_key_file = "authorized_key.json" + cloud_id = "b1gl9hdpdr35i83uh5t5" + folder_id = "b1gbb5kej5tlskp8i5oq" + zone = "ru-central1-a" +}