Update 4 files

- /roles/proxmox_base_setup/tasks/main.yml
- /roles/proxmox_base_setup/templates/node_exporter.service.j2
- /roles/proxmox_base_setup/templates/storcli_metrics.sh.j2
- /roles/proxmox_base_setup/handlers/main.yml
This commit is contained in:
Administrator 2025-11-14 06:18:58 +00:00
parent cf6e70603e
commit 906555ab4b
4 changed files with 416 additions and 0 deletions

View File

@ -0,0 +1,19 @@
---
- name: restart ssh
systemd:
name: ssh
state: restarted
- name: restart node_exporter
systemd:
name: node_exporter
state: restarted
daemon_reload: yes
enabled: yes
- name: restart storcli_metrics
systemd:
name: storcli_metrics.timer
state: restarted
daemon_reload: yes
when: storcli_available | default(false)

View File

@ -0,0 +1,302 @@
---
- name: Update package cache
apt:
update_cache: yes
cache_valid_time: 86400
- name: Upgrade installed packages (safe — не трогает pve-kernel и pve-пакеты)
apt:
upgrade: safe
notify: reboot if kernel updated
- name: Install essential base packages
apt:
name:
- curl
- wget
- gnupg
- apt-transport-https
- ca-certificates
- lsb-release
- net-tools
- iproute2
- pciutils
- smartmontools
- htop
- vim
- bash-completion
state: present
- name: Ensure 'locales' is installed (required for locale_gen)
apt:
name: locales
state: present
when: system_locale is defined and system_locale | length > 0
- name: Remove unused packages
apt:
autoremove: yes
autoclean: yes
- name: Disable IPv6 via sysctl
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: yes
state: present
reload: yes
loop:
- { name: 'net.ipv6.conf.all.disable_ipv6', value: '1' }
- { name: 'net.ipv6.conf.default.disable_ipv6', value: '1' }
- name: Ensure /root/.bashrc exists
file:
path: /root/.bashrc
state: touch
mode: '0644'
- name: Add custom aliases and env to ~/.bashrc
blockinfile:
path: /root/.bashrc
marker: "# {mark} ANSIBLE MANAGED BLOCK: PROXMOX CUSTOM ALIASES"
block: |
# ——— Общие ———
alias rm='rm -i' # Защита от случайного удаления
alias cp='cp -i'
alias mv='mv -i'
alias ls='ls --color=auto'
alias ll='ls -lah'
alias l.='ls -d .* --color=auto'
alias mount='mount | column -t'
alias h='history'
alias c='clear'
alias now='date +%T'
alias nowdate='date +%Y-%m-%d'
alias ping5='ping -c 5'
alias ports='ss -tulnp' # современная замена netstat
alias meminfo='free -h'
alias psmem='ps aux --sort=-%mem | head -11'
# ——— Proxmox ———
alias lxcstat='pct list'
alias qmstat='qm list'
alias ha='pvecm status && pve-ha-manager status'
alias stor='pvesm status'
# ——— RAID / Диски ———
alias storcli='/opt/MegaRAID/storcli/storcli64'
# ——— Обновление ———
alias aptup='apt update && apt list --upgradable'
owner: root
mode: '0644'
- name: Configure timezone
timezone:
name: "{{ timezone }}"
- name: Generate system locale
locale_gen:
name: "{{ system_locale }}"
state: present
when: system_locale is defined and system_locale | length > 0
- name: Set default LANG in /etc/default/locale
lineinfile:
path: /etc/default/locale
regexp: '^LANG='
line: "LANG={{ system_locale }}"
state: present
create: yes
when: system_locale is defined and system_locale | length > 0
- name: Ensure common dirs exist
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- /opt/scripts
- /etc/apt/keyrings
- name: Ensure python3-requests is available (for custom scripts)
apt:
name: python3-requests
state: present
- name: Ensure SSH directory exists
file:
path: /root/.ssh
state: directory
mode: '0700'
- name: Add authorized SSH keys for root
authorized_key:
user: root
state: present
key: "{{ item }}"
loop: "{{ ssh_public_keys | default([]) }}"
- name: Harden SSH configuration
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^{{ item.key }}\\s"
line: "{{ item.key }} {{ item.value }}"
state: present
loop:
- { key: 'PasswordAuthentication', value: 'no' }
- { key: 'PermitRootLogin', value: 'prohibit-password' }
- { key: 'PubkeyAuthentication', value: 'yes' }
- { key: 'X11Forwarding', value: 'no' }
notify: restart ssh
# ========== Node Exporter ==========
- name: Create node_exporter user
user:
name: node_exporter
system: yes
shell: /usr/sbin/nologin
create_home: no
- name: Download node_exporter
get_url:
url: "https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz"
dest: /tmp/node_exporter-1.8.2.linux-amd64.tar.gz
checksum: "sha256:https://github.com/prometheus/node_exporter/releases/download/v1.8.2/sha256sums.txt"
mode: '0644'
timeout: 60
- name: Extract node_exporter
unarchive:
src: /tmp/node_exporter-1.8.2.linux-amd64.tar.gz
dest: /tmp/
remote_src: yes
creates: /tmp/node_exporter-1.8.2.linux-amd64/node_exporter
- name: Install node_exporter binary
copy:
src: /tmp/node_exporter-1.8.2.linux-amd64/node_exporter
dest: /usr/local/bin/node_exporter
owner: root
group: root
mode: '0755'
remote_src: yes
notify: restart node_exporter
- name: Create textfile_collector directory
file:
path: /var/lib/node_exporter/textfile_collector
state: directory
owner: node_exporter
group: node_exporter
mode: '0755'
- name: Deploy node_exporter systemd service
template:
src: node_exporter.service.j2
dest: /etc/systemd/system/node_exporter.service
owner: root
group: root
mode: '0644'
notify: restart node_exporter
# ========== storcli — проверка и сбор метрик (без установки) ==========
- name: Detect MegaRAID controller (lspci check)
command: lspci -d 1000: | grep -q "MegaRAID"
register: lspci_megaraid
ignore_errors: yes
changed_when: false
- name: Check storcli binary exists
stat:
path: /opt/MegaRAID/storcli/storcli64
register: storcli_bin
when: lspci_megaraid.rc == 0
- name: Ensure storcli symlink in PATH
file:
src: /opt/MegaRAID/storcli/storcli64
dest: /usr/local/bin/storcli
state: link
force: yes
when:
- lspci_megaraid.rc == 0
- storcli_bin.stat.exists
- name: Verify storcli functionality
command: storcli /call show
register: storcli_test
changed_when: false
failed_when:
- storcli_test.rc != 0
- "'Controller' not in storcli_test.stdout"
when:
- lspci_megaraid.rc == 0
- storcli_bin.stat.exists
- name: Set fact — storcli is available
set_fact:
storcli_available: true
when:
- lspci_megaraid.rc == 0
- storcli_bin.stat.exists
- storcli_test is success
- name: Set fact — storcli NOT available
set_fact:
storcli_available: false
when: not (lspci_megaraid.rc == 0 and storcli_bin.stat.exists)
# Сбор метрик ТОЛЬКО при наличии storcli
- name: Deploy storcli metrics script
template:
src: storcli_metrics.sh.j2
dest: /opt/scripts/storcli_metrics.sh
owner: root
group: root
mode: '0755'
when: storcli_available | default(false)
- name: Deploy storcli_metrics systemd units
block:
- name: Create storcli_metrics.service
copy:
content: |
[Unit]
Description=Collect RAID/disk metrics via storcli
After=network.target
[Service]
Type=oneshot
ExecStart=/opt/scripts/storcli_metrics.sh
User=root
StandardOutput=journal
StandardError=journal
dest: /etc/systemd/system/storcli_metrics.service
owner: root
mode: '0644'
- name: Create storcli_metrics.timer (every 5 min)
copy:
content: |
[Unit]
Description=Run storcli metrics collector every 5 minutes
Requires=storcli_metrics.service
[Timer]
OnBootSec=60
OnUnitActiveSec=5m
AccuracySec=1s
[Install]
WantedBy=timers.target
dest: /etc/systemd/system/storcli_metrics.timer
owner: root
mode: '0644'
- name: Enable & start storcli_metrics.timer
systemd:
name: storcli_metrics.timer
state: started
enabled: yes
daemon_reload: yes
when: storcli_available | default(false)
notify: restart storcli_metrics

View File

@ -0,0 +1,31 @@
[Unit]
Description=Prometheus Node Exporter
Documentation=https://github.com/prometheus/node_exporter
After=network.target
[Service]
Type=simple
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.processes \
--collector.cpu \
--collector.meminfo \
--collector.diskstats \
--collector.netdev \
--collector.filesystem \
--collector.loadavg \
--collector.time \
--collector.textfile.directory=/var/lib/node_exporter/textfile_collector \
--web.listen-address=0.0.0.0:9100
Restart=always
RestartSec=5
# Защита от атак и случайных ошибок
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,64 @@
#!/bin/bash
if (enc != "" && slot != "") {
# Вывести предыдущий диск
gsub(/ /, "_", model);
printf "storcli_disk_temp{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, (temp ~ /^[0-9]+$/ ? temp : 0)
printf "storcli_disk_state{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, state_num
printf "storcli_disk_media_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, media_err
printf "storcli_disk_other_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, other_err
}
enc=""; slot=""; model=""; temp=""; media_err=0; other_err=0; state_num=0
}
/Enclosure Device ID:/ { enc = $4 }
/Slot Number:/ { slot = $3 }
/Device Id:/ { if (enc == "") enc = $3 } # fallback
/Model Number:/ { model = $3 }
/Drive Temperature/ {
match($0, /([0-9]+)C/);
if (RSTART) temp = substr($0, RSTART, RLENGTH-1)
}
/Firmware state:/ {
state = $3
if (state ~ /Online/) state_num = 2
else if (state ~ /Unconfigured.*Good/) state_num = 1
else if (state ~ /Failed/) state_num = 3
else if (state ~ /Rebuild/) state_num = 4
else if (state ~ /Offline/) state_num = 0
else state_num = -1
}
/Media Error Count:/ { media_err = $4 }
/Other Error Count:/ { other_err = $4 }
END {
if (enc != "" && slot != "") {
gsub(/ /, "_", model);
printf "storcli_disk_temp{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, (temp ~ /^[0-9]+$/ ? temp : 0)
printf "storcli_disk_state{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, state_num
printf "storcli_disk_media_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, media_err
printf "storcli_disk_other_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, other_err
}
}
' c="$c")
echo "$disks_info" >> "$OUT_FILE"
# Виртуальные диски (массивы)
vds=$(storcli /c$c/vall show | awk '
NR>8 && $1 ~ /^[0-9]+$/ {
vd = $1; state = $2; size = $3;
gsub(/,/,"", size);
# state: Optl=Online(1), Dgrd=Degraded(2), Offln=Offline(0), Ft=Failed(3)
state_num = 1;
if (state == "Dgrd") state_num = 2;
else if (state ~ /Offln|Pdgd/) state_num = 0;
else if (state == "Ft") state_num = 3;
printf "storcli_array_state{controller=\"%s\",vd=\"%s\",size=\"%s\"} %s\n", c, vd, size, state_num
}
')
echo "$vds" >> "$OUT_FILE"
done
# Атомарная замена
mv "$OUT_FILE" "$FINAL_FILE"
chmod 644 "$FINAL_FILE"
echo "$(date -Iseconds) storcli metrics updated" >&2