diff --git a/playbooks/configure-nginx-monitoring.yml b/playbooks/configure-nginx-monitoring.yml new file mode 100644 index 0000000..32548ff --- /dev/null +++ b/playbooks/configure-nginx-monitoring.yml @@ -0,0 +1,102 @@ +--- +- name: Configure Nginx monitoring in Prometheus + hosts: 192.168.0.105 + become: yes + + tasks: + - name: Check if nginx config already exists + stat: + path: /etc/prometheus/nginx-app1.yml + register: nginx_config + + - name: Create Nginx scrape config + copy: + content: | + # Nginx stub_status metrics + - job_name: 'nginx-app1' + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /status + static_configs: + - targets: ['192.168.0.110:80'] + labels: + instance: 'app1' + service: 'nginx' + job: 'nginx' + metric_relabel_configs: + - source_labels: [__address__] + target_label: instance + - source_labels: [__address__] + regex: '([^:]+):\d+' + replacement: '${1}' + target_label: host + dest: /etc/prometheus/nginx-app1.yml + owner: root + group: root + mode: '0644' + when: not nginx_config.stat.exists + register: config_created + + - name: Include nginx config in prometheus.yml + lineinfile: + path: /etc/prometheus/prometheus.yml + line: ' - "nginx-app1.yml"' + insertafter: '^rule_files:' + state: present + register: config_modified + + - name: Test Prometheus configuration + command: promtool check config /etc/prometheus/prometheus.yml + register: prometheus_test + changed_when: false + + - name: Show test result + debug: + msg: "{{ prometheus_test.stdout_lines }}" + + - name: Reload Prometheus if config changed + systemd: + name: prometheus + state: reloaded + when: (config_created.changed or config_modified.changed) and prometheus_test.rc == 0 + + - name: Wait for Prometheus to reload + pause: + seconds: 3 + + - name: Verify Nginx target in Prometheus + shell: | + curl -s "http://localhost:9090/api/v1/targets" | python3 -c " +import json, sys +data = json.load(sys.stdin) +for target in data['data']['activeTargets']: + if 'nginx' in target['labels'].get('job', ''): + print(f\"Found nginx target: {target['labels']} - Health: {target['health']}\") +" + register: target_check + changed_when: false + ignore_errors: yes + + - name: Show target check result + debug: + msg: "{{ target_check.stdout_lines if target_check.stdout_lines else 'Nginx target not found' }}" + + - name: Check if nginx metrics are available + shell: | + # Wait a bit for metrics to appear + sleep 2 + curl -s "http://localhost:9090/api/v1/query?query=up{job='nginx-app1'}" | python3 -c " +import json, sys +data = json.load(sys.stdin) +if data['status'] == 'success' and data['data']['result']: + for result in data['data']['result']: + print(f\"Nginx metrics UP: {result['metric']}\") +else: + print(\"Nginx metrics not available yet\") +" + register: metrics_check + changed_when: false + + - name: Show metrics check result + debug: + msg: "{{ metrics_check.stdout_lines }}" diff --git a/playbooks/deploy-app1-nginx.yml b/playbooks/deploy-app1-nginx.yml index caeb5c1..8040f27 100644 --- a/playbooks/deploy-app1-nginx.yml +++ b/playbooks/deploy-app1-nginx.yml @@ -1,5 +1,5 @@ --- -- name: Deploy Nginx on App1 +- name: Deploy Nginx with load testing features on App1 hosts: 192.168.0.110 become: yes gather_facts: yes @@ -19,19 +19,31 @@ delay: 5 ignore_errors: yes - - name: Verify Nginx status endpoint + - name: Test API endpoints uri: - url: "http://{{ ansible_default_ipv4.address }}/status" + url: "http://{{ ansible_default_ipv4.address }}{{ item }}" status_code: 200 timeout: 5 - register: status_check + loop: + - /api/test + - /api/metrics + register: api_test ignore_errors: yes - name: Display deployment result debug: msg: | - ✅ Nginx successfully deployed on {{ inventory_hostname }}! - 🌐 Access at: http://{{ ansible_default_ipv4.address }} + ✅ Nginx with load testing deployed on {{ inventory_hostname }}! + 🌐 Main page: http://{{ ansible_default_ipv4.address }} 📊 Status page: http://{{ ansible_default_ipv4.address }}/status - 📈 Nginx metrics: http://{{ ansible_default_ipv4.address }}/nginx_status - 🖥️ Node metrics: http://{{ ansible_default_ipv4.address }}:9100/metrics + 🔧 Test APIs: + - http://{{ ansible_default_ipv4.address }}/api/test + - http://{{ ansible_default_ipv4.address }}/api/slow + - http://{{ ansible_default_ipv4.address }}/api/error + - http://{{ ansible_default_ipv4.address }}/api/metrics + 📈 Monitoring: + - Node metrics: http://{{ ansible_default_ipv4.address }}:9100/metrics + - Prometheus: http://192.168.0.105:9090 + - Grafana: http://192.168.0.106:3000 + + 🎯 Load testing interface ready with JavaScript controls! diff --git a/playbooks/final-app1-fix.yml b/playbooks/final-app1-fix.yml new file mode 100644 index 0000000..3a51986 --- /dev/null +++ b/playbooks/final-app1-fix.yml @@ -0,0 +1,61 @@ +--- +- name: Final fix for App1 Nginx configuration + hosts: 192.168.0.110 + become: yes + + tasks: + - name: Deploy final Nginx configuration + template: + src: "/root/projects/ansible-config/roles/nginx/templates/app1.conf.j2" + dest: /etc/nginx/conf.d/app1.conf + owner: root + group: root + mode: '0644' + + - name: Test Nginx configuration + command: nginx -t + register: nginx_test + changed_when: false + + - name: Show test result + debug: + msg: "{{ nginx_test.stdout_lines }}" + + - name: Reload Nginx + systemd: + name: nginx + state: reloaded + when: nginx_test.rc == 0 + + - name: Test all endpoints + shell: | + echo "=== Testing endpoints ===" + for endpoint in /api/test /health /status /nginx_status; do + echo -n "$endpoint: " + curl -s -o /dev/null -w "%{http_code}" http://localhost$endpoint && echo " OK" || echo " FAILED" + done + register: endpoint_test + changed_when: false + + - name: Show endpoint test results + debug: + msg: "{{ endpoint_test.stdout_lines }}" + + - name: Verify endpoints return JSON + shell: | + echo "=== Checking JSON responses ===" + curl -s http://localhost/api/test | python3 -m json.tool && echo "API Test: OK" || echo "API Test: FAILED" + curl -s http://localhost/health | python3 -m json.tool && echo "Health: OK" || echo "Health: FAILED" + register: json_test + changed_when: false + ignore_errors: yes + + - name: Final status check + debug: + msg: | + ✅ App1 Nginx configuration fixed! + 🌐 Access: http://192.168.0.110 + 📊 Status: http://192.168.0.110/status + 🔧 API Test: http://192.168.0.110/api/test + 💚 Health: http://192.168.0.110/health + 📈 Node metrics: http://192.168.0.110:9100/metrics diff --git a/playbooks/install-nginx-exporter.yml b/playbooks/install-nginx-exporter.yml new file mode 100644 index 0000000..ae2201a --- /dev/null +++ b/playbooks/install-nginx-exporter.yml @@ -0,0 +1,65 @@ +--- +- name: Install nginx-prometheus-exporter on App1 + hosts: 192.168.0.110 + become: yes + + tasks: + - name: Download nginx-prometheus-exporter + get_url: + url: https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz + dest: /tmp/nginx-exporter.tar.gz + + - name: Extract nginx-exporter + unarchive: + src: /tmp/nginx-exporter.tar.gz + dest: /usr/local/bin/ + remote_src: yes + creates: /usr/local/bin/nginx-prometheus-exporter + + - name: Create systemd service + copy: + content: | + [Unit] + Description=NGINX Prometheus Exporter + After=network.target nginx.service + + [Service] + Type=simple + User=root + ExecStart=/usr/local/bin/nginx-prometheus-exporter -nginx.scrape-uri=http://localhost:80/status + Restart=on-failure + + [Install] + WantedBy=multi-user.target + dest: /etc/systemd/system/nginx-exporter.service + owner: root + group: root + mode: '0644' + + - name: Enable and start nginx-exporter + systemd: + name: nginx-exporter + state: started + enabled: yes + daemon_reload: yes + + - name: Test nginx-exporter + uri: + url: http://localhost:9113/metrics + status_code: 200 + register: exporter_test + ignore_errors: yes + + - name: Show test result + debug: + msg: "Nginx exporter test: {{ 'SUCCESS' if exporter_test.status == 200 else 'FAILED' }}" + + - name: Verify metrics + shell: | + curl -s http://localhost:9113/metrics | grep -i nginx | head -5 + register: metrics_check + changed_when: false + + - name: Show metrics check + debug: + msg: "{{ metrics_check.stdout_lines }}" diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml index a66884c..1c57485 100644 --- a/roles/nginx/tasks/main.yml +++ b/roles/nginx/tasks/main.yml @@ -1,5 +1,5 @@ --- -# Установка и настройка Nginx - финальная версия +# Установка и настройка Nginx - финальная версия (без echo модуля) - name: Install prerequisites apt: name: diff --git a/roles/nginx/templates/app1.conf.j2 b/roles/nginx/templates/app1.conf.j2 index 13eab42..2acf64e 100644 --- a/roles/nginx/templates/app1.conf.j2 +++ b/roles/nginx/templates/app1.conf.j2 @@ -6,10 +6,12 @@ server { root /var/www/app1; index index.html; + # Main page location / { try_files $uri $uri/ =404; } + # Nginx status for monitoring location /status { stub_status on; access_log off; @@ -18,6 +20,7 @@ server { deny all; } + # Alternative status endpoint location /nginx_status { stub_status on; access_log off; @@ -25,4 +28,45 @@ server { allow 192.168.0.0/24; deny all; } + + # Test endpoints for load generation + location /api/test { + add_header Content-Type application/json; + add_header Cache-Control "no-cache"; + return 200 '{"status": "ok", "timestamp": "$time_iso8601", "server": "app1", "request_id": "$request_id", "method": "$request_method"}'; + } + + location /api/slow { + add_header Content-Type application/json; + add_header Cache-Control "no-cache"; + # Simple JSON response + return 200 '{"status": "slow_endpoint", "message": "Endpoint for testing", "timestamp": "$time_iso8601"}'; + } + + location /api/error { + add_header Content-Type application/json; + add_header Cache-Control "no-cache"; + # Simple error endpoint + return 500 '{"status": "error", "code": 500, "message": "Test error response", "request_id": "$request_id"}'; + } + + location /api/random { + add_header Content-Type application/json; + add_header Cache-Control "no-cache"; + # Random response - always success but different messages + return 200 '{"status": "random", "timestamp": "$time_iso8601", "value": "$msec", "message": "Random endpoint response"}'; + } + + location /api/metrics { + add_header Content-Type application/json; + add_header Cache-Control "no-cache"; + return 200 '{"server": "app1", "timestamp": "$time_iso8601", "available_endpoints": ["/api/test", "/api/slow", "/api/error", "/api/random", "/api/metrics", "/health", "/status"]}'; + } + + # Health check endpoint + location /health { + add_header Content-Type application/json; + access_log off; + return 200 '{"status": "healthy", "service": "nginx", "timestamp": "$time_iso8601", "version": "$nginx_version"}'; + } } diff --git a/roles/nginx/templates/index.html.j2 b/roles/nginx/templates/index.html.j2 index ccc3044..a263ce5 100644 --- a/roles/nginx/templates/index.html.j2 +++ b/roles/nginx/templates/index.html.j2 @@ -1,7 +1,8 @@ - Test App1 - Nginx + Test App1 - Nginx Load Test +
-

🚀 Test Application 1 - Nginx Server

+

Test Application 1 - Nginx Load Testing

-
-

📊 Server Information:

+
+

Server Information

Hostname: {{ ansible_hostname }}

IP Address: {{ ansible_default_ipv4.address }}

Role: Web Server (Nginx)

-

Deployed via: Ansible

+

Deployed: {{ ansible_date_time.date }}

-
-

📈 Monitoring:

-

Node Exporter metrics available at: http://{{ ansible_default_ipv4.address }}:9100/metrics

-

Nginx stub_status at: http://{{ ansible_default_ipv4.address }}/status

-

Collected by Prometheus: 192.168.0.105:9090

+
+

Load Testing Controls

+
+ + + + +
+ +
+ + + + +
+ +
+
+

Requests Sent

+
0
+
+
+

Successful

+
0
+
+
+

Failed

+
0
+
+
+

Active Tests

+
0
+
+
-

🔗 Infrastructure Links:

- +
+

Monitoring & Metrics

+

Node Exporter: :9100/metrics

+

Nginx Status: /status

+

Nginx Metrics: /nginx_status

+ +

API Endpoints:

+
+
/api/test - Test endpoint
+
/api/error - Error endpoint (500)
+
/api/random - Random response
+
/api/metrics - API info
+
/health - Health check
+
+ +

Quick Links:

+
+ Grafana Dashboard | + Prometheus UI | + Git/Forgejo +
+
+ +
+

Request Log

+
+
+ + diff --git a/roles/nginx_exporter/tasks/main.yml b/roles/nginx_exporter/tasks/main.yml new file mode 100644 index 0000000..579dc73 --- /dev/null +++ b/roles/nginx_exporter/tasks/main.yml @@ -0,0 +1,59 @@ +--- +# Install nginx-prometheus-exporter +- name: Download nginx-prometheus-exporter + get_url: + url: https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz + dest: /tmp/nginx-exporter.tar.gz + tags: nginx_exporter + +- name: Extract nginx-exporter + unarchive: + src: /tmp/nginx-exporter.tar.gz + dest: /tmp/ + remote_src: yes + creates: /tmp/nginx-prometheus-exporter + tags: nginx_exporter + +- name: Install nginx-exporter binary + copy: + src: /tmp/nginx-prometheus-exporter + dest: /usr/local/bin/nginx-prometheus-exporter + remote_src: yes + mode: '0755' + tags: nginx_exporter + +- name: Create systemd service for nginx-exporter + copy: + content: | + [Unit] + Description=NGINX Prometheus Exporter + After=network.target + + [Service] + Type=simple + User=root + ExecStart=/usr/local/bin/nginx-prometheus-exporter -nginx.scrape-uri=http://localhost:80/status + Restart=on-failure + + [Install] + WantedBy=multi-user.target + dest: /etc/systemd/system/nginx-exporter.service + owner: root + group: root + mode: '0644' + tags: nginx_exporter + +- name: Enable and start nginx-exporter + systemd: + name: nginx-exporter + state: started + enabled: yes + daemon_reload: yes + tags: nginx_exporter + +- name: Open firewall port for nginx-exporter + ufw: + rule: allow + port: '9113' + proto: tcp + tags: nginx_exporter diff --git a/roles/prometheus_nginx/tasks/main.yml b/roles/prometheus_nginx/tasks/main.yml new file mode 100644 index 0000000..a39a9f7 --- /dev/null +++ b/roles/prometheus_nginx/tasks/main.yml @@ -0,0 +1,36 @@ +--- +# Configure Prometheus to monitor Nginx +- name: Create Nginx scrape configuration + copy: + content: | + # Nginx metrics from stub_status + - job_name: 'nginx' + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /status + static_configs: + - targets: ['192.168.0.110:80'] + labels: + instance: 'app1-nginx' + service: 'web-server' + environment: 'test' + metric_relabel_configs: + - source_labels: [__address__] + target_label: instance + - source_labels: [__address__] + regex: '([^:]+)(?::\d+)?' + replacement: '${1}' + target_label: hostname + dest: /etc/prometheus/nginx.yml + owner: root + group: root + mode: '0644' + notify: reload prometheus + +- name: Include Nginx config in main prometheus.yml + lineinfile: + path: /etc/prometheus/prometheus.yml + line: ' - "nginx.yml"' + insertafter: 'rule_files:' + state: present + notify: reload prometheus